Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753504Ab2BYHDn (ORCPT ); Sat, 25 Feb 2012 02:03:43 -0500 Received: from mga09.intel.com ([134.134.136.24]:20452 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752469Ab2BYHDm (ORCPT ); Sat, 25 Feb 2012 02:03:42 -0500 Authentication-Results: mr.google.com; spf=pass (google.com: domain of jarkko.sakkinen@intel.com designates 10.182.231.41 as permitted sender) smtp.mail=jarkko.sakkinen@intel.com MIME-Version: 1.0 In-Reply-To: References: <1329990365-23779-1-git-send-email-jarkko.sakkinen@intel.com> Date: Sat, 25 Feb 2012 09:03:40 +0200 Message-ID: Subject: Re: [PATCH] tmpfs: security xattr setting on inode creation From: "Sakkinen, Jarkko" To: Hugh Dickins Cc: Andrew Morton , James Morris , linux-mm@kvack.org, linux-kernel@vger.kernel.org, linux-security-module@vger.kernel.org Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: 8bit X-MIME-Autoconverted: from base64 to 8bit by nfs id q1P74WtQ010808 Content-Length: 7681 Lines: 188 Hi Hugh, On Sat, Feb 25, 2012 at 5:19 AM, Hugh Dickins wrote: > Thanks a lot for doing this, Jarkko: I knew nothing about it. > And thank you James for reviewing, I felt much happier seeing that. > > I did fiddle around with it slightly, to reduce the added textsize, > and eliminate it when CONFIG_TMPFS_XATTR is off.  Please, Jarkko > and James, complain bitterly if I've messed up the good work. Thank you for the nice feedback :) LGTM. > > [PATCH] tmpfs: security xattr setting on inode creation > > From: Jarkko Sakkinen > > Adds to generic xattr support introduced in Linux 3.0 by > implementing initxattrs callback. This enables consulting > of security attributes from LSM and EVM when inode is created. > > [hughd: moved under CONFIG_TMPFS_XATTR, with memcpy in shmem_xattr_alloc] > > Signed-off-by: Jarkko Sakkinen > Reviewed-by: James Morris > Signed-off-by: Hugh Dickins > --- >  mm/shmem.c |   88 +++++++++++++++++++++++++++++++++++++++++---------- >  1 file changed, 72 insertions(+), 16 deletions(-) > > --- a/mm/shmem.c > +++ b/mm/shmem.c > @@ -1178,6 +1178,12 @@ static struct inode *shmem_get_inode(str >  static const struct inode_operations shmem_symlink_inode_operations; >  static const struct inode_operations shmem_short_symlink_operations; > > +#ifdef CONFIG_TMPFS_XATTR > +static int shmem_initxattrs(struct inode *, const struct xattr *, void *); > +#else > +#define shmem_initxattrs NULL > +#endif > + >  static int >  shmem_write_begin(struct file *file, struct address_space *mapping, >                        loff_t pos, unsigned len, unsigned flags, > @@ -1490,7 +1496,7 @@ shmem_mknod(struct inode *dir, struct de >        if (inode) { >                error = security_inode_init_security(inode, dir, >                                                     &dentry->d_name, > -                                                    NULL, NULL); > +                                                    shmem_initxattrs, NULL); >                if (error) { >                        if (error != -EOPNOTSUPP) { >                                iput(inode); > @@ -1630,7 +1636,7 @@ static int shmem_symlink(struct inode *d >                return -ENOSPC; > >        error = security_inode_init_security(inode, dir, &dentry->d_name, > -                                            NULL, NULL); > +                                            shmem_initxattrs, NULL); >        if (error) { >                if (error != -EOPNOTSUPP) { >                        iput(inode); > @@ -1704,6 +1710,66 @@ static void shmem_put_link(struct dentry >  * filesystem level, though. >  */ > > +/* > + * Allocate new xattr and copy in the value; but leave the name to callers. > + */ > +static struct shmem_xattr *shmem_xattr_alloc(const void *value, size_t size) > +{ > +       struct shmem_xattr *new_xattr; > +       size_t len; > + > +       /* wrap around? */ > +       len = sizeof(*new_xattr) + size; > +       if (len <= sizeof(*new_xattr)) > +               return NULL; > + > +       new_xattr = kmalloc(len, GFP_KERNEL); > +       if (!new_xattr) > +               return NULL; > + > +       new_xattr->size = size; > +       memcpy(new_xattr->value, value, size); > +       return new_xattr; > +} > + > +/* > + * Callback for security_inode_init_security() for acquiring xattrs. > + */ > +static int shmem_initxattrs(struct inode *inode, > +                           const struct xattr *xattr_array, > +                           void *fs_info) > +{ > +       struct shmem_inode_info *info = SHMEM_I(inode); > +       const struct xattr *xattr; > +       struct shmem_xattr *new_xattr; > +       size_t len; > + > +       for (xattr = xattr_array; xattr->name != NULL; xattr++) { > +               new_xattr = shmem_xattr_alloc(xattr->value, xattr->value_len); > +               if (!new_xattr) > +                       return -ENOMEM; > + > +               len = strlen(xattr->name) + 1; > +               new_xattr->name = kmalloc(XATTR_SECURITY_PREFIX_LEN + len, > +                                         GFP_KERNEL); > +               if (!new_xattr->name) { > +                       kfree(new_xattr); > +                       return -ENOMEM; > +               } > + > +               memcpy(new_xattr->name, XATTR_SECURITY_PREFIX, > +                      XATTR_SECURITY_PREFIX_LEN); > +               memcpy(new_xattr->name + XATTR_SECURITY_PREFIX_LEN, > +                      xattr->name, len); > + > +               spin_lock(&info->lock); > +               list_add(&new_xattr->list, &info->xattr_list); > +               spin_unlock(&info->lock); > +       } > + > +       return 0; > +} > + >  static int shmem_xattr_get(struct dentry *dentry, const char *name, >                           void *buffer, size_t size) >  { > @@ -1731,24 +1797,17 @@ static int shmem_xattr_get(struct dentry >        return ret; >  } > > -static int shmem_xattr_set(struct dentry *dentry, const char *name, > +static int shmem_xattr_set(struct inode *inode, const char *name, >                           const void *value, size_t size, int flags) >  { > -       struct inode *inode = dentry->d_inode; >        struct shmem_inode_info *info = SHMEM_I(inode); >        struct shmem_xattr *xattr; >        struct shmem_xattr *new_xattr = NULL; > -       size_t len; >        int err = 0; > >        /* value == NULL means remove */ >        if (value) { > -               /* wrap around? */ > -               len = sizeof(*new_xattr) + size; > -               if (len <= sizeof(*new_xattr)) > -                       return -ENOMEM; > - > -               new_xattr = kmalloc(len, GFP_KERNEL); > +               new_xattr = shmem_xattr_alloc(value, size); >                if (!new_xattr) >                        return -ENOMEM; > > @@ -1757,9 +1816,6 @@ static int shmem_xattr_set(struct dentry >                        kfree(new_xattr); >                        return -ENOMEM; >                } > - > -               new_xattr->size = size; > -               memcpy(new_xattr->value, value, size); >        } > >        spin_lock(&info->lock); > @@ -1858,7 +1914,7 @@ static int shmem_setxattr(struct dentry >        if (size == 0) >                value = "";  /* empty EA, do not remove */ > > -       return shmem_xattr_set(dentry, name, value, size, flags); > +       return shmem_xattr_set(dentry->d_inode, name, value, size, flags); > >  } > > @@ -1878,7 +1934,7 @@ static int shmem_removexattr(struct dent >        if (err) >                return err; > > -       return shmem_xattr_set(dentry, name, NULL, 0, XATTR_REPLACE); > +       return shmem_xattr_set(dentry->d_inode, name, NULL, 0, XATTR_REPLACE); >  } > >  static bool xattr_is_trusted(const char *name) /Jarkko ????{.n?+???????+%?????ݶ??w??{.n?+????{??G?????{ay?ʇڙ?,j??f???h?????????z_??(?階?ݢj"???m??????G????????????&???~???iO???z??v?^?m???? ????????I?