diff options
Diffstat (limited to 'security/integrity')
-rw-r--r-- | security/integrity/evm/evm_main.c | 118 |
1 files changed, 102 insertions, 16 deletions
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index d35143179699..0a089af83a45 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -589,9 +589,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, int flags) +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; @@ -621,8 +621,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 @@ -672,9 +672,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; @@ -713,6 +715,24 @@ 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; @@ -761,9 +781,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, - int flags) +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; @@ -783,6 +805,21 @@ void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name, } /** + * 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 * @xattr_name: pointer to the affected extended attribute name @@ -792,7 +829,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; @@ -808,6 +846,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) { @@ -831,8 +885,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; @@ -883,8 +937,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 mnt_idmap *idmap, 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; @@ -901,7 +955,7 @@ void evm_inode_post_setattr(struct mnt_idmap *idmap, struct dentry *dentry, 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 */ @@ -1004,4 +1058,36 @@ 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), +}; + +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; +} + +DEFINE_LSM(evm) = { + .name = "evm", + .init = init_evm_lsm, + .order = LSM_ORDER_LAST, +}; + late_initcall(init_evm); |