diff options
-rw-r--r-- | MAINTAINERS | 2 | ||||
-rw-r--r-- | crypto/asymmetric_keys/signature.c | 1 | ||||
-rw-r--r-- | fs/namei.c | 2 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 2 | ||||
-rw-r--r-- | include/linux/ima.h | 4 | ||||
-rw-r--r-- | include/linux/security.h | 2 | ||||
-rw-r--r-- | security/integrity/Kconfig | 46 | ||||
-rw-r--r-- | security/integrity/Makefile | 6 | ||||
-rw-r--r-- | security/integrity/digsig_asymmetric.c | 5 | ||||
-rw-r--r-- | security/integrity/evm/Kconfig | 8 | ||||
-rw-r--r-- | security/integrity/evm/evm_main.c | 17 | ||||
-rw-r--r-- | security/integrity/ima/Kconfig | 2 | ||||
-rw-r--r-- | security/integrity/ima/ima.h | 15 | ||||
-rw-r--r-- | security/integrity/ima/ima_api.c | 5 | ||||
-rw-r--r-- | security/integrity/ima/ima_appraise.c | 11 | ||||
-rw-r--r-- | security/integrity/ima/ima_crypto.c | 20 | ||||
-rw-r--r-- | security/integrity/ima/ima_main.c | 52 | ||||
-rw-r--r-- | security/integrity/ima/ima_template.c | 30 | ||||
-rw-r--r-- | security/integrity/integrity.h | 2 |
19 files changed, 109 insertions, 123 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 55762cba8516..992335ca0b2c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -7955,6 +7955,8 @@ F: drivers/mmc/host/sdhci-pltfm.[ch] | |||
7955 | 7955 | ||
7956 | SECURE COMPUTING | 7956 | SECURE COMPUTING |
7957 | M: Kees Cook <keescook@chromium.org> | 7957 | M: Kees Cook <keescook@chromium.org> |
7958 | R: Andy Lutomirski <luto@amacapital.net> | ||
7959 | R: Will Drewry <wad@chromium.org> | ||
7958 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git seccomp | 7960 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git seccomp |
7959 | S: Supported | 7961 | S: Supported |
7960 | F: kernel/seccomp.c | 7962 | F: kernel/seccomp.c |
diff --git a/crypto/asymmetric_keys/signature.c b/crypto/asymmetric_keys/signature.c index 50b3f880b4ff..7525fd183574 100644 --- a/crypto/asymmetric_keys/signature.c +++ b/crypto/asymmetric_keys/signature.c | |||
@@ -11,6 +11,7 @@ | |||
11 | * 2 of the Licence, or (at your option) any later version. | 11 | * 2 of the Licence, or (at your option) any later version. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #define pr_fmt(fmt) "SIG: "fmt | ||
14 | #include <keys/asymmetric-subtype.h> | 15 | #include <keys/asymmetric-subtype.h> |
15 | #include <linux/module.h> | 16 | #include <linux/module.h> |
16 | #include <linux/err.h> | 17 | #include <linux/err.h> |
diff --git a/fs/namei.c b/fs/namei.c index 985c6f368485..005771f97189 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -3058,7 +3058,7 @@ opened: | |||
3058 | error = open_check_o_direct(file); | 3058 | error = open_check_o_direct(file); |
3059 | if (error) | 3059 | if (error) |
3060 | goto exit_fput; | 3060 | goto exit_fput; |
3061 | error = ima_file_check(file, op->acc_mode); | 3061 | error = ima_file_check(file, op->acc_mode, *opened); |
3062 | if (error) | 3062 | if (error) |
3063 | goto exit_fput; | 3063 | goto exit_fput; |
3064 | 3064 | ||
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 140c496f612c..d49c778faecb 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -709,7 +709,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, | |||
709 | host_err = PTR_ERR(*filp); | 709 | host_err = PTR_ERR(*filp); |
710 | *filp = NULL; | 710 | *filp = NULL; |
711 | } else { | 711 | } else { |
712 | host_err = ima_file_check(*filp, may_flags); | 712 | host_err = ima_file_check(*filp, may_flags, 0); |
713 | 713 | ||
714 | if (may_flags & NFSD_MAY_64BIT_COOKIE) | 714 | if (may_flags & NFSD_MAY_64BIT_COOKIE) |
715 | (*filp)->f_mode |= FMODE_64BITHASH; | 715 | (*filp)->f_mode |= FMODE_64BITHASH; |
diff --git a/include/linux/ima.h b/include/linux/ima.h index 7cf5e9b32550..120ccc53fcb7 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h | |||
@@ -15,7 +15,7 @@ struct linux_binprm; | |||
15 | 15 | ||
16 | #ifdef CONFIG_IMA | 16 | #ifdef CONFIG_IMA |
17 | extern int ima_bprm_check(struct linux_binprm *bprm); | 17 | extern int ima_bprm_check(struct linux_binprm *bprm); |
18 | extern int ima_file_check(struct file *file, int mask); | 18 | extern int ima_file_check(struct file *file, int mask, int opened); |
19 | extern void ima_file_free(struct file *file); | 19 | extern void ima_file_free(struct file *file); |
20 | extern int ima_file_mmap(struct file *file, unsigned long prot); | 20 | extern int ima_file_mmap(struct file *file, unsigned long prot); |
21 | extern int ima_module_check(struct file *file); | 21 | extern int ima_module_check(struct file *file); |
@@ -27,7 +27,7 @@ static inline int ima_bprm_check(struct linux_binprm *bprm) | |||
27 | return 0; | 27 | return 0; |
28 | } | 28 | } |
29 | 29 | ||
30 | static inline int ima_file_check(struct file *file, int mask) | 30 | static inline int ima_file_check(struct file *file, int mask, int opened) |
31 | { | 31 | { |
32 | return 0; | 32 | return 0; |
33 | } | 33 | } |
diff --git a/include/linux/security.h b/include/linux/security.h index 623f90e5f38d..3b3aeb1b74cb 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
@@ -2108,7 +2108,7 @@ static inline int security_dentry_init_security(struct dentry *dentry, | |||
2108 | static inline int security_inode_init_security(struct inode *inode, | 2108 | static inline int security_inode_init_security(struct inode *inode, |
2109 | struct inode *dir, | 2109 | struct inode *dir, |
2110 | const struct qstr *qstr, | 2110 | const struct qstr *qstr, |
2111 | const initxattrs initxattrs, | 2111 | const initxattrs xattrs, |
2112 | void *fs_data) | 2112 | void *fs_data) |
2113 | { | 2113 | { |
2114 | return 0; | 2114 | return 0; |
diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig index 245c6d92065b..b76235ae4786 100644 --- a/security/integrity/Kconfig +++ b/security/integrity/Kconfig | |||
@@ -1,11 +1,23 @@ | |||
1 | # | 1 | # |
2 | config INTEGRITY | 2 | config INTEGRITY |
3 | def_bool y | 3 | bool "Integrity subsystem" |
4 | depends on IMA || EVM | 4 | depends on SECURITY |
5 | default y | ||
6 | help | ||
7 | This option enables the integrity subsystem, which is comprised | ||
8 | of a number of different components including the Integrity | ||
9 | Measurement Architecture (IMA), Extended Verification Module | ||
10 | (EVM), IMA-appraisal extension, digital signature verification | ||
11 | extension and audit measurement log support. | ||
12 | |||
13 | Each of these components can be enabled/disabled separately. | ||
14 | Refer to the individual components for additional details. | ||
15 | |||
16 | if INTEGRITY | ||
5 | 17 | ||
6 | config INTEGRITY_SIGNATURE | 18 | config INTEGRITY_SIGNATURE |
7 | boolean "Digital signature verification using multiple keyrings" | 19 | boolean "Digital signature verification using multiple keyrings" |
8 | depends on INTEGRITY && KEYS | 20 | depends on KEYS |
9 | default n | 21 | default n |
10 | select SIGNATURE | 22 | select SIGNATURE |
11 | help | 23 | help |
@@ -17,9 +29,21 @@ config INTEGRITY_SIGNATURE | |||
17 | This is useful for evm and module keyrings, when keys are | 29 | This is useful for evm and module keyrings, when keys are |
18 | usually only added from initramfs. | 30 | usually only added from initramfs. |
19 | 31 | ||
32 | config INTEGRITY_ASYMMETRIC_KEYS | ||
33 | boolean "Enable asymmetric keys support" | ||
34 | depends on INTEGRITY_SIGNATURE | ||
35 | default n | ||
36 | select ASYMMETRIC_KEY_TYPE | ||
37 | select ASYMMETRIC_PUBLIC_KEY_SUBTYPE | ||
38 | select PUBLIC_KEY_ALGO_RSA | ||
39 | select X509_CERTIFICATE_PARSER | ||
40 | help | ||
41 | This option enables digital signature verification using | ||
42 | asymmetric keys. | ||
43 | |||
20 | config INTEGRITY_AUDIT | 44 | config INTEGRITY_AUDIT |
21 | bool "Enables integrity auditing support " | 45 | bool "Enables integrity auditing support " |
22 | depends on INTEGRITY && AUDIT | 46 | depends on AUDIT |
23 | default y | 47 | default y |
24 | help | 48 | help |
25 | In addition to enabling integrity auditing support, this | 49 | In addition to enabling integrity auditing support, this |
@@ -32,17 +56,7 @@ config INTEGRITY_AUDIT | |||
32 | be enabled by specifying 'integrity_audit=1' on the kernel | 56 | be enabled by specifying 'integrity_audit=1' on the kernel |
33 | command line. | 57 | command line. |
34 | 58 | ||
35 | config INTEGRITY_ASYMMETRIC_KEYS | ||
36 | boolean "Enable asymmetric keys support" | ||
37 | depends on INTEGRITY_SIGNATURE | ||
38 | default n | ||
39 | select ASYMMETRIC_KEY_TYPE | ||
40 | select ASYMMETRIC_PUBLIC_KEY_SUBTYPE | ||
41 | select PUBLIC_KEY_ALGO_RSA | ||
42 | select X509_CERTIFICATE_PARSER | ||
43 | help | ||
44 | This option enables digital signature verification using | ||
45 | asymmetric keys. | ||
46 | |||
47 | source security/integrity/ima/Kconfig | 59 | source security/integrity/ima/Kconfig |
48 | source security/integrity/evm/Kconfig | 60 | source security/integrity/evm/Kconfig |
61 | |||
62 | endif # if INTEGRITY | ||
diff --git a/security/integrity/Makefile b/security/integrity/Makefile index 0793f4811cb7..8d1f4bf51087 100644 --- a/security/integrity/Makefile +++ b/security/integrity/Makefile | |||
@@ -3,11 +3,11 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_INTEGRITY) += integrity.o | 5 | obj-$(CONFIG_INTEGRITY) += integrity.o |
6 | obj-$(CONFIG_INTEGRITY_AUDIT) += integrity_audit.o | ||
7 | obj-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o | ||
8 | obj-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o | ||
9 | 6 | ||
10 | integrity-y := iint.o | 7 | integrity-y := iint.o |
8 | integrity-$(CONFIG_INTEGRITY_AUDIT) += integrity_audit.o | ||
9 | integrity-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o | ||
10 | integrity-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o | ||
11 | 11 | ||
12 | subdir-$(CONFIG_IMA) += ima | 12 | subdir-$(CONFIG_IMA) += ima |
13 | obj-$(CONFIG_IMA) += ima/ | 13 | obj-$(CONFIG_IMA) += ima/ |
diff --git a/security/integrity/digsig_asymmetric.c b/security/integrity/digsig_asymmetric.c index 9eae4809006b..37e0d98517a8 100644 --- a/security/integrity/digsig_asymmetric.c +++ b/security/integrity/digsig_asymmetric.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
14 | 14 | ||
15 | #include <linux/err.h> | 15 | #include <linux/err.h> |
16 | #include <linux/ratelimit.h> | ||
16 | #include <linux/key-type.h> | 17 | #include <linux/key-type.h> |
17 | #include <crypto/public_key.h> | 18 | #include <crypto/public_key.h> |
18 | #include <keys/asymmetric-type.h> | 19 | #include <keys/asymmetric-type.h> |
@@ -45,8 +46,8 @@ static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid) | |||
45 | } | 46 | } |
46 | 47 | ||
47 | if (IS_ERR(key)) { | 48 | if (IS_ERR(key)) { |
48 | pr_warn("Request for unknown key '%s' err %ld\n", | 49 | pr_err_ratelimited("Request for unknown key '%s' err %ld\n", |
49 | name, PTR_ERR(key)); | 50 | name, PTR_ERR(key)); |
50 | switch (PTR_ERR(key)) { | 51 | switch (PTR_ERR(key)) { |
51 | /* Hide some search errors */ | 52 | /* Hide some search errors */ |
52 | case -EACCES: | 53 | case -EACCES: |
diff --git a/security/integrity/evm/Kconfig b/security/integrity/evm/Kconfig index d606f3d12d6b..df586fa00ef1 100644 --- a/security/integrity/evm/Kconfig +++ b/security/integrity/evm/Kconfig | |||
@@ -1,6 +1,5 @@ | |||
1 | config EVM | 1 | config EVM |
2 | boolean "EVM support" | 2 | boolean "EVM support" |
3 | depends on SECURITY | ||
4 | select KEYS | 3 | select KEYS |
5 | select ENCRYPTED_KEYS | 4 | select ENCRYPTED_KEYS |
6 | select CRYPTO_HMAC | 5 | select CRYPTO_HMAC |
@@ -12,10 +11,6 @@ config EVM | |||
12 | 11 | ||
13 | If you are unsure how to answer this question, answer N. | 12 | If you are unsure how to answer this question, answer N. |
14 | 13 | ||
15 | if EVM | ||
16 | |||
17 | menu "EVM options" | ||
18 | |||
19 | config EVM_ATTR_FSUUID | 14 | config EVM_ATTR_FSUUID |
20 | bool "FSUUID (version 2)" | 15 | bool "FSUUID (version 2)" |
21 | default y | 16 | default y |
@@ -47,6 +42,3 @@ config EVM_EXTRA_SMACK_XATTRS | |||
47 | additional info to the calculation, requires existing EVM | 42 | additional info to the calculation, requires existing EVM |
48 | labeled file systems to be relabeled. | 43 | labeled file systems to be relabeled. |
49 | 44 | ||
50 | endmenu | ||
51 | |||
52 | endif | ||
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index 3bcb80df4d01..9685af330de5 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c | |||
@@ -126,14 +126,15 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry, | |||
126 | rc = vfs_getxattr_alloc(dentry, XATTR_NAME_EVM, (char **)&xattr_data, 0, | 126 | rc = vfs_getxattr_alloc(dentry, XATTR_NAME_EVM, (char **)&xattr_data, 0, |
127 | GFP_NOFS); | 127 | GFP_NOFS); |
128 | if (rc <= 0) { | 128 | if (rc <= 0) { |
129 | if (rc == 0) | 129 | evm_status = INTEGRITY_FAIL; |
130 | evm_status = INTEGRITY_FAIL; /* empty */ | 130 | if (rc == -ENODATA) { |
131 | else if (rc == -ENODATA) { | ||
132 | rc = evm_find_protected_xattrs(dentry); | 131 | rc = evm_find_protected_xattrs(dentry); |
133 | if (rc > 0) | 132 | if (rc > 0) |
134 | evm_status = INTEGRITY_NOLABEL; | 133 | evm_status = INTEGRITY_NOLABEL; |
135 | else if (rc == 0) | 134 | else if (rc == 0) |
136 | evm_status = INTEGRITY_NOXATTRS; /* new file */ | 135 | evm_status = INTEGRITY_NOXATTRS; /* new file */ |
136 | } else if (rc == -EOPNOTSUPP) { | ||
137 | evm_status = INTEGRITY_UNKNOWN; | ||
137 | } | 138 | } |
138 | goto out; | 139 | goto out; |
139 | } | 140 | } |
@@ -284,6 +285,13 @@ static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name, | |||
284 | goto out; | 285 | goto out; |
285 | } | 286 | } |
286 | evm_status = evm_verify_current_integrity(dentry); | 287 | evm_status = evm_verify_current_integrity(dentry); |
288 | if (evm_status == INTEGRITY_NOXATTRS) { | ||
289 | struct integrity_iint_cache *iint; | ||
290 | |||
291 | iint = integrity_iint_find(dentry->d_inode); | ||
292 | if (iint && (iint->flags & IMA_NEW_FILE)) | ||
293 | return 0; | ||
294 | } | ||
287 | out: | 295 | out: |
288 | if (evm_status != INTEGRITY_PASS) | 296 | if (evm_status != INTEGRITY_PASS) |
289 | integrity_audit_msg(AUDIT_INTEGRITY_METADATA, dentry->d_inode, | 297 | integrity_audit_msg(AUDIT_INTEGRITY_METADATA, dentry->d_inode, |
@@ -352,7 +360,6 @@ void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name, | |||
352 | return; | 360 | return; |
353 | 361 | ||
354 | evm_update_evmxattr(dentry, xattr_name, xattr_value, xattr_value_len); | 362 | evm_update_evmxattr(dentry, xattr_name, xattr_value, xattr_value_len); |
355 | return; | ||
356 | } | 363 | } |
357 | 364 | ||
358 | /** | 365 | /** |
@@ -372,7 +379,6 @@ void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name) | |||
372 | mutex_lock(&inode->i_mutex); | 379 | mutex_lock(&inode->i_mutex); |
373 | evm_update_evmxattr(dentry, xattr_name, NULL, 0); | 380 | evm_update_evmxattr(dentry, xattr_name, NULL, 0); |
374 | mutex_unlock(&inode->i_mutex); | 381 | mutex_unlock(&inode->i_mutex); |
375 | return; | ||
376 | } | 382 | } |
377 | 383 | ||
378 | /** | 384 | /** |
@@ -414,7 +420,6 @@ void evm_inode_post_setattr(struct dentry *dentry, int ia_valid) | |||
414 | 420 | ||
415 | if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) | 421 | if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) |
416 | evm_update_evmxattr(dentry, NULL, NULL, 0); | 422 | evm_update_evmxattr(dentry, NULL, NULL, 0); |
417 | return; | ||
418 | } | 423 | } |
419 | 424 | ||
420 | /* | 425 | /* |
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index 08758fbd496f..e099875643c5 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig | |||
@@ -2,8 +2,6 @@ | |||
2 | # | 2 | # |
3 | config IMA | 3 | config IMA |
4 | bool "Integrity Measurement Architecture(IMA)" | 4 | bool "Integrity Measurement Architecture(IMA)" |
5 | depends on SECURITY | ||
6 | select INTEGRITY | ||
7 | select SECURITYFS | 5 | select SECURITYFS |
8 | select CRYPTO | 6 | select CRYPTO |
9 | select CRYPTO_HMAC | 7 | select CRYPTO_HMAC |
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 57da4bd7ba0c..8e4bb883fc13 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h | |||
@@ -90,10 +90,7 @@ extern struct list_head ima_measurements; /* list of all measurements */ | |||
90 | 90 | ||
91 | /* Internal IMA function definitions */ | 91 | /* Internal IMA function definitions */ |
92 | int ima_init(void); | 92 | int ima_init(void); |
93 | void ima_cleanup(void); | ||
94 | int ima_fs_init(void); | 93 | int ima_fs_init(void); |
95 | void ima_fs_cleanup(void); | ||
96 | int ima_inode_alloc(struct inode *inode); | ||
97 | int ima_add_template_entry(struct ima_template_entry *entry, int violation, | 94 | int ima_add_template_entry(struct ima_template_entry *entry, int violation, |
98 | const char *op, struct inode *inode, | 95 | const char *op, struct inode *inode, |
99 | const unsigned char *filename); | 96 | const unsigned char *filename); |
@@ -110,8 +107,6 @@ void ima_print_digest(struct seq_file *m, u8 *digest, int size); | |||
110 | struct ima_template_desc *ima_template_desc_current(void); | 107 | struct ima_template_desc *ima_template_desc_current(void); |
111 | int ima_init_template(void); | 108 | int ima_init_template(void); |
112 | 109 | ||
113 | int ima_init_template(void); | ||
114 | |||
115 | /* | 110 | /* |
116 | * used to protect h_table and sha_table | 111 | * used to protect h_table and sha_table |
117 | */ | 112 | */ |
@@ -151,12 +146,6 @@ int ima_store_template(struct ima_template_entry *entry, int violation, | |||
151 | void ima_free_template_entry(struct ima_template_entry *entry); | 146 | void ima_free_template_entry(struct ima_template_entry *entry); |
152 | const char *ima_d_path(struct path *path, char **pathbuf); | 147 | const char *ima_d_path(struct path *path, char **pathbuf); |
153 | 148 | ||
154 | /* rbtree tree calls to lookup, insert, delete | ||
155 | * integrity data associated with an inode. | ||
156 | */ | ||
157 | struct integrity_iint_cache *integrity_iint_insert(struct inode *inode); | ||
158 | struct integrity_iint_cache *integrity_iint_find(struct inode *inode); | ||
159 | |||
160 | /* IMA policy related functions */ | 149 | /* IMA policy related functions */ |
161 | enum ima_hooks { FILE_CHECK = 1, MMAP_CHECK, BPRM_CHECK, MODULE_CHECK, FIRMWARE_CHECK, POST_SETATTR }; | 150 | enum ima_hooks { FILE_CHECK = 1, MMAP_CHECK, BPRM_CHECK, MODULE_CHECK, FIRMWARE_CHECK, POST_SETATTR }; |
162 | 151 | ||
@@ -177,7 +166,7 @@ void ima_delete_rules(void); | |||
177 | int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, | 166 | int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, |
178 | struct file *file, const unsigned char *filename, | 167 | struct file *file, const unsigned char *filename, |
179 | struct evm_ima_xattr_data *xattr_value, | 168 | struct evm_ima_xattr_data *xattr_value, |
180 | int xattr_len); | 169 | int xattr_len, int opened); |
181 | int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func); | 170 | int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func); |
182 | void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file); | 171 | void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file); |
183 | enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, | 172 | enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, |
@@ -193,7 +182,7 @@ static inline int ima_appraise_measurement(int func, | |||
193 | struct file *file, | 182 | struct file *file, |
194 | const unsigned char *filename, | 183 | const unsigned char *filename, |
195 | struct evm_ima_xattr_data *xattr_value, | 184 | struct evm_ima_xattr_data *xattr_value, |
196 | int xattr_len) | 185 | int xattr_len, int opened) |
197 | { | 186 | { |
198 | return INTEGRITY_UNKNOWN; | 187 | return INTEGRITY_UNKNOWN; |
199 | } | 188 | } |
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index d9cd5ce14d2b..65c41a968cc1 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c | |||
@@ -330,10 +330,9 @@ const char *ima_d_path(struct path *path, char **pathbuf) | |||
330 | { | 330 | { |
331 | char *pathname = NULL; | 331 | char *pathname = NULL; |
332 | 332 | ||
333 | /* We will allow 11 spaces for ' (deleted)' to be appended */ | 333 | *pathbuf = kmalloc(PATH_MAX, GFP_KERNEL); |
334 | *pathbuf = kmalloc(PATH_MAX + 11, GFP_KERNEL); | ||
335 | if (*pathbuf) { | 334 | if (*pathbuf) { |
336 | pathname = d_path(path, *pathbuf, PATH_MAX + 11); | 335 | pathname = d_absolute_path(path, *pathbuf, PATH_MAX); |
337 | if (IS_ERR(pathname)) { | 336 | if (IS_ERR(pathname)) { |
338 | kfree(*pathbuf); | 337 | kfree(*pathbuf); |
339 | *pathbuf = NULL; | 338 | *pathbuf = NULL; |
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 86bfd5c5df85..013ec3f0e42d 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c | |||
@@ -183,7 +183,7 @@ int ima_read_xattr(struct dentry *dentry, | |||
183 | int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, | 183 | int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, |
184 | struct file *file, const unsigned char *filename, | 184 | struct file *file, const unsigned char *filename, |
185 | struct evm_ima_xattr_data *xattr_value, | 185 | struct evm_ima_xattr_data *xattr_value, |
186 | int xattr_len) | 186 | int xattr_len, int opened) |
187 | { | 187 | { |
188 | static const char op[] = "appraise_data"; | 188 | static const char op[] = "appraise_data"; |
189 | char *cause = "unknown"; | 189 | char *cause = "unknown"; |
@@ -192,8 +192,6 @@ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, | |||
192 | enum integrity_status status = INTEGRITY_UNKNOWN; | 192 | enum integrity_status status = INTEGRITY_UNKNOWN; |
193 | int rc = xattr_len, hash_start = 0; | 193 | int rc = xattr_len, hash_start = 0; |
194 | 194 | ||
195 | if (!ima_appraise) | ||
196 | return 0; | ||
197 | if (!inode->i_op->getxattr) | 195 | if (!inode->i_op->getxattr) |
198 | return INTEGRITY_UNKNOWN; | 196 | return INTEGRITY_UNKNOWN; |
199 | 197 | ||
@@ -202,8 +200,11 @@ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, | |||
202 | goto out; | 200 | goto out; |
203 | 201 | ||
204 | cause = "missing-hash"; | 202 | cause = "missing-hash"; |
205 | status = | 203 | status = INTEGRITY_NOLABEL; |
206 | (inode->i_size == 0) ? INTEGRITY_PASS : INTEGRITY_NOLABEL; | 204 | if (opened & FILE_CREATED) { |
205 | iint->flags |= IMA_NEW_FILE; | ||
206 | status = INTEGRITY_PASS; | ||
207 | } | ||
207 | goto out; | 208 | goto out; |
208 | } | 209 | } |
209 | 210 | ||
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index 0bd732843fe7..d34e7dfc1118 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c | |||
@@ -80,24 +80,24 @@ static int ima_kernel_read(struct file *file, loff_t offset, | |||
80 | { | 80 | { |
81 | mm_segment_t old_fs; | 81 | mm_segment_t old_fs; |
82 | char __user *buf = addr; | 82 | char __user *buf = addr; |
83 | ssize_t ret; | 83 | ssize_t ret = -EINVAL; |
84 | 84 | ||
85 | if (!(file->f_mode & FMODE_READ)) | 85 | if (!(file->f_mode & FMODE_READ)) |
86 | return -EBADF; | 86 | return -EBADF; |
87 | if (!file->f_op->read && !file->f_op->aio_read) | ||
88 | return -EINVAL; | ||
89 | 87 | ||
90 | old_fs = get_fs(); | 88 | old_fs = get_fs(); |
91 | set_fs(get_ds()); | 89 | set_fs(get_ds()); |
92 | if (file->f_op->read) | 90 | if (file->f_op->read) |
93 | ret = file->f_op->read(file, buf, count, &offset); | 91 | ret = file->f_op->read(file, buf, count, &offset); |
94 | else | 92 | else if (file->f_op->aio_read) |
95 | ret = do_sync_read(file, buf, count, &offset); | 93 | ret = do_sync_read(file, buf, count, &offset); |
94 | else if (file->f_op->read_iter) | ||
95 | ret = new_sync_read(file, buf, count, &offset); | ||
96 | set_fs(old_fs); | 96 | set_fs(old_fs); |
97 | return ret; | 97 | return ret; |
98 | } | 98 | } |
99 | 99 | ||
100 | int ima_init_crypto(void) | 100 | int __init ima_init_crypto(void) |
101 | { | 101 | { |
102 | long rc; | 102 | long rc; |
103 | 103 | ||
@@ -116,7 +116,10 @@ static struct crypto_shash *ima_alloc_tfm(enum hash_algo algo) | |||
116 | struct crypto_shash *tfm = ima_shash_tfm; | 116 | struct crypto_shash *tfm = ima_shash_tfm; |
117 | int rc; | 117 | int rc; |
118 | 118 | ||
119 | if (algo != ima_hash_algo && algo < HASH_ALGO__LAST) { | 119 | if (algo < 0 || algo >= HASH_ALGO__LAST) |
120 | algo = ima_hash_algo; | ||
121 | |||
122 | if (algo != ima_hash_algo) { | ||
120 | tfm = crypto_alloc_shash(hash_algo_name[algo], 0, 0); | 123 | tfm = crypto_alloc_shash(hash_algo_name[algo], 0, 0); |
121 | if (IS_ERR(tfm)) { | 124 | if (IS_ERR(tfm)) { |
122 | rc = PTR_ERR(tfm); | 125 | rc = PTR_ERR(tfm); |
@@ -200,7 +203,10 @@ static struct crypto_ahash *ima_alloc_atfm(enum hash_algo algo) | |||
200 | struct crypto_ahash *tfm = ima_ahash_tfm; | 203 | struct crypto_ahash *tfm = ima_ahash_tfm; |
201 | int rc; | 204 | int rc; |
202 | 205 | ||
203 | if ((algo != ima_hash_algo && algo < HASH_ALGO__LAST) || !tfm) { | 206 | if (algo < 0 || algo >= HASH_ALGO__LAST) |
207 | algo = ima_hash_algo; | ||
208 | |||
209 | if (algo != ima_hash_algo || !tfm) { | ||
204 | tfm = crypto_alloc_ahash(hash_algo_name[algo], 0, 0); | 210 | tfm = crypto_alloc_ahash(hash_algo_name[algo], 0, 0); |
205 | if (!IS_ERR(tfm)) { | 211 | if (!IS_ERR(tfm)) { |
206 | if (algo == ima_hash_algo) | 212 | if (algo == ima_hash_algo) |
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 2917f980bf30..673a37e92ba3 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c | |||
@@ -124,11 +124,13 @@ static void ima_check_last_writer(struct integrity_iint_cache *iint, | |||
124 | return; | 124 | return; |
125 | 125 | ||
126 | mutex_lock(&inode->i_mutex); | 126 | mutex_lock(&inode->i_mutex); |
127 | if (atomic_read(&inode->i_writecount) == 1 && | 127 | if (atomic_read(&inode->i_writecount) == 1) { |
128 | iint->version != inode->i_version) { | 128 | if ((iint->version != inode->i_version) || |
129 | iint->flags &= ~IMA_DONE_MASK; | 129 | (iint->flags & IMA_NEW_FILE)) { |
130 | if (iint->flags & IMA_APPRAISE) | 130 | iint->flags &= ~(IMA_DONE_MASK | IMA_NEW_FILE); |
131 | ima_update_xattr(iint, file); | 131 | if (iint->flags & IMA_APPRAISE) |
132 | ima_update_xattr(iint, file); | ||
133 | } | ||
132 | } | 134 | } |
133 | mutex_unlock(&inode->i_mutex); | 135 | mutex_unlock(&inode->i_mutex); |
134 | } | 136 | } |
@@ -154,15 +156,15 @@ void ima_file_free(struct file *file) | |||
154 | ima_check_last_writer(iint, inode, file); | 156 | ima_check_last_writer(iint, inode, file); |
155 | } | 157 | } |
156 | 158 | ||
157 | static int process_measurement(struct file *file, const char *filename, | 159 | static int process_measurement(struct file *file, int mask, int function, |
158 | int mask, int function) | 160 | int opened) |
159 | { | 161 | { |
160 | struct inode *inode = file_inode(file); | 162 | struct inode *inode = file_inode(file); |
161 | struct integrity_iint_cache *iint; | 163 | struct integrity_iint_cache *iint; |
162 | struct ima_template_desc *template_desc; | 164 | struct ima_template_desc *template_desc; |
163 | char *pathbuf = NULL; | 165 | char *pathbuf = NULL; |
164 | const char *pathname = NULL; | 166 | const char *pathname = NULL; |
165 | int rc = -ENOMEM, action, must_appraise, _func; | 167 | int rc = -ENOMEM, action, must_appraise; |
166 | struct evm_ima_xattr_data *xattr_value = NULL, **xattr_ptr = NULL; | 168 | struct evm_ima_xattr_data *xattr_value = NULL, **xattr_ptr = NULL; |
167 | int xattr_len = 0; | 169 | int xattr_len = 0; |
168 | 170 | ||
@@ -180,7 +182,8 @@ static int process_measurement(struct file *file, const char *filename, | |||
180 | must_appraise = action & IMA_APPRAISE; | 182 | must_appraise = action & IMA_APPRAISE; |
181 | 183 | ||
182 | /* Is the appraise rule hook specific? */ | 184 | /* Is the appraise rule hook specific? */ |
183 | _func = (action & IMA_FILE_APPRAISE) ? FILE_CHECK : function; | 185 | if (action & IMA_FILE_APPRAISE) |
186 | function = FILE_CHECK; | ||
184 | 187 | ||
185 | mutex_lock(&inode->i_mutex); | 188 | mutex_lock(&inode->i_mutex); |
186 | 189 | ||
@@ -199,15 +202,13 @@ static int process_measurement(struct file *file, const char *filename, | |||
199 | /* Nothing to do, just return existing appraised status */ | 202 | /* Nothing to do, just return existing appraised status */ |
200 | if (!action) { | 203 | if (!action) { |
201 | if (must_appraise) | 204 | if (must_appraise) |
202 | rc = ima_get_cache_status(iint, _func); | 205 | rc = ima_get_cache_status(iint, function); |
203 | goto out_digsig; | 206 | goto out_digsig; |
204 | } | 207 | } |
205 | 208 | ||
206 | template_desc = ima_template_desc_current(); | 209 | template_desc = ima_template_desc_current(); |
207 | if (strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) == 0) { | 210 | if ((action & IMA_APPRAISE_SUBMASK) || |
208 | if (action & IMA_APPRAISE_SUBMASK) | 211 | strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0) |
209 | xattr_ptr = &xattr_value; | ||
210 | } else | ||
211 | xattr_ptr = &xattr_value; | 212 | xattr_ptr = &xattr_value; |
212 | 213 | ||
213 | rc = ima_collect_measurement(iint, file, xattr_ptr, &xattr_len); | 214 | rc = ima_collect_measurement(iint, file, xattr_ptr, &xattr_len); |
@@ -217,14 +218,14 @@ static int process_measurement(struct file *file, const char *filename, | |||
217 | goto out_digsig; | 218 | goto out_digsig; |
218 | } | 219 | } |
219 | 220 | ||
220 | pathname = filename ?: ima_d_path(&file->f_path, &pathbuf); | 221 | pathname = ima_d_path(&file->f_path, &pathbuf); |
221 | 222 | ||
222 | if (action & IMA_MEASURE) | 223 | if (action & IMA_MEASURE) |
223 | ima_store_measurement(iint, file, pathname, | 224 | ima_store_measurement(iint, file, pathname, |
224 | xattr_value, xattr_len); | 225 | xattr_value, xattr_len); |
225 | if (action & IMA_APPRAISE_SUBMASK) | 226 | if (action & IMA_APPRAISE_SUBMASK) |
226 | rc = ima_appraise_measurement(_func, iint, file, pathname, | 227 | rc = ima_appraise_measurement(function, iint, file, pathname, |
227 | xattr_value, xattr_len); | 228 | xattr_value, xattr_len, opened); |
228 | if (action & IMA_AUDIT) | 229 | if (action & IMA_AUDIT) |
229 | ima_audit_measurement(iint, pathname); | 230 | ima_audit_measurement(iint, pathname); |
230 | kfree(pathbuf); | 231 | kfree(pathbuf); |
@@ -253,7 +254,7 @@ out: | |||
253 | int ima_file_mmap(struct file *file, unsigned long prot) | 254 | int ima_file_mmap(struct file *file, unsigned long prot) |
254 | { | 255 | { |
255 | if (file && (prot & PROT_EXEC)) | 256 | if (file && (prot & PROT_EXEC)) |
256 | return process_measurement(file, NULL, MAY_EXEC, MMAP_CHECK); | 257 | return process_measurement(file, MAY_EXEC, MMAP_CHECK, 0); |
257 | return 0; | 258 | return 0; |
258 | } | 259 | } |
259 | 260 | ||
@@ -272,10 +273,7 @@ int ima_file_mmap(struct file *file, unsigned long prot) | |||
272 | */ | 273 | */ |
273 | int ima_bprm_check(struct linux_binprm *bprm) | 274 | int ima_bprm_check(struct linux_binprm *bprm) |
274 | { | 275 | { |
275 | return process_measurement(bprm->file, | 276 | return process_measurement(bprm->file, MAY_EXEC, BPRM_CHECK, 0); |
276 | (strcmp(bprm->filename, bprm->interp) == 0) ? | ||
277 | bprm->filename : bprm->interp, | ||
278 | MAY_EXEC, BPRM_CHECK); | ||
279 | } | 277 | } |
280 | 278 | ||
281 | /** | 279 | /** |
@@ -288,12 +286,12 @@ int ima_bprm_check(struct linux_binprm *bprm) | |||
288 | * On success return 0. On integrity appraisal error, assuming the file | 286 | * On success return 0. On integrity appraisal error, assuming the file |
289 | * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. | 287 | * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. |
290 | */ | 288 | */ |
291 | int ima_file_check(struct file *file, int mask) | 289 | int ima_file_check(struct file *file, int mask, int opened) |
292 | { | 290 | { |
293 | ima_rdwr_violation_check(file); | 291 | ima_rdwr_violation_check(file); |
294 | return process_measurement(file, NULL, | 292 | return process_measurement(file, |
295 | mask & (MAY_READ | MAY_WRITE | MAY_EXEC), | 293 | mask & (MAY_READ | MAY_WRITE | MAY_EXEC), |
296 | FILE_CHECK); | 294 | FILE_CHECK, opened); |
297 | } | 295 | } |
298 | EXPORT_SYMBOL_GPL(ima_file_check); | 296 | EXPORT_SYMBOL_GPL(ima_file_check); |
299 | 297 | ||
@@ -316,7 +314,7 @@ int ima_module_check(struct file *file) | |||
316 | #endif | 314 | #endif |
317 | return 0; /* We rely on module signature checking */ | 315 | return 0; /* We rely on module signature checking */ |
318 | } | 316 | } |
319 | return process_measurement(file, NULL, MAY_EXEC, MODULE_CHECK); | 317 | return process_measurement(file, MAY_EXEC, MODULE_CHECK, 0); |
320 | } | 318 | } |
321 | 319 | ||
322 | int ima_fw_from_file(struct file *file, char *buf, size_t size) | 320 | int ima_fw_from_file(struct file *file, char *buf, size_t size) |
@@ -327,7 +325,7 @@ int ima_fw_from_file(struct file *file, char *buf, size_t size) | |||
327 | return -EACCES; /* INTEGRITY_UNKNOWN */ | 325 | return -EACCES; /* INTEGRITY_UNKNOWN */ |
328 | return 0; | 326 | return 0; |
329 | } | 327 | } |
330 | return process_measurement(file, NULL, MAY_EXEC, FIRMWARE_CHECK); | 328 | return process_measurement(file, MAY_EXEC, FIRMWARE_CHECK, 0); |
331 | } | 329 | } |
332 | 330 | ||
333 | static int __init init_ima(void) | 331 | static int __init init_ima(void) |
diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c index a076a967ec47..e854862c9337 100644 --- a/security/integrity/ima/ima_template.c +++ b/security/integrity/ima/ima_template.c | |||
@@ -152,24 +152,6 @@ out: | |||
152 | return result; | 152 | return result; |
153 | } | 153 | } |
154 | 154 | ||
155 | static int init_defined_templates(void) | ||
156 | { | ||
157 | int i = 0; | ||
158 | int result = 0; | ||
159 | |||
160 | /* Init defined templates. */ | ||
161 | for (i = 0; i < ARRAY_SIZE(defined_templates); i++) { | ||
162 | struct ima_template_desc *template = &defined_templates[i]; | ||
163 | |||
164 | result = template_desc_init_fields(template->fmt, | ||
165 | &(template->fields), | ||
166 | &(template->num_fields)); | ||
167 | if (result < 0) | ||
168 | return result; | ||
169 | } | ||
170 | return result; | ||
171 | } | ||
172 | |||
173 | struct ima_template_desc *ima_template_desc_current(void) | 155 | struct ima_template_desc *ima_template_desc_current(void) |
174 | { | 156 | { |
175 | if (!ima_template) | 157 | if (!ima_template) |
@@ -178,13 +160,11 @@ struct ima_template_desc *ima_template_desc_current(void) | |||
178 | return ima_template; | 160 | return ima_template; |
179 | } | 161 | } |
180 | 162 | ||
181 | int ima_init_template(void) | 163 | int __init ima_init_template(void) |
182 | { | 164 | { |
183 | int result; | 165 | struct ima_template_desc *template = ima_template_desc_current(); |
184 | |||
185 | result = init_defined_templates(); | ||
186 | if (result < 0) | ||
187 | return result; | ||
188 | 166 | ||
189 | return 0; | 167 | return template_desc_init_fields(template->fmt, |
168 | &(template->fields), | ||
169 | &(template->num_fields)); | ||
190 | } | 170 | } |
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index 19b8e314ca96..c0379d13dbe1 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h | |||
@@ -31,6 +31,7 @@ | |||
31 | #define IMA_DIGSIG 0x01000000 | 31 | #define IMA_DIGSIG 0x01000000 |
32 | #define IMA_DIGSIG_REQUIRED 0x02000000 | 32 | #define IMA_DIGSIG_REQUIRED 0x02000000 |
33 | #define IMA_PERMIT_DIRECTIO 0x04000000 | 33 | #define IMA_PERMIT_DIRECTIO 0x04000000 |
34 | #define IMA_NEW_FILE 0x08000000 | ||
34 | 35 | ||
35 | #define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT | \ | 36 | #define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT | \ |
36 | IMA_APPRAISE_SUBMASK) | 37 | IMA_APPRAISE_SUBMASK) |
@@ -116,7 +117,6 @@ struct integrity_iint_cache { | |||
116 | /* rbtree tree calls to lookup, insert, delete | 117 | /* rbtree tree calls to lookup, insert, delete |
117 | * integrity data associated with an inode. | 118 | * integrity data associated with an inode. |
118 | */ | 119 | */ |
119 | struct integrity_iint_cache *integrity_iint_insert(struct inode *inode); | ||
120 | struct integrity_iint_cache *integrity_iint_find(struct inode *inode); | 120 | struct integrity_iint_cache *integrity_iint_find(struct inode *inode); |
121 | 121 | ||
122 | #define INTEGRITY_KEYRING_EVM 0 | 122 | #define INTEGRITY_KEYRING_EVM 0 |