security: Introduce inode_post_removexattr hook
authorRoberto Sassu <roberto.sassu@huawei.com>
Thu, 15 Feb 2024 10:30:59 +0000 (11:30 +0100)
committerPaul Moore <paul@paul-moore.com>
Fri, 16 Feb 2024 04:43:42 +0000 (23:43 -0500)
In preparation for moving IMA and EVM to the LSM infrastructure, introduce
the inode_post_removexattr hook.

At inode_removexattr hook, EVM verifies the file's existing HMAC value. At
inode_post_removexattr, EVM re-calculates the file's HMAC with the passed
xattr removed and other file metadata.

Other LSMs could similarly take some action after successful xattr removal.

The new hook cannot return an error and cannot cause the operation to be
reverted.

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

index 09d9276034335f8658bcf421bf7fa0283c8c549f..f891c260a9712eee980958e2ec373a9a8cf40af9 100644 (file)
@@ -552,11 +552,12 @@ __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);
+       evm_inode_post_removexattr(dentry, name);
 
 out:
        return error;
index a0e9e48015a4f34832528d685b5ff9afc56bf1b7..f849f7d5bb5358d6b69364045e51194496876fbe 100644 (file)
@@ -149,6 +149,8 @@ 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(int, 0, inode_get_acl, struct mnt_idmap *idmap,
index 56c841aa399421dc5763aa0286a080d612865547..84ae036903409fc893972d800826d2954d338b8e 100644 (file)
@@ -380,6 +380,7 @@ 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,
@@ -942,6 +943,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);
index 56527d5415e23bcbf2d613a51321526012885387..d77fdd3ca1bceee3650a21ea67b2073c748a5ff3 100644 (file)
@@ -2452,6 +2452,20 @@ int security_inode_removexattr(struct mnt_idmap *idmap,
        return evm_inode_removexattr(idmap, dentry, name);
 }
 
+/**
+ * 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);
+}
+
 /**
  * security_inode_need_killpriv() - Check if security_inode_killpriv() required
  * @dentry: associated dentry