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