Merge tag 'jfs-3.14' of git://github.com/kleikamp/linux-shaggy
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 31 Jan 2014 16:14:35 +0000 (08:14 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 31 Jan 2014 16:14:35 +0000 (08:14 -0800)
Pull jfs fix from David Kleikamp:
 "Minor bug fix for linux-3.14"

* tag 'jfs-3.14' of git://github.com/kleikamp/linux-shaggy:
  jfs: fix xattr value size overflow in __jfs_setxattr

1  2 
fs/jfs/xattr.c

diff --combined fs/jfs/xattr.c
index 5324e4e2b9924babb2675451ed074f4a279d2ad4,9c6904eee0c6337fc09b118ced754a933266a912..3bd5ee45f7b3a13cf3dcc65f824fd8dad5ac6960
@@@ -665,13 -665,82 +665,13 @@@ static int ea_put(tid_t tid, struct ino
        return 0;
  }
  
 -/*
 - * can_set_system_xattr
 - *
 - * This code is specific to the system.* namespace.  It contains policy
 - * which doesn't belong in the main xattr codepath.
 - */
 -static int can_set_system_xattr(struct inode *inode, const char *name,
 -                              const void *value, size_t value_len)
 -{
 -#ifdef CONFIG_JFS_POSIX_ACL
 -      struct posix_acl *acl;
 -      int rc;
 -
 -      if (!inode_owner_or_capable(inode))
 -              return -EPERM;
 -
 -      /*
 -       * POSIX_ACL_XATTR_ACCESS is tied to i_mode
 -       */
 -      if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0) {
 -              acl = posix_acl_from_xattr(&init_user_ns, value, value_len);
 -              if (IS_ERR(acl)) {
 -                      rc = PTR_ERR(acl);
 -                      printk(KERN_ERR "posix_acl_from_xattr returned %d\n",
 -                             rc);
 -                      return rc;
 -              }
 -              if (acl) {
 -                      rc = posix_acl_equiv_mode(acl, &inode->i_mode);
 -                      posix_acl_release(acl);
 -                      if (rc < 0) {
 -                              printk(KERN_ERR
 -                                     "posix_acl_equiv_mode returned %d\n",
 -                                     rc);
 -                              return rc;
 -                      }
 -                      mark_inode_dirty(inode);
 -              }
 -              /*
 -               * We're changing the ACL.  Get rid of the cached one
 -               */
 -              forget_cached_acl(inode, ACL_TYPE_ACCESS);
 -
 -              return 0;
 -      } else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0) {
 -              acl = posix_acl_from_xattr(&init_user_ns, value, value_len);
 -              if (IS_ERR(acl)) {
 -                      rc = PTR_ERR(acl);
 -                      printk(KERN_ERR "posix_acl_from_xattr returned %d\n",
 -                             rc);
 -                      return rc;
 -              }
 -              posix_acl_release(acl);
 -
 -              /*
 -               * We're changing the default ACL.  Get rid of the cached one
 -               */
 -              forget_cached_acl(inode, ACL_TYPE_DEFAULT);
 -
 -              return 0;
 -      }
 -#endif                        /* CONFIG_JFS_POSIX_ACL */
 -      return -EOPNOTSUPP;
 -}
 -
  /*
   * Most of the permission checking is done by xattr_permission in the vfs.
 - * The local file system is responsible for handling the system.* namespace.
   * We also need to verify that this is a namespace that we recognize.
   */
  static int can_set_xattr(struct inode *inode, const char *name,
                         const void *value, size_t value_len)
  {
 -      if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
 -              return can_set_system_xattr(inode, name, value, value_len);
 -
        if (!strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN)) {
                /*
                 * This makes sure that we aren't trying to set an
                 * with "os2."
                 */
                if (is_known_namespace(name + XATTR_OS2_PREFIX_LEN))
 -                              return -EOPNOTSUPP;
 +                      return -EOPNOTSUPP;
                return 0;
        }
  
@@@ -791,6 -860,19 +791,19 @@@ int __jfs_setxattr(tid_t tid, struct in
                        /* Completely new ea list */
                        xattr_size = sizeof (struct jfs_ea_list);
  
+               /*
+                * The size of EA value is limitted by on-disk format up to
+                *  __le16, there would be an overflow if the size is equal
+                * to XATTR_SIZE_MAX (65536).  In order to avoid this issue,
+                * we can pre-checkup the value size against USHRT_MAX, and
+                * return -E2BIG in this case, which is consistent with the
+                * VFS setxattr interface.
+                */
+               if (value_len >= USHRT_MAX) {
+                       rc = -E2BIG;
+                       goto release;
+               }
                ea = (struct jfs_ea *) ((char *) ealist + xattr_size);
                ea->flag = 0;
                ea->namelen = namelen;
        /* DEBUG - If we did this right, these number match */
        if (xattr_size != new_size) {
                printk(KERN_ERR
-                      "jfs_xsetattr: xattr_size = %d, new_size = %d\n",
+                      "__jfs_setxattr: xattr_size = %d, new_size = %d\n",
                       xattr_size, new_size);
  
                rc = -EINVAL;
@@@ -844,14 -926,6 +857,14 @@@ int jfs_setxattr(struct dentry *dentry
        if ((rc = can_set_xattr(inode, name, value, value_len)))
                return rc;
  
 +      /*
 +       * If this is a request for a synthetic attribute in the system.*
 +       * namespace use the generic infrastructure to resolve a handler
 +       * for it via sb->s_xattr.
 +       */
 +      if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
 +              return generic_setxattr(dentry, name, value, value_len, flags);
 +
        if (value == NULL) {    /* empty EA, do not remove */
                value = "";
                value_len = 0;
@@@ -925,14 -999,6 +938,14 @@@ ssize_t jfs_getxattr(struct dentry *den
  {
        int err;
  
 +      /*
 +       * If this is a request for a synthetic attribute in the system.*
 +       * namespace use the generic infrastructure to resolve a handler
 +       * for it via sb->s_xattr.
 +       */
 +      if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
 +              return generic_getxattr(dentry, name, data, buf_size);
 +
        if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) {
                /*
                 * skip past "os2." prefix
@@@ -1024,14 -1090,6 +1037,14 @@@ int jfs_removexattr(struct dentry *dent
        if ((rc = can_set_xattr(inode, name, NULL, 0)))
                return rc;
  
 +      /*
 +       * If this is a request for a synthetic attribute in the system.*
 +       * namespace use the generic infrastructure to resolve a handler
 +       * for it via sb->s_xattr.
 +       */
 +      if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
 +              return generic_removexattr(dentry, name);
 +
        tid = txBegin(inode->i_sb, 0);
        mutex_lock(&ji->commit_mutex);
        rc = __jfs_setxattr(tid, dentry->d_inode, name, NULL, 0, XATTR_REPLACE);
        return rc;
  }
  
 +/*
 + * List of handlers for synthetic system.* attributes.  All real ondisk
 + * attributes are handled directly.
 + */
 +const struct xattr_handler *jfs_xattr_handlers[] = {
 +#ifdef JFS_POSIX_ACL
 +      &posix_acl_access_xattr_handler,
 +      &posix_acl_default_xattr_handler,
 +#endif
 +      NULL,
 +};
 +
 +
  #ifdef CONFIG_JFS_SECURITY
  static int jfs_initxattrs(struct inode *inode, const struct xattr *xattr_array,
                          void *fs_info)