From: Roberto Sassu <roberto.sassu@xxxxxxxxxx> In preparation for moving IMA and EVM to the LSM infrastructure, introduce the inode_post_set_acl hook. At inode_set_acl hook, EVM verifies the file's existing HMAC value. At inode_post_set_acl, EVM re-calculates the file's HMAC based on the modified POSIX ACL and other file metadata. Other LSMs could similarly take some action after successful POSIX ACL change. The new hook cannot return an error and cannot cause the operation to be reverted. Signed-off-by: Roberto Sassu <roberto.sassu@xxxxxxxxxx> Reviewed-by: Stefan Berger <stefanb@xxxxxxxxxxxxx> --- fs/posix_acl.c | 1 + include/linux/lsm_hook_defs.h | 2 ++ include/linux/security.h | 7 +++++++ security/security.c | 17 +++++++++++++++++ 4 files changed, 27 insertions(+) diff --git a/fs/posix_acl.c b/fs/posix_acl.c index a05fe94970ce..58e3c1e2fbbc 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c @@ -1137,6 +1137,7 @@ int vfs_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, error = -EIO; if (!error) { fsnotify_xattr(dentry); + security_inode_post_set_acl(dentry, acl_name, kacl); evm_inode_post_set_acl(dentry, acl_name, kacl); } diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 945ed6078890..42962ce8301a 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -157,6 +157,8 @@ 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, diff --git a/include/linux/security.h b/include/linux/security.h index fbc57f2fa158..278b97f688dc 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -372,6 +372,8 @@ 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, @@ -913,6 +915,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) diff --git a/security/security.c b/security/security.c index fcd16e853c42..622c24cbfbb6 100644 --- a/security/security.c +++ b/security/security.c @@ -2343,6 +2343,23 @@ int security_inode_set_acl(struct mnt_idmap *idmap, return evm_inode_set_acl(idmap, dentry, acl_name, kacl); } +/** + * security_inode_post_set_acl() - Update inode security after set_acl() + * @dentry: file + * @acl_name: acl name + * @kacl: acl struct + * + * Update inode security field after successful set_acl operation 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); +} + /** * security_inode_get_acl() - Check if reading posix acls is allowed * @idmap: idmap of the mount -- 2.34.1