[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 e.g. SELinux and other MAC systems.

I'm not entirely sure about the error path in the unlikely case where
yaffs_init_security() returns an error; the intent is to unwind the file
creation in that situation as if it had never been created. This error
case is however unlikely. The file must have a security attribute
assigned before it becomes accessible to userspace.

I only updated yaffs_vfs_multi.c, but the same code should work for
yaffs_vfs_single.c, using whichever branch of the #if that corresponds
to your target upstream kernel version.

Signed-off-by: Stephen Smalley <>

---

yaffs_vfs_multi.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 71 insertions(+), 2 deletions(-)

diff --git a/yaffs_vfs_multi.c b/yaffs_vfs_multi.c
index 7e28c40..5acd1de 100644
--- a/yaffs_vfs_multi.c
+++ b/yaffs_vfs_multi.c
@@ -78,6 +78,7 @@
#include <linux/interrupt.h>
#include <linux/string.h>
#include <linux/ctype.h>
+#include <linux/security.h>

 #if (YAFFS_NEW_FOLLOW_LINK == 1)
 #include <linux/namei.h>
@@ -1603,6 +1604,54 @@ out:
     return ret_val;
 }


+#ifdef CONFIG_YAFFS_XATTR
+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;
+}
+#else
+static int yaffs_init_security(struct inode *dir, struct dentry *dentry,
+                   struct inode *inode)
+{
+    return 0;
+}
+#endif
+
 /*
  * File creation. Allocate an inode, and we're done..
  */
@@ -1689,6 +1738,15 @@ static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,


     if (obj) {
         inode = yaffs_get_inode(dir->i_sb, mode, rdev, obj);
+        error = yaffs_init_security(dir, dentry, inode);
+        if (error) {
+            /* undo! */
+            iput(inode);
+            yaffs_gross_lock(dev);
+            yaffs_unlinker(parent, dentry->d_name.name);
+            yaffs_gross_unlock(dev);
+            return error;
+        }
         d_instantiate(dentry, inode);
         update_dir_time(dir);
         yaffs_trace(YAFFS_TRACE_OS,
@@ -1802,12 +1860,14 @@ static int yaffs_symlink(struct inode *dir, struct dentry *dentry,
     uid_t uid = YCRED(current)->fsuid;
     gid_t gid =
         (dir->i_mode & S_ISGID) ? dir->i_gid : YCRED(current)->fsgid;
+    struct yaffs_obj *parent = yaffs_inode_to_obj(dir);
+    int error;


     yaffs_trace(YAFFS_TRACE_OS, "yaffs_symlink");


-    dev = yaffs_inode_to_obj(dir)->my_dev;
+    dev = parent->my_dev;
     yaffs_gross_lock(dev);
-    obj = yaffs_create_symlink(yaffs_inode_to_obj(dir), dentry->d_name.name,
+    obj = yaffs_create_symlink(parent, dentry->d_name.name,
                    S_IFLNK | S_IRWXUGO, uid, gid, symname);
     yaffs_gross_unlock(dev);


@@ -1815,6 +1875,15 @@ 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);
+        error = yaffs_init_security(dir, dentry, inode);
+        if (error) {
+            /* undo! */
+            iput(inode);
+            yaffs_gross_lock(dev);
+            yaffs_unlinker(parent, dentry->d_name.name);
+            yaffs_gross_unlock(dev);
+            return error;
+        }
         d_instantiate(dentry, inode);
         update_dir_time(dir);
         yaffs_trace(YAFFS_TRACE_OS, "symlink created OK");



--
Stephen Smalley
National Security Agency