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

Top Page
Attachments:
Message as email
+ (text/plain)
Delete this message
Reply to this message
Author: Stephen Smalley
Date:  
To: yaffs
Subject: [Yaffs] [PATCH] 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 | 43 +++++++++++++++++++++++++++++++++++++++++++
yaffs_vfs_single.c | 39 +++++++++++++++++++++++++++++++++++++++
2 files changed, 82 insertions(+)

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

+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_dev *dev;
+    struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
+    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 */
+    dev = obj->my_dev;
+    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;
+}
+
 #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 +1735,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 +1869,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..5ce7a55 100644
--- a/yaffs_vfs_single.c
+++ b/yaffs_vfs_single.c
@@ -41,6 +41,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/fs.h>
+#include <linux/security.h>
 #include <linux/proc_fs.h>
 #include <linux/pagemap.h>
 #include <linux/mtd/mtd.h>
@@ -187,6 +188,42 @@ struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,
     return inode;
 }


+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_dev *dev;
+    struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
+    int result;
+
+    err = security_inode_init_security(inode, dir, &dentry->d_name,
+                       &suffix, &value, &size);
+    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 */
+    dev = obj->my_dev;
+    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;
+}
+
 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