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

Top Page
Attachments:
Message as email
+ (text/plain)
Delete this message
Reply to this message
Author: Stephen Smalley
Date:  
To: yaffs
Subject: Re: [Yaffs] [PATCH] yaffs: set security attribute at file creation
On Wed, 2011-04-13 at 16:36 -0400, Stephen Smalley wrote:
> 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 <>


BTW, if it is helpful, the code added by this patch can be considered to
be public domain, i.e. not copyrighted. Not clear it matters since
yaffs_vfs_multi.c is already marked as GPLv2 but wasn't sure if you had
concerns about retaining exclusive copyright on it.

>
> ---
>
> 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