[Yaffs] [PATCH v2] yaffs: set security attribute at file cre…

Top Page
Attachments:
Message as email
+ (text/plain)
Delete this message
Reply to this message
Author: Stephen Smalley
Date:  
To: yaffs
Subject: [Yaffs] [PATCH v2] yaffs: set security attribute at file creation
Add support to yaffs to set the security attribute of new inodes when
they are created. This parallels similar support in other filesystems,
and is a requirement for SELinux and other MAC systems. This support
is used by SE Android, http://selinuxproject.org/page/SEAndroid.

Signed-off-by: Stephen Smalley <>
---
yaffs_vfs_multi.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
yaffs_vfs_single.c | 39 ++++++++++++++++++++++++++
2 files changed, 119 insertions(+)

diff --git a/yaffs_vfs_multi.c b/yaffs_vfs_multi.c
index ce41d6c..ed343e2 100644
--- a/yaffs_vfs_multi.c
+++ b/yaffs_vfs_multi.c
@@ -71,6 +71,8 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/fs.h>
+#include <linux/security.h>
+#include <linux/xattr.h>
#include <linux/proc_fs.h>
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
#include <linux/smp_lock.h>
@@ -1618,6 +1620,82 @@ out:
#define YCRED(x) (x->cred)
#endif

+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
+int yaffs_initxattrs(struct inode *inode, const struct xattr *xattr_array,
+            void *fs_info)
+{
+    const struct xattr *xattr;
+    struct yaffs_obj *obj = fs_info;
+    struct yaffs_dev *dev = obj->my_dev;
+    char name[XATTR_NAME_MAX];
+    int err = 0;
+    int result = YAFFS_OK;
+
+    yaffs_gross_lock(dev);
+    for (xattr = xattr_array; xattr->name != NULL; xattr++) {
+        snprintf(name, sizeof name, "%s%s", XATTR_SECURITY_PREFIX, xattr->name);
+        /* inlined yaffs_setxattr: no instantiated dentry yet */
+        result = yaffs_set_xattrib(obj, name, xattr->value,
+                       xattr->value_len, 0);
+        if (result < 0)
+            break;
+    }
+    yaffs_gross_unlock(dev);
+    if (result == YAFFS_OK)
+        err = 0;
+    else if (result < 0)
+        err = result;
+    return err;
+}
+
+static int yaffs_init_security(struct inode *dir, struct dentry *dentry,
+                   struct inode *inode)
+{
+    struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
+    return security_inode_init_security(inode, dir, &dentry->d_name,
+                        &yaffs_initxattrs, obj);
+}
+#else
+static int yaffs_init_security(struct inode *dir, struct dentry *dentry,
+                   struct inode *inode)
+{
+    int err;
+    size_t size;
+    void *value;
+    char *suffix;
+    char name[XATTR_NAME_MAX];
+    struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
+    struct yaffs_dev *dev = obj->my_dev;
+    int result;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
+    err = security_inode_init_security(inode, dir, &dentry->d_name,
+                       &suffix, &value, &size);
+#else
+    err = security_inode_init_security(inode, dir, &suffix, &value, &size);
+#endif
+    if (err) {
+        if (err == -EOPNOTSUPP)
+            return 0;
+        return err;
+    }
+    snprintf(name, sizeof name, "%s%s", XATTR_SECURITY_PREFIX, suffix);
+
+    /* inlined yaffs_setxattr: no instantiated dentry yet */
+    yaffs_gross_lock(dev);
+    result = yaffs_set_xattrib(obj, name, value, size, 0);
+    if (result == YAFFS_OK)
+        err = 0;
+    else if (result < 0)
+        err = result;
+    yaffs_gross_unlock(dev);
+
+    kfree(value);
+    kfree(suffix);
+    return err;
+}
+#endif
+
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
 static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
                dev_t rdev)
@@ -1694,6 +1772,7 @@ static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,


     if (obj) {
         inode = yaffs_get_inode(dir->i_sb, mode, rdev, obj);
+        yaffs_init_security(dir, dentry, inode);
         d_instantiate(dentry, inode);
         update_dir_time(dir);
         yaffs_trace(YAFFS_TRACE_OS,
@@ -1827,6 +1906,7 @@ static int yaffs_symlink(struct inode *dir, struct dentry *dentry,
         struct inode *inode;


         inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj);
+        yaffs_init_security(dir, dentry, inode);
         d_instantiate(dentry, inode);
         update_dir_time(dir);
         yaffs_trace(YAFFS_TRACE_OS, "symlink created OK");
diff --git a/yaffs_vfs_single.c b/yaffs_vfs_single.c
index 8d41f69..f3e83df 100644
--- a/yaffs_vfs_single.c
+++ b/yaffs_vfs_single.c
@@ -41,6 +41,8 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/fs.h>
+#include <linux/security.h>
+#include <linux/xattr.h>
 #include <linux/proc_fs.h>
 #include <linux/pagemap.h>
 #include <linux/mtd/mtd.h>
@@ -187,6 +189,41 @@ struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,
     return inode;
 }


+int yaffs_initxattrs(struct inode *inode, const struct xattr *xattr_array,
+            void *fs_info)
+{
+    const struct xattr *xattr;
+    struct yaffs_obj *obj = fs_info;
+    struct yaffs_dev *dev = obj->my_dev;
+    char name[XATTR_NAME_MAX];
+    int err = 0;
+    int result = YAFFS_OK;
+
+    yaffs_gross_lock(dev);
+    for (xattr = xattr_array; xattr->name != NULL; xattr++) {
+        snprintf(name, sizeof name, "%s%s", XATTR_SECURITY_PREFIX, xattr->name);
+        /* inlined yaffs_setxattr: no instantiated dentry yet */
+        result = yaffs_set_xattrib(obj, name, xattr->value,
+                       xattr->value_len, 0);
+        if (result < 0)
+            break;
+    }
+    yaffs_gross_unlock(dev);
+    if (result == YAFFS_OK)
+        err = 0;
+    else if (result < 0)
+        err = result;
+    return err;
+}
+
+static int yaffs_init_security(struct inode *dir, struct dentry *dentry,
+                   struct inode *inode)
+{
+    struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
+    return security_inode_init_security(inode, dir, &dentry->d_name,
+                        &yaffs_initxattrs, obj);
+}
+
 static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
                dev_t rdev)
 {
@@ -259,6 +296,7 @@ static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,



     inode = yaffs_get_inode(dir->i_sb, mode, rdev, obj);
+    yaffs_init_security(dir, dentry, inode);
     d_instantiate(dentry, inode);
     update_dir_time(dir);
     yaffs_trace(YAFFS_TRACE_OS,
@@ -357,6 +395,7 @@ static int yaffs_symlink(struct inode *dir, struct dentry *dentry,
     }


     inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj);
+    yaffs_init_security(dir, dentry, inode);
     d_instantiate(dentry, inode);
     update_dir_time(dir);
     yaffs_trace(YAFFS_TRACE_OS, "symlink created OK");
-- 
1.7.11.2




--
Stephen Smalley
National Security Agency