On Thu, 2012-08-16 at 14:54 -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 SELinux and other MAC systems. This support > is used by SE Android, http://selinuxproject.org/page/SEAndroid > > Signed-off-by: Stephen Smalley Sorry, I see that they changed the hook interface again in v3.2; I'll update the patch to also handle kernels >= 3.2. > --- > 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 > #include > #include > +#include > #include > #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)) > #include > @@ -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 > #include > #include > +#include > #include > #include > #include > @@ -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