inode_init_security receives the LSM xattr array and its count as
separate parameters. For better compatibility with the bpf verifier,
update inode_init_security and its callers to consolidate these
parameters into a single context object: struct lsm_xattrs.

Signed-off-by: David Windsor <[email protected]>
---
 include/linux/evm.h               |  9 +++++----
 include/linux/lsm_hook_defs.h     |  4 ++--
 include/linux/lsm_hooks.h         | 16 +++++++---------
 include/linux/security.h          |  5 +++++
 security/integrity/evm/evm_main.c |  8 +++++---
 security/security.c               | 24 ++++++++++++------------
 security/selinux/hooks.c          |  4 ++--
 security/smack/smack_lsm.c        | 27 ++++++++++++---------------
 8 files changed, 50 insertions(+), 47 deletions(-)

diff --git a/include/linux/evm.h b/include/linux/evm.h
index 913f4573b203..528f360f3308 100644
--- a/include/linux/evm.h
+++ b/include/linux/evm.h
@@ -12,6 +12,8 @@
 #include <linux/integrity.h>
 #include <linux/xattr.h>
 
+struct lsm_xattrs;
+
 #ifdef CONFIG_EVM
 extern int evm_set_key(void *key, size_t keylen);
 extern enum integrity_status evm_verifyxattr(struct dentry *dentry,
@@ -21,8 +23,8 @@ extern enum integrity_status evm_verifyxattr(struct dentry 
*dentry,
 int evm_fix_hmac(struct dentry *dentry, const char *xattr_name,
                 const char *xattr_value, size_t xattr_value_len);
 int evm_inode_init_security(struct inode *inode, struct inode *dir,
-                           const struct qstr *qstr, struct xattr *xattrs,
-                           int *xattr_count);
+                           const struct qstr *qstr,
+                           struct lsm_xattrs *xattrs);
 extern bool evm_revalidate_status(const char *xattr_name);
 extern int evm_protected_xattr_if_enabled(const char *req_xattr_name);
 extern int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer,
@@ -63,8 +65,7 @@ static inline int evm_fix_hmac(struct dentry *dentry, const 
char *xattr_name,
 
 static inline int evm_inode_init_security(struct inode *inode, struct inode 
*dir,
                                          const struct qstr *qstr,
-                                         struct xattr *xattrs,
-                                         int *xattr_count)
+                                         struct lsm_xattrs *xattrs)
 {
        return 0;
 }
diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
index 65c9609ec207..5b2de7865ce8 100644
--- a/include/linux/lsm_hook_defs.h
+++ b/include/linux/lsm_hook_defs.h
@@ -116,8 +116,8 @@ LSM_HOOK(int, 0, inode_alloc_security, struct inode *inode)
 LSM_HOOK(void, LSM_RET_VOID, inode_free_security, struct inode *inode)
 LSM_HOOK(void, LSM_RET_VOID, inode_free_security_rcu, void *inode_security)
 LSM_HOOK(int, -EOPNOTSUPP, inode_init_security, struct inode *inode,
-        struct inode *dir, const struct qstr *qstr, struct xattr *xattrs,
-        int *xattr_count)
+        struct inode *dir, const struct qstr *qstr,
+        struct lsm_xattrs *xattrs)
 LSM_HOOK(int, 0, inode_init_security_anon, struct inode *inode,
         const struct qstr *name, const struct inode *context_inode)
 LSM_HOOK(int, 0, inode_create, struct inode *dir, struct dentry *dentry,
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index b4f8cad53ddb..7afe06a8d4c6 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -200,20 +200,18 @@ extern struct lsm_static_calls_table static_calls_table 
__ro_after_init;
 
 /**
  * lsm_get_xattr_slot - Return the next available slot and increment the index
- * @xattrs: array storing LSM-provided xattrs
- * @xattr_count: number of already stored xattrs (updated)
+ * @ctx: xattr state shared by inode_init_security hooks
  *
- * Retrieve the first available slot in the @xattrs array to fill with an 
xattr,
- * and increment @xattr_count.
+ * Retrieve the first available slot in the @ctx->xattrs array to fill with an
+ * xattr, and increment @ctx->xattr_count.
  *
- * Return: The slot to fill in @xattrs if non-NULL, NULL otherwise.
+ * Return: The slot to fill in @ctx->xattrs if non-NULL, NULL otherwise.
  */
-static inline struct xattr *lsm_get_xattr_slot(struct xattr *xattrs,
-                                              int *xattr_count)
+static inline struct xattr *lsm_get_xattr_slot(struct lsm_xattrs *ctx)
 {
-       if (unlikely(!xattrs))
+       if (unlikely(!ctx || !ctx->xattrs))
                return NULL;
-       return &xattrs[(*xattr_count)++];
+       return &ctx->xattrs[ctx->xattr_count++];
 }
 
 #endif /* ! __LINUX_LSM_HOOKS_H */
diff --git a/include/linux/security.h b/include/linux/security.h
index 153e9043058f..0be590c40689 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -68,6 +68,11 @@ struct watch;
 struct watch_notification;
 struct lsm_ctx;
 
+struct lsm_xattrs {
+       struct xattr *xattrs;
+       unsigned int xattr_count;
+};
+
 /* Default (no) options for the capable function */
 #define CAP_OPT_NONE 0x0
 /* If capable should audit the security request */
diff --git a/security/integrity/evm/evm_main.c 
b/security/integrity/evm/evm_main.c
index b59e3f121b8a..b7158fc63543 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -1062,14 +1062,16 @@ static int evm_inode_copy_up_xattr(struct dentry *src, 
const char *name)
  * evm_inode_init_security - initializes security.evm HMAC value
  */
 int evm_inode_init_security(struct inode *inode, struct inode *dir,
-                           const struct qstr *qstr, struct xattr *xattrs,
-                           int *xattr_count)
+                           const struct qstr *qstr,
+                           struct lsm_xattrs *lsm_xattrs)
 {
        struct evm_xattr *xattr_data;
        struct xattr *xattr, *evm_xattr;
+       struct xattr *xattrs;
        bool evm_protected_xattrs = false;
        int rc;
 
+       xattrs = lsm_xattrs ? lsm_xattrs->xattrs : NULL;
        if (!(evm_initialized & EVM_INIT_HMAC) || !xattrs)
                return 0;
 
@@ -1087,7 +1089,7 @@ int evm_inode_init_security(struct inode *inode, struct 
inode *dir,
        if (!evm_protected_xattrs)
                return 0;
 
-       evm_xattr = lsm_get_xattr_slot(xattrs, xattr_count);
+       evm_xattr = lsm_get_xattr_slot(lsm_xattrs);
        /*
         * Array terminator (xattr name = NULL) must be the first non-filled
         * xattr slot.
diff --git a/security/security.c b/security/security.c
index 71aea8fdf014..2ad7f09c1a61 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1333,8 +1333,8 @@ int security_inode_init_security(struct inode *inode, 
struct inode *dir,
                                 const initxattrs initxattrs, void *fs_data)
 {
        struct lsm_static_call *scall;
-       struct xattr *new_xattrs = NULL;
-       int ret = -EOPNOTSUPP, xattr_count = 0;
+       struct lsm_xattrs xattrs = {};
+       int ret = -EOPNOTSUPP;
 
        if (unlikely(IS_PRIVATE(inode)))
                return 0;
@@ -1344,15 +1344,15 @@ int security_inode_init_security(struct inode *inode, 
struct inode *dir,
 
        if (initxattrs) {
                /* Allocate +1 as terminator. */
-               new_xattrs = kcalloc(blob_sizes.lbs_xattr_count + 1,
-                                    sizeof(*new_xattrs), GFP_NOFS);
-               if (!new_xattrs)
+               xattrs.xattrs = kcalloc(blob_sizes.lbs_xattr_count + 1,
+                                       sizeof(*xattrs.xattrs), GFP_NOFS);
+               if (!xattrs.xattrs)
                        return -ENOMEM;
        }
 
        lsm_for_each_hook(scall, inode_init_security) {
-               ret = scall->hl->hook.inode_init_security(inode, dir, qstr, 
new_xattrs,
-                                                 &xattr_count);
+               ret = scall->hl->hook.inode_init_security(inode, dir, qstr,
+                                                         &xattrs);
                if (ret && ret != -EOPNOTSUPP)
                        goto out;
                /*
@@ -1364,14 +1364,14 @@ int security_inode_init_security(struct inode *inode, 
struct inode *dir,
        }
 
        /* If initxattrs() is NULL, xattr_count is zero, skip the call. */
-       if (!xattr_count)
+       if (!xattrs.xattr_count)
                goto out;
 
-       ret = initxattrs(inode, new_xattrs, fs_data);
+       ret = initxattrs(inode, xattrs.xattrs, fs_data);
 out:
-       for (; xattr_count > 0; xattr_count--)
-               kfree(new_xattrs[xattr_count - 1].value);
-       kfree(new_xattrs);
+       for (; xattrs.xattr_count > 0; xattrs.xattr_count--)
+               kfree(xattrs.xattrs[xattrs.xattr_count - 1].value);
+       kfree(xattrs.xattrs);
        return (ret == -EOPNOTSUPP) ? 0 : ret;
 }
 EXPORT_SYMBOL(security_inode_init_security);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 1a713d96206f..6bba6b212e17 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2962,7 +2962,7 @@ static int selinux_dentry_create_files_as(struct dentry 
*dentry, int mode,
 
 static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
                                       const struct qstr *qstr,
-                                      struct xattr *xattrs, int *xattr_count)
+                                      struct lsm_xattrs *xattrs)
 {
        const struct cred_security_struct *crsec = selinux_cred(current_cred());
        struct superblock_security_struct *sbsec;
@@ -2992,7 +2992,7 @@ static int selinux_inode_init_security(struct inode 
*inode, struct inode *dir,
            !(sbsec->flags & SBLABEL_MNT))
                return -EOPNOTSUPP;
 
-       xattr = lsm_get_xattr_slot(xattrs, xattr_count);
+       xattr = lsm_get_xattr_slot(xattrs);
        if (xattr) {
                rc = security_sid_to_context_force(newsid,
                                                   &context, &clen);
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index ff115068c5c0..4501078430ca 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -981,10 +981,10 @@ smk_rule_transmutes(struct smack_known *subject,
 }
 
 static int
-xattr_dupval(struct xattr *xattrs, int *xattr_count,
+xattr_dupval(struct lsm_xattrs *xattrs,
             const char *name, const void *value, unsigned int vallen)
 {
-       struct xattr * const xattr = lsm_get_xattr_slot(xattrs, xattr_count);
+       struct xattr * const xattr = lsm_get_xattr_slot(xattrs);
 
        if (!xattr)
                return 0;
@@ -1003,14 +1003,13 @@ xattr_dupval(struct xattr *xattrs, int *xattr_count,
  * @inode: the newly created inode
  * @dir: containing directory object
  * @qstr: unused
- * @xattrs: where to put the attributes
- * @xattr_count: current number of LSM-provided xattrs (updated)
+ * @xattrs: where to put attributes and update count
  *
  * Returns 0 if it all works out, -ENOMEM if there's no memory
  */
 static int smack_inode_init_security(struct inode *inode, struct inode *dir,
                                     const struct qstr *qstr,
-                                    struct xattr *xattrs, int *xattr_count)
+                                    struct lsm_xattrs *xattrs)
 {
        struct task_smack *tsp = smack_cred(current_cred());
        struct inode_smack * const issp = smack_inode(inode);
@@ -1057,21 +1056,19 @@ static int smack_inode_init_security(struct inode 
*inode, struct inode *dir,
                if (S_ISDIR(inode->i_mode)) {
                        transflag = SMK_INODE_TRANSMUTE;
 
-                       if (xattr_dupval(xattrs, xattr_count,
-                               XATTR_SMACK_TRANSMUTE,
-                               TRANS_TRUE,
-                               TRANS_TRUE_SIZE
-                       ))
+                       if (xattr_dupval(xattrs,
+                                        XATTR_SMACK_TRANSMUTE,
+                                        TRANS_TRUE,
+                                        TRANS_TRUE_SIZE))
                                rc = -ENOMEM;
                }
        }
 
        if (rc == 0)
-               if (xattr_dupval(xattrs, xattr_count,
-                           XATTR_SMACK_SUFFIX,
-                           issp->smk_inode->smk_known,
-                    strlen(issp->smk_inode->smk_known)
-               ))
+               if (xattr_dupval(xattrs,
+                                XATTR_SMACK_SUFFIX,
+                                issp->smk_inode->smk_known,
+                                strlen(issp->smk_inode->smk_known)))
                        rc = -ENOMEM;
 instant_inode:
        issp->smk_flags |= (SMK_INODE_INSTANT | transflag);
-- 
2.53.0


Reply via email to