From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757353Ab2DIPPe (ORCPT ); Mon, 9 Apr 2012 11:15:34 -0400 Received: from nm29-vm0.access.bullet.mail.mud.yahoo.com ([66.94.236.255]:33170 "HELO nm29-vm0.access.bullet.mail.mud.yahoo.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1757215Ab2DIPPd (ORCPT ); Mon, 9 Apr 2012 11:15:33 -0400 X-Greylist: delayed 419 seconds by postgrey-1.27 at vger.kernel.org; Mon, 09 Apr 2012 11:15:32 EDT X-Yahoo-Newman-Id: 838857.78125.bm@smtp102.biz.mail.gq1.yahoo.com X-Yahoo-Newman-Property: ymail-3 X-YMail-OSG: OoERxHkVM1kf.8i_kpkIMc1mOeNd8B7j61aJc023yXTz5q7 rmjGJFj.HmdlqRdEIEXpdVcIAe6HMDe88ir9yjBLXd1IYPykTphDst4Sf_d3 S_HQkwXLgv85kRcGoK00nv9StaKDYkPeoCMLm3lSAef7Qik69tVqBE5i065i 7TMNqMkRAN93IbBW9lRV6bQd0tsRRZ0pHhdbcdv3DNyAb95s.PN5KG.d0xx2 iTwlcWr3WWcx5PAUC57XDxOQWmdSiQrk1btAhoEV9nfjKa2_SZ7kxm5mbHfx pr4b1sF7s54Pdmzy6I.GU6ENgqqd1w9qzCjEDgLKC8i2pPNEpaeYvAIwKcYe fOf1cY7bj5_NS0EAqQygvZv7ympt8PLzzJa23VTvzqjcd9fBxAUvW.zz6aes q9MztIH51ENMV2KnIzmFJNz7FWTXN4zMqxg1j.V5KIWIQVHDcDVSpXE2r1Rq WB83S8cHGRKLkGyhh8bkjTpD3oLWmBC2cgFdNyWldxOEW7LlzZdn5YILka__ PRhUSYmQGRJpNTIbmg4i5mcZzGtOhOjwBI1V9fo8Gy56xE7WFGhMpx_bHkWb TKoE- X-Yahoo-SMTP: OIJXglSswBDfgLtXluJ6wiAYv6_cnw-- Message-ID: <4F82FB6F.7000706@schaufler-ca.com> Date: Mon, 09 Apr 2012 08:08:31 -0700 From: Casey Schaufler User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:11.0) Gecko/20120327 Thunderbird/11.0.1 MIME-Version: 1.0 To: Subodh Nijsure CC: linux-mtd@lists.infradead.org, Artem Bityutskiy , Adrian Hunter , linux-kernel@vger.kernel.org, Subodh Nijsure , LSM , SE Linux , Casey Schaufler Subject: Re: [PATCH] Add security.selinux XATTR support for the UBIFS. Also fix couple of bugs in UBIFS extended attribute length calculation. References: <1333892851-10758-1-git-send-email-snijsure@grid-net.com> <4F824B4F.8090107@schaufler-ca.com> In-Reply-To: Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 4/8/2012 11:40 PM, Subodh Nijsure wrote: > On Sun, Apr 8, 2012 at 7:37 PM, Casey Schaufler wrote: >> On 4/8/2012 6:47 AM, Subodh Nijsure wrote: >>> TESTING: Tested on MX28 based platforms using Micron MT29F2G08ABAEAH4 NAND >>> With these change we are able to label UBIFS filesystem with security.selinux >>> and run system with selinux enabled. >>> Also ran integck test on UBI filesystem. >>> >>> Signed-off-by: Subodh Nijsure >> There is no reason to restrict xattr support to SELinux. >> SELinux specific behavior belongs within the SELinux LSM. >> This code needs to support the full xattr semantics. >> >> Nacked-by: Casey Schaufler >> >>> --- >>> fs/ubifs/dir.c | 4 ++ >>> fs/ubifs/file.c | 6 ++ >>> fs/ubifs/journal.c | 12 +++- >>> fs/ubifs/super.c | 3 + >>> fs/ubifs/ubifs.h | 9 +++ >>> fs/ubifs/xattr.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++++---- >>> 6 files changed, 167 insertions(+), 14 deletions(-) >>> >>> diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c >>> index ec9f187..f4e06c4 100644 >>> --- a/fs/ubifs/dir.c >>> +++ b/fs/ubifs/dir.c >>> @@ -293,6 +293,7 @@ static int ubifs_create(struct inode *dir, struct dentry *dentry, umode_t mode, >>> ubifs_release_budget(c, &req); >>> insert_inode_hash(inode); >>> d_instantiate(dentry, inode); >>> + ubifs_init_security(dir, inode, &dentry->d_name); >>> return 0; >>> >>> out_cancel: >>> @@ -754,6 +755,7 @@ static int ubifs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) >>> >>> ubifs_release_budget(c, &req); >>> d_instantiate(dentry, inode); >>> + ubifs_init_security(dir, inode, &dentry->d_name); >>> return 0; >>> >>> out_cancel: >>> @@ -831,6 +833,7 @@ static int ubifs_mknod(struct inode *dir, struct dentry *dentry, >>> ubifs_release_budget(c, &req); >>> insert_inode_hash(inode); >>> d_instantiate(dentry, inode); >>> + ubifs_init_security(dir, inode, &dentry->d_name); >>> return 0; >>> >>> out_cancel: >>> @@ -907,6 +910,7 @@ static int ubifs_symlink(struct inode *dir, struct dentry *dentry, >>> ubifs_release_budget(c, &req); >>> insert_inode_hash(inode); >>> d_instantiate(dentry, inode); >>> + ubifs_init_security(dir, inode, &dentry->d_name); >>> return 0; >>> >>> out_cancel: >>> diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c >>> index 5c8f6dc..b8e9d66 100644 >>> --- a/fs/ubifs/file.c >>> +++ b/fs/ubifs/file.c >>> @@ -1575,6 +1575,12 @@ const struct inode_operations ubifs_symlink_inode_operations = { >>> .follow_link = ubifs_follow_link, >>> .setattr = ubifs_setattr, >>> .getattr = ubifs_getattr, >>> +#ifdef CONFIG_UBIFS_FS_XATTR >>> + .setxattr = ubifs_symlink_setxattr, >>> + .getxattr = ubifs_symlink_getxattr, >>> + .listxattr = ubifs_listxattr, >>> + .removexattr = ubifs_removexattr, >>> +#endif >>> }; >>> >>> const struct file_operations ubifs_file_operations = { >>> diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c >>> index 2f438ab..725dc17 100644 >>> --- a/fs/ubifs/journal.c >>> +++ b/fs/ubifs/journal.c >>> @@ -553,7 +553,8 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, >>> >>> dbg_jnl("ino %lu, dent '%.*s', data len %d in dir ino %lu", >>> inode->i_ino, nm->len, nm->name, ui->data_len, dir->i_ino); >>> - ubifs_assert(dir_ui->data_len == 0); >>> + if (!xent) >>> + ubifs_assert(dir_ui->data_len == 0); >>> ubifs_assert(mutex_is_locked(&dir_ui->ui_mutex)); >>> >>> dlen = UBIFS_DENT_NODE_SZ + nm->len + 1; >>> @@ -572,7 +573,11 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, >>> >>> aligned_dlen = ALIGN(dlen, 8); >>> aligned_ilen = ALIGN(ilen, 8); >>> - len = aligned_dlen + aligned_ilen + UBIFS_INO_NODE_SZ; >>> + /* Make sure to account for dir_ui+data_len in length calculation >>> + * in case there is extended attribute. >>> + */ >>> + len = aligned_dlen + aligned_ilen + >>> + UBIFS_INO_NODE_SZ + dir_ui->data_len; >>> dent = kmalloc(len, GFP_NOFS); >>> if (!dent) >>> return -ENOMEM; >>> @@ -649,7 +654,8 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, >>> >>> ino_key_init(c, &ino_key, dir->i_ino); >>> ino_offs += aligned_ilen; >>> - err = ubifs_tnc_add(c, &ino_key, lnum, ino_offs, UBIFS_INO_NODE_SZ); >>> + err = ubifs_tnc_add(c, &ino_key, lnum, ino_offs, >>> + UBIFS_INO_NODE_SZ + dir_ui->data_len); >>> if (err) >>> goto out_ro; >>> >>> diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c >>> index 76e4e05..c28ac04 100644 >>> --- a/fs/ubifs/super.c >>> +++ b/fs/ubifs/super.c >>> @@ -2061,6 +2061,9 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent) >>> if (c->max_inode_sz > MAX_LFS_FILESIZE) >>> sb->s_maxbytes = c->max_inode_sz = MAX_LFS_FILESIZE; >>> sb->s_op = &ubifs_super_operations; >>> +#ifdef CONFIG_UBIFS_FS_XATTR >>> + sb->s_xattr = ubifs_xattr_handlers; >>> +#endif >>> >>> mutex_lock(&c->umount_mutex); >>> err = mount_ubifs(c); >>> diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h >>> index 93d59ac..60b57f7 100644 >>> --- a/fs/ubifs/ubifs.h >>> +++ b/fs/ubifs/ubifs.h >>> @@ -36,6 +36,7 @@ >>> #include >>> #include >>> #include >>> +#include >>> #include "ubifs-media.h" >>> >>> /* Version of this UBIFS implementation */ >>> @@ -1454,6 +1455,7 @@ extern spinlock_t ubifs_infos_lock; >>> extern atomic_long_t ubifs_clean_zn_cnt; >>> extern struct kmem_cache *ubifs_inode_slab; >>> extern const struct super_operations ubifs_super_operations; >>> +extern const struct xattr_handler *ubifs_xattr_handlers[]; >>> extern const struct address_space_operations ubifs_file_address_operations; >>> extern const struct file_operations ubifs_file_operations; >>> extern const struct inode_operations ubifs_file_inode_operations; >>> @@ -1736,10 +1738,17 @@ int ubifs_getattr(struct vfsmount *mnt, struct dentry *dentry, >>> struct kstat *stat); >>> >>> /* xattr.c */ >>> + >>> int ubifs_setxattr(struct dentry *dentry, const char *name, >>> const void *value, size_t size, int flags); >>> +int ubifs_init_security(struct inode *dentry, struct inode *inode, >>> + const struct qstr *qstr); >>> +int ubifs_symlink_setxattr(struct dentry *dentry, const char *name, >>> + const void *value, size_t size, int flags); >>> ssize_t ubifs_getxattr(struct dentry *dentry, const char *name, void *buf, >>> size_t size); >>> +ssize_t ubifs_symlink_getxattr(struct dentry *dentry, const char *name, >>> + void *buf, size_t size); >>> ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size); >>> int ubifs_removexattr(struct dentry *dentry, const char *name); >>> >>> diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c >>> index 85b2722..a402c7d 100644 >>> --- a/fs/ubifs/xattr.c >>> +++ b/fs/ubifs/xattr.c >>> @@ -209,11 +209,11 @@ static int change_xattr(struct ubifs_info *c, struct inode *host, >>> goto out_free; >>> } >>> inode->i_size = ui->ui_size = size; >>> - ui->data_len = size; >>> >>> mutex_lock(&host_ui->ui_mutex); >>> host->i_ctime = ubifs_current_time(host); >>> host_ui->xattr_size -= CALC_XATTR_BYTES(ui->data_len); >>> + ui->data_len = size; >>> host_ui->xattr_size += CALC_XATTR_BYTES(size); >>> >>> /* >>> @@ -293,18 +293,16 @@ static struct inode *iget_xattr(struct ubifs_info *c, ino_t inum) >>> return ERR_PTR(-EINVAL); >>> } >>> >>> -int ubifs_setxattr(struct dentry *dentry, const char *name, >>> - const void *value, size_t size, int flags) >>> +static int __ubifs_setxattr(struct inode *host, const char *name, >>> + const void *value, size_t size, int flags) >>> { >>> - struct inode *inode, *host = dentry->d_inode; >>> + struct inode *inode; >>> struct ubifs_info *c = host->i_sb->s_fs_info; >>> struct qstr nm = { .name = name, .len = strlen(name) }; >>> struct ubifs_dent_node *xent; >>> union ubifs_key key; >>> int err, type; >>> >>> - dbg_gen("xattr '%s', host ino %lu ('%.*s'), size %zd", name, >>> - host->i_ino, dentry->d_name.len, dentry->d_name.name, size); >>> ubifs_assert(mutex_is_locked(&host->i_mutex)); >>> >>> if (size > UBIFS_MAX_INO_DATA) >>> @@ -356,10 +354,29 @@ out_free: >>> return err; >>> } >>> >>> -ssize_t ubifs_getxattr(struct dentry *dentry, const char *name, void *buf, >>> - size_t size) >>> +int ubifs_symlink_setxattr(struct dentry *dentry, const char *name, >>> + const void *value, size_t size, int flags) >>> { >>> - struct inode *inode, *host = dentry->d_inode; >>> + struct inode *host = dentry->d_inode; >>> + dbg_gen("xattr '%s', host ino %lu ('%.*s'), size %zd", name, >>> + host->i_ino, dentry->d_name.len, dentry->d_name.name, size); >>> + return __ubifs_setxattr(host, name, value, size, flags); >>> +} >>> + >>> +int ubifs_setxattr(struct dentry *dentry, const char *name, >>> + const void *value, size_t size, int flags) >>> +{ >>> + struct inode *host = dentry->d_inode; >>> + dbg_gen("xattr '%s', host ino %lu ('%.*s'), size %zd", name, >>> + host->i_ino, dentry->d_name.len, dentry->d_name.name, size); >>> + return __ubifs_setxattr(host, name, value, size, flags); >>> +} >>> + >>> +static >>> +ssize_t __ubifs_getxattr(struct inode *host, const char *name, void *buf, >>> + size_t size) >>> +{ >>> + struct inode *inode; >>> struct ubifs_info *c = host->i_sb->s_fs_info; >>> struct qstr nm = { .name = name, .len = strlen(name) }; >>> struct ubifs_inode *ui; >>> @@ -367,8 +384,8 @@ ssize_t ubifs_getxattr(struct dentry *dentry, const char *name, void *buf, >>> union ubifs_key key; >>> int err; >>> >>> - dbg_gen("xattr '%s', ino %lu ('%.*s'), buf size %zd", name, >>> - host->i_ino, dentry->d_name.len, dentry->d_name.name, size); >>> + dbg_gen("xattr '%s', ino %lu buf size %zd", name, >>> + host->i_ino, size); >>> >>> err = check_namespace(&nm); >>> if (err < 0) >>> @@ -416,6 +433,25 @@ out_unlock: >>> return err; >>> } >>> >>> +ssize_t ubifs_symlink_getxattr(struct dentry *dentry, const char *name, >>> + void *buf, size_t size) >>> +{ >>> + struct inode *host = dentry->d_inode; >>> + dbg_gen("xattr '%s', ino %lu ('%.*s'), buf size %zd", name, >>> + host->i_ino, dentry->d_name.len, dentry->d_name.name, size); >>> + return __ubifs_getxattr(host, name, buf, size); >>> +} >>> + >>> +ssize_t ubifs_getxattr(struct dentry *dentry, const char *name, void *buf, >>> + size_t size) >>> +{ >>> + struct inode *host = dentry->d_inode; >>> + dbg_gen("xattr '%s', ino %lu ('%.*s'), buf size %zd", name, >>> + host->i_ino, dentry->d_name.len, dentry->d_name.name, size); >>> + return __ubifs_getxattr(host, name, buf, size); >>> +} >>> + >>> + >>> ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size) >>> { >>> union ubifs_key key; >>> @@ -568,3 +604,92 @@ out_free: >>> kfree(xent); >>> return err; >>> } >>> + >>> +size_t >>> +ubifs_security_listxattr(struct dentry *d, char *list, size_t list_size, >>> + const char *name, size_t name_len, int flags) >>> +{ >>> + const int prefix_len = XATTR_SECURITY_PREFIX_LEN; >>> + const size_t total_len = prefix_len + name_len + 1; >>> + if (list && total_len <= list_size) { >>> + memcpy(list, XATTR_SECURITY_PREFIX, prefix_len); >>> + memcpy(list+prefix_len, name, name_len); >>> + list[prefix_len + name_len] = '\0'; >>> + } >>> + return total_len; >>> +} >>> + >>> + >>> +int ubifs_security_getxattr(struct dentry *d, const char *name, >>> + void *buffer, size_t size, int flags) >>> +{ >>> + if (strcmp(name, "") == 0) >>> + return -EINVAL; >>> + return __ubifs_getxattr(d->d_inode, XATTR_NAME_SELINUX, buffer, size); >>> +} >>> + >>> + >>> +int ubifs_security_setxattr(struct dentry *d, const char *name, >>> + const void *value, size_t size, >>> + int flags, int handler_flags) >>> +{ >>> + if (strcmp(name, "") == 0) >>> + return -EINVAL; >>> + return __ubifs_setxattr(d->d_inode, XATTR_NAME_SELINUX, value, >> This is silly. If you're supporting xattrs there is no reason >> single out a particular LSM. Make this general so that Smack >> and any other LSM that wants to use xattrs will work. >> >> Move the changes into the SELinux LSM if you are going to >> hard code it. >> > Yup, my bad, following change fixes that specific issue and one can > set xattr for all security.* namespace. Will submit patch v2 > shortly... Thank you. The update looks fine, although I haven't tried it. > > diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c > index a402c7d..c8be7cd 100644 > --- a/fs/ubifs/xattr.c > +++ b/fs/ubifs/xattr.c > @@ -625,7 +625,7 @@ int ubifs_security_getxattr(struct dentry *d, > const char *name, > { > if (strcmp(name, "") == 0) > return -EINVAL; > - return __ubifs_getxattr(d->d_inode, XATTR_NAME_SELINUX, buffer, size); > + return __ubifs_getxattr(d->d_inode, name, buffer, size); > } > > > @@ -635,7 +635,7 @@ int ubifs_security_setxattr(struct dentry *d, > const char *name, > { > if (strcmp(name, "") == 0) > return -EINVAL; > - return __ubifs_setxattr(d->d_inode, XATTR_NAME_SELINUX, value, > + return __ubifs_setxattr(d->d_inode, name, value, > size, flags); > } >