security: new security_inode_init_security API adds function callback
authorMimi Zohar <zohar@linux.vnet.ibm.com>
Mon, 6 Jun 2011 19:29:25 +0000 (15:29 -0400)
committerMimi Zohar <zohar@linux.vnet.ibm.com>
Mon, 18 Jul 2011 16:29:38 +0000 (12:29 -0400)
This patch changes the security_inode_init_security API by adding a
filesystem specific callback to write security extended attributes.
This change is in preparation for supporting the initialization of
multiple LSM xattrs and the EVM xattr.  Initially the callback function
walks an array of xattrs, writing each xattr separately, but could be
optimized to write multiple xattrs at once.

For existing security_inode_init_security() calls, which have not yet
been converted to use the new callback function, such as those in
reiserfs and ocfs2, this patch defines security_old_inode_init_security().

Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
14 files changed:
fs/btrfs/xattr.c
fs/ext2/xattr_security.c
fs/ext3/xattr_security.c
fs/ext4/xattr_security.c
fs/gfs2/inode.c
fs/jffs2/security.c
fs/jfs/xattr.c
fs/ocfs2/xattr.c
fs/reiserfs/xattr_security.c
fs/xfs/linux-2.6/xfs_iops.c
include/linux/security.h
include/linux/xattr.h
mm/shmem.c
security/security.c

index 5366fe452ab07db7402402e96351c1b956809e20..a039e6ed4ce0ed2812951d87e89974c6c0e3ab4c 100644 (file)
@@ -360,36 +360,36 @@ int btrfs_removexattr(struct dentry *dentry, const char *name)
                                XATTR_REPLACE);
 }
 
-int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
-                             struct inode *inode, struct inode *dir,
-                             const struct qstr *qstr)
+int btrfs_initxattrs(struct inode *inode, const struct xattr *xattr_array,
+                    void *fs_info)
 {
-       int err;
-       size_t len;
-       void *value;
-       char *suffix;
+       const struct xattr *xattr;
+       struct btrfs_trans_handle *trans = fs_info;
        char *name;
+       int err = 0;
 
-       err = security_inode_init_security(inode, dir, qstr, &suffix, &value,
-                                          &len);
-       if (err) {
-               if (err == -EOPNOTSUPP)
-                       return 0;
-               return err;
-       }
-
-       name = kmalloc(XATTR_SECURITY_PREFIX_LEN + strlen(suffix) + 1,
-                      GFP_NOFS);
-       if (!name) {
-               err = -ENOMEM;
-       } else {
+       for (xattr = xattr_array; xattr->name != NULL; xattr++) {
+               name = kmalloc(XATTR_SECURITY_PREFIX_LEN +
+                              strlen(xattr->name) + 1, GFP_NOFS);
+               if (!name) {
+                       err = -ENOMEM;
+                       break;
+               }
                strcpy(name, XATTR_SECURITY_PREFIX);
-               strcpy(name + XATTR_SECURITY_PREFIX_LEN, suffix);
-               err = __btrfs_setxattr(trans, inode, name, value, len, 0);
+               strcpy(name + XATTR_SECURITY_PREFIX_LEN, xattr->name);
+               err = __btrfs_setxattr(trans, inode, name,
+                                      xattr->value, xattr->value_len, 0);
                kfree(name);
+               if (err < 0)
+                       break;
        }
-
-       kfree(suffix);
-       kfree(value);
        return err;
 }
+
+int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
+                             struct inode *inode, struct inode *dir,
+                             const struct qstr *qstr)
+{
+       return security_inode_init_security(inode, dir, qstr,
+                                           &btrfs_initxattrs, trans);
+}
index 5d979b4347b03c3b3820f6cb14c8566cdeb9497a..c922adc8ef4175844c42a2dcb4b08d7499694d08 100644 (file)
@@ -46,28 +46,30 @@ ext2_xattr_security_set(struct dentry *dentry, const char *name,
                              value, size, flags);
 }
 
-int
-ext2_init_security(struct inode *inode, struct inode *dir,
-                  const struct qstr *qstr)
+int ext2_initxattrs(struct inode *inode, const struct xattr *xattr_array,
+                   void *fs_info)
 {
-       int err;
-       size_t len;
-       void *value;
-       char *name;
+       const struct xattr *xattr;
+       int err = 0;
 
-       err = security_inode_init_security(inode, dir, qstr, &name, &value, &len);
-       if (err) {
-               if (err == -EOPNOTSUPP)
-                       return 0;
-               return err;
+       for (xattr = xattr_array; xattr->name != NULL; xattr++) {
+               err = ext2_xattr_set(inode, EXT2_XATTR_INDEX_SECURITY,
+                                    xattr->name, xattr->value,
+                                    xattr->value_len, 0);
+               if (err < 0)
+                       break;
        }
-       err = ext2_xattr_set(inode, EXT2_XATTR_INDEX_SECURITY,
-                            name, value, len, 0);
-       kfree(name);
-       kfree(value);
        return err;
 }
 
+int
+ext2_init_security(struct inode *inode, struct inode *dir,
+                  const struct qstr *qstr)
+{
+       return security_inode_init_security(inode, dir, qstr,
+                                           &ext2_initxattrs, NULL);
+}
+
 const struct xattr_handler ext2_xattr_security_handler = {
        .prefix = XATTR_SECURITY_PREFIX,
        .list   = ext2_xattr_security_list,
index b8d9f83aa5c545f23b48f14530b6ee0578204a66..3c218b8a51d4a4668e3edb4ea144f92cc71dce7d 100644 (file)
@@ -48,28 +48,32 @@ ext3_xattr_security_set(struct dentry *dentry, const char *name,
                              name, value, size, flags);
 }
 
-int
-ext3_init_security(handle_t *handle, struct inode *inode, struct inode *dir,
-                  const struct qstr *qstr)
+int ext3_initxattrs(struct inode *inode, const struct xattr *xattr_array,
+                   void *fs_info)
 {
-       int err;
-       size_t len;
-       void *value;
-       char *name;
+       const struct xattr *xattr;
+       handle_t *handle = fs_info;
+       int err = 0;
 
-       err = security_inode_init_security(inode, dir, qstr, &name, &value, &len);
-       if (err) {
-               if (err == -EOPNOTSUPP)
-                       return 0;
-               return err;
+       for (xattr = xattr_array; xattr->name != NULL; xattr++) {
+               err = ext3_xattr_set_handle(handle, inode,
+                                           EXT3_XATTR_INDEX_SECURITY,
+                                           xattr->name, xattr->value,
+                                           xattr->value_len, 0);
+               if (err < 0)
+                       break;
        }
-       err = ext3_xattr_set_handle(handle, inode, EXT3_XATTR_INDEX_SECURITY,
-                                   name, value, len, 0);
-       kfree(name);
-       kfree(value);
        return err;
 }
 
+int
+ext3_init_security(handle_t *handle, struct inode *inode, struct inode *dir,
+                  const struct qstr *qstr)
+{
+       return security_inode_init_security(inode, dir, qstr,
+                                           &ext3_initxattrs, handle);
+}
+
 const struct xattr_handler ext3_xattr_security_handler = {
        .prefix = XATTR_SECURITY_PREFIX,
        .list   = ext3_xattr_security_list,
index 007c3bfbf094221988855d9eb754bfdf430d569e..34e4350dd4d92f2ee2273a909b3f1b85867cf580 100644 (file)
@@ -48,28 +48,32 @@ ext4_xattr_security_set(struct dentry *dentry, const char *name,
                              name, value, size, flags);
 }
 
-int
-ext4_init_security(handle_t *handle, struct inode *inode, struct inode *dir,
-                  const struct qstr *qstr)
+int ext4_initxattrs(struct inode *inode, const struct xattr *xattr_array,
+                   void *fs_info)
 {
-       int err;
-       size_t len;
-       void *value;
-       char *name;
+       const struct xattr *xattr;
+       handle_t *handle = fs_info;
+       int err = 0;
 
-       err = security_inode_init_security(inode, dir, qstr, &name, &value, &len);
-       if (err) {
-               if (err == -EOPNOTSUPP)
-                       return 0;
-               return err;
+       for (xattr = xattr_array; xattr->name != NULL; xattr++) {
+               err = ext4_xattr_set_handle(handle, inode,
+                                           EXT4_XATTR_INDEX_SECURITY,
+                                           xattr->name, xattr->value,
+                                           xattr->value_len, 0);
+               if (err < 0)
+                       break;
        }
-       err = ext4_xattr_set_handle(handle, inode, EXT4_XATTR_INDEX_SECURITY,
-                                   name, value, len, 0);
-       kfree(name);
-       kfree(value);
        return err;
 }
 
+int
+ext4_init_security(handle_t *handle, struct inode *inode, struct inode *dir,
+                  const struct qstr *qstr)
+{
+       return security_inode_init_security(inode, dir, qstr,
+                                           &ext4_initxattrs, handle);
+}
+
 const struct xattr_handler ext4_xattr_security_handler = {
        .prefix = XATTR_SECURITY_PREFIX,
        .list   = ext4_xattr_security_list,
index 03e0c529063e45042985fef09518ecd52b7be085..1d3a1a65172193a62f09c6bd5430d70122af10fa 100644 (file)
@@ -624,31 +624,29 @@ fail:
        return error;
 }
 
-static int gfs2_security_init(struct gfs2_inode *dip, struct gfs2_inode *ip,
-                             const struct qstr *qstr)
+int gfs2_initxattrs(struct inode *inode, const struct xattr *xattr_array,
+                   void *fs_info)
 {
-       int err;
-       size_t len;
-       void *value;
-       char *name;
-
-       err = security_inode_init_security(&ip->i_inode, &dip->i_inode, qstr,
-                                          &name, &value, &len);
-
-       if (err) {
-               if (err == -EOPNOTSUPP)
-                       return 0;
-               return err;
+       const struct xattr *xattr;
+       int err = 0;
+
+       for (xattr = xattr_array; xattr->name != NULL; xattr++) {
+               err = __gfs2_xattr_set(inode, xattr->name, xattr->value,
+                                      xattr->value_len, 0,
+                                      GFS2_EATYPE_SECURITY);
+               if (err < 0)
+                       break;
        }
-
-       err = __gfs2_xattr_set(&ip->i_inode, name, value, len, 0,
-                              GFS2_EATYPE_SECURITY);
-       kfree(value);
-       kfree(name);
-
        return err;
 }
 
+static int gfs2_security_init(struct gfs2_inode *dip, struct gfs2_inode *ip,
+                             const struct qstr *qstr)
+{
+       return security_inode_init_security(&ip->i_inode, &dip->i_inode, qstr,
+                                           &gfs2_initxattrs, NULL);
+}
+
 /**
  * gfs2_create_inode - Create a new inode
  * @dir: The parent directory
index cfeb7164b0853a0d163cf7552f89577743067575..0f20208df60278c9f63f6c14c7b626cfd632ebf2 100644 (file)
 #include <linux/security.h>
 #include "nodelist.h"
 
-/* ---- Initial Security Label Attachment -------------- */
-int jffs2_init_security(struct inode *inode, struct inode *dir,
-                       const struct qstr *qstr)
+/* ---- Initial Security Label(s) Attachment callback --- */
+int jffs2_initxattrs(struct inode *inode, const struct xattr *xattr_array,
+                    void *fs_info)
 {
-       int rc;
-       size_t len;
-       void *value;
-       char *name;
+       const struct xattr *xattr;
+       int err = 0;
 
-       rc = security_inode_init_security(inode, dir, qstr, &name, &value, &len);
-       if (rc) {
-               if (rc == -EOPNOTSUPP)
-                       return 0;
-               return rc;
+       for (xattr = xattr_array; xattr->name != NULL; xattr++) {
+               err = do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY,
+                                       xattr->name, xattr->value,
+                                       xattr->value_len, 0);
+               if (err < 0)
+                       break;
        }
-       rc = do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, name, value, len, 0);
+       return err;
+}
 
-       kfree(name);
-       kfree(value);
-       return rc;
+/* ---- Initial Security Label(s) Attachment ----------- */
+int jffs2_init_security(struct inode *inode, struct inode *dir,
+                       const struct qstr *qstr)
+{
+       return security_inode_init_security(inode, dir, qstr,
+                                           &jffs2_initxattrs, NULL);
 }
 
 /* ---- XATTR Handler for "security.*" ----------------- */
index 24838f1eeee5c0f5093d96fef01c80d1835991ea..e982509292f8ed02f48723eb5086c04f6add66df 100644 (file)
@@ -1091,38 +1091,37 @@ int jfs_removexattr(struct dentry *dentry, const char *name)
 }
 
 #ifdef CONFIG_JFS_SECURITY
-int jfs_init_security(tid_t tid, struct inode *inode, struct inode *dir,
-                     const struct qstr *qstr)
+int jfs_initxattrs(struct inode *inode, const struct xattr *xattr_array,
+                  void *fs_info)
 {
-       int rc;
-       size_t len;
-       void *value;
-       char *suffix;
+       const struct xattr *xattr;
+       tid_t *tid = fs_info;
        char *name;
-
-       rc = security_inode_init_security(inode, dir, qstr, &suffix, &value,
-                                         &len);
-       if (rc) {
-               if (rc == -EOPNOTSUPP)
-                       return 0;
-               return rc;
-       }
-       name = kmalloc(XATTR_SECURITY_PREFIX_LEN + 1 + strlen(suffix),
-                      GFP_NOFS);
-       if (!name) {
-               rc = -ENOMEM;
-               goto kmalloc_failed;
+       int err = 0;
+
+       for (xattr = xattr_array; xattr->name != NULL; xattr++) {
+               name = kmalloc(XATTR_SECURITY_PREFIX_LEN +
+                              strlen(xattr->name) + 1, GFP_NOFS);
+               if (!name) {
+                       err = -ENOMEM;
+                       break;
+               }
+               strcpy(name, XATTR_SECURITY_PREFIX);
+               strcpy(name + XATTR_SECURITY_PREFIX_LEN, xattr->name);
+
+               err = __jfs_setxattr(*tid, inode, name,
+                                    xattr->value, xattr->value_len, 0);
+               kfree(name);
+               if (err < 0)
+                       break;
        }
-       strcpy(name, XATTR_SECURITY_PREFIX);
-       strcpy(name + XATTR_SECURITY_PREFIX_LEN, suffix);
-
-       rc = __jfs_setxattr(tid, inode, name, value, len, 0);
-
-       kfree(name);
-kmalloc_failed:
-       kfree(suffix);
-       kfree(value);
+       return err;
+}
 
-       return rc;
+int jfs_init_security(tid_t tid, struct inode *inode, struct inode *dir,
+                     const struct qstr *qstr)
+{
+       return security_inode_init_security(inode, dir, qstr,
+                                           &jfs_initxattrs, &tid);
 }
 #endif
index 81ecf9c0bf0ad41e0ac2fd523b1538afc3f57a07..194fb22ef79d590580f3245b522d0b095ef3794c 100644 (file)
@@ -7185,20 +7185,9 @@ int ocfs2_init_security_and_acl(struct inode *dir,
 {
        int ret = 0;
        struct buffer_head *dir_bh = NULL;
-       struct ocfs2_security_xattr_info si = {
-               .enable = 1,
-       };
 
-       ret = ocfs2_init_security_get(inode, dir, qstr, &si);
+       ret = ocfs2_init_security_get(inode, dir, qstr, NULL);
        if (!ret) {
-               ret = ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_SECURITY,
-                                     si.name, si.value, si.value_len,
-                                     XATTR_CREATE);
-               if (ret) {
-                       mlog_errno(ret);
-                       goto leave;
-               }
-       } else if (ret != -EOPNOTSUPP) {
                mlog_errno(ret);
                goto leave;
        }
@@ -7255,6 +7244,22 @@ static int ocfs2_xattr_security_set(struct dentry *dentry, const char *name,
                               name, value, size, flags);
 }
 
+int ocfs2_initxattrs(struct inode *inode, const struct xattr *xattr_array,
+                    void *fs_info)
+{
+       const struct xattr *xattr;
+       int err = 0;
+
+       for (xattr = xattr_array; xattr->name != NULL; xattr++) {
+               err = ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_SECURITY,
+                                     xattr->name, xattr->value,
+                                     xattr->value_len, XATTR_CREATE);
+               if (err)
+                       break;
+       }
+       return err;
+}
+
 int ocfs2_init_security_get(struct inode *inode,
                            struct inode *dir,
                            const struct qstr *qstr,
@@ -7263,8 +7268,13 @@ int ocfs2_init_security_get(struct inode *inode,
        /* check whether ocfs2 support feature xattr */
        if (!ocfs2_supports_xattr(OCFS2_SB(dir->i_sb)))
                return -EOPNOTSUPP;
-       return security_inode_init_security(inode, dir, qstr, &si->name,
-                                           &si->value, &si->value_len);
+       if (si)
+               return security_old_inode_init_security(inode, dir, qstr,
+                                                       &si->name, &si->value,
+                                                       &si->value_len);
+
+       return security_inode_init_security(inode, dir, qstr,
+                                           &ocfs2_initxattrs, NULL);
 }
 
 int ocfs2_init_security_set(handle_t *handle,
index ef66c18a933266e9c658fde311f7a1d0e2d6d023..534668fa41bee012a038ce48a94af04ad0d19327 100644 (file)
@@ -66,8 +66,8 @@ int reiserfs_security_init(struct inode *dir, struct inode *inode,
        if (IS_PRIVATE(dir))
                return 0;
 
-       error = security_inode_init_security(inode, dir, qstr, &sec->name,
-                                            &sec->value, &sec->length);
+       error = security_old_inode_init_security(inode, dir, qstr, &sec->name,
+                                                &sec->value, &sec->length);
        if (error) {
                if (error == -EOPNOTSUPP)
                        error = 0;
index d44d92cd12b17c7645156b4754c39ea29b5b10e5..27a3658b830f8cdd294820ffddde092ce441574b 100644 (file)
@@ -93,37 +93,38 @@ xfs_mark_inode_dirty(
                mark_inode_dirty(inode);
 }
 
+
+int xfs_initxattrs(struct inode *inode, const struct xattr *xattr_array,
+                  void *fs_info)
+{
+       const struct xattr *xattr;
+       struct xfs_inode *ip = XFS_I(inode);
+       int error = 0;
+
+       for (xattr = xattr_array; xattr->name != NULL; xattr++) {
+               error = xfs_attr_set(ip, xattr->name, xattr->value,
+                                    xattr->value_len, ATTR_SECURE);
+               if (error < 0)
+                       break;
+       }
+       return error;
+}
+
 /*
  * Hook in SELinux.  This is not quite correct yet, what we really need
  * here (as we do for default ACLs) is a mechanism by which creation of
  * these attrs can be journalled at inode creation time (along with the
  * inode, of course, such that log replay can't cause these to be lost).
  */
+
 STATIC int
 xfs_init_security(
        struct inode    *inode,
        struct inode    *dir,
        const struct qstr *qstr)
 {
-       struct xfs_inode *ip = XFS_I(inode);
-       size_t          length;
-       void            *value;
-       unsigned char   *name;
-       int             error;
-
-       error = security_inode_init_security(inode, dir, qstr, (char **)&name,
-                                            &value, &length);
-       if (error) {
-               if (error == -EOPNOTSUPP)
-                       return 0;
-               return -error;
-       }
-
-       error = xfs_attr_set(ip, name, value, length, ATTR_SECURE);
-
-       kfree(name);
-       kfree(value);
-       return error;
+       return security_inode_init_security(inode, dir, qstr,
+                                           &xfs_initxattrs, NULL);
 }
 
 static void
index 8ce59ef3e5afbec48b903e5f8d3cd4318096f709..6a20c702549534a5d08fea7286625b86e79dd7d0 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/key.h>
 #include <linux/xfrm.h>
 #include <linux/slab.h>
+#include <linux/xattr.h>
 #include <net/flow.h>
 
 /* Maximum number of letters for an LSM name string */
@@ -147,6 +148,10 @@ extern int mmap_min_addr_handler(struct ctl_table *table, int write,
                                 void __user *buffer, size_t *lenp, loff_t *ppos);
 #endif
 
+/* security_inode_init_security callback function to write xattrs */
+typedef int (*initxattrs) (struct inode *inode,
+                          const struct xattr *xattr_array, void *fs_data);
+
 #ifdef CONFIG_SECURITY
 
 struct security_mnt_opts {
@@ -1704,8 +1709,11 @@ int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts);
 int security_inode_alloc(struct inode *inode);
 void security_inode_free(struct inode *inode);
 int security_inode_init_security(struct inode *inode, struct inode *dir,
-                                const struct qstr *qstr, char **name,
-                                void **value, size_t *len);
+                                const struct qstr *qstr,
+                                initxattrs initxattrs, void *fs_data);
+int security_old_inode_init_security(struct inode *inode, struct inode *dir,
+                                    const struct qstr *qstr, char **name,
+                                    void **value, size_t *len);
 int security_inode_create(struct inode *dir, struct dentry *dentry, int mode);
 int security_inode_link(struct dentry *old_dentry, struct inode *dir,
                         struct dentry *new_dentry);
@@ -2035,9 +2043,8 @@ static inline void security_inode_free(struct inode *inode)
 static inline int security_inode_init_security(struct inode *inode,
                                                struct inode *dir,
                                                const struct qstr *qstr,
-                                               char **name,
-                                               void **value,
-                                               size_t *len)
+                                               initxattrs initxattrs,
+                                               void *fs_data)
 {
        return -EOPNOTSUPP;
 }
index aed54c50aa665b89e61bf007c6715e65a26cbefb..7a378662ddff96c9772960274d79702cddd18db1 100644 (file)
@@ -67,6 +67,12 @@ struct xattr_handler {
                   size_t size, int flags, int handler_flags);
 };
 
+struct xattr {
+       char *name;
+       void *value;
+       size_t value_len;
+};
+
 ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
 ssize_t vfs_getxattr(struct dentry *, const char *, void *, size_t);
 ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
index fcedf5464eb79dba02ad485681fcc67530bdb720..01c19c62d6852b82dffd091d77592a1a17990b4d 100644 (file)
@@ -1878,7 +1878,7 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
        inode = shmem_get_inode(dir->i_sb, dir, mode, dev, VM_NORESERVE);
        if (inode) {
                error = security_inode_init_security(inode, dir,
-                                                    &dentry->d_name, NULL,
+                                                    &dentry->d_name,
                                                     NULL, NULL);
                if (error) {
                        if (error != -EOPNOTSUPP) {
@@ -2018,7 +2018,7 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
        if (!inode)
                return -ENOSPC;
 
-       error = security_inode_init_security(inode, dir, &dentry->d_name, NULL,
+       error = security_inode_init_security(inode, dir, &dentry->d_name,
                                             NULL, NULL);
        if (error) {
                if (error != -EOPNOTSUPP) {
index 4ba6d4cc061f294142b126b962a99986a1285a6c..3464d58a57661e6c2773d830d46609cf301e5c2b 100644 (file)
@@ -18,6 +18,8 @@
 #include <linux/security.h>
 #include <linux/ima.h>
 
+#define MAX_LSM_XATTR  1
+
 /* Boot-time LSM user choice */
 static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] =
        CONFIG_DEFAULT_SECURITY;
@@ -339,15 +341,46 @@ void security_inode_free(struct inode *inode)
 }
 
 int security_inode_init_security(struct inode *inode, struct inode *dir,
-                                const struct qstr *qstr, char **name,
-                                void **value, size_t *len)
+                                const struct qstr *qstr,
+                                const initxattrs initxattrs, void *fs_data)
+{
+       struct xattr new_xattrs[MAX_LSM_XATTR + 1];
+       struct xattr *lsm_xattr;
+       int ret;
+
+       if (unlikely(IS_PRIVATE(inode)))
+               return -EOPNOTSUPP;
+
+       memset(new_xattrs, 0, sizeof new_xattrs);
+       if (!initxattrs)
+               return security_ops->inode_init_security(inode, dir, qstr,
+                                                        NULL, NULL, NULL);
+       lsm_xattr = new_xattrs;
+       ret = security_ops->inode_init_security(inode, dir, qstr,
+                                               &lsm_xattr->name,
+                                               &lsm_xattr->value,
+                                               &lsm_xattr->value_len);
+       if (ret)
+               goto out;
+       ret = initxattrs(inode, new_xattrs, fs_data);
+out:
+       kfree(lsm_xattr->name);
+       kfree(lsm_xattr->value);
+
+       return (ret == -EOPNOTSUPP) ? 0 : ret;
+}
+EXPORT_SYMBOL(security_inode_init_security);
+
+int security_old_inode_init_security(struct inode *inode, struct inode *dir,
+                                    const struct qstr *qstr, char **name,
+                                    void **value, size_t *len)
 {
        if (unlikely(IS_PRIVATE(inode)))
                return -EOPNOTSUPP;
        return security_ops->inode_init_security(inode, dir, qstr, name, value,
                                                 len);
 }
-EXPORT_SYMBOL(security_inode_init_security);
+EXPORT_SYMBOL(security_old_inode_init_security);
 
 #ifdef CONFIG_SECURITY_PATH
 int security_path_mknod(struct path *dir, struct dentry *dentry, int mode,