Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ima: Move IMA-Appraisal to LSM infrastructure

A few additional IMA hooks are needed to reset the cached appraisal
status, causing the file's integrity to be re-evaluated on next access.
Register these IMA-appraisal only functions separately from the rest of IMA
functions, as appraisal is a separate feature not necessarily enabled in
the kernel configuration.

Reuse the same approach as for other IMA functions, move hardcoded calls
from various places in the kernel to the LSM infrastructure. Declare the
functions as static and register them as hook implementations in
init_ima_appraise_lsm(), called by init_ima_lsm().

Also move the inline function ima_inode_remove_acl() from the public ima.h
header to ima_appraise.c.

Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
Reviewed-by: Casey Schaufler <casey@schaufler-ca.com>
Acked-by: Christian Brauner <brauner@kernel.org>
Acked-by: Mimi Zohar <zohar@linux.ibm.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>

authored by

Roberto Sassu and committed by
Paul Moore
84594c9e cd3cec0a

+35 -79
-2
fs/attr.c
··· 17 17 #include <linux/filelock.h> 18 18 #include <linux/security.h> 19 19 #include <linux/evm.h> 20 - #include <linux/ima.h> 21 20 22 21 #include "internal.h" 23 22 ··· 502 503 if (!error) { 503 504 fsnotify_change(dentry, ia_valid); 504 505 security_inode_post_setattr(idmap, dentry, ia_valid); 505 - ima_inode_post_setattr(idmap, dentry, ia_valid); 506 506 evm_inode_post_setattr(idmap, dentry, ia_valid); 507 507 } 508 508
-55
include/linux/ima.h
··· 92 92 93 93 #ifdef CONFIG_IMA_APPRAISE 94 94 extern bool is_ima_appraise_enabled(void); 95 - extern void ima_inode_post_setattr(struct mnt_idmap *idmap, 96 - struct dentry *dentry, int ia_valid); 97 - extern int ima_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, 98 - const char *xattr_name, const void *xattr_value, 99 - size_t xattr_value_len, int flags); 100 - extern int ima_inode_set_acl(struct mnt_idmap *idmap, 101 - struct dentry *dentry, const char *acl_name, 102 - struct posix_acl *kacl); 103 - static inline int ima_inode_remove_acl(struct mnt_idmap *idmap, 104 - struct dentry *dentry, 105 - const char *acl_name) 106 - { 107 - return ima_inode_set_acl(idmap, dentry, acl_name, NULL); 108 - } 109 - 110 - extern int ima_inode_removexattr(struct mnt_idmap *idmap, struct dentry *dentry, 111 - const char *xattr_name); 112 95 #else 113 96 static inline bool is_ima_appraise_enabled(void) 114 - { 115 - return 0; 116 - } 117 - 118 - static inline void ima_inode_post_setattr(struct mnt_idmap *idmap, 119 - struct dentry *dentry, int ia_valid) 120 - { 121 - return; 122 - } 123 - 124 - static inline int ima_inode_setxattr(struct mnt_idmap *idmap, 125 - struct dentry *dentry, 126 - const char *xattr_name, 127 - const void *xattr_value, 128 - size_t xattr_value_len, 129 - int flags) 130 - { 131 - return 0; 132 - } 133 - 134 - static inline int ima_inode_set_acl(struct mnt_idmap *idmap, 135 - struct dentry *dentry, const char *acl_name, 136 - struct posix_acl *kacl) 137 - { 138 - 139 - return 0; 140 - } 141 - 142 - static inline int ima_inode_removexattr(struct mnt_idmap *idmap, 143 - struct dentry *dentry, 144 - const char *xattr_name) 145 - { 146 - return 0; 147 - } 148 - 149 - static inline int ima_inode_remove_acl(struct mnt_idmap *idmap, 150 - struct dentry *dentry, 151 - const char *acl_name) 152 97 { 153 98 return 0; 154 99 }
+5
security/integrity/ima/ima.h
··· 334 334 int xattr_len); 335 335 int ima_read_xattr(struct dentry *dentry, 336 336 struct evm_ima_xattr_data **xattr_value, int xattr_len); 337 + void __init init_ima_appraise_lsm(const struct lsm_id *lsmid); 337 338 338 339 #else 339 340 static inline int ima_check_blacklist(struct integrity_iint_cache *iint, ··· 384 383 int xattr_len) 385 384 { 386 385 return 0; 386 + } 387 + 388 + static inline void __init init_ima_appraise_lsm(const struct lsm_id *lsmid) 389 + { 387 390 } 388 391 389 392 #endif /* CONFIG_IMA_APPRAISE */
+29 -9
security/integrity/ima/ima_appraise.c
··· 636 636 * This function is called from notify_change(), which expects the caller 637 637 * to lock the inode's i_mutex. 638 638 */ 639 - void ima_inode_post_setattr(struct mnt_idmap *idmap, 640 - struct dentry *dentry, int ia_valid) 639 + static void ima_inode_post_setattr(struct mnt_idmap *idmap, 640 + struct dentry *dentry, int ia_valid) 641 641 { 642 642 struct inode *inode = d_backing_inode(dentry); 643 643 struct integrity_iint_cache *iint; ··· 750 750 return -EACCES; 751 751 } 752 752 753 - int ima_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, 754 - const char *xattr_name, const void *xattr_value, 755 - size_t xattr_value_len, int flags) 753 + static int ima_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, 754 + const char *xattr_name, const void *xattr_value, 755 + size_t xattr_value_len, int flags) 756 756 { 757 757 const struct evm_ima_xattr_data *xvalue = xattr_value; 758 758 int digsig = 0; ··· 781 781 return result; 782 782 } 783 783 784 - int ima_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, 785 - const char *acl_name, struct posix_acl *kacl) 784 + static int ima_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, 785 + const char *acl_name, struct posix_acl *kacl) 786 786 { 787 787 if (evm_revalidate_status(acl_name)) 788 788 ima_reset_appraise_flags(d_backing_inode(dentry), 0); ··· 790 790 return 0; 791 791 } 792 792 793 - int ima_inode_removexattr(struct mnt_idmap *idmap, struct dentry *dentry, 794 - const char *xattr_name) 793 + static int ima_inode_removexattr(struct mnt_idmap *idmap, struct dentry *dentry, 794 + const char *xattr_name) 795 795 { 796 796 int result; 797 797 ··· 802 802 result = 0; 803 803 } 804 804 return result; 805 + } 806 + 807 + static int ima_inode_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry, 808 + const char *acl_name) 809 + { 810 + return ima_inode_set_acl(idmap, dentry, acl_name, NULL); 811 + } 812 + 813 + static struct security_hook_list ima_appraise_hooks[] __ro_after_init = { 814 + LSM_HOOK_INIT(inode_post_setattr, ima_inode_post_setattr), 815 + LSM_HOOK_INIT(inode_setxattr, ima_inode_setxattr), 816 + LSM_HOOK_INIT(inode_set_acl, ima_inode_set_acl), 817 + LSM_HOOK_INIT(inode_removexattr, ima_inode_removexattr), 818 + LSM_HOOK_INIT(inode_remove_acl, ima_inode_remove_acl), 819 + }; 820 + 821 + void __init init_ima_appraise_lsm(const struct lsm_id *lsmid) 822 + { 823 + security_add_hooks(ima_appraise_hooks, ARRAY_SIZE(ima_appraise_hooks), 824 + lsmid); 805 825 }
+1
security/integrity/ima/ima_main.c
··· 1182 1182 static int __init init_ima_lsm(void) 1183 1183 { 1184 1184 security_add_hooks(ima_hooks, ARRAY_SIZE(ima_hooks), &ima_lsmid); 1185 + init_ima_appraise_lsm(&ima_lsmid); 1185 1186 return 0; 1186 1187 } 1187 1188
-13
security/security.c
··· 20 20 #include <linux/kernel_read_file.h> 21 21 #include <linux/lsm_hooks.h> 22 22 #include <linux/integrity.h> 23 - #include <linux/ima.h> 24 23 #include <linux/evm.h> 25 24 #include <linux/fsnotify.h> 26 25 #include <linux/mman.h> ··· 2309 2310 ret = cap_inode_setxattr(dentry, name, value, size, flags); 2310 2311 if (ret) 2311 2312 return ret; 2312 - ret = ima_inode_setxattr(idmap, dentry, name, value, size, flags); 2313 - if (ret) 2314 - return ret; 2315 2313 return evm_inode_setxattr(idmap, dentry, name, value, size, flags); 2316 2314 } 2317 2315 ··· 2334 2338 return 0; 2335 2339 ret = call_int_hook(inode_set_acl, 0, idmap, dentry, acl_name, 2336 2340 kacl); 2337 - if (ret) 2338 - return ret; 2339 - ret = ima_inode_set_acl(idmap, dentry, acl_name, kacl); 2340 2341 if (ret) 2341 2342 return ret; 2342 2343 return evm_inode_set_acl(idmap, dentry, acl_name, kacl); ··· 2394 2401 if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) 2395 2402 return 0; 2396 2403 ret = call_int_hook(inode_remove_acl, 0, idmap, dentry, acl_name); 2397 - if (ret) 2398 - return ret; 2399 - ret = ima_inode_remove_acl(idmap, dentry, acl_name); 2400 2404 if (ret) 2401 2405 return ret; 2402 2406 return evm_inode_remove_acl(idmap, dentry, acl_name); ··· 2493 2503 ret = call_int_hook(inode_removexattr, 1, idmap, dentry, name); 2494 2504 if (ret == 1) 2495 2505 ret = cap_inode_removexattr(idmap, dentry, name); 2496 - if (ret) 2497 - return ret; 2498 - ret = ima_inode_removexattr(idmap, dentry, name); 2499 2506 if (ret) 2500 2507 return ret; 2501 2508 return evm_inode_removexattr(idmap, dentry, name);