diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-07 18:40:37 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-07 18:40:37 -0400 |
| commit | 00d535a386c071a06e111fd846f6beda445126a5 (patch) | |
| tree | f0ebe350b705281ba9816d9e023c2442a2bc0304 /security | |
| parent | 289cf155d95df07ac1e692dfaa7036f10235c77c (diff) | |
| parent | b5c90a7526fe39164c2204f0404ce8f8ff21e522 (diff) | |
Merge branch 'next-integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull integrity updates from James Morris:
"From Mimi:
- add run time support for specifying additional security xattrs
included in the security.evm HMAC/signature
- some code clean up and bug fixes"
* 'next-integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
EVM: unlock on error path in evm_read_xattrs()
EVM: prevent array underflow in evm_write_xattrs()
EVM: Fix null dereference on xattr when xattr fails to allocate
EVM: fix memory leak of temporary buffer 'temp'
IMA: use list_splice_tail_init_rcu() instead of its open coded variant
ima: use match_string() helper
ima: fix updating the ima_appraise flag
ima: based on policy verify firmware signatures (pre-allocated buffer)
ima: define a new policy condition based on the filesystem name
EVM: Allow runtime modification of the set of verified xattrs
EVM: turn evm_config_xattrnames into a list
integrity: Add an integrity directory in securityfs
ima: Remove unused variable ima_initialized
ima: Unify logging
ima: Reflect correct permissions for policy
Diffstat (limited to 'security')
| -rw-r--r-- | security/integrity/evm/Kconfig | 11 | ||||
| -rw-r--r-- | security/integrity/evm/evm.h | 7 | ||||
| -rw-r--r-- | security/integrity/evm/evm_crypto.c | 10 | ||||
| -rw-r--r-- | security/integrity/evm/evm_main.c | 79 | ||||
| -rw-r--r-- | security/integrity/evm/evm_secfs.c | 206 | ||||
| -rw-r--r-- | security/integrity/iint.c | 18 | ||||
| -rw-r--r-- | security/integrity/ima/ima.h | 1 | ||||
| -rw-r--r-- | security/integrity/ima/ima_fs.c | 18 | ||||
| -rw-r--r-- | security/integrity/ima/ima_kexec.c | 2 | ||||
| -rw-r--r-- | security/integrity/ima/ima_main.c | 19 | ||||
| -rw-r--r-- | security/integrity/ima/ima_policy.c | 70 | ||||
| -rw-r--r-- | security/integrity/ima/ima_template_lib.c | 2 | ||||
| -rw-r--r-- | security/integrity/integrity.h | 2 |
13 files changed, 362 insertions, 83 deletions
diff --git a/security/integrity/evm/Kconfig b/security/integrity/evm/Kconfig index e825e0ae78e7..d593346d0bba 100644 --- a/security/integrity/evm/Kconfig +++ b/security/integrity/evm/Kconfig | |||
| @@ -42,6 +42,17 @@ config EVM_EXTRA_SMACK_XATTRS | |||
| 42 | additional info to the calculation, requires existing EVM | 42 | additional info to the calculation, requires existing EVM |
| 43 | labeled file systems to be relabeled. | 43 | labeled file systems to be relabeled. |
| 44 | 44 | ||
| 45 | config EVM_ADD_XATTRS | ||
| 46 | bool "Add additional EVM extended attributes at runtime" | ||
| 47 | depends on EVM | ||
| 48 | default n | ||
| 49 | help | ||
| 50 | Allow userland to provide additional xattrs for HMAC calculation. | ||
| 51 | |||
| 52 | When this option is enabled, root can add additional xattrs to the | ||
| 53 | list used by EVM by writing them into | ||
| 54 | /sys/kernel/security/integrity/evm/evm_xattrs. | ||
| 55 | |||
| 45 | config EVM_LOAD_X509 | 56 | config EVM_LOAD_X509 |
| 46 | bool "Load an X509 certificate onto the '.evm' trusted keyring" | 57 | bool "Load an X509 certificate onto the '.evm' trusted keyring" |
| 47 | depends on EVM && INTEGRITY_TRUSTED_KEYRING | 58 | depends on EVM && INTEGRITY_TRUSTED_KEYRING |
diff --git a/security/integrity/evm/evm.h b/security/integrity/evm/evm.h index 45c4a89c02ff..1257c3c24723 100644 --- a/security/integrity/evm/evm.h +++ b/security/integrity/evm/evm.h | |||
| @@ -30,6 +30,11 @@ | |||
| 30 | #define EVM_INIT_MASK (EVM_INIT_HMAC | EVM_INIT_X509 | EVM_SETUP_COMPLETE | \ | 30 | #define EVM_INIT_MASK (EVM_INIT_HMAC | EVM_INIT_X509 | EVM_SETUP_COMPLETE | \ |
| 31 | EVM_ALLOW_METADATA_WRITES) | 31 | EVM_ALLOW_METADATA_WRITES) |
| 32 | 32 | ||
| 33 | struct xattr_list { | ||
| 34 | struct list_head list; | ||
| 35 | char *name; | ||
| 36 | }; | ||
| 37 | |||
| 33 | extern int evm_initialized; | 38 | extern int evm_initialized; |
| 34 | 39 | ||
| 35 | #define EVM_ATTR_FSUUID 0x0001 | 40 | #define EVM_ATTR_FSUUID 0x0001 |
| @@ -40,7 +45,7 @@ extern struct crypto_shash *hmac_tfm; | |||
| 40 | extern struct crypto_shash *hash_tfm; | 45 | extern struct crypto_shash *hash_tfm; |
| 41 | 46 | ||
| 42 | /* List of EVM protected security xattrs */ | 47 | /* List of EVM protected security xattrs */ |
| 43 | extern char *evm_config_xattrnames[]; | 48 | extern struct list_head evm_config_xattrnames; |
| 44 | 49 | ||
| 45 | int evm_init_key(void); | 50 | int evm_init_key(void); |
| 46 | int evm_update_evmxattr(struct dentry *dentry, | 51 | int evm_update_evmxattr(struct dentry *dentry, |
diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c index facf9cdd577d..b60524310855 100644 --- a/security/integrity/evm/evm_crypto.c +++ b/security/integrity/evm/evm_crypto.c | |||
| @@ -192,8 +192,8 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry, | |||
| 192 | char type, char *digest) | 192 | char type, char *digest) |
| 193 | { | 193 | { |
| 194 | struct inode *inode = d_backing_inode(dentry); | 194 | struct inode *inode = d_backing_inode(dentry); |
| 195 | struct xattr_list *xattr; | ||
| 195 | struct shash_desc *desc; | 196 | struct shash_desc *desc; |
| 196 | char **xattrname; | ||
| 197 | size_t xattr_size = 0; | 197 | size_t xattr_size = 0; |
| 198 | char *xattr_value = NULL; | 198 | char *xattr_value = NULL; |
| 199 | int error; | 199 | int error; |
| @@ -209,14 +209,14 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry, | |||
| 209 | return PTR_ERR(desc); | 209 | return PTR_ERR(desc); |
| 210 | 210 | ||
| 211 | error = -ENODATA; | 211 | error = -ENODATA; |
| 212 | for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) { | 212 | list_for_each_entry_rcu(xattr, &evm_config_xattrnames, list) { |
| 213 | bool is_ima = false; | 213 | bool is_ima = false; |
| 214 | 214 | ||
| 215 | if (strcmp(*xattrname, XATTR_NAME_IMA) == 0) | 215 | if (strcmp(xattr->name, XATTR_NAME_IMA) == 0) |
| 216 | is_ima = true; | 216 | is_ima = true; |
| 217 | 217 | ||
| 218 | if ((req_xattr_name && req_xattr_value) | 218 | if ((req_xattr_name && req_xattr_value) |
| 219 | && !strcmp(*xattrname, req_xattr_name)) { | 219 | && !strcmp(xattr->name, req_xattr_name)) { |
| 220 | error = 0; | 220 | error = 0; |
| 221 | crypto_shash_update(desc, (const u8 *)req_xattr_value, | 221 | crypto_shash_update(desc, (const u8 *)req_xattr_value, |
| 222 | req_xattr_value_len); | 222 | req_xattr_value_len); |
| @@ -224,7 +224,7 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry, | |||
| 224 | ima_present = true; | 224 | ima_present = true; |
| 225 | continue; | 225 | continue; |
| 226 | } | 226 | } |
| 227 | size = vfs_getxattr_alloc(dentry, *xattrname, | 227 | size = vfs_getxattr_alloc(dentry, xattr->name, |
| 228 | &xattr_value, xattr_size, GFP_NOFS); | 228 | &xattr_value, xattr_size, GFP_NOFS); |
| 229 | if (size == -ENOMEM) { | 229 | if (size == -ENOMEM) { |
| 230 | error = -ENOMEM; | 230 | error = -ENOMEM; |
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index 9ea9c19a545c..f9eff5041e4c 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c | |||
| @@ -35,28 +35,29 @@ static const char * const integrity_status_msg[] = { | |||
| 35 | }; | 35 | }; |
| 36 | int evm_hmac_attrs; | 36 | int evm_hmac_attrs; |
| 37 | 37 | ||
| 38 | char *evm_config_xattrnames[] = { | 38 | static struct xattr_list evm_config_default_xattrnames[] = { |
| 39 | #ifdef CONFIG_SECURITY_SELINUX | 39 | #ifdef CONFIG_SECURITY_SELINUX |
| 40 | XATTR_NAME_SELINUX, | 40 | {.name = XATTR_NAME_SELINUX}, |
| 41 | #endif | 41 | #endif |
| 42 | #ifdef CONFIG_SECURITY_SMACK | 42 | #ifdef CONFIG_SECURITY_SMACK |
| 43 | XATTR_NAME_SMACK, | 43 | {.name = XATTR_NAME_SMACK}, |
| 44 | #ifdef CONFIG_EVM_EXTRA_SMACK_XATTRS | 44 | #ifdef CONFIG_EVM_EXTRA_SMACK_XATTRS |
| 45 | XATTR_NAME_SMACKEXEC, | 45 | {.name = XATTR_NAME_SMACKEXEC}, |
| 46 | XATTR_NAME_SMACKTRANSMUTE, | 46 | {.name = XATTR_NAME_SMACKTRANSMUTE}, |
| 47 | XATTR_NAME_SMACKMMAP, | 47 | {.name = XATTR_NAME_SMACKMMAP}, |
| 48 | #endif | 48 | #endif |
| 49 | #endif | 49 | #endif |
| 50 | #ifdef CONFIG_SECURITY_APPARMOR | 50 | #ifdef CONFIG_SECURITY_APPARMOR |
| 51 | XATTR_NAME_APPARMOR, | 51 | {.name = XATTR_NAME_APPARMOR}, |
| 52 | #endif | 52 | #endif |
| 53 | #ifdef CONFIG_IMA_APPRAISE | 53 | #ifdef CONFIG_IMA_APPRAISE |
| 54 | XATTR_NAME_IMA, | 54 | {.name = XATTR_NAME_IMA}, |
| 55 | #endif | 55 | #endif |
| 56 | XATTR_NAME_CAPS, | 56 | {.name = XATTR_NAME_CAPS}, |
| 57 | NULL | ||
| 58 | }; | 57 | }; |
| 59 | 58 | ||
| 59 | LIST_HEAD(evm_config_xattrnames); | ||
| 60 | |||
| 60 | static int evm_fixmode; | 61 | static int evm_fixmode; |
| 61 | static int __init evm_set_fixmode(char *str) | 62 | static int __init evm_set_fixmode(char *str) |
| 62 | { | 63 | { |
| @@ -68,6 +69,17 @@ __setup("evm=", evm_set_fixmode); | |||
| 68 | 69 | ||
| 69 | static void __init evm_init_config(void) | 70 | static void __init evm_init_config(void) |
| 70 | { | 71 | { |
| 72 | int i, xattrs; | ||
| 73 | |||
| 74 | xattrs = ARRAY_SIZE(evm_config_default_xattrnames); | ||
| 75 | |||
| 76 | pr_info("Initialising EVM extended attributes:\n"); | ||
| 77 | for (i = 0; i < xattrs; i++) { | ||
| 78 | pr_info("%s\n", evm_config_default_xattrnames[i].name); | ||
| 79 | list_add_tail(&evm_config_default_xattrnames[i].list, | ||
| 80 | &evm_config_xattrnames); | ||
| 81 | } | ||
| 82 | |||
| 71 | #ifdef CONFIG_EVM_ATTR_FSUUID | 83 | #ifdef CONFIG_EVM_ATTR_FSUUID |
| 72 | evm_hmac_attrs |= EVM_ATTR_FSUUID; | 84 | evm_hmac_attrs |= EVM_ATTR_FSUUID; |
| 73 | #endif | 85 | #endif |
| @@ -82,15 +94,15 @@ static bool evm_key_loaded(void) | |||
| 82 | static int evm_find_protected_xattrs(struct dentry *dentry) | 94 | static int evm_find_protected_xattrs(struct dentry *dentry) |
| 83 | { | 95 | { |
| 84 | struct inode *inode = d_backing_inode(dentry); | 96 | struct inode *inode = d_backing_inode(dentry); |
| 85 | char **xattr; | 97 | struct xattr_list *xattr; |
| 86 | int error; | 98 | int error; |
| 87 | int count = 0; | 99 | int count = 0; |
| 88 | 100 | ||
| 89 | if (!(inode->i_opflags & IOP_XATTR)) | 101 | if (!(inode->i_opflags & IOP_XATTR)) |
| 90 | return -EOPNOTSUPP; | 102 | return -EOPNOTSUPP; |
| 91 | 103 | ||
| 92 | for (xattr = evm_config_xattrnames; *xattr != NULL; xattr++) { | 104 | list_for_each_entry_rcu(xattr, &evm_config_xattrnames, list) { |
| 93 | error = __vfs_getxattr(dentry, inode, *xattr, NULL, 0); | 105 | error = __vfs_getxattr(dentry, inode, xattr->name, NULL, 0); |
| 94 | if (error < 0) { | 106 | if (error < 0) { |
| 95 | if (error == -ENODATA) | 107 | if (error == -ENODATA) |
| 96 | continue; | 108 | continue; |
| @@ -211,24 +223,25 @@ out: | |||
| 211 | 223 | ||
| 212 | static int evm_protected_xattr(const char *req_xattr_name) | 224 | static int evm_protected_xattr(const char *req_xattr_name) |
| 213 | { | 225 | { |
| 214 | char **xattrname; | ||
| 215 | int namelen; | 226 | int namelen; |
| 216 | int found = 0; | 227 | int found = 0; |
| 228 | struct xattr_list *xattr; | ||
| 217 | 229 | ||
| 218 | namelen = strlen(req_xattr_name); | 230 | namelen = strlen(req_xattr_name); |
| 219 | for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) { | 231 | list_for_each_entry_rcu(xattr, &evm_config_xattrnames, list) { |
| 220 | if ((strlen(*xattrname) == namelen) | 232 | if ((strlen(xattr->name) == namelen) |
| 221 | && (strncmp(req_xattr_name, *xattrname, namelen) == 0)) { | 233 | && (strncmp(req_xattr_name, xattr->name, namelen) == 0)) { |
| 222 | found = 1; | 234 | found = 1; |
| 223 | break; | 235 | break; |
| 224 | } | 236 | } |
| 225 | if (strncmp(req_xattr_name, | 237 | if (strncmp(req_xattr_name, |
| 226 | *xattrname + XATTR_SECURITY_PREFIX_LEN, | 238 | xattr->name + XATTR_SECURITY_PREFIX_LEN, |
| 227 | strlen(req_xattr_name)) == 0) { | 239 | strlen(req_xattr_name)) == 0) { |
| 228 | found = 1; | 240 | found = 1; |
| 229 | break; | 241 | break; |
| 230 | } | 242 | } |
| 231 | } | 243 | } |
| 244 | |||
| 232 | return found; | 245 | return found; |
| 233 | } | 246 | } |
| 234 | 247 | ||
| @@ -544,35 +557,35 @@ void __init evm_load_x509(void) | |||
| 544 | static int __init init_evm(void) | 557 | static int __init init_evm(void) |
| 545 | { | 558 | { |
| 546 | int error; | 559 | int error; |
| 560 | struct list_head *pos, *q; | ||
| 561 | struct xattr_list *xattr; | ||
| 547 | 562 | ||
| 548 | evm_init_config(); | 563 | evm_init_config(); |
| 549 | 564 | ||
| 550 | error = integrity_init_keyring(INTEGRITY_KEYRING_EVM); | 565 | error = integrity_init_keyring(INTEGRITY_KEYRING_EVM); |
| 551 | if (error) | 566 | if (error) |
| 552 | return error; | 567 | goto error; |
| 553 | 568 | ||
| 554 | error = evm_init_secfs(); | 569 | error = evm_init_secfs(); |
| 555 | if (error < 0) { | 570 | if (error < 0) { |
| 556 | pr_info("Error registering secfs\n"); | 571 | pr_info("Error registering secfs\n"); |
| 557 | return error; | 572 | goto error; |
| 558 | } | 573 | } |
| 559 | 574 | ||
| 560 | return 0; | 575 | error: |
| 561 | } | 576 | if (error != 0) { |
| 562 | 577 | if (!list_empty(&evm_config_xattrnames)) { | |
| 563 | /* | 578 | list_for_each_safe(pos, q, &evm_config_xattrnames) { |
| 564 | * evm_display_config - list the EVM protected security extended attributes | 579 | xattr = list_entry(pos, struct xattr_list, |
| 565 | */ | 580 | list); |
| 566 | static int __init evm_display_config(void) | 581 | list_del(pos); |
| 567 | { | 582 | } |
| 568 | char **xattrname; | 583 | } |
| 584 | } | ||
| 569 | 585 | ||
| 570 | for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++) | 586 | return error; |
| 571 | pr_info("%s\n", *xattrname); | ||
| 572 | return 0; | ||
| 573 | } | 587 | } |
| 574 | 588 | ||
| 575 | pure_initcall(evm_display_config); | ||
| 576 | late_initcall(init_evm); | 589 | late_initcall(init_evm); |
| 577 | 590 | ||
| 578 | MODULE_DESCRIPTION("Extended Verification Module"); | 591 | MODULE_DESCRIPTION("Extended Verification Module"); |
diff --git a/security/integrity/evm/evm_secfs.c b/security/integrity/evm/evm_secfs.c index feba03bbedae..637eb999e340 100644 --- a/security/integrity/evm/evm_secfs.c +++ b/security/integrity/evm/evm_secfs.c | |||
| @@ -15,11 +15,21 @@ | |||
| 15 | 15 | ||
| 16 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 16 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
| 17 | 17 | ||
| 18 | #include <linux/audit.h> | ||
| 18 | #include <linux/uaccess.h> | 19 | #include <linux/uaccess.h> |
| 19 | #include <linux/module.h> | 20 | #include <linux/module.h> |
| 21 | #include <linux/mutex.h> | ||
| 20 | #include "evm.h" | 22 | #include "evm.h" |
| 21 | 23 | ||
| 24 | static struct dentry *evm_dir; | ||
| 22 | static struct dentry *evm_init_tpm; | 25 | static struct dentry *evm_init_tpm; |
| 26 | static struct dentry *evm_symlink; | ||
| 27 | |||
| 28 | #ifdef CONFIG_EVM_ADD_XATTRS | ||
| 29 | static struct dentry *evm_xattrs; | ||
| 30 | static DEFINE_MUTEX(xattr_list_mutex); | ||
| 31 | static int evm_xattrs_locked; | ||
| 32 | #endif | ||
| 23 | 33 | ||
| 24 | /** | 34 | /** |
| 25 | * evm_read_key - read() for <securityfs>/evm | 35 | * evm_read_key - read() for <securityfs>/evm |
| @@ -107,13 +117,203 @@ static const struct file_operations evm_key_ops = { | |||
| 107 | .write = evm_write_key, | 117 | .write = evm_write_key, |
| 108 | }; | 118 | }; |
| 109 | 119 | ||
| 120 | #ifdef CONFIG_EVM_ADD_XATTRS | ||
| 121 | /** | ||
| 122 | * evm_read_xattrs - read() for <securityfs>/evm_xattrs | ||
| 123 | * | ||
| 124 | * @filp: file pointer, not actually used | ||
| 125 | * @buf: where to put the result | ||
| 126 | * @count: maximum to send along | ||
| 127 | * @ppos: where to start | ||
| 128 | * | ||
| 129 | * Returns number of bytes read or error code, as appropriate | ||
| 130 | */ | ||
| 131 | static ssize_t evm_read_xattrs(struct file *filp, char __user *buf, | ||
| 132 | size_t count, loff_t *ppos) | ||
| 133 | { | ||
| 134 | char *temp; | ||
| 135 | int offset = 0; | ||
| 136 | ssize_t rc, size = 0; | ||
| 137 | struct xattr_list *xattr; | ||
| 138 | |||
| 139 | if (*ppos != 0) | ||
| 140 | return 0; | ||
| 141 | |||
| 142 | rc = mutex_lock_interruptible(&xattr_list_mutex); | ||
| 143 | if (rc) | ||
| 144 | return -ERESTARTSYS; | ||
| 145 | |||
| 146 | list_for_each_entry(xattr, &evm_config_xattrnames, list) | ||
| 147 | size += strlen(xattr->name) + 1; | ||
| 148 | |||
| 149 | temp = kmalloc(size + 1, GFP_KERNEL); | ||
| 150 | if (!temp) { | ||
| 151 | mutex_unlock(&xattr_list_mutex); | ||
| 152 | return -ENOMEM; | ||
| 153 | } | ||
| 154 | |||
| 155 | list_for_each_entry(xattr, &evm_config_xattrnames, list) { | ||
| 156 | sprintf(temp + offset, "%s\n", xattr->name); | ||
| 157 | offset += strlen(xattr->name) + 1; | ||
| 158 | } | ||
| 159 | |||
| 160 | mutex_unlock(&xattr_list_mutex); | ||
| 161 | rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp)); | ||
| 162 | |||
| 163 | kfree(temp); | ||
| 164 | |||
| 165 | return rc; | ||
| 166 | } | ||
| 167 | |||
| 168 | /** | ||
| 169 | * evm_write_xattrs - write() for <securityfs>/evm_xattrs | ||
| 170 | * @file: file pointer, not actually used | ||
| 171 | * @buf: where to get the data from | ||
| 172 | * @count: bytes sent | ||
| 173 | * @ppos: where to start | ||
| 174 | * | ||
| 175 | * Returns number of bytes written or error code, as appropriate | ||
| 176 | */ | ||
| 177 | static ssize_t evm_write_xattrs(struct file *file, const char __user *buf, | ||
| 178 | size_t count, loff_t *ppos) | ||
| 179 | { | ||
| 180 | int len, err; | ||
| 181 | struct xattr_list *xattr, *tmp; | ||
| 182 | struct audit_buffer *ab; | ||
| 183 | struct iattr newattrs; | ||
| 184 | struct inode *inode; | ||
| 185 | |||
| 186 | if (!capable(CAP_SYS_ADMIN) || evm_xattrs_locked) | ||
| 187 | return -EPERM; | ||
| 188 | |||
| 189 | if (*ppos != 0) | ||
| 190 | return -EINVAL; | ||
| 191 | |||
| 192 | if (count > XATTR_NAME_MAX) | ||
| 193 | return -E2BIG; | ||
| 194 | |||
| 195 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_INTEGRITY_EVM_XATTR); | ||
| 196 | if (IS_ERR(ab)) | ||
| 197 | return PTR_ERR(ab); | ||
| 198 | |||
| 199 | xattr = kmalloc(sizeof(struct xattr_list), GFP_KERNEL); | ||
| 200 | if (!xattr) { | ||
| 201 | err = -ENOMEM; | ||
| 202 | goto out; | ||
| 203 | } | ||
| 204 | |||
| 205 | xattr->name = memdup_user_nul(buf, count); | ||
| 206 | if (IS_ERR(xattr->name)) { | ||
| 207 | err = PTR_ERR(xattr->name); | ||
| 208 | xattr->name = NULL; | ||
| 209 | goto out; | ||
| 210 | } | ||
| 211 | |||
| 212 | /* Remove any trailing newline */ | ||
| 213 | len = strlen(xattr->name); | ||
| 214 | if (len && xattr->name[len-1] == '\n') | ||
| 215 | xattr->name[len-1] = '\0'; | ||
| 216 | |||
| 217 | if (strcmp(xattr->name, ".") == 0) { | ||
| 218 | evm_xattrs_locked = 1; | ||
| 219 | newattrs.ia_mode = S_IFREG | 0440; | ||
| 220 | newattrs.ia_valid = ATTR_MODE; | ||
| 221 | inode = evm_xattrs->d_inode; | ||
| 222 | inode_lock(inode); | ||
| 223 | err = simple_setattr(evm_xattrs, &newattrs); | ||
| 224 | inode_unlock(inode); | ||
| 225 | audit_log_format(ab, "locked"); | ||
| 226 | if (!err) | ||
| 227 | err = count; | ||
| 228 | goto out; | ||
| 229 | } | ||
| 230 | |||
| 231 | audit_log_format(ab, "xattr="); | ||
| 232 | audit_log_untrustedstring(ab, xattr->name); | ||
| 233 | |||
| 234 | if (strncmp(xattr->name, XATTR_SECURITY_PREFIX, | ||
| 235 | XATTR_SECURITY_PREFIX_LEN) != 0) { | ||
| 236 | err = -EINVAL; | ||
| 237 | goto out; | ||
| 238 | } | ||
| 239 | |||
| 240 | /* Guard against races in evm_read_xattrs */ | ||
| 241 | mutex_lock(&xattr_list_mutex); | ||
| 242 | list_for_each_entry(tmp, &evm_config_xattrnames, list) { | ||
| 243 | if (strcmp(xattr->name, tmp->name) == 0) { | ||
| 244 | err = -EEXIST; | ||
| 245 | mutex_unlock(&xattr_list_mutex); | ||
| 246 | goto out; | ||
| 247 | } | ||
| 248 | } | ||
| 249 | list_add_tail_rcu(&xattr->list, &evm_config_xattrnames); | ||
| 250 | mutex_unlock(&xattr_list_mutex); | ||
| 251 | |||
| 252 | audit_log_format(ab, " res=0"); | ||
| 253 | audit_log_end(ab); | ||
| 254 | return count; | ||
| 255 | out: | ||
| 256 | audit_log_format(ab, " res=%d", err); | ||
| 257 | audit_log_end(ab); | ||
| 258 | if (xattr) { | ||
| 259 | kfree(xattr->name); | ||
| 260 | kfree(xattr); | ||
| 261 | } | ||
| 262 | return err; | ||
| 263 | } | ||
| 264 | |||
| 265 | static const struct file_operations evm_xattr_ops = { | ||
| 266 | .read = evm_read_xattrs, | ||
| 267 | .write = evm_write_xattrs, | ||
| 268 | }; | ||
| 269 | |||
| 270 | static int evm_init_xattrs(void) | ||
| 271 | { | ||
| 272 | evm_xattrs = securityfs_create_file("evm_xattrs", 0660, evm_dir, NULL, | ||
| 273 | &evm_xattr_ops); | ||
| 274 | if (!evm_xattrs || IS_ERR(evm_xattrs)) | ||
| 275 | return -EFAULT; | ||
| 276 | |||
| 277 | return 0; | ||
| 278 | } | ||
| 279 | #else | ||
| 280 | static int evm_init_xattrs(void) | ||
| 281 | { | ||
| 282 | return 0; | ||
| 283 | } | ||
| 284 | #endif | ||
| 285 | |||
| 110 | int __init evm_init_secfs(void) | 286 | int __init evm_init_secfs(void) |
| 111 | { | 287 | { |
| 112 | int error = 0; | 288 | int error = 0; |
| 113 | 289 | ||
| 114 | evm_init_tpm = securityfs_create_file("evm", S_IRUSR | S_IRGRP, | 290 | evm_dir = securityfs_create_dir("evm", integrity_dir); |
| 115 | NULL, NULL, &evm_key_ops); | 291 | if (!evm_dir || IS_ERR(evm_dir)) |
| 116 | if (!evm_init_tpm || IS_ERR(evm_init_tpm)) | 292 | return -EFAULT; |
| 293 | |||
| 294 | evm_init_tpm = securityfs_create_file("evm", 0660, | ||
| 295 | evm_dir, NULL, &evm_key_ops); | ||
| 296 | if (!evm_init_tpm || IS_ERR(evm_init_tpm)) { | ||
| 117 | error = -EFAULT; | 297 | error = -EFAULT; |
| 298 | goto out; | ||
| 299 | } | ||
| 300 | |||
| 301 | evm_symlink = securityfs_create_symlink("evm", NULL, | ||
| 302 | "integrity/evm/evm", NULL); | ||
| 303 | if (!evm_symlink || IS_ERR(evm_symlink)) { | ||
| 304 | error = -EFAULT; | ||
| 305 | goto out; | ||
| 306 | } | ||
| 307 | |||
| 308 | if (evm_init_xattrs() != 0) { | ||
| 309 | error = -EFAULT; | ||
| 310 | goto out; | ||
| 311 | } | ||
| 312 | |||
| 313 | return 0; | ||
| 314 | out: | ||
| 315 | securityfs_remove(evm_symlink); | ||
| 316 | securityfs_remove(evm_init_tpm); | ||
| 317 | securityfs_remove(evm_dir); | ||
| 118 | return error; | 318 | return error; |
| 119 | } | 319 | } |
diff --git a/security/integrity/iint.c b/security/integrity/iint.c index f266e4b3b7d4..149faa81f6f0 100644 --- a/security/integrity/iint.c +++ b/security/integrity/iint.c | |||
| @@ -21,12 +21,15 @@ | |||
| 21 | #include <linux/rbtree.h> | 21 | #include <linux/rbtree.h> |
| 22 | #include <linux/file.h> | 22 | #include <linux/file.h> |
| 23 | #include <linux/uaccess.h> | 23 | #include <linux/uaccess.h> |
| 24 | #include <linux/security.h> | ||
| 24 | #include "integrity.h" | 25 | #include "integrity.h" |
| 25 | 26 | ||
| 26 | static struct rb_root integrity_iint_tree = RB_ROOT; | 27 | static struct rb_root integrity_iint_tree = RB_ROOT; |
| 27 | static DEFINE_RWLOCK(integrity_iint_lock); | 28 | static DEFINE_RWLOCK(integrity_iint_lock); |
| 28 | static struct kmem_cache *iint_cache __read_mostly; | 29 | static struct kmem_cache *iint_cache __read_mostly; |
| 29 | 30 | ||
| 31 | struct dentry *integrity_dir; | ||
| 32 | |||
| 30 | /* | 33 | /* |
| 31 | * __integrity_iint_find - return the iint associated with an inode | 34 | * __integrity_iint_find - return the iint associated with an inode |
| 32 | */ | 35 | */ |
| @@ -211,3 +214,18 @@ void __init integrity_load_keys(void) | |||
| 211 | ima_load_x509(); | 214 | ima_load_x509(); |
| 212 | evm_load_x509(); | 215 | evm_load_x509(); |
| 213 | } | 216 | } |
| 217 | |||
| 218 | static int __init integrity_fs_init(void) | ||
| 219 | { | ||
| 220 | integrity_dir = securityfs_create_dir("integrity", NULL); | ||
| 221 | if (IS_ERR(integrity_dir)) { | ||
| 222 | pr_err("Unable to create integrity sysfs dir: %ld\n", | ||
| 223 | PTR_ERR(integrity_dir)); | ||
| 224 | integrity_dir = NULL; | ||
| 225 | return PTR_ERR(integrity_dir); | ||
| 226 | } | ||
| 227 | |||
| 228 | return 0; | ||
| 229 | } | ||
| 230 | |||
| 231 | late_initcall(integrity_fs_init) | ||
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 35fe91aa1fc9..354bb5716ce3 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h | |||
| @@ -53,7 +53,6 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 }; | |||
| 53 | extern int ima_policy_flag; | 53 | extern int ima_policy_flag; |
| 54 | 54 | ||
| 55 | /* set during initialization */ | 55 | /* set during initialization */ |
| 56 | extern int ima_initialized; | ||
| 57 | extern int ima_used_chip; | 56 | extern int ima_used_chip; |
| 58 | extern int ima_hash_algo; | 57 | extern int ima_hash_algo; |
| 59 | extern int ima_appraise; | 58 | extern int ima_appraise; |
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index fa540c0469da..ae9d5c766a3c 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c | |||
| @@ -15,6 +15,9 @@ | |||
| 15 | * implemenents security file system for reporting | 15 | * implemenents security file system for reporting |
| 16 | * current measurement list and IMA statistics | 16 | * current measurement list and IMA statistics |
| 17 | */ | 17 | */ |
| 18 | |||
| 19 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 20 | |||
| 18 | #include <linux/fcntl.h> | 21 | #include <linux/fcntl.h> |
| 19 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
| 20 | #include <linux/module.h> | 23 | #include <linux/module.h> |
| @@ -336,7 +339,7 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf, | |||
| 336 | if (data[0] == '/') { | 339 | if (data[0] == '/') { |
| 337 | result = ima_read_policy(data); | 340 | result = ima_read_policy(data); |
| 338 | } else if (ima_appraise & IMA_APPRAISE_POLICY) { | 341 | } else if (ima_appraise & IMA_APPRAISE_POLICY) { |
| 339 | pr_err("IMA: signed policy file (specified as an absolute pathname) required\n"); | 342 | pr_err("signed policy file (specified as an absolute pathname) required\n"); |
| 340 | integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL, | 343 | integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL, |
| 341 | "policy_update", "signed policy required", | 344 | "policy_update", "signed policy required", |
| 342 | 1, 0); | 345 | 1, 0); |
| @@ -356,6 +359,7 @@ out: | |||
| 356 | } | 359 | } |
| 357 | 360 | ||
| 358 | static struct dentry *ima_dir; | 361 | static struct dentry *ima_dir; |
| 362 | static struct dentry *ima_symlink; | ||
| 359 | static struct dentry *binary_runtime_measurements; | 363 | static struct dentry *binary_runtime_measurements; |
| 360 | static struct dentry *ascii_runtime_measurements; | 364 | static struct dentry *ascii_runtime_measurements; |
| 361 | static struct dentry *runtime_measurements_count; | 365 | static struct dentry *runtime_measurements_count; |
| @@ -417,7 +421,7 @@ static int ima_release_policy(struct inode *inode, struct file *file) | |||
| 417 | valid_policy = 0; | 421 | valid_policy = 0; |
| 418 | } | 422 | } |
| 419 | 423 | ||
| 420 | pr_info("IMA: policy update %s\n", cause); | 424 | pr_info("policy update %s\n", cause); |
| 421 | integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL, | 425 | integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL, |
| 422 | "policy_update", cause, !valid_policy, 0); | 426 | "policy_update", cause, !valid_policy, 0); |
| 423 | 427 | ||
| @@ -434,6 +438,8 @@ static int ima_release_policy(struct inode *inode, struct file *file) | |||
| 434 | ima_policy = NULL; | 438 | ima_policy = NULL; |
| 435 | #elif defined(CONFIG_IMA_WRITE_POLICY) | 439 | #elif defined(CONFIG_IMA_WRITE_POLICY) |
| 436 | clear_bit(IMA_FS_BUSY, &ima_fs_flags); | 440 | clear_bit(IMA_FS_BUSY, &ima_fs_flags); |
| 441 | #elif defined(CONFIG_IMA_READ_POLICY) | ||
| 442 | inode->i_mode &= ~S_IWUSR; | ||
| 437 | #endif | 443 | #endif |
| 438 | return 0; | 444 | return 0; |
| 439 | } | 445 | } |
| @@ -448,10 +454,15 @@ static const struct file_operations ima_measure_policy_ops = { | |||
| 448 | 454 | ||
| 449 | int __init ima_fs_init(void) | 455 | int __init ima_fs_init(void) |
| 450 | { | 456 | { |
| 451 | ima_dir = securityfs_create_dir("ima", NULL); | 457 | ima_dir = securityfs_create_dir("ima", integrity_dir); |
| 452 | if (IS_ERR(ima_dir)) | 458 | if (IS_ERR(ima_dir)) |
| 453 | return -1; | 459 | return -1; |
| 454 | 460 | ||
| 461 | ima_symlink = securityfs_create_symlink("ima", NULL, "integrity/ima", | ||
| 462 | NULL); | ||
| 463 | if (IS_ERR(ima_symlink)) | ||
| 464 | goto out; | ||
| 465 | |||
| 455 | binary_runtime_measurements = | 466 | binary_runtime_measurements = |
| 456 | securityfs_create_file("binary_runtime_measurements", | 467 | securityfs_create_file("binary_runtime_measurements", |
| 457 | S_IRUSR | S_IRGRP, ima_dir, NULL, | 468 | S_IRUSR | S_IRGRP, ima_dir, NULL, |
| @@ -491,6 +502,7 @@ out: | |||
| 491 | securityfs_remove(runtime_measurements_count); | 502 | securityfs_remove(runtime_measurements_count); |
| 492 | securityfs_remove(ascii_runtime_measurements); | 503 | securityfs_remove(ascii_runtime_measurements); |
| 493 | securityfs_remove(binary_runtime_measurements); | 504 | securityfs_remove(binary_runtime_measurements); |
| 505 | securityfs_remove(ima_symlink); | ||
| 494 | securityfs_remove(ima_dir); | 506 | securityfs_remove(ima_dir); |
| 495 | securityfs_remove(ima_policy); | 507 | securityfs_remove(ima_policy); |
| 496 | return -1; | 508 | return -1; |
diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c index e473eee913cb..16bd18747cfa 100644 --- a/security/integrity/ima/ima_kexec.c +++ b/security/integrity/ima/ima_kexec.c | |||
| @@ -10,6 +10,8 @@ | |||
| 10 | * the Free Software Foundation; either version 2 of the License, or | 10 | * the Free Software Foundation; either version 2 of the License, or |
| 11 | * (at your option) any later version. | 11 | * (at your option) any later version. |
| 12 | */ | 12 | */ |
| 13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 14 | |||
| 13 | #include <linux/seq_file.h> | 15 | #include <linux/seq_file.h> |
| 14 | #include <linux/vmalloc.h> | 16 | #include <linux/vmalloc.h> |
| 15 | #include <linux/kexec.h> | 17 | #include <linux/kexec.h> |
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 74d0bd7e76d7..dca44cf7838e 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c | |||
| @@ -32,8 +32,6 @@ | |||
| 32 | 32 | ||
| 33 | #include "ima.h" | 33 | #include "ima.h" |
| 34 | 34 | ||
| 35 | int ima_initialized; | ||
| 36 | |||
| 37 | #ifdef CONFIG_IMA_APPRAISE | 35 | #ifdef CONFIG_IMA_APPRAISE |
| 38 | int ima_appraise = IMA_APPRAISE_ENFORCE; | 36 | int ima_appraise = IMA_APPRAISE_ENFORCE; |
| 39 | #else | 37 | #else |
| @@ -61,14 +59,11 @@ static int __init hash_setup(char *str) | |||
| 61 | goto out; | 59 | goto out; |
| 62 | } | 60 | } |
| 63 | 61 | ||
| 64 | for (i = 0; i < HASH_ALGO__LAST; i++) { | 62 | i = match_string(hash_algo_name, HASH_ALGO__LAST, str); |
| 65 | if (strcmp(str, hash_algo_name[i]) == 0) { | 63 | if (i < 0) |
| 66 | ima_hash_algo = i; | ||
| 67 | break; | ||
| 68 | } | ||
| 69 | } | ||
| 70 | if (i == HASH_ALGO__LAST) | ||
| 71 | return 1; | 64 | return 1; |
| 65 | |||
| 66 | ima_hash_algo = i; | ||
| 72 | out: | 67 | out: |
| 73 | hash_setup_done = 1; | 68 | hash_setup_done = 1; |
| 74 | return 1; | 69 | return 1; |
| @@ -449,6 +444,7 @@ int ima_read_file(struct file *file, enum kernel_read_file_id read_id) | |||
| 449 | 444 | ||
| 450 | static int read_idmap[READING_MAX_ID] = { | 445 | static int read_idmap[READING_MAX_ID] = { |
| 451 | [READING_FIRMWARE] = FIRMWARE_CHECK, | 446 | [READING_FIRMWARE] = FIRMWARE_CHECK, |
| 447 | [READING_FIRMWARE_PREALLOC_BUFFER] = FIRMWARE_CHECK, | ||
| 452 | [READING_MODULE] = MODULE_CHECK, | 448 | [READING_MODULE] = MODULE_CHECK, |
| 453 | [READING_KEXEC_IMAGE] = KEXEC_KERNEL_CHECK, | 449 | [READING_KEXEC_IMAGE] = KEXEC_KERNEL_CHECK, |
| 454 | [READING_KEXEC_INITRAMFS] = KEXEC_INITRAMFS_CHECK, | 450 | [READING_KEXEC_INITRAMFS] = KEXEC_INITRAMFS_CHECK, |
| @@ -517,10 +513,9 @@ static int __init init_ima(void) | |||
| 517 | error = ima_init(); | 513 | error = ima_init(); |
| 518 | } | 514 | } |
| 519 | 515 | ||
| 520 | if (!error) { | 516 | if (!error) |
| 521 | ima_initialized = 1; | ||
| 522 | ima_update_policy_flag(); | 517 | ima_update_policy_flag(); |
| 523 | } | 518 | |
| 524 | return error; | 519 | return error; |
| 525 | } | 520 | } |
| 526 | 521 | ||
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index d89bebf85421..cdcc9a7b4e24 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #define IMA_INMASK 0x0040 | 33 | #define IMA_INMASK 0x0040 |
| 34 | #define IMA_EUID 0x0080 | 34 | #define IMA_EUID 0x0080 |
| 35 | #define IMA_PCR 0x0100 | 35 | #define IMA_PCR 0x0100 |
| 36 | #define IMA_FSNAME 0x0200 | ||
| 36 | 37 | ||
| 37 | #define UNKNOWN 0 | 38 | #define UNKNOWN 0 |
| 38 | #define MEASURE 0x0001 /* same as IMA_MEASURE */ | 39 | #define MEASURE 0x0001 /* same as IMA_MEASURE */ |
| @@ -74,6 +75,7 @@ struct ima_rule_entry { | |||
| 74 | void *args_p; /* audit value */ | 75 | void *args_p; /* audit value */ |
| 75 | int type; /* audit type */ | 76 | int type; /* audit type */ |
| 76 | } lsm[MAX_LSM_RULES]; | 77 | } lsm[MAX_LSM_RULES]; |
| 78 | char *fsname; | ||
| 77 | }; | 79 | }; |
| 78 | 80 | ||
| 79 | /* | 81 | /* |
| @@ -273,6 +275,9 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode, | |||
| 273 | if ((rule->flags & IMA_FSMAGIC) | 275 | if ((rule->flags & IMA_FSMAGIC) |
| 274 | && rule->fsmagic != inode->i_sb->s_magic) | 276 | && rule->fsmagic != inode->i_sb->s_magic) |
| 275 | return false; | 277 | return false; |
| 278 | if ((rule->flags & IMA_FSNAME) | ||
| 279 | && strcmp(rule->fsname, inode->i_sb->s_type->name)) | ||
| 280 | return false; | ||
| 276 | if ((rule->flags & IMA_FSUUID) && | 281 | if ((rule->flags & IMA_FSUUID) && |
| 277 | !uuid_equal(&rule->fsuuid, &inode->i_sb->s_uuid)) | 282 | !uuid_equal(&rule->fsuuid, &inode->i_sb->s_uuid)) |
| 278 | return false; | 283 | return false; |
| @@ -435,6 +440,17 @@ void ima_update_policy_flag(void) | |||
| 435 | ima_policy_flag &= ~IMA_APPRAISE; | 440 | ima_policy_flag &= ~IMA_APPRAISE; |
| 436 | } | 441 | } |
| 437 | 442 | ||
| 443 | static int ima_appraise_flag(enum ima_hooks func) | ||
| 444 | { | ||
| 445 | if (func == MODULE_CHECK) | ||
| 446 | return IMA_APPRAISE_MODULES; | ||
| 447 | else if (func == FIRMWARE_CHECK) | ||
| 448 | return IMA_APPRAISE_FIRMWARE; | ||
| 449 | else if (func == POLICY_CHECK) | ||
| 450 | return IMA_APPRAISE_POLICY; | ||
| 451 | return 0; | ||
| 452 | } | ||
| 453 | |||
| 438 | /** | 454 | /** |
| 439 | * ima_init_policy - initialize the default measure rules. | 455 | * ima_init_policy - initialize the default measure rules. |
| 440 | * | 456 | * |
| @@ -473,9 +489,11 @@ void __init ima_init_policy(void) | |||
| 473 | * Insert the appraise rules requiring file signatures, prior to | 489 | * Insert the appraise rules requiring file signatures, prior to |
| 474 | * any other appraise rules. | 490 | * any other appraise rules. |
| 475 | */ | 491 | */ |
| 476 | for (i = 0; i < secure_boot_entries; i++) | 492 | for (i = 0; i < secure_boot_entries; i++) { |
| 477 | list_add_tail(&secure_boot_rules[i].list, | 493 | list_add_tail(&secure_boot_rules[i].list, &ima_default_rules); |
| 478 | &ima_default_rules); | 494 | temp_ima_appraise |= |
| 495 | ima_appraise_flag(secure_boot_rules[i].func); | ||
| 496 | } | ||
| 479 | 497 | ||
| 480 | for (i = 0; i < appraise_entries; i++) { | 498 | for (i = 0; i < appraise_entries; i++) { |
| 481 | list_add_tail(&default_appraise_rules[i].list, | 499 | list_add_tail(&default_appraise_rules[i].list, |
| @@ -509,22 +527,9 @@ int ima_check_policy(void) | |||
| 509 | */ | 527 | */ |
| 510 | void ima_update_policy(void) | 528 | void ima_update_policy(void) |
| 511 | { | 529 | { |
| 512 | struct list_head *first, *last, *policy; | 530 | struct list_head *policy = &ima_policy_rules; |
| 513 | |||
| 514 | /* append current policy with the new rules */ | ||
| 515 | first = (&ima_temp_rules)->next; | ||
| 516 | last = (&ima_temp_rules)->prev; | ||
| 517 | policy = &ima_policy_rules; | ||
| 518 | |||
| 519 | synchronize_rcu(); | ||
| 520 | 531 | ||
| 521 | last->next = policy; | 532 | list_splice_tail_init_rcu(&ima_temp_rules, policy, synchronize_rcu); |
| 522 | rcu_assign_pointer(list_next_rcu(policy->prev), first); | ||
| 523 | first->prev = policy->prev; | ||
| 524 | policy->prev = last; | ||
| 525 | |||
| 526 | /* prepare for the next policy rules addition */ | ||
| 527 | INIT_LIST_HEAD(&ima_temp_rules); | ||
| 528 | 533 | ||
| 529 | if (ima_rules != policy) { | 534 | if (ima_rules != policy) { |
| 530 | ima_policy_flag = 0; | 535 | ima_policy_flag = 0; |
| @@ -540,7 +545,7 @@ enum { | |||
| 540 | Opt_audit, Opt_hash, Opt_dont_hash, | 545 | Opt_audit, Opt_hash, Opt_dont_hash, |
| 541 | Opt_obj_user, Opt_obj_role, Opt_obj_type, | 546 | Opt_obj_user, Opt_obj_role, Opt_obj_type, |
| 542 | Opt_subj_user, Opt_subj_role, Opt_subj_type, | 547 | Opt_subj_user, Opt_subj_role, Opt_subj_type, |
| 543 | Opt_func, Opt_mask, Opt_fsmagic, | 548 | Opt_func, Opt_mask, Opt_fsmagic, Opt_fsname, |
| 544 | Opt_fsuuid, Opt_uid_eq, Opt_euid_eq, Opt_fowner_eq, | 549 | Opt_fsuuid, Opt_uid_eq, Opt_euid_eq, Opt_fowner_eq, |
| 545 | Opt_uid_gt, Opt_euid_gt, Opt_fowner_gt, | 550 | Opt_uid_gt, Opt_euid_gt, Opt_fowner_gt, |
| 546 | Opt_uid_lt, Opt_euid_lt, Opt_fowner_lt, | 551 | Opt_uid_lt, Opt_euid_lt, Opt_fowner_lt, |
| @@ -565,6 +570,7 @@ static match_table_t policy_tokens = { | |||
| 565 | {Opt_func, "func=%s"}, | 570 | {Opt_func, "func=%s"}, |
| 566 | {Opt_mask, "mask=%s"}, | 571 | {Opt_mask, "mask=%s"}, |
| 567 | {Opt_fsmagic, "fsmagic=%s"}, | 572 | {Opt_fsmagic, "fsmagic=%s"}, |
| 573 | {Opt_fsname, "fsname=%s"}, | ||
| 568 | {Opt_fsuuid, "fsuuid=%s"}, | 574 | {Opt_fsuuid, "fsuuid=%s"}, |
| 569 | {Opt_uid_eq, "uid=%s"}, | 575 | {Opt_uid_eq, "uid=%s"}, |
| 570 | {Opt_euid_eq, "euid=%s"}, | 576 | {Opt_euid_eq, "euid=%s"}, |
| @@ -776,6 +782,17 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) | |||
| 776 | if (!result) | 782 | if (!result) |
| 777 | entry->flags |= IMA_FSMAGIC; | 783 | entry->flags |= IMA_FSMAGIC; |
| 778 | break; | 784 | break; |
| 785 | case Opt_fsname: | ||
| 786 | ima_log_string(ab, "fsname", args[0].from); | ||
| 787 | |||
| 788 | entry->fsname = kstrdup(args[0].from, GFP_KERNEL); | ||
| 789 | if (!entry->fsname) { | ||
| 790 | result = -ENOMEM; | ||
| 791 | break; | ||
| 792 | } | ||
| 793 | result = 0; | ||
| 794 | entry->flags |= IMA_FSNAME; | ||
| 795 | break; | ||
| 779 | case Opt_fsuuid: | 796 | case Opt_fsuuid: |
| 780 | ima_log_string(ab, "fsuuid", args[0].from); | 797 | ima_log_string(ab, "fsuuid", args[0].from); |
| 781 | 798 | ||
| @@ -917,12 +934,9 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) | |||
| 917 | } | 934 | } |
| 918 | if (!result && (entry->action == UNKNOWN)) | 935 | if (!result && (entry->action == UNKNOWN)) |
| 919 | result = -EINVAL; | 936 | result = -EINVAL; |
| 920 | else if (entry->func == MODULE_CHECK) | 937 | else if (entry->action == APPRAISE) |
| 921 | temp_ima_appraise |= IMA_APPRAISE_MODULES; | 938 | temp_ima_appraise |= ima_appraise_flag(entry->func); |
| 922 | else if (entry->func == FIRMWARE_CHECK) | 939 | |
| 923 | temp_ima_appraise |= IMA_APPRAISE_FIRMWARE; | ||
| 924 | else if (entry->func == POLICY_CHECK) | ||
| 925 | temp_ima_appraise |= IMA_APPRAISE_POLICY; | ||
| 926 | audit_log_format(ab, "res=%d", !result); | 940 | audit_log_format(ab, "res=%d", !result); |
| 927 | audit_log_end(ab); | 941 | audit_log_end(ab); |
| 928 | return result; | 942 | return result; |
| @@ -1104,6 +1118,12 @@ int ima_policy_show(struct seq_file *m, void *v) | |||
| 1104 | seq_puts(m, " "); | 1118 | seq_puts(m, " "); |
| 1105 | } | 1119 | } |
| 1106 | 1120 | ||
| 1121 | if (entry->flags & IMA_FSNAME) { | ||
| 1122 | snprintf(tbuf, sizeof(tbuf), "%s", entry->fsname); | ||
| 1123 | seq_printf(m, pt(Opt_fsname), tbuf); | ||
| 1124 | seq_puts(m, " "); | ||
| 1125 | } | ||
| 1126 | |||
| 1107 | if (entry->flags & IMA_PCR) { | 1127 | if (entry->flags & IMA_PCR) { |
| 1108 | snprintf(tbuf, sizeof(tbuf), "%d", entry->pcr); | 1128 | snprintf(tbuf, sizeof(tbuf), "%d", entry->pcr); |
| 1109 | seq_printf(m, pt(Opt_pcr), tbuf); | 1129 | seq_printf(m, pt(Opt_pcr), tbuf); |
diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c index 5afaa53decc5..43752002c222 100644 --- a/security/integrity/ima/ima_template_lib.c +++ b/security/integrity/ima/ima_template_lib.c | |||
| @@ -13,6 +13,8 @@ | |||
| 13 | * Library of supported template fields. | 13 | * Library of supported template fields. |
| 14 | */ | 14 | */ |
| 15 | 15 | ||
| 16 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 17 | |||
| 16 | #include "ima_template_lib.h" | 18 | #include "ima_template_lib.h" |
| 17 | 19 | ||
| 18 | static bool ima_template_hash_algo_allowed(u8 algo) | 20 | static bool ima_template_hash_algo_allowed(u8 algo) |
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index 5e58e02ba8dc..0bb372eed62a 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h | |||
| @@ -143,6 +143,8 @@ int integrity_kernel_read(struct file *file, loff_t offset, | |||
| 143 | #define INTEGRITY_KEYRING_MODULE 2 | 143 | #define INTEGRITY_KEYRING_MODULE 2 |
| 144 | #define INTEGRITY_KEYRING_MAX 3 | 144 | #define INTEGRITY_KEYRING_MAX 3 |
| 145 | 145 | ||
| 146 | extern struct dentry *integrity_dir; | ||
| 147 | |||
| 146 | #ifdef CONFIG_INTEGRITY_SIGNATURE | 148 | #ifdef CONFIG_INTEGRITY_SIGNATURE |
| 147 | 149 | ||
| 148 | int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, | 150 | int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, |
