EVM: turn evm_config_xattrnames into a list
authorMatthew Garrett <mjg59@google.com>
Fri, 11 May 2018 23:12:35 +0000 (16:12 -0700)
committerMimi Zohar <zohar@linux.vnet.ibm.com>
Fri, 18 May 2018 19:34:36 +0000 (15:34 -0400)
Use a list of xattrs rather than an array - this makes it easier to
extend the list at runtime.

Signed-off-by: Matthew Garrett <mjg59@google.com>
Reviewed-by: James Morris <james.morris@microsoft.com>
Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
security/integrity/evm/evm.h
security/integrity/evm/evm_crypto.c
security/integrity/evm/evm_main.c

index 45c4a89..1257c3c 100644 (file)
 #define EVM_INIT_MASK (EVM_INIT_HMAC | EVM_INIT_X509 | EVM_SETUP_COMPLETE | \
                       EVM_ALLOW_METADATA_WRITES)
 
+struct xattr_list {
+       struct list_head list;
+       char *name;
+};
+
 extern int evm_initialized;
 
 #define EVM_ATTR_FSUUID                0x0001
@@ -40,7 +45,7 @@ extern struct crypto_shash *hmac_tfm;
 extern struct crypto_shash *hash_tfm;
 
 /* List of EVM protected security xattrs */
-extern char *evm_config_xattrnames[];
+extern struct list_head evm_config_xattrnames;
 
 int evm_init_key(void);
 int evm_update_evmxattr(struct dentry *dentry,
index a46fba3..caeea20 100644 (file)
@@ -192,8 +192,8 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
                                char type, char *digest)
 {
        struct inode *inode = d_backing_inode(dentry);
+       struct xattr_list *xattr;
        struct shash_desc *desc;
-       char **xattrname;
        size_t xattr_size = 0;
        char *xattr_value = NULL;
        int error;
@@ -208,14 +208,14 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
                return PTR_ERR(desc);
 
        error = -ENODATA;
-       for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) {
+       list_for_each_entry(xattr, &evm_config_xattrnames, list) {
                bool is_ima = false;
 
-               if (strcmp(*xattrname, XATTR_NAME_IMA) == 0)
+               if (strcmp(xattr->name, XATTR_NAME_IMA) == 0)
                        is_ima = true;
 
                if ((req_xattr_name && req_xattr_value)
-                   && !strcmp(*xattrname, req_xattr_name)) {
+                   && !strcmp(xattr->name, req_xattr_name)) {
                        error = 0;
                        crypto_shash_update(desc, (const u8 *)req_xattr_value,
                                             req_xattr_value_len);
@@ -223,7 +223,7 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
                                ima_present = true;
                        continue;
                }
-               size = vfs_getxattr_alloc(dentry, *xattrname,
+               size = vfs_getxattr_alloc(dentry, xattr->name,
                                          &xattr_value, xattr_size, GFP_NOFS);
                if (size == -ENOMEM) {
                        error = -ENOMEM;
index 9ea9c19..09582d4 100644 (file)
@@ -35,28 +35,29 @@ static const char * const integrity_status_msg[] = {
 };
 int evm_hmac_attrs;
 
-char *evm_config_xattrnames[] = {
+static struct xattr_list evm_config_default_xattrnames[] __ro_after_init = {
 #ifdef CONFIG_SECURITY_SELINUX
-       XATTR_NAME_SELINUX,
+       {.name = XATTR_NAME_SELINUX},
 #endif
 #ifdef CONFIG_SECURITY_SMACK
-       XATTR_NAME_SMACK,
+       {.name = XATTR_NAME_SMACK},
 #ifdef CONFIG_EVM_EXTRA_SMACK_XATTRS
-       XATTR_NAME_SMACKEXEC,
-       XATTR_NAME_SMACKTRANSMUTE,
-       XATTR_NAME_SMACKMMAP,
+       {.name = XATTR_NAME_SMACKEXEC},
+       {.name = XATTR_NAME_SMACKTRANSMUTE},
+       {.name = XATTR_NAME_SMACKMMAP},
 #endif
 #endif
 #ifdef CONFIG_SECURITY_APPARMOR
-       XATTR_NAME_APPARMOR,
+       {.name = XATTR_NAME_APPARMOR},
 #endif
 #ifdef CONFIG_IMA_APPRAISE
-       XATTR_NAME_IMA,
+       {.name = XATTR_NAME_IMA},
 #endif
-       XATTR_NAME_CAPS,
-       NULL
+       {.name = XATTR_NAME_CAPS},
 };
 
+LIST_HEAD(evm_config_xattrnames);
+
 static int evm_fixmode;
 static int __init evm_set_fixmode(char *str)
 {
@@ -68,6 +69,17 @@ __setup("evm=", evm_set_fixmode);
 
 static void __init evm_init_config(void)
 {
+       int i, xattrs;
+
+       xattrs = ARRAY_SIZE(evm_config_default_xattrnames);
+
+       pr_info("Initialising EVM extended attributes:\n");
+       for (i = 0; i < xattrs; i++) {
+               pr_info("%s\n", evm_config_default_xattrnames[i].name);
+               list_add_tail(&evm_config_default_xattrnames[i].list,
+                             &evm_config_xattrnames);
+       }
+
 #ifdef CONFIG_EVM_ATTR_FSUUID
        evm_hmac_attrs |= EVM_ATTR_FSUUID;
 #endif
@@ -82,15 +94,15 @@ static bool evm_key_loaded(void)
 static int evm_find_protected_xattrs(struct dentry *dentry)
 {
        struct inode *inode = d_backing_inode(dentry);
-       char **xattr;
+       struct xattr_list *xattr;
        int error;
        int count = 0;
 
        if (!(inode->i_opflags & IOP_XATTR))
                return -EOPNOTSUPP;
 
-       for (xattr = evm_config_xattrnames; *xattr != NULL; xattr++) {
-               error = __vfs_getxattr(dentry, inode, *xattr, NULL, 0);
+       list_for_each_entry(xattr, &evm_config_xattrnames, list) {
+               error = __vfs_getxattr(dentry, inode, xattr->name, NULL, 0);
                if (error < 0) {
                        if (error == -ENODATA)
                                continue;
@@ -211,24 +223,25 @@ out:
 
 static int evm_protected_xattr(const char *req_xattr_name)
 {
-       char **xattrname;
        int namelen;
        int found = 0;
+       struct xattr_list *xattr;
 
        namelen = strlen(req_xattr_name);
-       for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) {
-               if ((strlen(*xattrname) == namelen)
-                   && (strncmp(req_xattr_name, *xattrname, namelen) == 0)) {
+       list_for_each_entry(xattr, &evm_config_xattrnames, list) {
+               if ((strlen(xattr->name) == namelen)
+                   && (strncmp(req_xattr_name, xattr->name, namelen) == 0)) {
                        found = 1;
                        break;
                }
                if (strncmp(req_xattr_name,
-                           *xattrname + XATTR_SECURITY_PREFIX_LEN,
+                           xattr->name + XATTR_SECURITY_PREFIX_LEN,
                            strlen(req_xattr_name)) == 0) {
                        found = 1;
                        break;
                }
        }
+
        return found;
 }
 
@@ -544,35 +557,35 @@ void __init evm_load_x509(void)
 static int __init init_evm(void)
 {
        int error;
+       struct list_head *pos, *q;
+       struct xattr_list *xattr;
 
        evm_init_config();
 
        error = integrity_init_keyring(INTEGRITY_KEYRING_EVM);
        if (error)
-               return error;
+               goto error;
 
        error = evm_init_secfs();
        if (error < 0) {
                pr_info("Error registering secfs\n");
-               return error;
+               goto error;
        }
 
-       return 0;
-}
-
-/*
- * evm_display_config - list the EVM protected security extended attributes
- */
-static int __init evm_display_config(void)
-{
-       char **xattrname;
+error:
+       if (error != 0) {
+               if (!list_empty(&evm_config_xattrnames)) {
+                       list_for_each_safe(pos, q, &evm_config_xattrnames) {
+                               xattr = list_entry(pos, struct xattr_list,
+                                                  list);
+                               list_del(pos);
+                       }
+               }
+       }
 
-       for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++)
-               pr_info("%s\n", *xattrname);
-       return 0;
+       return error;
 }
 
-pure_initcall(evm_display_config);
 late_initcall(init_evm);
 
 MODULE_DESCRIPTION("Extended Verification Module");