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 > #include > #include > +#include > > #if (YAFFS_NEW_FOLLOW_LINK == 1) > #include > @@ -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