diff --git a/fs/attr.c b/fs/attr.c index 49d23b5dbab4..960a310581eb 100644 --- a/fs/attr.c +++ b/fs/attr.c @@ -16,8 +16,6 @@ #include #include #include -#include -#include #include "internal.h" @@ -502,8 +500,7 @@ int notify_change(struct mnt_idmap *idmap, struct dentry *dentry, if (!error) { fsnotify_change(dentry, ia_valid); - ima_inode_post_setattr(idmap, dentry); - evm_inode_post_setattr(dentry, ia_valid); + security_inode_post_setattr(idmap, dentry, ia_valid); } return error; diff --git a/fs/file_table.c b/fs/file_table.c index 6925522faa0a..4f03beed4737 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -414,7 +413,7 @@ static void __fput(struct file *file) eventpoll_release(file); locks_remove_file(file); - ima_file_free(file); + security_file_release(file); if (unlikely(file->f_flags & FASYNC)) { if (file->f_op->fasync) file->f_op->fasync(-1, file, 0); diff --git a/fs/namei.c b/fs/namei.c index 97952440277b..ceb9ddf8dfdd 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -3642,7 +3641,7 @@ static int do_open(struct nameidata *nd, if (!error && !(file->f_mode & FMODE_OPENED)) error = vfs_open(&nd->path, file); if (!error) - error = ima_file_check(file, op->acc_mode); + error = security_file_post_open(file, op->acc_mode); if (!error && do_truncate) error = handle_truncate(idmap, file); if (unlikely(error > 0)) { @@ -3705,7 +3704,7 @@ static int vfs_tmpfile(struct mnt_idmap *idmap, inode->i_state |= I_LINKABLE; spin_unlock(&inode->i_lock); } - ima_post_create_tmpfile(idmap, inode); + security_inode_post_create_tmpfile(idmap, inode); return 0; } @@ -4051,8 +4050,6 @@ retry: case 0: case S_IFREG: error = vfs_create(idmap, path.dentry->d_inode, dentry, mode, true); - if (!error) - ima_post_path_mknod(idmap, dentry); break; case S_IFCHR: case S_IFBLK: error = vfs_mknod(idmap, path.dentry->d_inode, @@ -4063,6 +4060,11 @@ retry: dentry, mode, 0); break; } + + if (error) + goto out2; + + security_path_post_mknod(idmap, dentry); out2: done_path_create(&path, dentry); if (retry_estale(error, lookup_flags)) { diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 6a4c506038e0..6a9464262fae 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -895,7 +894,7 @@ __nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, goto out; } - host_err = ima_file_check(file, may_flags); + host_err = security_file_post_open(file, may_flags); if (host_err) { fput(file); goto out; diff --git a/fs/open.c b/fs/open.c index a7d4bb2c725f..ee8460c83c77 100644 --- a/fs/open.c +++ b/fs/open.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include diff --git a/fs/posix_acl.c b/fs/posix_acl.c index 6bf587d1a9b8..3f87297dbfdb 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -1137,7 +1136,7 @@ retry_deleg: error = -EIO; if (!error) { fsnotify_xattr(dentry); - evm_inode_post_set_acl(dentry, acl_name, kacl); + security_inode_post_set_acl(dentry, acl_name, kacl); } out_inode_unlock: @@ -1245,7 +1244,7 @@ retry_deleg: error = -EIO; if (!error) { fsnotify_xattr(dentry); - evm_inode_post_remove_acl(idmap, dentry, acl_name); + security_inode_post_remove_acl(idmap, dentry, acl_name); } out_inode_unlock: diff --git a/fs/xattr.c b/fs/xattr.c index 09d927603433..f8b643f91a98 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -552,11 +551,11 @@ __vfs_removexattr_locked(struct mnt_idmap *idmap, goto out; error = __vfs_removexattr(idmap, dentry, name); + if (error) + return error; - if (!error) { - fsnotify_xattr(dentry); - evm_inode_post_removexattr(dentry, name); - } + fsnotify_xattr(dentry); + security_inode_post_removexattr(dentry, name); out: return error; diff --git a/include/linux/evm.h b/include/linux/evm.h index 36ec884320d9..d48d6da32315 100644 --- a/include/linux/evm.h +++ b/include/linux/evm.h @@ -12,52 +12,12 @@ #include #include -struct integrity_iint_cache; - #ifdef CONFIG_EVM extern int evm_set_key(void *key, size_t keylen); extern enum integrity_status evm_verifyxattr(struct dentry *dentry, const char *xattr_name, void *xattr_value, - size_t xattr_value_len, - struct integrity_iint_cache *iint); -extern int evm_inode_setattr(struct mnt_idmap *idmap, - struct dentry *dentry, struct iattr *attr); -extern void evm_inode_post_setattr(struct dentry *dentry, int ia_valid); -extern int evm_inode_setxattr(struct mnt_idmap *idmap, - struct dentry *dentry, const char *name, - const void *value, size_t size); -extern void evm_inode_post_setxattr(struct dentry *dentry, - const char *xattr_name, - const void *xattr_value, - size_t xattr_value_len); -extern int evm_inode_copy_up_xattr(const char *name); -extern int evm_inode_removexattr(struct mnt_idmap *idmap, - struct dentry *dentry, const char *xattr_name); -extern void evm_inode_post_removexattr(struct dentry *dentry, - const char *xattr_name); -static inline void evm_inode_post_remove_acl(struct mnt_idmap *idmap, - struct dentry *dentry, - const char *acl_name) -{ - evm_inode_post_removexattr(dentry, acl_name); -} -extern int evm_inode_set_acl(struct mnt_idmap *idmap, - struct dentry *dentry, const char *acl_name, - struct posix_acl *kacl); -static inline int evm_inode_remove_acl(struct mnt_idmap *idmap, - struct dentry *dentry, - const char *acl_name) -{ - return evm_inode_set_acl(idmap, dentry, acl_name, NULL); -} -static inline void evm_inode_post_set_acl(struct dentry *dentry, - const char *acl_name, - struct posix_acl *kacl) -{ - return evm_inode_post_setxattr(dentry, acl_name, NULL, 0); -} - + size_t xattr_value_len); int evm_inode_init_security(struct inode *inode, struct inode *dir, const struct qstr *qstr, struct xattr *xattrs, int *xattr_count); @@ -85,85 +45,12 @@ static inline int evm_set_key(void *key, size_t keylen) static inline enum integrity_status evm_verifyxattr(struct dentry *dentry, const char *xattr_name, void *xattr_value, - size_t xattr_value_len, - struct integrity_iint_cache *iint) + size_t xattr_value_len) { return INTEGRITY_UNKNOWN; } #endif -static inline int evm_inode_setattr(struct mnt_idmap *idmap, - struct dentry *dentry, struct iattr *attr) -{ - return 0; -} - -static inline void evm_inode_post_setattr(struct dentry *dentry, int ia_valid) -{ - return; -} - -static inline int evm_inode_setxattr(struct mnt_idmap *idmap, - struct dentry *dentry, const char *name, - const void *value, size_t size) -{ - return 0; -} - -static inline void evm_inode_post_setxattr(struct dentry *dentry, - const char *xattr_name, - const void *xattr_value, - size_t xattr_value_len) -{ - return; -} - -static inline int evm_inode_copy_up_xattr(const char *name) -{ - return 0; -} - -static inline int evm_inode_removexattr(struct mnt_idmap *idmap, - struct dentry *dentry, - const char *xattr_name) -{ - return 0; -} - -static inline void evm_inode_post_removexattr(struct dentry *dentry, - const char *xattr_name) -{ - return; -} - -static inline void evm_inode_post_remove_acl(struct mnt_idmap *idmap, - struct dentry *dentry, - const char *acl_name) -{ - return; -} - -static inline int evm_inode_set_acl(struct mnt_idmap *idmap, - struct dentry *dentry, const char *acl_name, - struct posix_acl *kacl) -{ - return 0; -} - -static inline int evm_inode_remove_acl(struct mnt_idmap *idmap, - struct dentry *dentry, - const char *acl_name) -{ - return 0; -} - -static inline void evm_inode_post_set_acl(struct dentry *dentry, - const char *acl_name, - struct posix_acl *kacl) -{ - return; -} - static inline int evm_inode_init_security(struct inode *inode, struct inode *dir, const struct qstr *qstr, struct xattr *xattrs, diff --git a/include/linux/ima.h b/include/linux/ima.h index 86b57757c7b1..0bae61a15b60 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -16,23 +16,6 @@ struct linux_binprm; #ifdef CONFIG_IMA extern enum hash_algo ima_get_current_hash_algo(void); -extern int ima_bprm_check(struct linux_binprm *bprm); -extern int ima_file_check(struct file *file, int mask); -extern void ima_post_create_tmpfile(struct mnt_idmap *idmap, - struct inode *inode); -extern void ima_file_free(struct file *file); -extern int ima_file_mmap(struct file *file, unsigned long reqprot, - unsigned long prot, unsigned long flags); -extern int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot); -extern int ima_load_data(enum kernel_load_data_id id, bool contents); -extern int ima_post_load_data(char *buf, loff_t size, - enum kernel_load_data_id id, char *description); -extern int ima_read_file(struct file *file, enum kernel_read_file_id id, - bool contents); -extern int ima_post_read_file(struct file *file, void *buf, loff_t size, - enum kernel_read_file_id id); -extern void ima_post_path_mknod(struct mnt_idmap *idmap, - struct dentry *dentry); extern int ima_file_hash(struct file *file, char *buf, size_t buf_size); extern int ima_inode_hash(struct inode *inode, char *buf, size_t buf_size); extern void ima_kexec_cmdline(int kernel_fd, const void *buf, int size); @@ -57,68 +40,6 @@ static inline enum hash_algo ima_get_current_hash_algo(void) return HASH_ALGO__LAST; } -static inline int ima_bprm_check(struct linux_binprm *bprm) -{ - return 0; -} - -static inline int ima_file_check(struct file *file, int mask) -{ - return 0; -} - -static inline void ima_post_create_tmpfile(struct mnt_idmap *idmap, - struct inode *inode) -{ -} - -static inline void ima_file_free(struct file *file) -{ - return; -} - -static inline int ima_file_mmap(struct file *file, unsigned long reqprot, - unsigned long prot, unsigned long flags) -{ - return 0; -} - -static inline int ima_file_mprotect(struct vm_area_struct *vma, - unsigned long prot) -{ - return 0; -} - -static inline int ima_load_data(enum kernel_load_data_id id, bool contents) -{ - return 0; -} - -static inline int ima_post_load_data(char *buf, loff_t size, - enum kernel_load_data_id id, - char *description) -{ - return 0; -} - -static inline int ima_read_file(struct file *file, enum kernel_read_file_id id, - bool contents) -{ - return 0; -} - -static inline int ima_post_read_file(struct file *file, void *buf, loff_t size, - enum kernel_read_file_id id) -{ - return 0; -} - -static inline void ima_post_path_mknod(struct mnt_idmap *idmap, - struct dentry *dentry) -{ - return; -} - static inline int ima_file_hash(struct file *file, char *buf, size_t buf_size) { return -EOPNOTSUPP; @@ -169,76 +90,13 @@ static inline void ima_add_kexec_buffer(struct kimage *image) {} #endif -#ifdef CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS -extern void ima_post_key_create_or_update(struct key *keyring, - struct key *key, - const void *payload, size_t plen, - unsigned long flags, bool create); -#else -static inline void ima_post_key_create_or_update(struct key *keyring, - struct key *key, - const void *payload, - size_t plen, - unsigned long flags, - bool create) {} -#endif /* CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS */ - #ifdef CONFIG_IMA_APPRAISE extern bool is_ima_appraise_enabled(void); -extern void ima_inode_post_setattr(struct mnt_idmap *idmap, - struct dentry *dentry); -extern int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name, - const void *xattr_value, size_t xattr_value_len); -extern int ima_inode_set_acl(struct mnt_idmap *idmap, - struct dentry *dentry, const char *acl_name, - struct posix_acl *kacl); -static inline int ima_inode_remove_acl(struct mnt_idmap *idmap, - struct dentry *dentry, - const char *acl_name) -{ - return ima_inode_set_acl(idmap, dentry, acl_name, NULL); -} -extern int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name); #else static inline bool is_ima_appraise_enabled(void) { return 0; } - -static inline void ima_inode_post_setattr(struct mnt_idmap *idmap, - struct dentry *dentry) -{ - return; -} - -static inline int ima_inode_setxattr(struct dentry *dentry, - const char *xattr_name, - const void *xattr_value, - size_t xattr_value_len) -{ - return 0; -} - -static inline int ima_inode_set_acl(struct mnt_idmap *idmap, - struct dentry *dentry, const char *acl_name, - struct posix_acl *kacl) -{ - - return 0; -} - -static inline int ima_inode_removexattr(struct dentry *dentry, - const char *xattr_name) -{ - return 0; -} - -static inline int ima_inode_remove_acl(struct mnt_idmap *idmap, - struct dentry *dentry, - const char *acl_name) -{ - return 0; -} #endif /* CONFIG_IMA_APPRAISE */ #if defined(CONFIG_IMA_APPRAISE) && defined(CONFIG_INTEGRITY_TRUSTED_KEYRING) diff --git a/include/linux/integrity.h b/include/linux/integrity.h index 2ea0f2f65ab6..459b79683783 100644 --- a/include/linux/integrity.h +++ b/include/linux/integrity.h @@ -19,40 +19,13 @@ enum integrity_status { INTEGRITY_UNKNOWN, }; -/* List of EVM protected security xattrs */ #ifdef CONFIG_INTEGRITY -extern struct integrity_iint_cache *integrity_inode_get(struct inode *inode); -extern void integrity_inode_free(struct inode *inode); extern void __init integrity_load_keys(void); #else -static inline struct integrity_iint_cache * - integrity_inode_get(struct inode *inode) -{ - return NULL; -} - -static inline void integrity_inode_free(struct inode *inode) -{ - return; -} - static inline void integrity_load_keys(void) { } #endif /* CONFIG_INTEGRITY */ -#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS - -extern int integrity_kernel_module_request(char *kmod_name); - -#else - -static inline int integrity_kernel_module_request(char *kmod_name) -{ - return 0; -} - -#endif /* CONFIG_INTEGRITY_ASYMMETRIC_KEYS */ - #endif /* _LINUX_INTEGRITY_H */ diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 642272576582..a8057a3f8de6 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -94,6 +94,8 @@ LSM_HOOK(int, 0, path_mkdir, const struct path *dir, struct dentry *dentry, LSM_HOOK(int, 0, path_rmdir, const struct path *dir, struct dentry *dentry) LSM_HOOK(int, 0, path_mknod, const struct path *dir, struct dentry *dentry, umode_t mode, unsigned int dev) +LSM_HOOK(void, LSM_RET_VOID, path_post_mknod, struct mnt_idmap *idmap, + struct dentry *dentry) LSM_HOOK(int, 0, path_truncate, const struct path *path) LSM_HOOK(int, 0, path_symlink, const struct path *dir, struct dentry *dentry, const char *old_name) @@ -119,6 +121,8 @@ LSM_HOOK(int, 0, inode_init_security_anon, struct inode *inode, const struct qstr *name, const struct inode *context_inode) LSM_HOOK(int, 0, inode_create, struct inode *dir, struct dentry *dentry, umode_t mode) +LSM_HOOK(void, LSM_RET_VOID, inode_post_create_tmpfile, struct mnt_idmap *idmap, + struct inode *inode) LSM_HOOK(int, 0, inode_link, struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) LSM_HOOK(int, 0, inode_unlink, struct inode *dir, struct dentry *dentry) @@ -135,7 +139,10 @@ LSM_HOOK(int, 0, inode_readlink, struct dentry *dentry) LSM_HOOK(int, 0, inode_follow_link, struct dentry *dentry, struct inode *inode, bool rcu) LSM_HOOK(int, 0, inode_permission, struct inode *inode, int mask) -LSM_HOOK(int, 0, inode_setattr, struct dentry *dentry, struct iattr *attr) +LSM_HOOK(int, 0, inode_setattr, struct mnt_idmap *idmap, struct dentry *dentry, + struct iattr *attr) +LSM_HOOK(void, LSM_RET_VOID, inode_post_setattr, struct mnt_idmap *idmap, + struct dentry *dentry, int ia_valid) LSM_HOOK(int, 0, inode_getattr, const struct path *path) LSM_HOOK(int, 0, inode_setxattr, struct mnt_idmap *idmap, struct dentry *dentry, const char *name, const void *value, @@ -146,12 +153,18 @@ LSM_HOOK(int, 0, inode_getxattr, struct dentry *dentry, const char *name) LSM_HOOK(int, 0, inode_listxattr, struct dentry *dentry) LSM_HOOK(int, 0, inode_removexattr, struct mnt_idmap *idmap, struct dentry *dentry, const char *name) +LSM_HOOK(void, LSM_RET_VOID, inode_post_removexattr, struct dentry *dentry, + const char *name) LSM_HOOK(int, 0, inode_set_acl, struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name, struct posix_acl *kacl) +LSM_HOOK(void, LSM_RET_VOID, inode_post_set_acl, struct dentry *dentry, + const char *acl_name, struct posix_acl *kacl) LSM_HOOK(int, 0, inode_get_acl, struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name) LSM_HOOK(int, 0, inode_remove_acl, struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name) +LSM_HOOK(void, LSM_RET_VOID, inode_post_remove_acl, struct mnt_idmap *idmap, + struct dentry *dentry, const char *acl_name) LSM_HOOK(int, 0, inode_need_killpriv, struct dentry *dentry) LSM_HOOK(int, 0, inode_killpriv, struct mnt_idmap *idmap, struct dentry *dentry) @@ -168,6 +181,7 @@ LSM_HOOK(int, 0, kernfs_init_security, struct kernfs_node *kn_dir, struct kernfs_node *kn) LSM_HOOK(int, 0, file_permission, struct file *file, int mask) LSM_HOOK(int, 0, file_alloc_security, struct file *file) +LSM_HOOK(void, LSM_RET_VOID, file_release, struct file *file) LSM_HOOK(void, LSM_RET_VOID, file_free_security, struct file *file) LSM_HOOK(int, 0, file_ioctl, struct file *file, unsigned int cmd, unsigned long arg) @@ -186,6 +200,7 @@ LSM_HOOK(int, 0, file_send_sigiotask, struct task_struct *tsk, struct fown_struct *fown, int sig) LSM_HOOK(int, 0, file_receive, struct file *file) LSM_HOOK(int, 0, file_open, struct file *file) +LSM_HOOK(int, 0, file_post_open, struct file *file, int mask) LSM_HOOK(int, 0, file_truncate, struct file *file) LSM_HOOK(int, 0, task_alloc, struct task_struct *task, unsigned long clone_flags) @@ -390,6 +405,9 @@ LSM_HOOK(void, LSM_RET_VOID, key_free, struct key *key) LSM_HOOK(int, 0, key_permission, key_ref_t key_ref, const struct cred *cred, enum key_need_perm need_perm) LSM_HOOK(int, 0, key_getsecurity, struct key *key, char **buffer) +LSM_HOOK(void, LSM_RET_VOID, key_post_create_or_update, struct key *keyring, + struct key *key, const void *payload, size_t payload_len, + unsigned long flags, bool create) #endif /* CONFIG_KEYS */ #ifdef CONFIG_AUDIT diff --git a/include/linux/security.h b/include/linux/security.h index 15804af54f37..f249f5b9a9d7 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -345,6 +345,8 @@ int security_inode_init_security_anon(struct inode *inode, const struct qstr *name, const struct inode *context_inode); int security_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode); +void security_inode_post_create_tmpfile(struct mnt_idmap *idmap, + struct inode *inode); int security_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry); int security_inode_unlink(struct inode *dir, struct dentry *dentry); @@ -362,6 +364,8 @@ int security_inode_follow_link(struct dentry *dentry, struct inode *inode, int security_inode_permission(struct inode *inode, int mask); int security_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry, struct iattr *attr); +void security_inode_post_setattr(struct mnt_idmap *idmap, struct dentry *dentry, + int ia_valid); int security_inode_getattr(const struct path *path); int security_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, const char *name, @@ -369,16 +373,22 @@ int security_inode_setxattr(struct mnt_idmap *idmap, int security_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name, struct posix_acl *kacl); +void security_inode_post_set_acl(struct dentry *dentry, const char *acl_name, + struct posix_acl *kacl); int security_inode_get_acl(struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name); int security_inode_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name); +void security_inode_post_remove_acl(struct mnt_idmap *idmap, + struct dentry *dentry, + const char *acl_name); void security_inode_post_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags); int security_inode_getxattr(struct dentry *dentry, const char *name); int security_inode_listxattr(struct dentry *dentry); int security_inode_removexattr(struct mnt_idmap *idmap, struct dentry *dentry, const char *name); +void security_inode_post_removexattr(struct dentry *dentry, const char *name); int security_inode_need_killpriv(struct dentry *dentry); int security_inode_killpriv(struct mnt_idmap *idmap, struct dentry *dentry); int security_inode_getsecurity(struct mnt_idmap *idmap, @@ -393,6 +403,7 @@ int security_kernfs_init_security(struct kernfs_node *kn_dir, struct kernfs_node *kn); int security_file_permission(struct file *file, int mask); int security_file_alloc(struct file *file); +void security_file_release(struct file *file); void security_file_free(struct file *file); int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg); int security_file_ioctl_compat(struct file *file, unsigned int cmd, @@ -409,6 +420,7 @@ int security_file_send_sigiotask(struct task_struct *tsk, struct fown_struct *fown, int sig); int security_file_receive(struct file *file); int security_file_open(struct file *file); +int security_file_post_open(struct file *file, int mask); int security_file_truncate(struct file *file); int security_task_alloc(struct task_struct *task, unsigned long clone_flags); void security_task_free(struct task_struct *task); @@ -807,6 +819,10 @@ static inline int security_inode_create(struct inode *dir, return 0; } +static inline void +security_inode_post_create_tmpfile(struct mnt_idmap *idmap, struct inode *inode) +{ } + static inline int security_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) @@ -880,6 +896,11 @@ static inline int security_inode_setattr(struct mnt_idmap *idmap, return 0; } +static inline void +security_inode_post_setattr(struct mnt_idmap *idmap, struct dentry *dentry, + int ia_valid) +{ } + static inline int security_inode_getattr(const struct path *path) { return 0; @@ -900,6 +921,11 @@ static inline int security_inode_set_acl(struct mnt_idmap *idmap, return 0; } +static inline void security_inode_post_set_acl(struct dentry *dentry, + const char *acl_name, + struct posix_acl *kacl) +{ } + static inline int security_inode_get_acl(struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name) @@ -914,6 +940,11 @@ static inline int security_inode_remove_acl(struct mnt_idmap *idmap, return 0; } +static inline void security_inode_post_remove_acl(struct mnt_idmap *idmap, + struct dentry *dentry, + const char *acl_name) +{ } + static inline void security_inode_post_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { } @@ -936,6 +967,10 @@ static inline int security_inode_removexattr(struct mnt_idmap *idmap, return cap_inode_removexattr(idmap, dentry, name); } +static inline void security_inode_post_removexattr(struct dentry *dentry, + const char *name) +{ } + static inline int security_inode_need_killpriv(struct dentry *dentry) { return cap_inode_need_killpriv(dentry); @@ -996,6 +1031,9 @@ static inline int security_file_alloc(struct file *file) return 0; } +static inline void security_file_release(struct file *file) +{ } + static inline void security_file_free(struct file *file) { } @@ -1063,6 +1101,11 @@ static inline int security_file_open(struct file *file) return 0; } +static inline int security_file_post_open(struct file *file, int mask) +{ + return 0; +} + static inline int security_file_truncate(struct file *file) { return 0; @@ -1872,6 +1915,7 @@ int security_path_mkdir(const struct path *dir, struct dentry *dentry, umode_t m int security_path_rmdir(const struct path *dir, struct dentry *dentry); int security_path_mknod(const struct path *dir, struct dentry *dentry, umode_t mode, unsigned int dev); +void security_path_post_mknod(struct mnt_idmap *idmap, struct dentry *dentry); int security_path_truncate(const struct path *path); int security_path_symlink(const struct path *dir, struct dentry *dentry, const char *old_name); @@ -1906,6 +1950,10 @@ static inline int security_path_mknod(const struct path *dir, struct dentry *den return 0; } +static inline void security_path_post_mknod(struct mnt_idmap *idmap, + struct dentry *dentry) +{ } + static inline int security_path_truncate(const struct path *path) { return 0; @@ -1957,6 +2005,9 @@ void security_key_free(struct key *key); int security_key_permission(key_ref_t key_ref, const struct cred *cred, enum key_need_perm need_perm); int security_key_getsecurity(struct key *key, char **_buffer); +void security_key_post_create_or_update(struct key *keyring, struct key *key, + const void *payload, size_t payload_len, + unsigned long flags, bool create); #else @@ -1984,6 +2035,14 @@ static inline int security_key_getsecurity(struct key *key, char **_buffer) return 0; } +static inline void security_key_post_create_or_update(struct key *keyring, + struct key *key, + const void *payload, + size_t payload_len, + unsigned long flags, + bool create) +{ } + #endif #endif /* CONFIG_KEYS */ diff --git a/include/uapi/linux/lsm.h b/include/uapi/linux/lsm.h index f8aef9ade549..33d8c9f4aa6b 100644 --- a/include/uapi/linux/lsm.h +++ b/include/uapi/linux/lsm.h @@ -62,6 +62,8 @@ struct lsm_ctx { #define LSM_ID_LOCKDOWN 108 #define LSM_ID_BPF 109 #define LSM_ID_LANDLOCK 110 +#define LSM_ID_IMA 111 +#define LSM_ID_EVM 112 /* * LSM_ATTR_XXX definitions identify different LSM attributes diff --git a/kernel/cred.c b/kernel/cred.c index c033a201c808..075cfa7c896f 100644 --- a/kernel/cred.c +++ b/kernel/cred.c @@ -606,8 +606,8 @@ int set_cred_ucounts(struct cred *new) void __init cred_init(void) { /* allocate a slab in which we can store credentials */ - cred_jar = kmem_cache_create("cred_jar", sizeof(struct cred), 0, - SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_ACCOUNT, NULL); + cred_jar = KMEM_CACHE(cred, + SLAB_HWCACHE_ALIGN | SLAB_PANIC | SLAB_ACCOUNT); } /** diff --git a/security/integrity/Makefile b/security/integrity/Makefile index d0ffe37dc1d6..92b63039c654 100644 --- a/security/integrity/Makefile +++ b/security/integrity/Makefile @@ -18,5 +18,6 @@ integrity-$(CONFIG_LOAD_IPL_KEYS) += platform_certs/load_ipl_s390.o integrity-$(CONFIG_LOAD_PPC_KEYS) += platform_certs/efi_parser.o \ platform_certs/load_powerpc.o \ platform_certs/keyring_handler.o +# The relative order of the 'ima' and 'evm' LSMs depends on the order below. obj-$(CONFIG_IMA) += ima/ obj-$(CONFIG_EVM) += evm/ diff --git a/security/integrity/digsig_asymmetric.c b/security/integrity/digsig_asymmetric.c index 895f4b9ce8c6..de603cf42ac7 100644 --- a/security/integrity/digsig_asymmetric.c +++ b/security/integrity/digsig_asymmetric.c @@ -132,26 +132,3 @@ out: pr_debug("%s() = %d\n", __func__, ret); return ret; } - -/** - * integrity_kernel_module_request - prevent crypto-pkcs1pad(rsa,*) requests - * @kmod_name: kernel module name - * - * We have situation, when public_key_verify_signature() in case of RSA - * algorithm use alg_name to store internal information in order to - * construct an algorithm on the fly, but crypto_larval_lookup() will try - * to use alg_name in order to load kernel module with same name. - * Since we don't have any real "crypto-pkcs1pad(rsa,*)" kernel modules, - * we are safe to fail such module request from crypto_larval_lookup(). - * - * In this way we prevent modprobe execution during digsig verification - * and avoid possible deadlock if modprobe and/or it's dependencies - * also signed with digsig. - */ -int integrity_kernel_module_request(char *kmod_name) -{ - if (strncmp(kmod_name, "crypto-pkcs1pad(rsa,", 20) == 0) - return -EINVAL; - - return 0; -} diff --git a/security/integrity/evm/Kconfig b/security/integrity/evm/Kconfig index fba9ee359bc9..861b3bacab82 100644 --- a/security/integrity/evm/Kconfig +++ b/security/integrity/evm/Kconfig @@ -6,6 +6,7 @@ config EVM select CRYPTO_HMAC select CRYPTO_SHA1 select CRYPTO_HASH_INFO + select SECURITY_PATH default n help EVM protects a file's security extended attributes against diff --git a/security/integrity/evm/evm.h b/security/integrity/evm/evm.h index 53bd7fec93fa..eb1a2c343bd7 100644 --- a/security/integrity/evm/evm.h +++ b/security/integrity/evm/evm.h @@ -32,6 +32,25 @@ struct xattr_list { bool enabled; }; +#define EVM_NEW_FILE 0x00000001 +#define EVM_IMMUTABLE_DIGSIG 0x00000002 + +/* EVM integrity metadata associated with an inode */ +struct evm_iint_cache { + unsigned long flags; + enum integrity_status evm_status:4; +}; + +extern struct lsm_blob_sizes evm_blob_sizes; + +static inline struct evm_iint_cache *evm_iint_inode(const struct inode *inode) +{ + if (unlikely(!inode->i_security)) + return NULL; + + return inode->i_security + evm_blob_sizes.lbs_inode; +} + extern int evm_initialized; #define EVM_ATTR_FSUUID 0x0001 diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c index b1ffd4cc0b44..7552d49d0725 100644 --- a/security/integrity/evm/evm_crypto.c +++ b/security/integrity/evm/evm_crypto.c @@ -322,10 +322,10 @@ int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name, static int evm_is_immutable(struct dentry *dentry, struct inode *inode) { const struct evm_ima_xattr_data *xattr_data = NULL; - struct integrity_iint_cache *iint; + struct evm_iint_cache *iint; int rc = 0; - iint = integrity_iint_find(inode); + iint = evm_iint_inode(inode); if (iint && (iint->flags & EVM_IMMUTABLE_DIGSIG)) return 1; diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index cc7956d7878b..81dbade5b9b3 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -178,14 +178,14 @@ static int is_unsupported_fs(struct dentry *dentry) static enum integrity_status evm_verify_hmac(struct dentry *dentry, const char *xattr_name, char *xattr_value, - size_t xattr_value_len, - struct integrity_iint_cache *iint) + size_t xattr_value_len) { struct evm_ima_xattr_data *xattr_data = NULL; struct signature_v2_hdr *hdr; enum integrity_status evm_status = INTEGRITY_PASS; struct evm_digest digest; - struct inode *inode; + struct inode *inode = d_backing_inode(dentry); + struct evm_iint_cache *iint = evm_iint_inode(inode); int rc, xattr_len, evm_immutable = 0; if (iint && (iint->evm_status == INTEGRITY_PASS || @@ -254,8 +254,6 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry, (const char *)xattr_data, xattr_len, digest.digest, digest.hdr.length); if (!rc) { - inode = d_backing_inode(dentry); - if (xattr_data->type == EVM_XATTR_PORTABLE_DIGSIG) { if (iint) iint->flags |= EVM_IMMUTABLE_DIGSIG; @@ -403,7 +401,6 @@ int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer, * @xattr_name: requested xattr * @xattr_value: requested xattr value * @xattr_value_len: requested xattr value length - * @iint: inode integrity metadata * * Calculate the HMAC for the given dentry and verify it against the stored * security.evm xattr. For performance, use the xattr value and length @@ -416,8 +413,7 @@ int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer, */ enum integrity_status evm_verifyxattr(struct dentry *dentry, const char *xattr_name, - void *xattr_value, size_t xattr_value_len, - struct integrity_iint_cache *iint) + void *xattr_value, size_t xattr_value_len) { if (!evm_key_loaded() || !evm_protected_xattr(xattr_name)) return INTEGRITY_UNKNOWN; @@ -425,13 +421,8 @@ enum integrity_status evm_verifyxattr(struct dentry *dentry, if (is_unsupported_fs(dentry)) return INTEGRITY_UNKNOWN; - if (!iint) { - iint = integrity_iint_find(d_backing_inode(dentry)); - if (!iint) - return INTEGRITY_UNKNOWN; - } return evm_verify_hmac(dentry, xattr_name, xattr_value, - xattr_value_len, iint); + xattr_value_len); } EXPORT_SYMBOL_GPL(evm_verifyxattr); @@ -448,7 +439,7 @@ static enum integrity_status evm_verify_current_integrity(struct dentry *dentry) if (!evm_key_loaded() || !S_ISREG(inode->i_mode) || evm_fixmode) return INTEGRITY_PASS; - return evm_verify_hmac(dentry, NULL, NULL, 0, NULL); + return evm_verify_hmac(dentry, NULL, NULL, 0); } /* @@ -526,14 +517,14 @@ static int evm_protect_xattr(struct mnt_idmap *idmap, evm_status = evm_verify_current_integrity(dentry); if (evm_status == INTEGRITY_NOXATTRS) { - struct integrity_iint_cache *iint; + struct evm_iint_cache *iint; /* Exception if the HMAC is not going to be calculated. */ if (evm_hmac_disabled()) return 0; - iint = integrity_iint_find(d_backing_inode(dentry)); - if (iint && (iint->flags & IMA_NEW_FILE)) + iint = evm_iint_inode(d_backing_inode(dentry)); + if (iint && (iint->flags & EVM_NEW_FILE)) return 0; /* exception for pseudo filesystems */ @@ -581,6 +572,7 @@ out: * @xattr_name: pointer to the affected extended attribute name * @xattr_value: pointer to the new extended attribute value * @xattr_value_len: pointer to the new extended attribute value length + * @flags: flags to pass into filesystem operations * * Before allowing the 'security.evm' protected xattr to be updated, * verify the existing value is valid. As only the kernel should have @@ -588,9 +580,9 @@ out: * userspace from writing HMAC value. Writing 'security.evm' requires * requires CAP_SYS_ADMIN privileges. */ -int evm_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, - const char *xattr_name, const void *xattr_value, - size_t xattr_value_len) +static int evm_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, + const char *xattr_name, const void *xattr_value, + size_t xattr_value_len, int flags) { const struct evm_ima_xattr_data *xattr_data = xattr_value; @@ -620,8 +612,8 @@ int evm_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, * Removing 'security.evm' requires CAP_SYS_ADMIN privileges and that * the current value is valid. */ -int evm_inode_removexattr(struct mnt_idmap *idmap, - struct dentry *dentry, const char *xattr_name) +static int evm_inode_removexattr(struct mnt_idmap *idmap, struct dentry *dentry, + const char *xattr_name) { /* Policy permits modification of the protected xattrs even though * there's no HMAC key loaded @@ -671,9 +663,11 @@ static inline int evm_inode_set_acl_change(struct mnt_idmap *idmap, * Prevent modifying posix acls causing the EVM HMAC to be re-calculated * and 'security.evm' xattr updated, unless the existing 'security.evm' is * valid. + * + * Return: zero on success, -EPERM on failure. */ -int evm_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, - const char *acl_name, struct posix_acl *kacl) +static int evm_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, + const char *acl_name, struct posix_acl *kacl) { enum integrity_status evm_status; @@ -712,11 +706,29 @@ int evm_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, return -EPERM; } +/** + * evm_inode_remove_acl - Protect the EVM extended attribute from posix acls + * @idmap: idmap of the mount + * @dentry: pointer to the affected dentry + * @acl_name: name of the posix acl + * + * Prevent removing posix acls causing the EVM HMAC to be re-calculated + * and 'security.evm' xattr updated, unless the existing 'security.evm' is + * valid. + * + * Return: zero on success, -EPERM on failure. + */ +static int evm_inode_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry, + const char *acl_name) +{ + return evm_inode_set_acl(idmap, dentry, acl_name, NULL); +} + static void evm_reset_status(struct inode *inode) { - struct integrity_iint_cache *iint; + struct evm_iint_cache *iint; - iint = integrity_iint_find(inode); + iint = evm_iint_inode(inode); if (iint) iint->evm_status = INTEGRITY_UNKNOWN; } @@ -752,6 +764,7 @@ bool evm_revalidate_status(const char *xattr_name) * @xattr_name: pointer to the affected extended attribute name * @xattr_value: pointer to the new extended attribute value * @xattr_value_len: pointer to the new extended attribute value length + * @flags: flags to pass into filesystem operations * * Update the HMAC stored in 'security.evm' to reflect the change. * @@ -759,8 +772,11 @@ bool evm_revalidate_status(const char *xattr_name) * __vfs_setxattr_noperm(). The caller of which has taken the inode's * i_mutex lock. */ -void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name, - const void *xattr_value, size_t xattr_value_len) +static void evm_inode_post_setxattr(struct dentry *dentry, + const char *xattr_name, + const void *xattr_value, + size_t xattr_value_len, + int flags) { if (!evm_revalidate_status(xattr_name)) return; @@ -779,6 +795,21 @@ void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name, evm_update_evmxattr(dentry, xattr_name, xattr_value, xattr_value_len); } +/** + * evm_inode_post_set_acl - Update the EVM extended attribute from posix acls + * @dentry: pointer to the affected dentry + * @acl_name: name of the posix acl + * @kacl: pointer to the posix acls + * + * Update the 'security.evm' xattr with the EVM HMAC re-calculated after setting + * posix acls. + */ +static void evm_inode_post_set_acl(struct dentry *dentry, const char *acl_name, + struct posix_acl *kacl) +{ + return evm_inode_post_setxattr(dentry, acl_name, NULL, 0, 0); +} + /** * evm_inode_post_removexattr - update 'security.evm' after removing the xattr * @dentry: pointer to the affected dentry @@ -789,7 +820,8 @@ void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name, * No need to take the i_mutex lock here, as this function is called from * vfs_removexattr() which takes the i_mutex. */ -void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name) +static void evm_inode_post_removexattr(struct dentry *dentry, + const char *xattr_name) { if (!evm_revalidate_status(xattr_name)) return; @@ -805,6 +837,22 @@ void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name) evm_update_evmxattr(dentry, xattr_name, NULL, 0); } +/** + * evm_inode_post_remove_acl - Update the EVM extended attribute from posix acls + * @idmap: idmap of the mount + * @dentry: pointer to the affected dentry + * @acl_name: name of the posix acl + * + * Update the 'security.evm' xattr with the EVM HMAC re-calculated after + * removing posix acls. + */ +static inline void evm_inode_post_remove_acl(struct mnt_idmap *idmap, + struct dentry *dentry, + const char *acl_name) +{ + evm_inode_post_removexattr(dentry, acl_name); +} + static int evm_attr_change(struct mnt_idmap *idmap, struct dentry *dentry, struct iattr *attr) { @@ -828,8 +876,8 @@ static int evm_attr_change(struct mnt_idmap *idmap, * Permit update of file attributes when files have a valid EVM signature, * except in the case of them having an immutable portable signature. */ -int evm_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry, - struct iattr *attr) +static int evm_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry, + struct iattr *attr) { unsigned int ia_valid = attr->ia_valid; enum integrity_status evm_status; @@ -870,6 +918,7 @@ int evm_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry, /** * evm_inode_post_setattr - update 'security.evm' after modifying metadata + * @idmap: idmap of the idmapped mount * @dentry: pointer to the affected dentry * @ia_valid: for the UID and GID status * @@ -879,7 +928,8 @@ int evm_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry, * This function is called from notify_change(), which expects the caller * to lock the inode's i_mutex. */ -void evm_inode_post_setattr(struct dentry *dentry, int ia_valid) +static void evm_inode_post_setattr(struct mnt_idmap *idmap, + struct dentry *dentry, int ia_valid) { if (!evm_revalidate_status(NULL)) return; @@ -896,7 +946,7 @@ void evm_inode_post_setattr(struct dentry *dentry, int ia_valid) evm_update_evmxattr(dentry, NULL, NULL, 0); } -int evm_inode_copy_up_xattr(const char *name) +static int evm_inode_copy_up_xattr(const char *name) { if (strcmp(name, XATTR_NAME_EVM) == 0) return 1; /* Discard */ @@ -960,6 +1010,42 @@ out: } EXPORT_SYMBOL_GPL(evm_inode_init_security); +static int evm_inode_alloc_security(struct inode *inode) +{ + struct evm_iint_cache *iint = evm_iint_inode(inode); + + /* Called by security_inode_alloc(), it cannot be NULL. */ + iint->flags = 0UL; + iint->evm_status = INTEGRITY_UNKNOWN; + + return 0; +} + +static void evm_file_release(struct file *file) +{ + struct inode *inode = file_inode(file); + struct evm_iint_cache *iint = evm_iint_inode(inode); + fmode_t mode = file->f_mode; + + if (!S_ISREG(inode->i_mode) || !(mode & FMODE_WRITE)) + return; + + if (iint && atomic_read(&inode->i_writecount) == 1) + iint->flags &= ~EVM_NEW_FILE; +} + +static void evm_post_path_mknod(struct mnt_idmap *idmap, struct dentry *dentry) +{ + struct inode *inode = d_backing_inode(dentry); + struct evm_iint_cache *iint = evm_iint_inode(inode); + + if (!S_ISREG(inode->i_mode)) + return; + + if (iint) + iint->flags |= EVM_NEW_FILE; +} + #ifdef CONFIG_EVM_LOAD_X509 void __init evm_load_x509(void) { @@ -999,4 +1085,45 @@ error: return error; } +static struct security_hook_list evm_hooks[] __ro_after_init = { + LSM_HOOK_INIT(inode_setattr, evm_inode_setattr), + LSM_HOOK_INIT(inode_post_setattr, evm_inode_post_setattr), + LSM_HOOK_INIT(inode_copy_up_xattr, evm_inode_copy_up_xattr), + LSM_HOOK_INIT(inode_setxattr, evm_inode_setxattr), + LSM_HOOK_INIT(inode_post_setxattr, evm_inode_post_setxattr), + LSM_HOOK_INIT(inode_set_acl, evm_inode_set_acl), + LSM_HOOK_INIT(inode_post_set_acl, evm_inode_post_set_acl), + LSM_HOOK_INIT(inode_remove_acl, evm_inode_remove_acl), + LSM_HOOK_INIT(inode_post_remove_acl, evm_inode_post_remove_acl), + LSM_HOOK_INIT(inode_removexattr, evm_inode_removexattr), + LSM_HOOK_INIT(inode_post_removexattr, evm_inode_post_removexattr), + LSM_HOOK_INIT(inode_init_security, evm_inode_init_security), + LSM_HOOK_INIT(inode_alloc_security, evm_inode_alloc_security), + LSM_HOOK_INIT(file_release, evm_file_release), + LSM_HOOK_INIT(path_post_mknod, evm_post_path_mknod), +}; + +static const struct lsm_id evm_lsmid = { + .name = "evm", + .id = LSM_ID_EVM, +}; + +static int __init init_evm_lsm(void) +{ + security_add_hooks(evm_hooks, ARRAY_SIZE(evm_hooks), &evm_lsmid); + return 0; +} + +struct lsm_blob_sizes evm_blob_sizes __ro_after_init = { + .lbs_inode = sizeof(struct evm_iint_cache), + .lbs_xattr_count = 1, +}; + +DEFINE_LSM(evm) = { + .name = "evm", + .init = init_evm_lsm, + .order = LSM_ORDER_LAST, + .blobs = &evm_blob_sizes, +}; + late_initcall(init_evm); diff --git a/security/integrity/iint.c b/security/integrity/iint.c index d4419a2a1e24..068ac6c2ae1e 100644 --- a/security/integrity/iint.c +++ b/security/integrity/iint.c @@ -6,207 +6,14 @@ * Mimi Zohar * * File: integrity_iint.c - * - implements the integrity hooks: integrity_inode_alloc, - * integrity_inode_free - * - cache integrity information associated with an inode - * using a rbtree tree. + * - initialize the integrity directory in securityfs + * - load IMA and EVM keys */ -#include -#include -#include -#include -#include -#include #include -#include #include "integrity.h" -static struct rb_root integrity_iint_tree = RB_ROOT; -static DEFINE_RWLOCK(integrity_iint_lock); -static struct kmem_cache *iint_cache __ro_after_init; - struct dentry *integrity_dir; -/* - * __integrity_iint_find - return the iint associated with an inode - */ -static struct integrity_iint_cache *__integrity_iint_find(struct inode *inode) -{ - struct integrity_iint_cache *iint; - struct rb_node *n = integrity_iint_tree.rb_node; - - while (n) { - iint = rb_entry(n, struct integrity_iint_cache, rb_node); - - if (inode < iint->inode) - n = n->rb_left; - else if (inode > iint->inode) - n = n->rb_right; - else - return iint; - } - - return NULL; -} - -/* - * integrity_iint_find - return the iint associated with an inode - */ -struct integrity_iint_cache *integrity_iint_find(struct inode *inode) -{ - struct integrity_iint_cache *iint; - - if (!IS_IMA(inode)) - return NULL; - - read_lock(&integrity_iint_lock); - iint = __integrity_iint_find(inode); - read_unlock(&integrity_iint_lock); - - return iint; -} - -#define IMA_MAX_NESTING (FILESYSTEM_MAX_STACK_DEPTH+1) - -/* - * It is not clear that IMA should be nested at all, but as long is it measures - * files both on overlayfs and on underlying fs, we need to annotate the iint - * mutex to avoid lockdep false positives related to IMA + overlayfs. - * See ovl_lockdep_annotate_inode_mutex_key() for more details. - */ -static inline void iint_lockdep_annotate(struct integrity_iint_cache *iint, - struct inode *inode) -{ -#ifdef CONFIG_LOCKDEP - static struct lock_class_key iint_mutex_key[IMA_MAX_NESTING]; - - int depth = inode->i_sb->s_stack_depth; - - if (WARN_ON_ONCE(depth < 0 || depth >= IMA_MAX_NESTING)) - depth = 0; - - lockdep_set_class(&iint->mutex, &iint_mutex_key[depth]); -#endif -} - -static void iint_init_always(struct integrity_iint_cache *iint, - struct inode *inode) -{ - iint->ima_hash = NULL; - iint->version = 0; - iint->flags = 0UL; - iint->atomic_flags = 0UL; - iint->ima_file_status = INTEGRITY_UNKNOWN; - iint->ima_mmap_status = INTEGRITY_UNKNOWN; - iint->ima_bprm_status = INTEGRITY_UNKNOWN; - iint->ima_read_status = INTEGRITY_UNKNOWN; - iint->ima_creds_status = INTEGRITY_UNKNOWN; - iint->evm_status = INTEGRITY_UNKNOWN; - iint->measured_pcrs = 0; - mutex_init(&iint->mutex); - iint_lockdep_annotate(iint, inode); -} - -static void iint_free(struct integrity_iint_cache *iint) -{ - kfree(iint->ima_hash); - mutex_destroy(&iint->mutex); - kmem_cache_free(iint_cache, iint); -} - -/** - * integrity_inode_get - find or allocate an iint associated with an inode - * @inode: pointer to the inode - * @return: allocated iint - * - * Caller must lock i_mutex - */ -struct integrity_iint_cache *integrity_inode_get(struct inode *inode) -{ - struct rb_node **p; - struct rb_node *node, *parent = NULL; - struct integrity_iint_cache *iint, *test_iint; - - iint = integrity_iint_find(inode); - if (iint) - return iint; - - iint = kmem_cache_alloc(iint_cache, GFP_NOFS); - if (!iint) - return NULL; - - iint_init_always(iint, inode); - - write_lock(&integrity_iint_lock); - - p = &integrity_iint_tree.rb_node; - while (*p) { - parent = *p; - test_iint = rb_entry(parent, struct integrity_iint_cache, - rb_node); - if (inode < test_iint->inode) { - p = &(*p)->rb_left; - } else if (inode > test_iint->inode) { - p = &(*p)->rb_right; - } else { - write_unlock(&integrity_iint_lock); - kmem_cache_free(iint_cache, iint); - return test_iint; - } - } - - iint->inode = inode; - node = &iint->rb_node; - inode->i_flags |= S_IMA; - rb_link_node(node, parent, p); - rb_insert_color(node, &integrity_iint_tree); - - write_unlock(&integrity_iint_lock); - return iint; -} - -/** - * integrity_inode_free - called on security_inode_free - * @inode: pointer to the inode - * - * Free the integrity information(iint) associated with an inode. - */ -void integrity_inode_free(struct inode *inode) -{ - struct integrity_iint_cache *iint; - - if (!IS_IMA(inode)) - return; - - write_lock(&integrity_iint_lock); - iint = __integrity_iint_find(inode); - rb_erase(&iint->rb_node, &integrity_iint_tree); - write_unlock(&integrity_iint_lock); - - iint_free(iint); -} - -static void iint_init_once(void *foo) -{ - struct integrity_iint_cache *iint = (struct integrity_iint_cache *) foo; - - memset(iint, 0, sizeof(*iint)); -} - -static int __init integrity_iintcache_init(void) -{ - iint_cache = - kmem_cache_create("iint_cache", sizeof(struct integrity_iint_cache), - 0, SLAB_PANIC, iint_init_once); - return 0; -} -DEFINE_LSM(integrity) = { - .name = "integrity", - .init = integrity_iintcache_init, - .order = LSM_ORDER_LAST, -}; - - /* * integrity_kernel_read - read data from the file * diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index b98bfe9efd0c..475c32615006 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -8,6 +8,7 @@ config IMA select CRYPTO_HMAC select CRYPTO_SHA1 select CRYPTO_HASH_INFO + select SECURITY_PATH select TCG_TPM if HAS_IOMEM select TCG_TIS if TCG_TPM && X86 select TCG_CRB if TCG_TPM && ACPI diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile index 2499f2485c04..b376d38b4ee6 100644 --- a/security/integrity/ima/Makefile +++ b/security/integrity/ima/Makefile @@ -4,7 +4,7 @@ # Measurement Architecture(IMA). # -obj-$(CONFIG_IMA) += ima.o +obj-$(CONFIG_IMA) += ima.o ima_iint.o ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \ ima_policy.o ima_template.o ima_template_lib.o diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index c29db699c996..11d7c0332207 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -60,7 +60,7 @@ extern const char boot_aggregate_name[]; /* IMA event related data */ struct ima_event_data { - struct integrity_iint_cache *iint; + struct ima_iint_cache *iint; struct file *file; const unsigned char *filename; struct evm_ima_xattr_data *xattr_value; @@ -119,6 +119,107 @@ struct ima_kexec_hdr { u64 count; }; +/* IMA iint action cache flags */ +#define IMA_MEASURE 0x00000001 +#define IMA_MEASURED 0x00000002 +#define IMA_APPRAISE 0x00000004 +#define IMA_APPRAISED 0x00000008 +/*#define IMA_COLLECT 0x00000010 do not use this flag */ +#define IMA_COLLECTED 0x00000020 +#define IMA_AUDIT 0x00000040 +#define IMA_AUDITED 0x00000080 +#define IMA_HASH 0x00000100 +#define IMA_HASHED 0x00000200 + +/* IMA iint policy rule cache flags */ +#define IMA_NONACTION_FLAGS 0xff000000 +#define IMA_DIGSIG_REQUIRED 0x01000000 +#define IMA_PERMIT_DIRECTIO 0x02000000 +#define IMA_NEW_FILE 0x04000000 +#define IMA_FAIL_UNVERIFIABLE_SIGS 0x10000000 +#define IMA_MODSIG_ALLOWED 0x20000000 +#define IMA_CHECK_BLACKLIST 0x40000000 +#define IMA_VERITY_REQUIRED 0x80000000 + +#define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT | \ + IMA_HASH | IMA_APPRAISE_SUBMASK) +#define IMA_DONE_MASK (IMA_MEASURED | IMA_APPRAISED | IMA_AUDITED | \ + IMA_HASHED | IMA_COLLECTED | \ + IMA_APPRAISED_SUBMASK) + +/* IMA iint subaction appraise cache flags */ +#define IMA_FILE_APPRAISE 0x00001000 +#define IMA_FILE_APPRAISED 0x00002000 +#define IMA_MMAP_APPRAISE 0x00004000 +#define IMA_MMAP_APPRAISED 0x00008000 +#define IMA_BPRM_APPRAISE 0x00010000 +#define IMA_BPRM_APPRAISED 0x00020000 +#define IMA_READ_APPRAISE 0x00040000 +#define IMA_READ_APPRAISED 0x00080000 +#define IMA_CREDS_APPRAISE 0x00100000 +#define IMA_CREDS_APPRAISED 0x00200000 +#define IMA_APPRAISE_SUBMASK (IMA_FILE_APPRAISE | IMA_MMAP_APPRAISE | \ + IMA_BPRM_APPRAISE | IMA_READ_APPRAISE | \ + IMA_CREDS_APPRAISE) +#define IMA_APPRAISED_SUBMASK (IMA_FILE_APPRAISED | IMA_MMAP_APPRAISED | \ + IMA_BPRM_APPRAISED | IMA_READ_APPRAISED | \ + IMA_CREDS_APPRAISED) + +/* IMA iint cache atomic_flags */ +#define IMA_CHANGE_XATTR 0 +#define IMA_UPDATE_XATTR 1 +#define IMA_CHANGE_ATTR 2 +#define IMA_DIGSIG 3 +#define IMA_MUST_MEASURE 4 + +/* IMA integrity metadata associated with an inode */ +struct ima_iint_cache { + struct mutex mutex; /* protects: version, flags, digest */ + u64 version; /* track inode changes */ + unsigned long flags; + unsigned long measured_pcrs; + unsigned long atomic_flags; + unsigned long real_ino; + dev_t real_dev; + enum integrity_status ima_file_status:4; + enum integrity_status ima_mmap_status:4; + enum integrity_status ima_bprm_status:4; + enum integrity_status ima_read_status:4; + enum integrity_status ima_creds_status:4; + struct ima_digest_data *ima_hash; +}; + +extern struct lsm_blob_sizes ima_blob_sizes; + +static inline struct ima_iint_cache * +ima_inode_get_iint(const struct inode *inode) +{ + struct ima_iint_cache **iint_sec; + + if (unlikely(!inode->i_security)) + return NULL; + + iint_sec = inode->i_security + ima_blob_sizes.lbs_inode; + return *iint_sec; +} + +static inline void ima_inode_set_iint(const struct inode *inode, + struct ima_iint_cache *iint) +{ + struct ima_iint_cache **iint_sec; + + if (unlikely(!inode->i_security)) + return; + + iint_sec = inode->i_security + ima_blob_sizes.lbs_inode; + *iint_sec = iint; +} + +struct ima_iint_cache *ima_iint_find(struct inode *inode); +struct ima_iint_cache *ima_inode_get(struct inode *inode); +void ima_inode_free(struct inode *inode); +void __init ima_iintcache_init(void); + extern const int read_idmap[]; #ifdef CONFIG_HAVE_IMA_KEXEC @@ -127,6 +228,12 @@ void ima_load_kexec_buffer(void); static inline void ima_load_kexec_buffer(void) {} #endif /* CONFIG_HAVE_IMA_KEXEC */ +#ifdef CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS +void ima_post_key_create_or_update(struct key *keyring, struct key *key, + const void *payload, size_t plen, + unsigned long flags, bool create); +#endif + /* * The default binary_runtime_measurements list format is defined as the * platform native format. The canonical format is defined as little-endian. @@ -146,8 +253,8 @@ int ima_calc_field_array_hash(struct ima_field_data *field_data, struct ima_template_entry *entry); int ima_calc_boot_aggregate(struct ima_digest_data *hash); void ima_add_violation(struct file *file, const unsigned char *filename, - struct integrity_iint_cache *iint, - const char *op, const char *cause); + struct ima_iint_cache *iint, const char *op, + const char *cause); int ima_init_crypto(void); void ima_putc(struct seq_file *m, void *data, int datalen); void ima_print_digest(struct seq_file *m, u8 *digest, u32 size); @@ -261,10 +368,10 @@ int ima_get_action(struct mnt_idmap *idmap, struct inode *inode, struct ima_template_desc **template_desc, const char *func_data, unsigned int *allowed_algos); int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func); -int ima_collect_measurement(struct integrity_iint_cache *iint, - struct file *file, void *buf, loff_t size, - enum hash_algo algo, struct modsig *modsig); -void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file, +int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file, + void *buf, loff_t size, enum hash_algo algo, + struct modsig *modsig); +void ima_store_measurement(struct ima_iint_cache *iint, struct file *file, const unsigned char *filename, struct evm_ima_xattr_data *xattr_value, int xattr_len, const struct modsig *modsig, int pcr, @@ -274,7 +381,7 @@ int process_buffer_measurement(struct mnt_idmap *idmap, const char *eventname, enum ima_hooks func, int pcr, const char *func_data, bool buf_hash, u8 *digest, size_t digest_len); -void ima_audit_measurement(struct integrity_iint_cache *iint, +void ima_audit_measurement(struct ima_iint_cache *iint, const unsigned char *filename); int ima_alloc_init_template(struct ima_event_data *event_data, struct ima_template_entry **entry, @@ -312,32 +419,32 @@ int ima_policy_show(struct seq_file *m, void *v); #define IMA_APPRAISE_KEXEC 0x40 #ifdef CONFIG_IMA_APPRAISE -int ima_check_blacklist(struct integrity_iint_cache *iint, +int ima_check_blacklist(struct ima_iint_cache *iint, const struct modsig *modsig, int pcr); -int ima_appraise_measurement(enum ima_hooks func, - struct integrity_iint_cache *iint, +int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint, struct file *file, const unsigned char *filename, struct evm_ima_xattr_data *xattr_value, int xattr_len, const struct modsig *modsig); int ima_must_appraise(struct mnt_idmap *idmap, struct inode *inode, int mask, enum ima_hooks func); -void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file); -enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, +void ima_update_xattr(struct ima_iint_cache *iint, struct file *file); +enum integrity_status ima_get_cache_status(struct ima_iint_cache *iint, enum ima_hooks func); enum hash_algo ima_get_hash_algo(const struct evm_ima_xattr_data *xattr_value, int xattr_len); int ima_read_xattr(struct dentry *dentry, struct evm_ima_xattr_data **xattr_value, int xattr_len); +void __init init_ima_appraise_lsm(const struct lsm_id *lsmid); #else -static inline int ima_check_blacklist(struct integrity_iint_cache *iint, +static inline int ima_check_blacklist(struct ima_iint_cache *iint, const struct modsig *modsig, int pcr) { return 0; } static inline int ima_appraise_measurement(enum ima_hooks func, - struct integrity_iint_cache *iint, + struct ima_iint_cache *iint, struct file *file, const unsigned char *filename, struct evm_ima_xattr_data *xattr_value, @@ -354,14 +461,13 @@ static inline int ima_must_appraise(struct mnt_idmap *idmap, return 0; } -static inline void ima_update_xattr(struct integrity_iint_cache *iint, +static inline void ima_update_xattr(struct ima_iint_cache *iint, struct file *file) { } -static inline enum integrity_status ima_get_cache_status(struct integrity_iint_cache - *iint, - enum ima_hooks func) +static inline enum integrity_status +ima_get_cache_status(struct ima_iint_cache *iint, enum ima_hooks func) { return INTEGRITY_UNKNOWN; } @@ -379,6 +485,10 @@ static inline int ima_read_xattr(struct dentry *dentry, return 0; } +static inline void __init init_ima_appraise_lsm(const struct lsm_id *lsmid) +{ +} + #endif /* CONFIG_IMA_APPRAISE */ #ifdef CONFIG_IMA_APPRAISE_MODSIG diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index 597ea0c4d72f..b37d043d5748 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -131,8 +131,8 @@ int ima_store_template(struct ima_template_entry *entry, * value is invalidated. */ void ima_add_violation(struct file *file, const unsigned char *filename, - struct integrity_iint_cache *iint, - const char *op, const char *cause) + struct ima_iint_cache *iint, const char *op, + const char *cause) { struct ima_template_entry *entry; struct inode *inode = file_inode(file); @@ -201,7 +201,8 @@ int ima_get_action(struct mnt_idmap *idmap, struct inode *inode, allowed_algos); } -static bool ima_get_verity_digest(struct integrity_iint_cache *iint, +static bool ima_get_verity_digest(struct ima_iint_cache *iint, + struct inode *inode, struct ima_max_digest_data *hash) { enum hash_algo alg; @@ -211,7 +212,7 @@ static bool ima_get_verity_digest(struct integrity_iint_cache *iint, * On failure, 'measure' policy rules will result in a file data * hash containing 0's. */ - digest_len = fsverity_get_digest(iint->inode, hash->digest, NULL, &alg); + digest_len = fsverity_get_digest(inode, hash->digest, NULL, &alg); if (digest_len == 0) return false; @@ -237,9 +238,9 @@ static bool ima_get_verity_digest(struct integrity_iint_cache *iint, * * Return 0 on success, error code otherwise */ -int ima_collect_measurement(struct integrity_iint_cache *iint, - struct file *file, void *buf, loff_t size, - enum hash_algo algo, struct modsig *modsig) +int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file, + void *buf, loff_t size, enum hash_algo algo, + struct modsig *modsig) { const char *audit_cause = "failed"; struct inode *inode = file_inode(file); @@ -280,7 +281,7 @@ int ima_collect_measurement(struct integrity_iint_cache *iint, memset(&hash.digest, 0, sizeof(hash.digest)); if (iint->flags & IMA_VERITY_REQUIRED) { - if (!ima_get_verity_digest(iint, &hash)) { + if (!ima_get_verity_digest(iint, inode, &hash)) { audit_cause = "no-verity-digest"; result = -ENODATA; } @@ -338,8 +339,8 @@ out: * * Must be called with iint->mutex held. */ -void ima_store_measurement(struct integrity_iint_cache *iint, - struct file *file, const unsigned char *filename, +void ima_store_measurement(struct ima_iint_cache *iint, struct file *file, + const unsigned char *filename, struct evm_ima_xattr_data *xattr_value, int xattr_len, const struct modsig *modsig, int pcr, struct ima_template_desc *template_desc) @@ -382,7 +383,7 @@ void ima_store_measurement(struct integrity_iint_cache *iint, ima_free_template_entry(entry); } -void ima_audit_measurement(struct integrity_iint_cache *iint, +void ima_audit_measurement(struct ima_iint_cache *iint, const unsigned char *filename) { struct audit_buffer *ab; diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 870dde67707b..3497741caea9 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -84,8 +84,7 @@ int ima_must_appraise(struct mnt_idmap *idmap, struct inode *inode, NULL, NULL, NULL); } -static int ima_fix_xattr(struct dentry *dentry, - struct integrity_iint_cache *iint) +static int ima_fix_xattr(struct dentry *dentry, struct ima_iint_cache *iint) { int rc, offset; u8 algo = iint->ima_hash->algo; @@ -106,7 +105,7 @@ static int ima_fix_xattr(struct dentry *dentry, } /* Return specific func appraised cached result */ -enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, +enum integrity_status ima_get_cache_status(struct ima_iint_cache *iint, enum ima_hooks func) { switch (func) { @@ -126,7 +125,7 @@ enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, } } -static void ima_set_cache_status(struct integrity_iint_cache *iint, +static void ima_set_cache_status(struct ima_iint_cache *iint, enum ima_hooks func, enum integrity_status status) { @@ -152,8 +151,7 @@ static void ima_set_cache_status(struct integrity_iint_cache *iint, } } -static void ima_cache_flags(struct integrity_iint_cache *iint, - enum ima_hooks func) +static void ima_cache_flags(struct ima_iint_cache *iint, enum ima_hooks func) { switch (func) { case MMAP_CHECK: @@ -276,7 +274,7 @@ static int calc_file_id_hash(enum evm_ima_xattr_type type, * * Return 0 on success, error code otherwise. */ -static int xattr_verify(enum ima_hooks func, struct integrity_iint_cache *iint, +static int xattr_verify(enum ima_hooks func, struct ima_iint_cache *iint, struct evm_ima_xattr_data *xattr_value, int xattr_len, enum integrity_status *status, const char **cause) { @@ -443,7 +441,7 @@ static int modsig_verify(enum ima_hooks func, const struct modsig *modsig, * * Returns -EPERM if the hash is blacklisted. */ -int ima_check_blacklist(struct integrity_iint_cache *iint, +int ima_check_blacklist(struct ima_iint_cache *iint, const struct modsig *modsig, int pcr) { enum hash_algo hash_algo; @@ -477,8 +475,7 @@ int ima_check_blacklist(struct integrity_iint_cache *iint, * * Return 0 on success, error code otherwise */ -int ima_appraise_measurement(enum ima_hooks func, - struct integrity_iint_cache *iint, +int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint, struct file *file, const unsigned char *filename, struct evm_ima_xattr_data *xattr_value, int xattr_len, const struct modsig *modsig) @@ -520,7 +517,7 @@ int ima_appraise_measurement(enum ima_hooks func, } status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, - rc < 0 ? 0 : rc, iint); + rc < 0 ? 0 : rc); switch (status) { case INTEGRITY_PASS: case INTEGRITY_PASS_IMMUTABLE: @@ -603,7 +600,7 @@ out: /* * ima_update_xattr - update 'security.ima' hash value */ -void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file) +void ima_update_xattr(struct ima_iint_cache *iint, struct file *file) { struct dentry *dentry = file_dentry(file); int rc = 0; @@ -629,17 +626,18 @@ void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file) * ima_inode_post_setattr - reflect file metadata changes * @idmap: idmap of the mount the inode was found from * @dentry: pointer to the affected dentry + * @ia_valid: for the UID and GID status * * Changes to a dentry's metadata might result in needing to appraise. * * This function is called from notify_change(), which expects the caller * to lock the inode's i_mutex. */ -void ima_inode_post_setattr(struct mnt_idmap *idmap, - struct dentry *dentry) +static void ima_inode_post_setattr(struct mnt_idmap *idmap, + struct dentry *dentry, int ia_valid) { struct inode *inode = d_backing_inode(dentry); - struct integrity_iint_cache *iint; + struct ima_iint_cache *iint; int action; if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode) @@ -647,7 +645,7 @@ void ima_inode_post_setattr(struct mnt_idmap *idmap, return; action = ima_must_appraise(idmap, inode, MAY_ACCESS, POST_SETATTR); - iint = integrity_iint_find(inode); + iint = ima_iint_find(inode); if (iint) { set_bit(IMA_CHANGE_ATTR, &iint->atomic_flags); if (!action) @@ -673,12 +671,12 @@ static int ima_protect_xattr(struct dentry *dentry, const char *xattr_name, static void ima_reset_appraise_flags(struct inode *inode, int digsig) { - struct integrity_iint_cache *iint; + struct ima_iint_cache *iint; if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)) return; - iint = integrity_iint_find(inode); + iint = ima_iint_find(inode); if (!iint) return; iint->measured_pcrs = 0; @@ -749,8 +747,9 @@ static int validate_hash_algo(struct dentry *dentry, return -EACCES; } -int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name, - const void *xattr_value, size_t xattr_value_len) +static int ima_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, + const char *xattr_name, const void *xattr_value, + size_t xattr_value_len, int flags) { const struct evm_ima_xattr_data *xvalue = xattr_value; int digsig = 0; @@ -779,8 +778,8 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name, return result; } -int ima_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, - const char *acl_name, struct posix_acl *kacl) +static int ima_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, + const char *acl_name, struct posix_acl *kacl) { if (evm_revalidate_status(acl_name)) ima_reset_appraise_flags(d_backing_inode(dentry), 0); @@ -788,7 +787,8 @@ int ima_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, return 0; } -int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name) +static int ima_inode_removexattr(struct mnt_idmap *idmap, struct dentry *dentry, + const char *xattr_name) { int result; @@ -800,3 +800,23 @@ int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name) } return result; } + +static int ima_inode_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry, + const char *acl_name) +{ + return ima_inode_set_acl(idmap, dentry, acl_name, NULL); +} + +static struct security_hook_list ima_appraise_hooks[] __ro_after_init = { + LSM_HOOK_INIT(inode_post_setattr, ima_inode_post_setattr), + LSM_HOOK_INIT(inode_setxattr, ima_inode_setxattr), + LSM_HOOK_INIT(inode_set_acl, ima_inode_set_acl), + LSM_HOOK_INIT(inode_removexattr, ima_inode_removexattr), + LSM_HOOK_INIT(inode_remove_acl, ima_inode_remove_acl), +}; + +void __init init_ima_appraise_lsm(const struct lsm_id *lsmid) +{ + security_add_hooks(ima_appraise_hooks, ARRAY_SIZE(ima_appraise_hooks), + lsmid); +} diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c new file mode 100644 index 000000000000..e7c9c216c1c6 --- /dev/null +++ b/security/integrity/ima/ima_iint.c @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2008 IBM Corporation + * + * Authors: + * Mimi Zohar + * + * File: ima_iint.c + * - implements the IMA hook: ima_inode_free + * - cache integrity information in the inode security blob + */ +#include + +#include "ima.h" + +static struct kmem_cache *ima_iint_cache __ro_after_init; + +/** + * ima_iint_find - Return the iint associated with an inode + * @inode: Pointer to the inode + * + * Return the IMA integrity information (iint) associated with an inode, if the + * inode was processed by IMA. + * + * Return: Found iint or NULL. + */ +struct ima_iint_cache *ima_iint_find(struct inode *inode) +{ + if (!IS_IMA(inode)) + return NULL; + + return ima_inode_get_iint(inode); +} + +#define IMA_MAX_NESTING (FILESYSTEM_MAX_STACK_DEPTH + 1) + +/* + * It is not clear that IMA should be nested at all, but as long is it measures + * files both on overlayfs and on underlying fs, we need to annotate the iint + * mutex to avoid lockdep false positives related to IMA + overlayfs. + * See ovl_lockdep_annotate_inode_mutex_key() for more details. + */ +static inline void ima_iint_lockdep_annotate(struct ima_iint_cache *iint, + struct inode *inode) +{ +#ifdef CONFIG_LOCKDEP + static struct lock_class_key ima_iint_mutex_key[IMA_MAX_NESTING]; + + int depth = inode->i_sb->s_stack_depth; + + if (WARN_ON_ONCE(depth < 0 || depth >= IMA_MAX_NESTING)) + depth = 0; + + lockdep_set_class(&iint->mutex, &ima_iint_mutex_key[depth]); +#endif +} + +static void ima_iint_init_always(struct ima_iint_cache *iint, + struct inode *inode) +{ + iint->ima_hash = NULL; + iint->version = 0; + iint->flags = 0UL; + iint->atomic_flags = 0UL; + iint->ima_file_status = INTEGRITY_UNKNOWN; + iint->ima_mmap_status = INTEGRITY_UNKNOWN; + iint->ima_bprm_status = INTEGRITY_UNKNOWN; + iint->ima_read_status = INTEGRITY_UNKNOWN; + iint->ima_creds_status = INTEGRITY_UNKNOWN; + iint->measured_pcrs = 0; + mutex_init(&iint->mutex); + ima_iint_lockdep_annotate(iint, inode); +} + +static void ima_iint_free(struct ima_iint_cache *iint) +{ + kfree(iint->ima_hash); + mutex_destroy(&iint->mutex); + kmem_cache_free(ima_iint_cache, iint); +} + +/** + * ima_inode_get - Find or allocate an iint associated with an inode + * @inode: Pointer to the inode + * + * Find an iint associated with an inode, and allocate a new one if not found. + * Caller must lock i_mutex. + * + * Return: An iint on success, NULL on error. + */ +struct ima_iint_cache *ima_inode_get(struct inode *inode) +{ + struct ima_iint_cache *iint; + + iint = ima_iint_find(inode); + if (iint) + return iint; + + iint = kmem_cache_alloc(ima_iint_cache, GFP_NOFS); + if (!iint) + return NULL; + + ima_iint_init_always(iint, inode); + + inode->i_flags |= S_IMA; + ima_inode_set_iint(inode, iint); + + return iint; +} + +/** + * ima_inode_free - Called on inode free + * @inode: Pointer to the inode + * + * Free the iint associated with an inode. + */ +void ima_inode_free(struct inode *inode) +{ + struct ima_iint_cache *iint; + + if (!IS_IMA(inode)) + return; + + iint = ima_iint_find(inode); + ima_inode_set_iint(inode, NULL); + + ima_iint_free(iint); +} + +static void ima_iint_init_once(void *foo) +{ + struct ima_iint_cache *iint = (struct ima_iint_cache *)foo; + + memset(iint, 0, sizeof(*iint)); +} + +void __init ima_iintcache_init(void) +{ + ima_iint_cache = + kmem_cache_create("ima_iint_cache", sizeof(struct ima_iint_cache), + 0, SLAB_PANIC, ima_iint_init_once); +} diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index 63979aefc95f..393f5c7912d5 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -44,7 +44,7 @@ static int __init ima_add_boot_aggregate(void) static const char op[] = "add_boot_aggregate"; const char *audit_cause = "ENOMEM"; struct ima_template_entry *entry; - struct integrity_iint_cache tmp_iint, *iint = &tmp_iint; + struct ima_iint_cache tmp_iint, *iint = &tmp_iint; struct ima_event_data event_data = { .iint = iint, .filename = boot_aggregate_name }; struct ima_max_digest_data hash; diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index cc1217ac2c6f..c84e8c55333d 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -114,7 +114,7 @@ static int mmap_violation_check(enum ima_hooks func, struct file *file, * */ static void ima_rdwr_violation_check(struct file *file, - struct integrity_iint_cache *iint, + struct ima_iint_cache *iint, int must_measure, char **pathbuf, const char **pathname, @@ -127,7 +127,7 @@ static void ima_rdwr_violation_check(struct file *file, if (mode & FMODE_WRITE) { if (atomic_read(&inode->i_readcount) && IS_IMA(inode)) { if (!iint) - iint = integrity_iint_find(inode); + iint = ima_iint_find(inode); /* IMA_MEASURE is set from reader side */ if (iint && test_bit(IMA_MUST_MEASURE, &iint->atomic_flags)) @@ -153,7 +153,7 @@ static void ima_rdwr_violation_check(struct file *file, "invalid_pcr", "open_writers"); } -static void ima_check_last_writer(struct integrity_iint_cache *iint, +static void ima_check_last_writer(struct ima_iint_cache *iint, struct inode *inode, struct file *file) { fmode_t mode = file->f_mode; @@ -189,15 +189,15 @@ static void ima_check_last_writer(struct integrity_iint_cache *iint, * * Flag files that changed, based on i_version */ -void ima_file_free(struct file *file) +static void ima_file_free(struct file *file) { struct inode *inode = file_inode(file); - struct integrity_iint_cache *iint; + struct ima_iint_cache *iint; if (!ima_policy_flag || !S_ISREG(inode->i_mode)) return; - iint = integrity_iint_find(inode); + iint = ima_iint_find(inode); if (!iint) return; @@ -209,7 +209,7 @@ static int process_measurement(struct file *file, const struct cred *cred, enum ima_hooks func) { struct inode *backing_inode, *inode = file_inode(file); - struct integrity_iint_cache *iint = NULL; + struct ima_iint_cache *iint = NULL; struct ima_template_desc *template_desc = NULL; char *pathbuf = NULL; char filename[NAME_MAX]; @@ -248,7 +248,7 @@ static int process_measurement(struct file *file, const struct cred *cred, inode_lock(inode); if (action) { - iint = integrity_inode_get(inode); + iint = ima_inode_get(inode); if (!iint) rc = -ENOMEM; } @@ -427,8 +427,8 @@ out: * On success return 0. On integrity appraisal error, assuming the file * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. */ -int ima_file_mmap(struct file *file, unsigned long reqprot, - unsigned long prot, unsigned long flags) +static int ima_file_mmap(struct file *file, unsigned long reqprot, + unsigned long prot, unsigned long flags) { u32 secid; int ret; @@ -455,7 +455,8 @@ int ima_file_mmap(struct file *file, unsigned long reqprot, /** * ima_file_mprotect - based on policy, limit mprotect change * @vma: vm_area_struct protection is set to - * @prot: contains the protection that will be applied by the kernel. + * @reqprot: protection requested by the application + * @prot: protection that will be applied by the kernel * * Files can be mmap'ed read/write and later changed to execute to circumvent * IMA's mmap appraisal policy rules. Due to locking issues (mmap semaphore @@ -465,7 +466,8 @@ int ima_file_mmap(struct file *file, unsigned long reqprot, * * On mprotect change success, return 0. On failure, return -EACESS. */ -int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot) +static int ima_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, + unsigned long prot) { struct ima_template_desc *template = NULL; struct file *file; @@ -523,7 +525,7 @@ int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot) * On success return 0. On integrity appraisal error, assuming the file * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. */ -int ima_bprm_check(struct linux_binprm *bprm) +static int ima_bprm_check(struct linux_binprm *bprm) { int ret; u32 secid; @@ -549,7 +551,7 @@ int ima_bprm_check(struct linux_binprm *bprm) * On success return 0. On integrity appraisal error, assuming the file * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. */ -int ima_file_check(struct file *file, int mask) +static int ima_file_check(struct file *file, int mask) { u32 secid; @@ -558,16 +560,15 @@ int ima_file_check(struct file *file, int mask) mask & (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND), FILE_CHECK); } -EXPORT_SYMBOL_GPL(ima_file_check); static int __ima_inode_hash(struct inode *inode, struct file *file, char *buf, size_t buf_size) { - struct integrity_iint_cache *iint = NULL, tmp_iint; + struct ima_iint_cache *iint = NULL, tmp_iint; int rc, hash_algo; if (ima_policy_flag) { - iint = integrity_iint_find(inode); + iint = ima_iint_find(inode); if (iint) mutex_lock(&iint->mutex); } @@ -577,7 +578,6 @@ static int __ima_inode_hash(struct inode *inode, struct file *file, char *buf, mutex_unlock(&iint->mutex); memset(&tmp_iint, 0, sizeof(tmp_iint)); - tmp_iint.inode = inode; mutex_init(&tmp_iint.mutex); rc = ima_collect_measurement(&tmp_iint, file, NULL, 0, @@ -683,10 +683,11 @@ EXPORT_SYMBOL_GPL(ima_inode_hash); * Skip calling process_measurement(), but indicate which newly, created * tmpfiles are in policy. */ -void ima_post_create_tmpfile(struct mnt_idmap *idmap, - struct inode *inode) +static void ima_post_create_tmpfile(struct mnt_idmap *idmap, + struct inode *inode) + { - struct integrity_iint_cache *iint; + struct ima_iint_cache *iint; int must_appraise; if (!ima_policy_flag || !S_ISREG(inode->i_mode)) @@ -698,7 +699,7 @@ void ima_post_create_tmpfile(struct mnt_idmap *idmap, return; /* Nothing to do if we can't allocate memory */ - iint = integrity_inode_get(inode); + iint = ima_inode_get(inode); if (!iint) return; @@ -715,10 +716,9 @@ void ima_post_create_tmpfile(struct mnt_idmap *idmap, * Mark files created via the mknodat syscall as new, so that the * file data can be written later. */ -void ima_post_path_mknod(struct mnt_idmap *idmap, - struct dentry *dentry) +static void ima_post_path_mknod(struct mnt_idmap *idmap, struct dentry *dentry) { - struct integrity_iint_cache *iint; + struct ima_iint_cache *iint; struct inode *inode = dentry->d_inode; int must_appraise; @@ -731,7 +731,7 @@ void ima_post_path_mknod(struct mnt_idmap *idmap, return; /* Nothing to do if we can't allocate memory */ - iint = integrity_inode_get(inode); + iint = ima_inode_get(inode); if (!iint) return; @@ -751,8 +751,8 @@ void ima_post_path_mknod(struct mnt_idmap *idmap, * * For permission return 0, otherwise return -EACCES. */ -int ima_read_file(struct file *file, enum kernel_read_file_id read_id, - bool contents) +static int ima_read_file(struct file *file, enum kernel_read_file_id read_id, + bool contents) { enum ima_hooks func; u32 secid; @@ -801,8 +801,8 @@ const int read_idmap[READING_MAX_ID] = { * On success return 0. On integrity appraisal error, assuming the file * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. */ -int ima_post_read_file(struct file *file, void *buf, loff_t size, - enum kernel_read_file_id read_id) +static int ima_post_read_file(struct file *file, char *buf, loff_t size, + enum kernel_read_file_id read_id) { enum ima_hooks func; u32 secid; @@ -835,7 +835,7 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size, * * For permission return 0, otherwise return -EACCES. */ -int ima_load_data(enum kernel_load_data_id id, bool contents) +static int ima_load_data(enum kernel_load_data_id id, bool contents) { bool ima_enforce, sig_enforce; @@ -889,9 +889,9 @@ int ima_load_data(enum kernel_load_data_id id, bool contents) * On success return 0. On integrity appraisal error, assuming the file * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. */ -int ima_post_load_data(char *buf, loff_t size, - enum kernel_load_data_id load_id, - char *description) +static int ima_post_load_data(char *buf, loff_t size, + enum kernel_load_data_id load_id, + char *description) { if (load_id == LOADING_FIRMWARE) { if ((ima_appraise & IMA_APPRAISE_FIRMWARE) && @@ -934,7 +934,7 @@ int process_buffer_measurement(struct mnt_idmap *idmap, int ret = 0; const char *audit_cause = "ENOMEM"; struct ima_template_entry *entry = NULL; - struct integrity_iint_cache iint = {}; + struct ima_iint_cache iint = {}; struct ima_event_data event_data = {.iint = &iint, .filename = eventname, .buf = buf, @@ -1089,6 +1089,39 @@ int ima_measure_critical_data(const char *event_label, } EXPORT_SYMBOL_GPL(ima_measure_critical_data); +#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS + +/** + * ima_kernel_module_request - Prevent crypto-pkcs1pad(rsa,*) requests + * @kmod_name: kernel module name + * + * Avoid a verification loop where verifying the signature of the modprobe + * binary requires executing modprobe itself. Since the modprobe iint->mutex + * is already held when the signature verification is performed, a deadlock + * occurs as soon as modprobe is executed within the critical region, since + * the same lock cannot be taken again. + * + * This happens when public_key_verify_signature(), in case of RSA algorithm, + * use alg_name to store internal information in order to construct an + * algorithm on the fly, but crypto_larval_lookup() will try to use alg_name + * in order to load a kernel module with same name. + * + * Since we don't have any real "crypto-pkcs1pad(rsa,*)" kernel modules, + * we are safe to fail such module request from crypto_larval_lookup(), and + * avoid the verification loop. + * + * Return: Zero if it is safe to load the kernel module, -EINVAL otherwise. + */ +static int ima_kernel_module_request(char *kmod_name) +{ + if (strncmp(kmod_name, "crypto-pkcs1pad(rsa,", 20) == 0) + return -EINVAL; + + return 0; +} + +#endif /* CONFIG_INTEGRITY_ASYMMETRIC_KEYS */ + static int __init init_ima(void) { int error; @@ -1120,4 +1153,49 @@ static int __init init_ima(void) return error; } +static struct security_hook_list ima_hooks[] __ro_after_init = { + LSM_HOOK_INIT(bprm_check_security, ima_bprm_check), + LSM_HOOK_INIT(file_post_open, ima_file_check), + LSM_HOOK_INIT(inode_post_create_tmpfile, ima_post_create_tmpfile), + LSM_HOOK_INIT(file_release, ima_file_free), + LSM_HOOK_INIT(mmap_file, ima_file_mmap), + LSM_HOOK_INIT(file_mprotect, ima_file_mprotect), + LSM_HOOK_INIT(kernel_load_data, ima_load_data), + LSM_HOOK_INIT(kernel_post_load_data, ima_post_load_data), + LSM_HOOK_INIT(kernel_read_file, ima_read_file), + LSM_HOOK_INIT(kernel_post_read_file, ima_post_read_file), + LSM_HOOK_INIT(path_post_mknod, ima_post_path_mknod), +#ifdef CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS + LSM_HOOK_INIT(key_post_create_or_update, ima_post_key_create_or_update), +#endif +#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS + LSM_HOOK_INIT(kernel_module_request, ima_kernel_module_request), +#endif + LSM_HOOK_INIT(inode_free_security, ima_inode_free), +}; + +static const struct lsm_id ima_lsmid = { + .name = "ima", + .id = LSM_ID_IMA, +}; + +static int __init init_ima_lsm(void) +{ + ima_iintcache_init(); + security_add_hooks(ima_hooks, ARRAY_SIZE(ima_hooks), &ima_lsmid); + init_ima_appraise_lsm(&ima_lsmid); + return 0; +} + +struct lsm_blob_sizes ima_blob_sizes __ro_after_init = { + .lbs_inode = sizeof(struct ima_iint_cache *), +}; + +DEFINE_LSM(ima) = { + .name = "ima", + .init = init_ima_lsm, + .order = LSM_ORDER_LAST, + .blobs = &ima_blob_sizes, +}; + late_initcall(init_ima); /* Start IMA after the TPM is available */ diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index f69062617754..c0556907c2e6 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -49,7 +49,7 @@ #define DONT_HASH 0x0200 #define INVALID_PCR(a) (((a) < 0) || \ - (a) >= (sizeof_field(struct integrity_iint_cache, measured_pcrs) * 8)) + (a) >= (sizeof_field(struct ima_iint_cache, measured_pcrs) * 8)) int ima_policy_flag; static int temp_ima_appraise; diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index 9561db7cf6b4..50d6f798e613 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h @@ -18,60 +18,7 @@ #include #include #include - -/* iint action cache flags */ -#define IMA_MEASURE 0x00000001 -#define IMA_MEASURED 0x00000002 -#define IMA_APPRAISE 0x00000004 -#define IMA_APPRAISED 0x00000008 -/*#define IMA_COLLECT 0x00000010 do not use this flag */ -#define IMA_COLLECTED 0x00000020 -#define IMA_AUDIT 0x00000040 -#define IMA_AUDITED 0x00000080 -#define IMA_HASH 0x00000100 -#define IMA_HASHED 0x00000200 - -/* iint policy rule cache flags */ -#define IMA_NONACTION_FLAGS 0xff000000 -#define IMA_DIGSIG_REQUIRED 0x01000000 -#define IMA_PERMIT_DIRECTIO 0x02000000 -#define IMA_NEW_FILE 0x04000000 -#define EVM_IMMUTABLE_DIGSIG 0x08000000 -#define IMA_FAIL_UNVERIFIABLE_SIGS 0x10000000 -#define IMA_MODSIG_ALLOWED 0x20000000 -#define IMA_CHECK_BLACKLIST 0x40000000 -#define IMA_VERITY_REQUIRED 0x80000000 - -#define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT | \ - IMA_HASH | IMA_APPRAISE_SUBMASK) -#define IMA_DONE_MASK (IMA_MEASURED | IMA_APPRAISED | IMA_AUDITED | \ - IMA_HASHED | IMA_COLLECTED | \ - IMA_APPRAISED_SUBMASK) - -/* iint subaction appraise cache flags */ -#define IMA_FILE_APPRAISE 0x00001000 -#define IMA_FILE_APPRAISED 0x00002000 -#define IMA_MMAP_APPRAISE 0x00004000 -#define IMA_MMAP_APPRAISED 0x00008000 -#define IMA_BPRM_APPRAISE 0x00010000 -#define IMA_BPRM_APPRAISED 0x00020000 -#define IMA_READ_APPRAISE 0x00040000 -#define IMA_READ_APPRAISED 0x00080000 -#define IMA_CREDS_APPRAISE 0x00100000 -#define IMA_CREDS_APPRAISED 0x00200000 -#define IMA_APPRAISE_SUBMASK (IMA_FILE_APPRAISE | IMA_MMAP_APPRAISE | \ - IMA_BPRM_APPRAISE | IMA_READ_APPRAISE | \ - IMA_CREDS_APPRAISE) -#define IMA_APPRAISED_SUBMASK (IMA_FILE_APPRAISED | IMA_MMAP_APPRAISED | \ - IMA_BPRM_APPRAISED | IMA_READ_APPRAISED | \ - IMA_CREDS_APPRAISED) - -/* iint cache atomic_flags */ -#define IMA_CHANGE_XATTR 0 -#define IMA_UPDATE_XATTR 1 -#define IMA_CHANGE_ATTR 2 -#define IMA_DIGSIG 3 -#define IMA_MUST_MEASURE 4 +#include enum evm_ima_xattr_type { IMA_XATTR_DIGEST = 0x01, @@ -155,31 +102,6 @@ struct ima_file_id { __u8 hash[HASH_MAX_DIGESTSIZE]; } __packed; -/* integrity data associated with an inode */ -struct integrity_iint_cache { - struct rb_node rb_node; /* rooted in integrity_iint_tree */ - struct mutex mutex; /* protects: version, flags, digest */ - struct inode *inode; /* back pointer to inode in question */ - u64 version; /* track inode changes */ - unsigned long flags; - unsigned long measured_pcrs; - unsigned long atomic_flags; - unsigned long real_ino; - dev_t real_dev; - enum integrity_status ima_file_status:4; - enum integrity_status ima_mmap_status:4; - enum integrity_status ima_bprm_status:4; - enum integrity_status ima_read_status:4; - enum integrity_status ima_creds_status:4; - enum integrity_status evm_status:4; - struct ima_digest_data *ima_hash; -}; - -/* rbtree tree calls to lookup, insert, delete - * integrity data associated with an inode. - */ -struct integrity_iint_cache *integrity_iint_find(struct inode *inode); - int integrity_kernel_read(struct file *file, loff_t offset, void *addr, unsigned long count); diff --git a/security/keys/key.c b/security/keys/key.c index 5b10641debd5..560790038329 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include "internal.h" @@ -930,8 +929,8 @@ static key_ref_t __key_create_or_update(key_ref_t keyring_ref, goto error_link_end; } - ima_post_key_create_or_update(keyring, key, payload, plen, - flags, true); + security_key_post_create_or_update(keyring, key, payload, plen, flags, + true); key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); @@ -964,9 +963,8 @@ error: key_ref = __key_update(key_ref, &prep); if (!IS_ERR(key_ref)) - ima_post_key_create_or_update(keyring, key, - payload, plen, - flags, false); + security_key_post_create_or_update(keyring, key, payload, plen, + flags, false); goto error_free_prep; } diff --git a/security/security.c b/security/security.c index aef69632d0a9..a07f43c58d65 100644 --- a/security/security.c +++ b/security/security.c @@ -19,15 +19,13 @@ #include #include #include -#include -#include -#include #include #include #include #include #include #include +#include #include #include #include @@ -51,7 +49,9 @@ (IS_ENABLED(CONFIG_SECURITY_SAFESETID) ? 1 : 0) + \ (IS_ENABLED(CONFIG_SECURITY_LOCKDOWN_LSM) ? 1 : 0) + \ (IS_ENABLED(CONFIG_BPF_LSM) ? 1 : 0) + \ - (IS_ENABLED(CONFIG_SECURITY_LANDLOCK) ? 1 : 0)) + (IS_ENABLED(CONFIG_SECURITY_LANDLOCK) ? 1 : 0) + \ + (IS_ENABLED(CONFIG_IMA) ? 1 : 0) + \ + (IS_ENABLED(CONFIG_EVM) ? 1 : 0)) /* * These are descriptions of the reasons that can be passed to the @@ -856,14 +856,14 @@ out: P->hook.FUNC(__VA_ARGS__); \ } while (0) -#define call_int_hook(FUNC, IRC, ...) ({ \ - int RC = IRC; \ +#define call_int_hook(FUNC, ...) ({ \ + int RC = LSM_RET_DEFAULT(FUNC); \ do { \ struct security_hook_list *P; \ \ hlist_for_each_entry(P, &security_hook_heads.FUNC, list) { \ RC = P->hook.FUNC(__VA_ARGS__); \ - if (RC != 0) \ + if (RC != LSM_RET_DEFAULT(FUNC)) \ break; \ } \ } while (0); \ @@ -882,7 +882,7 @@ out: */ int security_binder_set_context_mgr(const struct cred *mgr) { - return call_int_hook(binder_set_context_mgr, 0, mgr); + return call_int_hook(binder_set_context_mgr, mgr); } /** @@ -897,7 +897,7 @@ int security_binder_set_context_mgr(const struct cred *mgr) int security_binder_transaction(const struct cred *from, const struct cred *to) { - return call_int_hook(binder_transaction, 0, from, to); + return call_int_hook(binder_transaction, from, to); } /** @@ -912,7 +912,7 @@ int security_binder_transaction(const struct cred *from, int security_binder_transfer_binder(const struct cred *from, const struct cred *to) { - return call_int_hook(binder_transfer_binder, 0, from, to); + return call_int_hook(binder_transfer_binder, from, to); } /** @@ -928,7 +928,7 @@ int security_binder_transfer_binder(const struct cred *from, int security_binder_transfer_file(const struct cred *from, const struct cred *to, const struct file *file) { - return call_int_hook(binder_transfer_file, 0, from, to, file); + return call_int_hook(binder_transfer_file, from, to, file); } /** @@ -947,7 +947,7 @@ int security_binder_transfer_file(const struct cred *from, */ int security_ptrace_access_check(struct task_struct *child, unsigned int mode) { - return call_int_hook(ptrace_access_check, 0, child, mode); + return call_int_hook(ptrace_access_check, child, mode); } /** @@ -962,7 +962,7 @@ int security_ptrace_access_check(struct task_struct *child, unsigned int mode) */ int security_ptrace_traceme(struct task_struct *parent) { - return call_int_hook(ptrace_traceme, 0, parent); + return call_int_hook(ptrace_traceme, parent); } /** @@ -984,8 +984,7 @@ int security_capget(const struct task_struct *target, kernel_cap_t *inheritable, kernel_cap_t *permitted) { - return call_int_hook(capget, 0, target, - effective, inheritable, permitted); + return call_int_hook(capget, target, effective, inheritable, permitted); } /** @@ -1006,8 +1005,8 @@ int security_capset(struct cred *new, const struct cred *old, const kernel_cap_t *inheritable, const kernel_cap_t *permitted) { - return call_int_hook(capset, 0, new, old, - effective, inheritable, permitted); + return call_int_hook(capset, new, old, effective, inheritable, + permitted); } /** @@ -1028,7 +1027,7 @@ int security_capable(const struct cred *cred, int cap, unsigned int opts) { - return call_int_hook(capable, 0, cred, ns, cap, opts); + return call_int_hook(capable, cred, ns, cap, opts); } /** @@ -1044,7 +1043,7 @@ int security_capable(const struct cred *cred, */ int security_quotactl(int cmds, int type, int id, const struct super_block *sb) { - return call_int_hook(quotactl, 0, cmds, type, id, sb); + return call_int_hook(quotactl, cmds, type, id, sb); } /** @@ -1057,7 +1056,7 @@ int security_quotactl(int cmds, int type, int id, const struct super_block *sb) */ int security_quota_on(struct dentry *dentry) { - return call_int_hook(quota_on, 0, dentry); + return call_int_hook(quota_on, dentry); } /** @@ -1072,7 +1071,7 @@ int security_quota_on(struct dentry *dentry) */ int security_syslog(int type) { - return call_int_hook(syslog, 0, type); + return call_int_hook(syslog, type); } /** @@ -1087,7 +1086,7 @@ int security_syslog(int type) */ int security_settime64(const struct timespec64 *ts, const struct timezone *tz) { - return call_int_hook(settime, 0, ts, tz); + return call_int_hook(settime, ts, tz); } /** @@ -1142,7 +1141,7 @@ int security_vm_enough_memory_mm(struct mm_struct *mm, long pages) */ int security_bprm_creds_for_exec(struct linux_binprm *bprm) { - return call_int_hook(bprm_creds_for_exec, 0, bprm); + return call_int_hook(bprm_creds_for_exec, bprm); } /** @@ -1166,7 +1165,7 @@ int security_bprm_creds_for_exec(struct linux_binprm *bprm) */ int security_bprm_creds_from_file(struct linux_binprm *bprm, const struct file *file) { - return call_int_hook(bprm_creds_from_file, 0, bprm, file); + return call_int_hook(bprm_creds_from_file, bprm, file); } /** @@ -1183,12 +1182,7 @@ int security_bprm_creds_from_file(struct linux_binprm *bprm, const struct file * */ int security_bprm_check(struct linux_binprm *bprm) { - int ret; - - ret = call_int_hook(bprm_check_security, 0, bprm); - if (ret) - return ret; - return ima_bprm_check(bprm); + return call_int_hook(bprm_check_security, bprm); } /** @@ -1235,7 +1229,7 @@ void security_bprm_committed_creds(const struct linux_binprm *bprm) */ int security_fs_context_submount(struct fs_context *fc, struct super_block *reference) { - return call_int_hook(fs_context_submount, 0, fc, reference); + return call_int_hook(fs_context_submount, fc, reference); } /** @@ -1251,7 +1245,7 @@ int security_fs_context_submount(struct fs_context *fc, struct super_block *refe */ int security_fs_context_dup(struct fs_context *fc, struct fs_context *src_fc) { - return call_int_hook(fs_context_dup, 0, fc, src_fc); + return call_int_hook(fs_context_dup, fc, src_fc); } /** @@ -1300,7 +1294,7 @@ int security_sb_alloc(struct super_block *sb) if (unlikely(rc)) return rc; - rc = call_int_hook(sb_alloc_security, 0, sb); + rc = call_int_hook(sb_alloc_security, sb); if (unlikely(rc)) security_sb_free(sb); return rc; @@ -1358,7 +1352,7 @@ EXPORT_SYMBOL(security_free_mnt_opts); */ int security_sb_eat_lsm_opts(char *options, void **mnt_opts) { - return call_int_hook(sb_eat_lsm_opts, 0, options, mnt_opts); + return call_int_hook(sb_eat_lsm_opts, options, mnt_opts); } EXPORT_SYMBOL(security_sb_eat_lsm_opts); @@ -1375,7 +1369,7 @@ EXPORT_SYMBOL(security_sb_eat_lsm_opts); int security_sb_mnt_opts_compat(struct super_block *sb, void *mnt_opts) { - return call_int_hook(sb_mnt_opts_compat, 0, sb, mnt_opts); + return call_int_hook(sb_mnt_opts_compat, sb, mnt_opts); } EXPORT_SYMBOL(security_sb_mnt_opts_compat); @@ -1392,7 +1386,7 @@ EXPORT_SYMBOL(security_sb_mnt_opts_compat); int security_sb_remount(struct super_block *sb, void *mnt_opts) { - return call_int_hook(sb_remount, 0, sb, mnt_opts); + return call_int_hook(sb_remount, sb, mnt_opts); } EXPORT_SYMBOL(security_sb_remount); @@ -1406,7 +1400,7 @@ EXPORT_SYMBOL(security_sb_remount); */ int security_sb_kern_mount(const struct super_block *sb) { - return call_int_hook(sb_kern_mount, 0, sb); + return call_int_hook(sb_kern_mount, sb); } /** @@ -1420,7 +1414,7 @@ int security_sb_kern_mount(const struct super_block *sb) */ int security_sb_show_options(struct seq_file *m, struct super_block *sb) { - return call_int_hook(sb_show_options, 0, m, sb); + return call_int_hook(sb_show_options, m, sb); } /** @@ -1434,7 +1428,7 @@ int security_sb_show_options(struct seq_file *m, struct super_block *sb) */ int security_sb_statfs(struct dentry *dentry) { - return call_int_hook(sb_statfs, 0, dentry); + return call_int_hook(sb_statfs, dentry); } /** @@ -1457,7 +1451,7 @@ int security_sb_statfs(struct dentry *dentry) int security_sb_mount(const char *dev_name, const struct path *path, const char *type, unsigned long flags, void *data) { - return call_int_hook(sb_mount, 0, dev_name, path, type, flags, data); + return call_int_hook(sb_mount, dev_name, path, type, flags, data); } /** @@ -1471,7 +1465,7 @@ int security_sb_mount(const char *dev_name, const struct path *path, */ int security_sb_umount(struct vfsmount *mnt, int flags) { - return call_int_hook(sb_umount, 0, mnt, flags); + return call_int_hook(sb_umount, mnt, flags); } /** @@ -1486,7 +1480,7 @@ int security_sb_umount(struct vfsmount *mnt, int flags) int security_sb_pivotroot(const struct path *old_path, const struct path *new_path) { - return call_int_hook(sb_pivotroot, 0, old_path, new_path); + return call_int_hook(sb_pivotroot, old_path, new_path); } /** @@ -1505,9 +1499,17 @@ int security_sb_set_mnt_opts(struct super_block *sb, unsigned long kern_flags, unsigned long *set_kern_flags) { - return call_int_hook(sb_set_mnt_opts, - mnt_opts ? -EOPNOTSUPP : 0, sb, - mnt_opts, kern_flags, set_kern_flags); + struct security_hook_list *hp; + int rc = mnt_opts ? -EOPNOTSUPP : LSM_RET_DEFAULT(sb_set_mnt_opts); + + hlist_for_each_entry(hp, &security_hook_heads.sb_set_mnt_opts, + list) { + rc = hp->hook.sb_set_mnt_opts(sb, mnt_opts, kern_flags, + set_kern_flags); + if (rc != LSM_RET_DEFAULT(sb_set_mnt_opts)) + break; + } + return rc; } EXPORT_SYMBOL(security_sb_set_mnt_opts); @@ -1527,7 +1529,7 @@ int security_sb_clone_mnt_opts(const struct super_block *oldsb, unsigned long kern_flags, unsigned long *set_kern_flags) { - return call_int_hook(sb_clone_mnt_opts, 0, oldsb, newsb, + return call_int_hook(sb_clone_mnt_opts, oldsb, newsb, kern_flags, set_kern_flags); } EXPORT_SYMBOL(security_sb_clone_mnt_opts); @@ -1544,7 +1546,7 @@ EXPORT_SYMBOL(security_sb_clone_mnt_opts); int security_move_mount(const struct path *from_path, const struct path *to_path) { - return call_int_hook(move_mount, 0, from_path, to_path); + return call_int_hook(move_mount, from_path, to_path); } /** @@ -1561,7 +1563,7 @@ int security_move_mount(const struct path *from_path, int security_path_notify(const struct path *path, u64 mask, unsigned int obj_type) { - return call_int_hook(path_notify, 0, path, mask, obj_type); + return call_int_hook(path_notify, path, mask, obj_type); } /** @@ -1580,7 +1582,7 @@ int security_inode_alloc(struct inode *inode) if (unlikely(rc)) return rc; - rc = call_int_hook(inode_alloc_security, 0, inode); + rc = call_int_hook(inode_alloc_security, inode); if (unlikely(rc)) security_inode_free(inode); return rc; @@ -1602,7 +1604,6 @@ static void inode_free_by_rcu(struct rcu_head *head) */ void security_inode_free(struct inode *inode) { - integrity_inode_free(inode); call_void_hook(inode_free_security, inode); /* * The inode may still be referenced in a path walk and @@ -1638,20 +1639,8 @@ int security_dentry_init_security(struct dentry *dentry, int mode, const char **xattr_name, void **ctx, u32 *ctxlen) { - struct security_hook_list *hp; - int rc; - - /* - * Only one module will provide a security context. - */ - hlist_for_each_entry(hp, &security_hook_heads.dentry_init_security, - list) { - rc = hp->hook.dentry_init_security(dentry, mode, name, - xattr_name, ctx, ctxlen); - if (rc != LSM_RET_DEFAULT(dentry_init_security)) - return rc; - } - return LSM_RET_DEFAULT(dentry_init_security); + return call_int_hook(dentry_init_security, dentry, mode, name, + xattr_name, ctx, ctxlen); } EXPORT_SYMBOL(security_dentry_init_security); @@ -1674,7 +1663,7 @@ int security_dentry_create_files_as(struct dentry *dentry, int mode, struct qstr *name, const struct cred *old, struct cred *new) { - return call_int_hook(dentry_create_files_as, 0, dentry, mode, + return call_int_hook(dentry_create_files_as, dentry, mode, name, old, new); } EXPORT_SYMBOL(security_dentry_create_files_as); @@ -1721,8 +1710,8 @@ int security_inode_init_security(struct inode *inode, struct inode *dir, return 0; if (initxattrs) { - /* Allocate +1 for EVM and +1 as terminator. */ - new_xattrs = kcalloc(blob_sizes.lbs_xattr_count + 2, + /* Allocate +1 as terminator. */ + new_xattrs = kcalloc(blob_sizes.lbs_xattr_count + 1, sizeof(*new_xattrs), GFP_NOFS); if (!new_xattrs) return -ENOMEM; @@ -1746,10 +1735,6 @@ int security_inode_init_security(struct inode *inode, struct inode *dir, if (!xattr_count) goto out; - ret = evm_inode_init_security(inode, dir, qstr, new_xattrs, - &xattr_count); - if (ret) - goto out; ret = initxattrs(inode, new_xattrs, fs_data); out: for (; xattr_count > 0; xattr_count--) @@ -1775,7 +1760,7 @@ int security_inode_init_security_anon(struct inode *inode, const struct qstr *name, const struct inode *context_inode) { - return call_int_hook(inode_init_security_anon, 0, inode, name, + return call_int_hook(inode_init_security_anon, inode, name, context_inode); } @@ -1797,10 +1782,24 @@ int security_path_mknod(const struct path *dir, struct dentry *dentry, { if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry)))) return 0; - return call_int_hook(path_mknod, 0, dir, dentry, mode, dev); + return call_int_hook(path_mknod, dir, dentry, mode, dev); } EXPORT_SYMBOL(security_path_mknod); +/** + * security_path_post_mknod() - Update inode security field after file creation + * @idmap: idmap of the mount + * @dentry: new file + * + * Update inode security field after a file has been created. + */ +void security_path_post_mknod(struct mnt_idmap *idmap, struct dentry *dentry) +{ + if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) + return; + call_void_hook(path_post_mknod, idmap, dentry); +} + /** * security_path_mkdir() - Check if creating a new directory is allowed * @dir: parent directory @@ -1816,7 +1815,7 @@ int security_path_mkdir(const struct path *dir, struct dentry *dentry, { if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry)))) return 0; - return call_int_hook(path_mkdir, 0, dir, dentry, mode); + return call_int_hook(path_mkdir, dir, dentry, mode); } EXPORT_SYMBOL(security_path_mkdir); @@ -1833,7 +1832,7 @@ int security_path_rmdir(const struct path *dir, struct dentry *dentry) { if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry)))) return 0; - return call_int_hook(path_rmdir, 0, dir, dentry); + return call_int_hook(path_rmdir, dir, dentry); } /** @@ -1849,7 +1848,7 @@ int security_path_unlink(const struct path *dir, struct dentry *dentry) { if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry)))) return 0; - return call_int_hook(path_unlink, 0, dir, dentry); + return call_int_hook(path_unlink, dir, dentry); } EXPORT_SYMBOL(security_path_unlink); @@ -1868,7 +1867,7 @@ int security_path_symlink(const struct path *dir, struct dentry *dentry, { if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry)))) return 0; - return call_int_hook(path_symlink, 0, dir, dentry, old_name); + return call_int_hook(path_symlink, dir, dentry, old_name); } /** @@ -1886,7 +1885,7 @@ int security_path_link(struct dentry *old_dentry, const struct path *new_dir, { if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)))) return 0; - return call_int_hook(path_link, 0, old_dentry, new_dir, new_dentry); + return call_int_hook(path_link, old_dentry, new_dir, new_dentry); } /** @@ -1910,7 +1909,7 @@ int security_path_rename(const struct path *old_dir, struct dentry *old_dentry, IS_PRIVATE(d_backing_inode(new_dentry))))) return 0; - return call_int_hook(path_rename, 0, old_dir, old_dentry, new_dir, + return call_int_hook(path_rename, old_dir, old_dentry, new_dir, new_dentry, flags); } EXPORT_SYMBOL(security_path_rename); @@ -1929,7 +1928,7 @@ int security_path_truncate(const struct path *path) { if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry)))) return 0; - return call_int_hook(path_truncate, 0, path); + return call_int_hook(path_truncate, path); } /** @@ -1947,7 +1946,7 @@ int security_path_chmod(const struct path *path, umode_t mode) { if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry)))) return 0; - return call_int_hook(path_chmod, 0, path, mode); + return call_int_hook(path_chmod, path, mode); } /** @@ -1964,7 +1963,7 @@ int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid) { if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry)))) return 0; - return call_int_hook(path_chown, 0, path, uid, gid); + return call_int_hook(path_chown, path, uid, gid); } /** @@ -1977,7 +1976,7 @@ int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid) */ int security_path_chroot(const struct path *path) { - return call_int_hook(path_chroot, 0, path); + return call_int_hook(path_chroot, path); } #endif /* CONFIG_SECURITY_PATH */ @@ -1996,10 +1995,25 @@ int security_inode_create(struct inode *dir, struct dentry *dentry, { if (unlikely(IS_PRIVATE(dir))) return 0; - return call_int_hook(inode_create, 0, dir, dentry, mode); + return call_int_hook(inode_create, dir, dentry, mode); } EXPORT_SYMBOL_GPL(security_inode_create); +/** + * security_inode_post_create_tmpfile() - Update inode security of new tmpfile + * @idmap: idmap of the mount + * @inode: inode of the new tmpfile + * + * Update inode security data after a tmpfile has been created. + */ +void security_inode_post_create_tmpfile(struct mnt_idmap *idmap, + struct inode *inode) +{ + if (unlikely(IS_PRIVATE(inode))) + return; + call_void_hook(inode_post_create_tmpfile, idmap, inode); +} + /** * security_inode_link() - Check if creating a hard link is allowed * @old_dentry: existing file @@ -2015,7 +2029,7 @@ int security_inode_link(struct dentry *old_dentry, struct inode *dir, { if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)))) return 0; - return call_int_hook(inode_link, 0, old_dentry, dir, new_dentry); + return call_int_hook(inode_link, old_dentry, dir, new_dentry); } /** @@ -2031,7 +2045,7 @@ int security_inode_unlink(struct inode *dir, struct dentry *dentry) { if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return 0; - return call_int_hook(inode_unlink, 0, dir, dentry); + return call_int_hook(inode_unlink, dir, dentry); } /** @@ -2049,7 +2063,7 @@ int security_inode_symlink(struct inode *dir, struct dentry *dentry, { if (unlikely(IS_PRIVATE(dir))) return 0; - return call_int_hook(inode_symlink, 0, dir, dentry, old_name); + return call_int_hook(inode_symlink, dir, dentry, old_name); } /** @@ -2067,7 +2081,7 @@ int security_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) { if (unlikely(IS_PRIVATE(dir))) return 0; - return call_int_hook(inode_mkdir, 0, dir, dentry, mode); + return call_int_hook(inode_mkdir, dir, dentry, mode); } EXPORT_SYMBOL_GPL(security_inode_mkdir); @@ -2084,7 +2098,7 @@ int security_inode_rmdir(struct inode *dir, struct dentry *dentry) { if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return 0; - return call_int_hook(inode_rmdir, 0, dir, dentry); + return call_int_hook(inode_rmdir, dir, dentry); } /** @@ -2106,7 +2120,7 @@ int security_inode_mknod(struct inode *dir, struct dentry *dentry, { if (unlikely(IS_PRIVATE(dir))) return 0; - return call_int_hook(inode_mknod, 0, dir, dentry, mode, dev); + return call_int_hook(inode_mknod, dir, dentry, mode, dev); } /** @@ -2131,13 +2145,13 @@ int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry, return 0; if (flags & RENAME_EXCHANGE) { - int err = call_int_hook(inode_rename, 0, new_dir, new_dentry, + int err = call_int_hook(inode_rename, new_dir, new_dentry, old_dir, old_dentry); if (err) return err; } - return call_int_hook(inode_rename, 0, old_dir, old_dentry, + return call_int_hook(inode_rename, old_dir, old_dentry, new_dir, new_dentry); } @@ -2153,7 +2167,7 @@ int security_inode_readlink(struct dentry *dentry) { if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return 0; - return call_int_hook(inode_readlink, 0, dentry); + return call_int_hook(inode_readlink, dentry); } /** @@ -2172,7 +2186,7 @@ int security_inode_follow_link(struct dentry *dentry, struct inode *inode, { if (unlikely(IS_PRIVATE(inode))) return 0; - return call_int_hook(inode_follow_link, 0, dentry, inode, rcu); + return call_int_hook(inode_follow_link, dentry, inode, rcu); } /** @@ -2193,7 +2207,7 @@ int security_inode_permission(struct inode *inode, int mask) { if (unlikely(IS_PRIVATE(inode))) return 0; - return call_int_hook(inode_permission, 0, inode, mask); + return call_int_hook(inode_permission, inode, mask); } /** @@ -2212,17 +2226,28 @@ int security_inode_permission(struct inode *inode, int mask) int security_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry, struct iattr *attr) { - int ret; - if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return 0; - ret = call_int_hook(inode_setattr, 0, dentry, attr); - if (ret) - return ret; - return evm_inode_setattr(idmap, dentry, attr); + return call_int_hook(inode_setattr, idmap, dentry, attr); } EXPORT_SYMBOL_GPL(security_inode_setattr); +/** + * security_inode_post_setattr() - Update the inode after a setattr operation + * @idmap: idmap of the mount + * @dentry: file + * @ia_valid: file attributes set + * + * Update inode security field after successful setting file attributes. + */ +void security_inode_post_setattr(struct mnt_idmap *idmap, struct dentry *dentry, + int ia_valid) +{ + if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) + return; + call_void_hook(inode_post_setattr, idmap, dentry, ia_valid); +} + /** * security_inode_getattr() - Check if getting file attributes is allowed * @path: file @@ -2235,7 +2260,7 @@ int security_inode_getattr(const struct path *path) { if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry)))) return 0; - return call_int_hook(inode_getattr, 0, path); + return call_int_hook(inode_getattr, path); } /** @@ -2263,17 +2288,12 @@ int security_inode_setxattr(struct mnt_idmap *idmap, * SELinux and Smack integrate the cap call, * so assume that all LSMs supplying this call do so. */ - ret = call_int_hook(inode_setxattr, 1, idmap, dentry, name, value, - size, flags); + ret = call_int_hook(inode_setxattr, idmap, dentry, name, value, size, + flags); if (ret == 1) ret = cap_inode_setxattr(dentry, name, value, size, flags); - if (ret) - return ret; - ret = ima_inode_setxattr(dentry, name, value, size); - if (ret) - return ret; - return evm_inode_setxattr(idmap, dentry, name, value, size); + return ret; } /** @@ -2292,18 +2312,26 @@ int security_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name, struct posix_acl *kacl) { - int ret; - if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return 0; - ret = call_int_hook(inode_set_acl, 0, idmap, dentry, acl_name, - kacl); - if (ret) - return ret; - ret = ima_inode_set_acl(idmap, dentry, acl_name, kacl); - if (ret) - return ret; - return evm_inode_set_acl(idmap, dentry, acl_name, kacl); + return call_int_hook(inode_set_acl, idmap, dentry, acl_name, kacl); +} + +/** + * security_inode_post_set_acl() - Update inode security from posix acls set + * @dentry: file + * @acl_name: acl name + * @kacl: acl struct + * + * Update inode security data after successfully setting posix acls on @dentry. + * The posix acls in @kacl are identified by @acl_name. + */ +void security_inode_post_set_acl(struct dentry *dentry, const char *acl_name, + struct posix_acl *kacl) +{ + if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) + return; + call_void_hook(inode_post_set_acl, dentry, acl_name, kacl); } /** @@ -2322,7 +2350,7 @@ int security_inode_get_acl(struct mnt_idmap *idmap, { if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return 0; - return call_int_hook(inode_get_acl, 0, idmap, dentry, acl_name); + return call_int_hook(inode_get_acl, idmap, dentry, acl_name); } /** @@ -2339,17 +2367,26 @@ int security_inode_get_acl(struct mnt_idmap *idmap, int security_inode_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name) { - int ret; - if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return 0; - ret = call_int_hook(inode_remove_acl, 0, idmap, dentry, acl_name); - if (ret) - return ret; - ret = ima_inode_remove_acl(idmap, dentry, acl_name); - if (ret) - return ret; - return evm_inode_remove_acl(idmap, dentry, acl_name); + return call_int_hook(inode_remove_acl, idmap, dentry, acl_name); +} + +/** + * security_inode_post_remove_acl() - Update inode security after rm posix acls + * @idmap: idmap of the mount + * @dentry: file + * @acl_name: acl name + * + * Update inode security data after successfully removing posix acls on + * @dentry in @idmap. The posix acls are identified by @acl_name. + */ +void security_inode_post_remove_acl(struct mnt_idmap *idmap, + struct dentry *dentry, const char *acl_name) +{ + if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) + return; + call_void_hook(inode_post_remove_acl, idmap, dentry, acl_name); } /** @@ -2368,7 +2405,6 @@ void security_inode_post_setxattr(struct dentry *dentry, const char *name, if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return; call_void_hook(inode_post_setxattr, dentry, name, value, size, flags); - evm_inode_post_setxattr(dentry, name, value, size); } /** @@ -2385,7 +2421,7 @@ int security_inode_getxattr(struct dentry *dentry, const char *name) { if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return 0; - return call_int_hook(inode_getxattr, 0, dentry, name); + return call_int_hook(inode_getxattr, dentry, name); } /** @@ -2401,7 +2437,7 @@ int security_inode_listxattr(struct dentry *dentry) { if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) return 0; - return call_int_hook(inode_listxattr, 0, dentry); + return call_int_hook(inode_listxattr, dentry); } /** @@ -2426,15 +2462,24 @@ int security_inode_removexattr(struct mnt_idmap *idmap, * SELinux and Smack integrate the cap call, * so assume that all LSMs supplying this call do so. */ - ret = call_int_hook(inode_removexattr, 1, idmap, dentry, name); + ret = call_int_hook(inode_removexattr, idmap, dentry, name); if (ret == 1) ret = cap_inode_removexattr(idmap, dentry, name); - if (ret) - return ret; - ret = ima_inode_removexattr(dentry, name); - if (ret) - return ret; - return evm_inode_removexattr(idmap, dentry, name); + return ret; +} + +/** + * security_inode_post_removexattr() - Update the inode after a removexattr op + * @dentry: file + * @name: xattr name + * + * Update the inode after a successful removexattr operation. + */ +void security_inode_post_removexattr(struct dentry *dentry, const char *name) +{ + if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) + return; + call_void_hook(inode_post_removexattr, dentry, name); } /** @@ -2450,7 +2495,7 @@ int security_inode_removexattr(struct mnt_idmap *idmap, */ int security_inode_need_killpriv(struct dentry *dentry) { - return call_int_hook(inode_need_killpriv, 0, dentry); + return call_int_hook(inode_need_killpriv, dentry); } /** @@ -2467,7 +2512,7 @@ int security_inode_need_killpriv(struct dentry *dentry) int security_inode_killpriv(struct mnt_idmap *idmap, struct dentry *dentry) { - return call_int_hook(inode_killpriv, 0, idmap, dentry); + return call_int_hook(inode_killpriv, idmap, dentry); } /** @@ -2490,21 +2535,11 @@ int security_inode_getsecurity(struct mnt_idmap *idmap, struct inode *inode, const char *name, void **buffer, bool alloc) { - struct security_hook_list *hp; - int rc; - if (unlikely(IS_PRIVATE(inode))) return LSM_RET_DEFAULT(inode_getsecurity); - /* - * Only one module will provide an attribute with a given name. - */ - hlist_for_each_entry(hp, &security_hook_heads.inode_getsecurity, list) { - rc = hp->hook.inode_getsecurity(idmap, inode, name, buffer, - alloc); - if (rc != LSM_RET_DEFAULT(inode_getsecurity)) - return rc; - } - return LSM_RET_DEFAULT(inode_getsecurity); + + return call_int_hook(inode_getsecurity, idmap, inode, name, buffer, + alloc); } /** @@ -2525,21 +2560,11 @@ int security_inode_getsecurity(struct mnt_idmap *idmap, int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags) { - struct security_hook_list *hp; - int rc; - if (unlikely(IS_PRIVATE(inode))) return LSM_RET_DEFAULT(inode_setsecurity); - /* - * Only one module will provide an attribute with a given name. - */ - hlist_for_each_entry(hp, &security_hook_heads.inode_setsecurity, list) { - rc = hp->hook.inode_setsecurity(inode, name, value, size, - flags); - if (rc != LSM_RET_DEFAULT(inode_setsecurity)) - return rc; - } - return LSM_RET_DEFAULT(inode_setsecurity); + + return call_int_hook(inode_setsecurity, inode, name, value, size, + flags); } /** @@ -2560,7 +2585,7 @@ int security_inode_listsecurity(struct inode *inode, { if (unlikely(IS_PRIVATE(inode))) return 0; - return call_int_hook(inode_listsecurity, 0, inode, buffer, buffer_size); + return call_int_hook(inode_listsecurity, inode, buffer, buffer_size); } EXPORT_SYMBOL(security_inode_listsecurity); @@ -2591,7 +2616,7 @@ void security_inode_getsecid(struct inode *inode, u32 *secid) */ int security_inode_copy_up(struct dentry *src, struct cred **new) { - return call_int_hook(inode_copy_up, 0, src, new); + return call_int_hook(inode_copy_up, src, new); } EXPORT_SYMBOL(security_inode_copy_up); @@ -2609,7 +2634,6 @@ EXPORT_SYMBOL(security_inode_copy_up); */ int security_inode_copy_up_xattr(const char *name) { - struct security_hook_list *hp; int rc; /* @@ -2617,14 +2641,11 @@ int security_inode_copy_up_xattr(const char *name) * xattr), -EOPNOTSUPP if it does not know anything about the xattr or * any other error code in case of an error. */ - hlist_for_each_entry(hp, - &security_hook_heads.inode_copy_up_xattr, list) { - rc = hp->hook.inode_copy_up_xattr(name); - if (rc != LSM_RET_DEFAULT(inode_copy_up_xattr)) - return rc; - } + rc = call_int_hook(inode_copy_up_xattr, name); + if (rc != LSM_RET_DEFAULT(inode_copy_up_xattr)) + return rc; - return evm_inode_copy_up_xattr(name); + return LSM_RET_DEFAULT(inode_copy_up_xattr); } EXPORT_SYMBOL(security_inode_copy_up_xattr); @@ -2641,7 +2662,7 @@ EXPORT_SYMBOL(security_inode_copy_up_xattr); int security_kernfs_init_security(struct kernfs_node *kn_dir, struct kernfs_node *kn) { - return call_int_hook(kernfs_init_security, 0, kn_dir, kn); + return call_int_hook(kernfs_init_security, kn_dir, kn); } /** @@ -2665,7 +2686,7 @@ int security_kernfs_init_security(struct kernfs_node *kn_dir, */ int security_file_permission(struct file *file, int mask) { - return call_int_hook(file_permission, 0, file, mask); + return call_int_hook(file_permission, file, mask); } /** @@ -2683,12 +2704,23 @@ int security_file_alloc(struct file *file) if (rc) return rc; - rc = call_int_hook(file_alloc_security, 0, file); + rc = call_int_hook(file_alloc_security, file); if (unlikely(rc)) security_file_free(file); return rc; } +/** + * security_file_release() - Perform actions before releasing the file ref + * @file: the file + * + * Perform actions before releasing the last reference to a file. + */ +void security_file_release(struct file *file) +{ + call_void_hook(file_release, file); +} + /** * security_file_free() - Free a file's LSM blob * @file: the file @@ -2723,7 +2755,7 @@ void security_file_free(struct file *file) */ int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - return call_int_hook(file_ioctl, 0, file, cmd, arg); + return call_int_hook(file_ioctl, file, cmd, arg); } EXPORT_SYMBOL_GPL(security_file_ioctl); @@ -2741,7 +2773,7 @@ EXPORT_SYMBOL_GPL(security_file_ioctl); int security_file_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) { - return call_int_hook(file_ioctl_compat, 0, file, cmd, arg); + return call_int_hook(file_ioctl_compat, file, cmd, arg); } EXPORT_SYMBOL_GPL(security_file_ioctl_compat); @@ -2792,13 +2824,8 @@ static inline unsigned long mmap_prot(struct file *file, unsigned long prot) int security_mmap_file(struct file *file, unsigned long prot, unsigned long flags) { - unsigned long prot_adj = mmap_prot(file, prot); - int ret; - - ret = call_int_hook(mmap_file, 0, file, prot, prot_adj, flags); - if (ret) - return ret; - return ima_file_mmap(file, prot, prot_adj, flags); + return call_int_hook(mmap_file, file, prot, mmap_prot(file, prot), + flags); } /** @@ -2811,7 +2838,7 @@ int security_mmap_file(struct file *file, unsigned long prot, */ int security_mmap_addr(unsigned long addr) { - return call_int_hook(mmap_addr, 0, addr); + return call_int_hook(mmap_addr, addr); } /** @@ -2827,12 +2854,7 @@ int security_mmap_addr(unsigned long addr) int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, unsigned long prot) { - int ret; - - ret = call_int_hook(file_mprotect, 0, vma, reqprot, prot); - if (ret) - return ret; - return ima_file_mprotect(vma, prot); + return call_int_hook(file_mprotect, vma, reqprot, prot); } /** @@ -2847,7 +2869,7 @@ int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, */ int security_file_lock(struct file *file, unsigned int cmd) { - return call_int_hook(file_lock, 0, file, cmd); + return call_int_hook(file_lock, file, cmd); } /** @@ -2866,7 +2888,7 @@ int security_file_lock(struct file *file, unsigned int cmd) */ int security_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg) { - return call_int_hook(file_fcntl, 0, file, cmd, arg); + return call_int_hook(file_fcntl, file, cmd, arg); } /** @@ -2900,11 +2922,11 @@ void security_file_set_fowner(struct file *file) int security_file_send_sigiotask(struct task_struct *tsk, struct fown_struct *fown, int sig) { - return call_int_hook(file_send_sigiotask, 0, tsk, fown, sig); + return call_int_hook(file_send_sigiotask, tsk, fown, sig); } /** - * security_file_receive() - Check is receiving a file via IPC is allowed + * security_file_receive() - Check if receiving a file via IPC is allowed * @file: file being received * * This hook allows security modules to control the ability of a process to @@ -2914,7 +2936,7 @@ int security_file_send_sigiotask(struct task_struct *tsk, */ int security_file_receive(struct file *file) { - return call_int_hook(file_receive, 0, file); + return call_int_hook(file_receive, file); } /** @@ -2930,13 +2952,30 @@ int security_file_open(struct file *file) { int ret; - ret = call_int_hook(file_open, 0, file); + ret = call_int_hook(file_open, file); if (ret) return ret; return fsnotify_open_perm(file); } +/** + * security_file_post_open() - Evaluate a file after it has been opened + * @file: the file + * @mask: access mask + * + * Evaluate an opened file and the access mask requested with open(). The hook + * is useful for LSMs that require the file content to be available in order to + * make decisions. + * + * Return: Returns 0 if permission is granted. + */ +int security_file_post_open(struct file *file, int mask) +{ + return call_int_hook(file_post_open, file, mask); +} +EXPORT_SYMBOL_GPL(security_file_post_open); + /** * security_file_truncate() - Check if truncating a file is allowed * @file: file @@ -2949,7 +2988,7 @@ int security_file_open(struct file *file) */ int security_file_truncate(struct file *file) { - return call_int_hook(file_truncate, 0, file); + return call_int_hook(file_truncate, file); } /** @@ -2967,7 +3006,7 @@ int security_task_alloc(struct task_struct *task, unsigned long clone_flags) if (rc) return rc; - rc = call_int_hook(task_alloc, 0, task, clone_flags); + rc = call_int_hook(task_alloc, task, clone_flags); if (unlikely(rc)) security_task_free(task); return rc; @@ -3005,7 +3044,7 @@ int security_cred_alloc_blank(struct cred *cred, gfp_t gfp) if (rc) return rc; - rc = call_int_hook(cred_alloc_blank, 0, cred, gfp); + rc = call_int_hook(cred_alloc_blank, cred, gfp); if (unlikely(rc)) security_cred_free(cred); return rc; @@ -3049,7 +3088,7 @@ int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp) if (rc) return rc; - rc = call_int_hook(cred_prepare, 0, new, old, gfp); + rc = call_int_hook(cred_prepare, new, old, gfp); if (unlikely(rc)) security_cred_free(new); return rc; @@ -3094,7 +3133,7 @@ EXPORT_SYMBOL(security_cred_getsecid); */ int security_kernel_act_as(struct cred *new, u32 secid) { - return call_int_hook(kernel_act_as, 0, new, secid); + return call_int_hook(kernel_act_as, new, secid); } /** @@ -3110,11 +3149,11 @@ int security_kernel_act_as(struct cred *new, u32 secid) */ int security_kernel_create_files_as(struct cred *new, struct inode *inode) { - return call_int_hook(kernel_create_files_as, 0, new, inode); + return call_int_hook(kernel_create_files_as, new, inode); } /** - * security_kernel_module_request() - Check is loading a module is allowed + * security_kernel_module_request() - Check if loading a module is allowed * @kmod_name: module name * * Ability to trigger the kernel to automatically upcall to userspace for @@ -3124,12 +3163,7 @@ int security_kernel_create_files_as(struct cred *new, struct inode *inode) */ int security_kernel_module_request(char *kmod_name) { - int ret; - - ret = call_int_hook(kernel_module_request, 0, kmod_name); - if (ret) - return ret; - return integrity_kernel_module_request(kmod_name); + return call_int_hook(kernel_module_request, kmod_name); } /** @@ -3145,12 +3179,7 @@ int security_kernel_module_request(char *kmod_name) int security_kernel_read_file(struct file *file, enum kernel_read_file_id id, bool contents) { - int ret; - - ret = call_int_hook(kernel_read_file, 0, file, id, contents); - if (ret) - return ret; - return ima_read_file(file, id, contents); + return call_int_hook(kernel_read_file, file, id, contents); } EXPORT_SYMBOL_GPL(security_kernel_read_file); @@ -3170,12 +3199,7 @@ EXPORT_SYMBOL_GPL(security_kernel_read_file); int security_kernel_post_read_file(struct file *file, char *buf, loff_t size, enum kernel_read_file_id id) { - int ret; - - ret = call_int_hook(kernel_post_read_file, 0, file, buf, size, id); - if (ret) - return ret; - return ima_post_read_file(file, buf, size, id); + return call_int_hook(kernel_post_read_file, file, buf, size, id); } EXPORT_SYMBOL_GPL(security_kernel_post_read_file); @@ -3190,12 +3214,7 @@ EXPORT_SYMBOL_GPL(security_kernel_post_read_file); */ int security_kernel_load_data(enum kernel_load_data_id id, bool contents) { - int ret; - - ret = call_int_hook(kernel_load_data, 0, id, contents); - if (ret) - return ret; - return ima_load_data(id, contents); + return call_int_hook(kernel_load_data, id, contents); } EXPORT_SYMBOL_GPL(security_kernel_load_data); @@ -3217,13 +3236,7 @@ int security_kernel_post_load_data(char *buf, loff_t size, enum kernel_load_data_id id, char *description) { - int ret; - - ret = call_int_hook(kernel_post_load_data, 0, buf, size, id, - description); - if (ret) - return ret; - return ima_post_load_data(buf, size, id, description); + return call_int_hook(kernel_post_load_data, buf, size, id, description); } EXPORT_SYMBOL_GPL(security_kernel_post_load_data); @@ -3244,7 +3257,7 @@ EXPORT_SYMBOL_GPL(security_kernel_post_load_data); int security_task_fix_setuid(struct cred *new, const struct cred *old, int flags) { - return call_int_hook(task_fix_setuid, 0, new, old, flags); + return call_int_hook(task_fix_setuid, new, old, flags); } /** @@ -3264,7 +3277,7 @@ int security_task_fix_setuid(struct cred *new, const struct cred *old, int security_task_fix_setgid(struct cred *new, const struct cred *old, int flags) { - return call_int_hook(task_fix_setgid, 0, new, old, flags); + return call_int_hook(task_fix_setgid, new, old, flags); } /** @@ -3281,7 +3294,7 @@ int security_task_fix_setgid(struct cred *new, const struct cred *old, */ int security_task_fix_setgroups(struct cred *new, const struct cred *old) { - return call_int_hook(task_fix_setgroups, 0, new, old); + return call_int_hook(task_fix_setgroups, new, old); } /** @@ -3296,7 +3309,7 @@ int security_task_fix_setgroups(struct cred *new, const struct cred *old) */ int security_task_setpgid(struct task_struct *p, pid_t pgid) { - return call_int_hook(task_setpgid, 0, p, pgid); + return call_int_hook(task_setpgid, p, pgid); } /** @@ -3310,7 +3323,7 @@ int security_task_setpgid(struct task_struct *p, pid_t pgid) */ int security_task_getpgid(struct task_struct *p) { - return call_int_hook(task_getpgid, 0, p); + return call_int_hook(task_getpgid, p); } /** @@ -3323,7 +3336,7 @@ int security_task_getpgid(struct task_struct *p) */ int security_task_getsid(struct task_struct *p) { - return call_int_hook(task_getsid, 0, p); + return call_int_hook(task_getsid, p); } /** @@ -3366,7 +3379,7 @@ EXPORT_SYMBOL(security_task_getsecid_obj); */ int security_task_setnice(struct task_struct *p, int nice) { - return call_int_hook(task_setnice, 0, p, nice); + return call_int_hook(task_setnice, p, nice); } /** @@ -3380,7 +3393,7 @@ int security_task_setnice(struct task_struct *p, int nice) */ int security_task_setioprio(struct task_struct *p, int ioprio) { - return call_int_hook(task_setioprio, 0, p, ioprio); + return call_int_hook(task_setioprio, p, ioprio); } /** @@ -3393,7 +3406,7 @@ int security_task_setioprio(struct task_struct *p, int ioprio) */ int security_task_getioprio(struct task_struct *p) { - return call_int_hook(task_getioprio, 0, p); + return call_int_hook(task_getioprio, p); } /** @@ -3410,7 +3423,7 @@ int security_task_getioprio(struct task_struct *p) int security_task_prlimit(const struct cred *cred, const struct cred *tcred, unsigned int flags) { - return call_int_hook(task_prlimit, 0, cred, tcred, flags); + return call_int_hook(task_prlimit, cred, tcred, flags); } /** @@ -3428,7 +3441,7 @@ int security_task_prlimit(const struct cred *cred, const struct cred *tcred, int security_task_setrlimit(struct task_struct *p, unsigned int resource, struct rlimit *new_rlim) { - return call_int_hook(task_setrlimit, 0, p, resource, new_rlim); + return call_int_hook(task_setrlimit, p, resource, new_rlim); } /** @@ -3442,7 +3455,7 @@ int security_task_setrlimit(struct task_struct *p, unsigned int resource, */ int security_task_setscheduler(struct task_struct *p) { - return call_int_hook(task_setscheduler, 0, p); + return call_int_hook(task_setscheduler, p); } /** @@ -3455,7 +3468,7 @@ int security_task_setscheduler(struct task_struct *p) */ int security_task_getscheduler(struct task_struct *p) { - return call_int_hook(task_getscheduler, 0, p); + return call_int_hook(task_getscheduler, p); } /** @@ -3468,7 +3481,7 @@ int security_task_getscheduler(struct task_struct *p) */ int security_task_movememory(struct task_struct *p) { - return call_int_hook(task_movememory, 0, p); + return call_int_hook(task_movememory, p); } /** @@ -3489,7 +3502,7 @@ int security_task_movememory(struct task_struct *p) int security_task_kill(struct task_struct *p, struct kernel_siginfo *info, int sig, const struct cred *cred) { - return call_int_hook(task_kill, 0, p, info, sig, cred); + return call_int_hook(task_kill, p, info, sig, cred); } /** @@ -3547,7 +3560,7 @@ void security_task_to_inode(struct task_struct *p, struct inode *inode) */ int security_create_user_ns(const struct cred *cred) { - return call_int_hook(userns_create, 0, cred); + return call_int_hook(userns_create, cred); } /** @@ -3561,7 +3574,7 @@ int security_create_user_ns(const struct cred *cred) */ int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag) { - return call_int_hook(ipc_permission, 0, ipcp, flag); + return call_int_hook(ipc_permission, ipcp, flag); } /** @@ -3593,7 +3606,7 @@ int security_msg_msg_alloc(struct msg_msg *msg) if (unlikely(rc)) return rc; - rc = call_int_hook(msg_msg_alloc_security, 0, msg); + rc = call_int_hook(msg_msg_alloc_security, msg); if (unlikely(rc)) security_msg_msg_free(msg); return rc; @@ -3627,7 +3640,7 @@ int security_msg_queue_alloc(struct kern_ipc_perm *msq) if (unlikely(rc)) return rc; - rc = call_int_hook(msg_queue_alloc_security, 0, msq); + rc = call_int_hook(msg_queue_alloc_security, msq); if (unlikely(rc)) security_msg_queue_free(msq); return rc; @@ -3659,7 +3672,7 @@ void security_msg_queue_free(struct kern_ipc_perm *msq) */ int security_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg) { - return call_int_hook(msg_queue_associate, 0, msq, msqflg); + return call_int_hook(msg_queue_associate, msq, msqflg); } /** @@ -3674,7 +3687,7 @@ int security_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg) */ int security_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd) { - return call_int_hook(msg_queue_msgctl, 0, msq, cmd); + return call_int_hook(msg_queue_msgctl, msq, cmd); } /** @@ -3691,7 +3704,7 @@ int security_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd) int security_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *msg, int msqflg) { - return call_int_hook(msg_queue_msgsnd, 0, msq, msg, msqflg); + return call_int_hook(msg_queue_msgsnd, msq, msg, msqflg); } /** @@ -3712,7 +3725,7 @@ int security_msg_queue_msgsnd(struct kern_ipc_perm *msq, int security_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *msg, struct task_struct *target, long type, int mode) { - return call_int_hook(msg_queue_msgrcv, 0, msq, msg, target, type, mode); + return call_int_hook(msg_queue_msgrcv, msq, msg, target, type, mode); } /** @@ -3730,7 +3743,7 @@ int security_shm_alloc(struct kern_ipc_perm *shp) if (unlikely(rc)) return rc; - rc = call_int_hook(shm_alloc_security, 0, shp); + rc = call_int_hook(shm_alloc_security, shp); if (unlikely(rc)) security_shm_free(shp); return rc; @@ -3763,7 +3776,7 @@ void security_shm_free(struct kern_ipc_perm *shp) */ int security_shm_associate(struct kern_ipc_perm *shp, int shmflg) { - return call_int_hook(shm_associate, 0, shp, shmflg); + return call_int_hook(shm_associate, shp, shmflg); } /** @@ -3778,7 +3791,7 @@ int security_shm_associate(struct kern_ipc_perm *shp, int shmflg) */ int security_shm_shmctl(struct kern_ipc_perm *shp, int cmd) { - return call_int_hook(shm_shmctl, 0, shp, cmd); + return call_int_hook(shm_shmctl, shp, cmd); } /** @@ -3796,7 +3809,7 @@ int security_shm_shmctl(struct kern_ipc_perm *shp, int cmd) int security_shm_shmat(struct kern_ipc_perm *shp, char __user *shmaddr, int shmflg) { - return call_int_hook(shm_shmat, 0, shp, shmaddr, shmflg); + return call_int_hook(shm_shmat, shp, shmaddr, shmflg); } /** @@ -3814,7 +3827,7 @@ int security_sem_alloc(struct kern_ipc_perm *sma) if (unlikely(rc)) return rc; - rc = call_int_hook(sem_alloc_security, 0, sma); + rc = call_int_hook(sem_alloc_security, sma); if (unlikely(rc)) security_sem_free(sma); return rc; @@ -3846,7 +3859,7 @@ void security_sem_free(struct kern_ipc_perm *sma) */ int security_sem_associate(struct kern_ipc_perm *sma, int semflg) { - return call_int_hook(sem_associate, 0, sma, semflg); + return call_int_hook(sem_associate, sma, semflg); } /** @@ -3861,7 +3874,7 @@ int security_sem_associate(struct kern_ipc_perm *sma, int semflg) */ int security_sem_semctl(struct kern_ipc_perm *sma, int cmd) { - return call_int_hook(sem_semctl, 0, sma, cmd); + return call_int_hook(sem_semctl, sma, cmd); } /** @@ -3879,7 +3892,7 @@ int security_sem_semctl(struct kern_ipc_perm *sma, int cmd) int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops, unsigned nsops, int alter) { - return call_int_hook(sem_semop, 0, sma, sops, nsops, alter); + return call_int_hook(sem_semop, sma, sops, nsops, alter); } /** @@ -4110,11 +4123,11 @@ int security_setprocattr(int lsmid, const char *name, void *value, size_t size) */ int security_netlink_send(struct sock *sk, struct sk_buff *skb) { - return call_int_hook(netlink_send, 0, sk, skb); + return call_int_hook(netlink_send, sk, skb); } /** - * security_ismaclabel() - Check is the named attribute is a MAC label + * security_ismaclabel() - Check if the named attribute is a MAC label * @name: full extended attribute name * * Check if the extended attribute specified by @name represents a MAC label. @@ -4123,7 +4136,7 @@ int security_netlink_send(struct sock *sk, struct sk_buff *skb) */ int security_ismaclabel(const char *name) { - return call_int_hook(ismaclabel, 0, name); + return call_int_hook(ismaclabel, name); } EXPORT_SYMBOL(security_ismaclabel); @@ -4142,20 +4155,7 @@ EXPORT_SYMBOL(security_ismaclabel); */ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) { - struct security_hook_list *hp; - int rc; - - /* - * Currently, only one LSM can implement secid_to_secctx (i.e this - * LSM hook is not "stackable"). - */ - hlist_for_each_entry(hp, &security_hook_heads.secid_to_secctx, list) { - rc = hp->hook.secid_to_secctx(secid, secdata, seclen); - if (rc != LSM_RET_DEFAULT(secid_to_secctx)) - return rc; - } - - return LSM_RET_DEFAULT(secid_to_secctx); + return call_int_hook(secid_to_secctx, secid, secdata, seclen); } EXPORT_SYMBOL(security_secid_to_secctx); @@ -4172,7 +4172,7 @@ EXPORT_SYMBOL(security_secid_to_secctx); int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) { *secid = 0; - return call_int_hook(secctx_to_secid, 0, secdata, seclen, secid); + return call_int_hook(secctx_to_secid, secdata, seclen, secid); } EXPORT_SYMBOL(security_secctx_to_secid); @@ -4219,7 +4219,7 @@ EXPORT_SYMBOL(security_inode_invalidate_secctx); */ int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) { - return call_int_hook(inode_notifysecctx, 0, inode, ctx, ctxlen); + return call_int_hook(inode_notifysecctx, inode, ctx, ctxlen); } EXPORT_SYMBOL(security_inode_notifysecctx); @@ -4241,7 +4241,7 @@ EXPORT_SYMBOL(security_inode_notifysecctx); */ int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) { - return call_int_hook(inode_setsecctx, 0, dentry, ctx, ctxlen); + return call_int_hook(inode_setsecctx, dentry, ctx, ctxlen); } EXPORT_SYMBOL(security_inode_setsecctx); @@ -4258,19 +4258,7 @@ EXPORT_SYMBOL(security_inode_setsecctx); */ int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) { - struct security_hook_list *hp; - int rc; - - /* - * Only one module will provide a security context. - */ - hlist_for_each_entry(hp, &security_hook_heads.inode_getsecctx, list) { - rc = hp->hook.inode_getsecctx(inode, ctx, ctxlen); - if (rc != LSM_RET_DEFAULT(inode_getsecctx)) - return rc; - } - - return LSM_RET_DEFAULT(inode_getsecctx); + return call_int_hook(inode_getsecctx, inode, ctx, ctxlen); } EXPORT_SYMBOL(security_inode_getsecctx); @@ -4289,7 +4277,7 @@ int security_post_notification(const struct cred *w_cred, const struct cred *cred, struct watch_notification *n) { - return call_int_hook(post_notification, 0, w_cred, cred, n); + return call_int_hook(post_notification, w_cred, cred, n); } #endif /* CONFIG_WATCH_QUEUE */ @@ -4305,7 +4293,7 @@ int security_post_notification(const struct cred *w_cred, */ int security_watch_key(struct key *key) { - return call_int_hook(watch_key, 0, key); + return call_int_hook(watch_key, key); } #endif /* CONFIG_KEY_NOTIFICATIONS */ @@ -4334,7 +4322,7 @@ int security_watch_key(struct key *key) int security_unix_stream_connect(struct sock *sock, struct sock *other, struct sock *newsk) { - return call_int_hook(unix_stream_connect, 0, sock, other, newsk); + return call_int_hook(unix_stream_connect, sock, other, newsk); } EXPORT_SYMBOL(security_unix_stream_connect); @@ -4360,7 +4348,7 @@ EXPORT_SYMBOL(security_unix_stream_connect); */ int security_unix_may_send(struct socket *sock, struct socket *other) { - return call_int_hook(unix_may_send, 0, sock, other); + return call_int_hook(unix_may_send, sock, other); } EXPORT_SYMBOL(security_unix_may_send); @@ -4377,7 +4365,7 @@ EXPORT_SYMBOL(security_unix_may_send); */ int security_socket_create(int family, int type, int protocol, int kern) { - return call_int_hook(socket_create, 0, family, type, protocol, kern); + return call_int_hook(socket_create, family, type, protocol, kern); } /** @@ -4401,7 +4389,7 @@ int security_socket_create(int family, int type, int protocol, int kern) int security_socket_post_create(struct socket *sock, int family, int type, int protocol, int kern) { - return call_int_hook(socket_post_create, 0, sock, family, type, + return call_int_hook(socket_post_create, sock, family, type, protocol, kern); } @@ -4417,7 +4405,7 @@ int security_socket_post_create(struct socket *sock, int family, */ int security_socket_socketpair(struct socket *socka, struct socket *sockb) { - return call_int_hook(socket_socketpair, 0, socka, sockb); + return call_int_hook(socket_socketpair, socka, sockb); } EXPORT_SYMBOL(security_socket_socketpair); @@ -4436,7 +4424,7 @@ EXPORT_SYMBOL(security_socket_socketpair); int security_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) { - return call_int_hook(socket_bind, 0, sock, address, addrlen); + return call_int_hook(socket_bind, sock, address, addrlen); } /** @@ -4453,7 +4441,7 @@ int security_socket_bind(struct socket *sock, int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) { - return call_int_hook(socket_connect, 0, sock, address, addrlen); + return call_int_hook(socket_connect, sock, address, addrlen); } /** @@ -4467,7 +4455,7 @@ int security_socket_connect(struct socket *sock, */ int security_socket_listen(struct socket *sock, int backlog) { - return call_int_hook(socket_listen, 0, sock, backlog); + return call_int_hook(socket_listen, sock, backlog); } /** @@ -4483,11 +4471,11 @@ int security_socket_listen(struct socket *sock, int backlog) */ int security_socket_accept(struct socket *sock, struct socket *newsock) { - return call_int_hook(socket_accept, 0, sock, newsock); + return call_int_hook(socket_accept, sock, newsock); } /** - * security_socket_sendmsg() - Check is sending a message is allowed + * security_socket_sendmsg() - Check if sending a message is allowed * @sock: sending socket * @msg: message to send * @size: size of message @@ -4498,7 +4486,7 @@ int security_socket_accept(struct socket *sock, struct socket *newsock) */ int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size) { - return call_int_hook(socket_sendmsg, 0, sock, msg, size); + return call_int_hook(socket_sendmsg, sock, msg, size); } /** @@ -4515,7 +4503,7 @@ int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size) int security_socket_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags) { - return call_int_hook(socket_recvmsg, 0, sock, msg, size, flags); + return call_int_hook(socket_recvmsg, sock, msg, size, flags); } /** @@ -4529,7 +4517,7 @@ int security_socket_recvmsg(struct socket *sock, struct msghdr *msg, */ int security_socket_getsockname(struct socket *sock) { - return call_int_hook(socket_getsockname, 0, sock); + return call_int_hook(socket_getsockname, sock); } /** @@ -4542,7 +4530,7 @@ int security_socket_getsockname(struct socket *sock) */ int security_socket_getpeername(struct socket *sock) { - return call_int_hook(socket_getpeername, 0, sock); + return call_int_hook(socket_getpeername, sock); } /** @@ -4558,7 +4546,7 @@ int security_socket_getpeername(struct socket *sock) */ int security_socket_getsockopt(struct socket *sock, int level, int optname) { - return call_int_hook(socket_getsockopt, 0, sock, level, optname); + return call_int_hook(socket_getsockopt, sock, level, optname); } /** @@ -4573,7 +4561,7 @@ int security_socket_getsockopt(struct socket *sock, int level, int optname) */ int security_socket_setsockopt(struct socket *sock, int level, int optname) { - return call_int_hook(socket_setsockopt, 0, sock, level, optname); + return call_int_hook(socket_setsockopt, sock, level, optname); } /** @@ -4588,7 +4576,7 @@ int security_socket_setsockopt(struct socket *sock, int level, int optname) */ int security_socket_shutdown(struct socket *sock, int how) { - return call_int_hook(socket_shutdown, 0, sock, how); + return call_int_hook(socket_shutdown, sock, how); } /** @@ -4605,7 +4593,7 @@ int security_socket_shutdown(struct socket *sock, int how) */ int security_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) { - return call_int_hook(socket_sock_rcv_skb, 0, sk, skb); + return call_int_hook(socket_sock_rcv_skb, sk, skb); } EXPORT_SYMBOL(security_sock_rcv_skb); @@ -4627,20 +4615,8 @@ EXPORT_SYMBOL(security_sock_rcv_skb); int security_socket_getpeersec_stream(struct socket *sock, sockptr_t optval, sockptr_t optlen, unsigned int len) { - struct security_hook_list *hp; - int rc; - - /* - * Only one module will provide a security context. - */ - hlist_for_each_entry(hp, &security_hook_heads.socket_getpeersec_stream, - list) { - rc = hp->hook.socket_getpeersec_stream(sock, optval, optlen, - len); - if (rc != LSM_RET_DEFAULT(socket_getpeersec_stream)) - return rc; - } - return LSM_RET_DEFAULT(socket_getpeersec_stream); + return call_int_hook(socket_getpeersec_stream, sock, optval, optlen, + len); } /** @@ -4660,19 +4636,7 @@ int security_socket_getpeersec_stream(struct socket *sock, sockptr_t optval, int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid) { - struct security_hook_list *hp; - int rc; - - /* - * Only one module will provide a security context. - */ - hlist_for_each_entry(hp, &security_hook_heads.socket_getpeersec_dgram, - list) { - rc = hp->hook.socket_getpeersec_dgram(sock, skb, secid); - if (rc != LSM_RET_DEFAULT(socket_getpeersec_dgram)) - return rc; - } - return LSM_RET_DEFAULT(socket_getpeersec_dgram); + return call_int_hook(socket_getpeersec_dgram, sock, skb, secid); } EXPORT_SYMBOL(security_socket_getpeersec_dgram); @@ -4689,7 +4653,7 @@ EXPORT_SYMBOL(security_socket_getpeersec_dgram); */ int security_sk_alloc(struct sock *sk, int family, gfp_t priority) { - return call_int_hook(sk_alloc_security, 0, sk, family, priority); + return call_int_hook(sk_alloc_security, sk, family, priority); } /** @@ -4770,7 +4734,7 @@ EXPORT_SYMBOL(security_sock_graft); int security_inet_conn_request(const struct sock *sk, struct sk_buff *skb, struct request_sock *req) { - return call_int_hook(inet_conn_request, 0, sk, skb, req); + return call_int_hook(inet_conn_request, sk, skb, req); } EXPORT_SYMBOL(security_inet_conn_request); @@ -4811,7 +4775,7 @@ EXPORT_SYMBOL(security_inet_conn_established); */ int security_secmark_relabel_packet(u32 secid) { - return call_int_hook(secmark_relabel_packet, 0, secid); + return call_int_hook(secmark_relabel_packet, secid); } EXPORT_SYMBOL(security_secmark_relabel_packet); @@ -4848,7 +4812,7 @@ EXPORT_SYMBOL(security_secmark_refcount_dec); */ int security_tun_dev_alloc_security(void **security) { - return call_int_hook(tun_dev_alloc_security, 0, security); + return call_int_hook(tun_dev_alloc_security, security); } EXPORT_SYMBOL(security_tun_dev_alloc_security); @@ -4873,7 +4837,7 @@ EXPORT_SYMBOL(security_tun_dev_free_security); */ int security_tun_dev_create(void) { - return call_int_hook(tun_dev_create, 0); + return call_int_hook(tun_dev_create); } EXPORT_SYMBOL(security_tun_dev_create); @@ -4887,7 +4851,7 @@ EXPORT_SYMBOL(security_tun_dev_create); */ int security_tun_dev_attach_queue(void *security) { - return call_int_hook(tun_dev_attach_queue, 0, security); + return call_int_hook(tun_dev_attach_queue, security); } EXPORT_SYMBOL(security_tun_dev_attach_queue); @@ -4903,7 +4867,7 @@ EXPORT_SYMBOL(security_tun_dev_attach_queue); */ int security_tun_dev_attach(struct sock *sk, void *security) { - return call_int_hook(tun_dev_attach, 0, sk, security); + return call_int_hook(tun_dev_attach, sk, security); } EXPORT_SYMBOL(security_tun_dev_attach); @@ -4918,7 +4882,7 @@ EXPORT_SYMBOL(security_tun_dev_attach); */ int security_tun_dev_open(void *security) { - return call_int_hook(tun_dev_open, 0, security); + return call_int_hook(tun_dev_open, security); } EXPORT_SYMBOL(security_tun_dev_open); @@ -4934,7 +4898,7 @@ EXPORT_SYMBOL(security_tun_dev_open); int security_sctp_assoc_request(struct sctp_association *asoc, struct sk_buff *skb) { - return call_int_hook(sctp_assoc_request, 0, asoc, skb); + return call_int_hook(sctp_assoc_request, asoc, skb); } EXPORT_SYMBOL(security_sctp_assoc_request); @@ -4955,8 +4919,7 @@ EXPORT_SYMBOL(security_sctp_assoc_request); int security_sctp_bind_connect(struct sock *sk, int optname, struct sockaddr *address, int addrlen) { - return call_int_hook(sctp_bind_connect, 0, sk, optname, - address, addrlen); + return call_int_hook(sctp_bind_connect, sk, optname, address, addrlen); } EXPORT_SYMBOL(security_sctp_bind_connect); @@ -4990,7 +4953,7 @@ EXPORT_SYMBOL(security_sctp_sk_clone); int security_sctp_assoc_established(struct sctp_association *asoc, struct sk_buff *skb) { - return call_int_hook(sctp_assoc_established, 0, asoc, skb); + return call_int_hook(sctp_assoc_established, asoc, skb); } EXPORT_SYMBOL(security_sctp_assoc_established); @@ -5008,7 +4971,7 @@ EXPORT_SYMBOL(security_sctp_assoc_established); */ int security_mptcp_add_subflow(struct sock *sk, struct sock *ssk) { - return call_int_hook(mptcp_add_subflow, 0, sk, ssk); + return call_int_hook(mptcp_add_subflow, sk, ssk); } #endif /* CONFIG_SECURITY_NETWORK */ @@ -5026,7 +4989,7 @@ int security_mptcp_add_subflow(struct sock *sk, struct sock *ssk) */ int security_ib_pkey_access(void *sec, u64 subnet_prefix, u16 pkey) { - return call_int_hook(ib_pkey_access, 0, sec, subnet_prefix, pkey); + return call_int_hook(ib_pkey_access, sec, subnet_prefix, pkey); } EXPORT_SYMBOL(security_ib_pkey_access); @@ -5043,8 +5006,7 @@ EXPORT_SYMBOL(security_ib_pkey_access); int security_ib_endport_manage_subnet(void *sec, const char *dev_name, u8 port_num) { - return call_int_hook(ib_endport_manage_subnet, 0, sec, - dev_name, port_num); + return call_int_hook(ib_endport_manage_subnet, sec, dev_name, port_num); } EXPORT_SYMBOL(security_ib_endport_manage_subnet); @@ -5058,7 +5020,7 @@ EXPORT_SYMBOL(security_ib_endport_manage_subnet); */ int security_ib_alloc_security(void **sec) { - return call_int_hook(ib_alloc_security, 0, sec); + return call_int_hook(ib_alloc_security, sec); } EXPORT_SYMBOL(security_ib_alloc_security); @@ -5091,7 +5053,7 @@ int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx, gfp_t gfp) { - return call_int_hook(xfrm_policy_alloc_security, 0, ctxp, sec_ctx, gfp); + return call_int_hook(xfrm_policy_alloc_security, ctxp, sec_ctx, gfp); } EXPORT_SYMBOL(security_xfrm_policy_alloc); @@ -5108,7 +5070,7 @@ EXPORT_SYMBOL(security_xfrm_policy_alloc); int security_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctxp) { - return call_int_hook(xfrm_policy_clone_security, 0, old_ctx, new_ctxp); + return call_int_hook(xfrm_policy_clone_security, old_ctx, new_ctxp); } /** @@ -5133,7 +5095,7 @@ EXPORT_SYMBOL(security_xfrm_policy_free); */ int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx) { - return call_int_hook(xfrm_policy_delete_security, 0, ctx); + return call_int_hook(xfrm_policy_delete_security, ctx); } /** @@ -5150,7 +5112,7 @@ int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx) int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx) { - return call_int_hook(xfrm_state_alloc, 0, x, sec_ctx); + return call_int_hook(xfrm_state_alloc, x, sec_ctx); } EXPORT_SYMBOL(security_xfrm_state_alloc); @@ -5169,7 +5131,7 @@ EXPORT_SYMBOL(security_xfrm_state_alloc); int security_xfrm_state_alloc_acquire(struct xfrm_state *x, struct xfrm_sec_ctx *polsec, u32 secid) { - return call_int_hook(xfrm_state_alloc_acquire, 0, x, polsec, secid); + return call_int_hook(xfrm_state_alloc_acquire, x, polsec, secid); } /** @@ -5182,7 +5144,7 @@ int security_xfrm_state_alloc_acquire(struct xfrm_state *x, */ int security_xfrm_state_delete(struct xfrm_state *x) { - return call_int_hook(xfrm_state_delete_security, 0, x); + return call_int_hook(xfrm_state_delete_security, x); } EXPORT_SYMBOL(security_xfrm_state_delete); @@ -5211,7 +5173,7 @@ void security_xfrm_state_free(struct xfrm_state *x) */ int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid) { - return call_int_hook(xfrm_policy_lookup, 0, ctx, fl_secid); + return call_int_hook(xfrm_policy_lookup, ctx, fl_secid); } /** @@ -5259,12 +5221,12 @@ int security_xfrm_state_pol_flow_match(struct xfrm_state *x, */ int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid) { - return call_int_hook(xfrm_decode_session, 0, skb, secid, 1); + return call_int_hook(xfrm_decode_session, skb, secid, 1); } void security_skb_classify_flow(struct sk_buff *skb, struct flowi_common *flic) { - int rc = call_int_hook(xfrm_decode_session, 0, skb, &flic->flowic_secid, + int rc = call_int_hook(xfrm_decode_session, skb, &flic->flowic_secid, 0); BUG_ON(rc); @@ -5287,7 +5249,7 @@ EXPORT_SYMBOL(security_skb_classify_flow); int security_key_alloc(struct key *key, const struct cred *cred, unsigned long flags) { - return call_int_hook(key_alloc, 0, key, cred, flags); + return call_int_hook(key_alloc, key, cred, flags); } /** @@ -5314,7 +5276,7 @@ void security_key_free(struct key *key) int security_key_permission(key_ref_t key_ref, const struct cred *cred, enum key_need_perm need_perm) { - return call_int_hook(key_permission, 0, key_ref, cred, need_perm); + return call_int_hook(key_permission, key_ref, cred, need_perm); } /** @@ -5333,7 +5295,26 @@ int security_key_permission(key_ref_t key_ref, const struct cred *cred, int security_key_getsecurity(struct key *key, char **buffer) { *buffer = NULL; - return call_int_hook(key_getsecurity, 0, key, buffer); + return call_int_hook(key_getsecurity, key, buffer); +} + +/** + * security_key_post_create_or_update() - Notification of key create or update + * @keyring: keyring to which the key is linked to + * @key: created or updated key + * @payload: data used to instantiate or update the key + * @payload_len: length of payload + * @flags: key flags + * @create: flag indicating whether the key was created or updated + * + * Notify the caller of a key creation or update. + */ +void security_key_post_create_or_update(struct key *keyring, struct key *key, + const void *payload, size_t payload_len, + unsigned long flags, bool create) +{ + call_void_hook(key_post_create_or_update, keyring, key, payload, + payload_len, flags, create); } #endif /* CONFIG_KEYS */ @@ -5352,7 +5333,7 @@ int security_key_getsecurity(struct key *key, char **buffer) */ int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule) { - return call_int_hook(audit_rule_init, 0, field, op, rulestr, lsmrule); + return call_int_hook(audit_rule_init, field, op, rulestr, lsmrule); } /** @@ -5366,7 +5347,7 @@ int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule) */ int security_audit_rule_known(struct audit_krule *krule) { - return call_int_hook(audit_rule_known, 0, krule); + return call_int_hook(audit_rule_known, krule); } /** @@ -5396,7 +5377,7 @@ void security_audit_rule_free(void *lsmrule) */ int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule) { - return call_int_hook(audit_rule_match, 0, secid, field, op, lsmrule); + return call_int_hook(audit_rule_match, secid, field, op, lsmrule); } #endif /* CONFIG_AUDIT */ @@ -5415,7 +5396,7 @@ int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule) */ int security_bpf(int cmd, union bpf_attr *attr, unsigned int size) { - return call_int_hook(bpf, 0, cmd, attr, size); + return call_int_hook(bpf, cmd, attr, size); } /** @@ -5430,7 +5411,7 @@ int security_bpf(int cmd, union bpf_attr *attr, unsigned int size) */ int security_bpf_map(struct bpf_map *map, fmode_t fmode) { - return call_int_hook(bpf_map, 0, map, fmode); + return call_int_hook(bpf_map, map, fmode); } /** @@ -5444,7 +5425,7 @@ int security_bpf_map(struct bpf_map *map, fmode_t fmode) */ int security_bpf_prog(struct bpf_prog *prog) { - return call_int_hook(bpf_prog, 0, prog); + return call_int_hook(bpf_prog, prog); } /** @@ -5461,7 +5442,7 @@ int security_bpf_prog(struct bpf_prog *prog) int security_bpf_map_create(struct bpf_map *map, union bpf_attr *attr, struct bpf_token *token) { - return call_int_hook(bpf_map_create, 0, map, attr, token); + return call_int_hook(bpf_map_create, map, attr, token); } /** @@ -5479,7 +5460,7 @@ int security_bpf_map_create(struct bpf_map *map, union bpf_attr *attr, int security_bpf_prog_load(struct bpf_prog *prog, union bpf_attr *attr, struct bpf_token *token) { - return call_int_hook(bpf_prog_load, 0, prog, attr, token); + return call_int_hook(bpf_prog_load, prog, attr, token); } /** @@ -5496,7 +5477,7 @@ int security_bpf_prog_load(struct bpf_prog *prog, union bpf_attr *attr, int security_bpf_token_create(struct bpf_token *token, union bpf_attr *attr, struct path *path) { - return call_int_hook(bpf_token_create, 0, token, attr, path); + return call_int_hook(bpf_token_create, token, attr, path); } /** @@ -5512,7 +5493,7 @@ int security_bpf_token_create(struct bpf_token *token, union bpf_attr *attr, */ int security_bpf_token_cmd(const struct bpf_token *token, enum bpf_cmd cmd) { - return call_int_hook(bpf_token_cmd, 0, token, cmd); + return call_int_hook(bpf_token_cmd, token, cmd); } /** @@ -5528,7 +5509,7 @@ int security_bpf_token_cmd(const struct bpf_token *token, enum bpf_cmd cmd) */ int security_bpf_token_capable(const struct bpf_token *token, int cap) { - return call_int_hook(bpf_token_capable, 0, token, cap); + return call_int_hook(bpf_token_capable, token, cap); } /** @@ -5576,7 +5557,7 @@ void security_bpf_token_free(struct bpf_token *token) */ int security_locked_down(enum lockdown_reason what) { - return call_int_hook(locked_down, 0, what); + return call_int_hook(locked_down, what); } EXPORT_SYMBOL(security_locked_down); @@ -5592,7 +5573,7 @@ EXPORT_SYMBOL(security_locked_down); */ int security_perf_event_open(struct perf_event_attr *attr, int type) { - return call_int_hook(perf_event_open, 0, attr, type); + return call_int_hook(perf_event_open, attr, type); } /** @@ -5605,7 +5586,7 @@ int security_perf_event_open(struct perf_event_attr *attr, int type) */ int security_perf_event_alloc(struct perf_event *event) { - return call_int_hook(perf_event_alloc, 0, event); + return call_int_hook(perf_event_alloc, event); } /** @@ -5629,7 +5610,7 @@ void security_perf_event_free(struct perf_event *event) */ int security_perf_event_read(struct perf_event *event) { - return call_int_hook(perf_event_read, 0, event); + return call_int_hook(perf_event_read, event); } /** @@ -5642,7 +5623,7 @@ int security_perf_event_read(struct perf_event *event) */ int security_perf_event_write(struct perf_event *event) { - return call_int_hook(perf_event_write, 0, event); + return call_int_hook(perf_event_write, event); } #endif /* CONFIG_PERF_EVENTS */ @@ -5658,7 +5639,7 @@ int security_perf_event_write(struct perf_event *event) */ int security_uring_override_creds(const struct cred *new) { - return call_int_hook(uring_override_creds, 0, new); + return call_int_hook(uring_override_creds, new); } /** @@ -5671,7 +5652,7 @@ int security_uring_override_creds(const struct cred *new) */ int security_uring_sqpoll(void) { - return call_int_hook(uring_sqpoll, 0); + return call_int_hook(uring_sqpoll); } /** @@ -5684,6 +5665,6 @@ int security_uring_sqpoll(void) */ int security_uring_cmd(struct io_uring_cmd *ioucmd) { - return call_int_hook(uring_cmd, 0, ioucmd); + return call_int_hook(uring_cmd, ioucmd); } #endif /* CONFIG_IO_URING */ diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 860e558e9fd5..8db4875164ab 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3135,7 +3135,8 @@ static int selinux_inode_permission(struct inode *inode, int mask) return rc; } -static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) +static int selinux_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry, + struct iattr *iattr) { const struct cred *cred = current_cred(); struct inode *inode = d_backing_inode(dentry); diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index b18b50232947..28be26712396 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -1238,12 +1238,14 @@ static int smack_inode_permission(struct inode *inode, int mask) /** * smack_inode_setattr - Smack check for setting attributes + * @idmap: idmap of the mount * @dentry: the object * @iattr: for the force flag * * Returns 0 if access is permitted, an error code otherwise */ -static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr) +static int smack_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry, + struct iattr *iattr) { struct smk_audit_info ad; int rc; diff --git a/tools/testing/selftests/lsm/lsm_list_modules_test.c b/tools/testing/selftests/lsm/lsm_list_modules_test.c index 9df29b1e3497..4d5d4cee2586 100644 --- a/tools/testing/selftests/lsm/lsm_list_modules_test.c +++ b/tools/testing/selftests/lsm/lsm_list_modules_test.c @@ -122,6 +122,12 @@ TEST(correct_lsm_list_modules) case LSM_ID_LANDLOCK: name = "landlock"; break; + case LSM_ID_IMA: + name = "ima"; + break; + case LSM_ID_EVM: + name = "evm"; + break; default: name = "INVALID"; break;