diff mbox series

[v3,16/25] security: Introduce path_post_mknod hook

Message ID 20230904133415.1799503-17-roberto.sassu@huaweicloud.com (mailing list archive)
State Handled Elsewhere
Delegated to: Paul Moore
Headers show
Series security: Move IMA and EVM to the LSM infrastructure | expand

Commit Message

Roberto Sassu Sept. 4, 2023, 1:34 p.m. UTC
From: Roberto Sassu <roberto.sassu@huawei.com>

In preparation for moving IMA and EVM to the LSM infrastructure, introduce
the path_post_mknod hook.

It is useful for IMA to let new empty files be subsequently opened for
further modification.

LSMs can benefit from this hook to update the inode state after a file has
been successfully created. The new hook cannot return an error and cannot
cause the operation to be canceled.

Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
---
 fs/namei.c                    |  5 +++++
 include/linux/lsm_hook_defs.h |  3 +++
 include/linux/security.h      |  9 +++++++++
 security/security.c           | 19 +++++++++++++++++++
 4 files changed, 36 insertions(+)

Comments

Stefan Berger Sept. 5, 2023, 6:48 p.m. UTC | #1
On 9/4/23 09:34, Roberto Sassu wrote:
> From: Roberto Sassu <roberto.sassu@huawei.com>
>
> In preparation for moving IMA and EVM to the LSM infrastructure, introduce
> the path_post_mknod hook.
>
> It is useful for IMA to let new empty files be subsequently opened for
> further modification.
>
> LSMs can benefit from this hook to update the inode state after a file has
> been successfully created. The new hook cannot return an error and cannot
> cause the operation to be canceled.
>
> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
> ---
>   fs/namei.c                    |  5 +++++
>   include/linux/lsm_hook_defs.h |  3 +++
>   include/linux/security.h      |  9 +++++++++
>   security/security.c           | 19 +++++++++++++++++++
>   4 files changed, 36 insertions(+)
>
> diff --git a/fs/namei.c b/fs/namei.c
> index 7dc4626859f0..c8c4ab26b52a 100644
> --- a/fs/namei.c
> +++ b/fs/namei.c
> @@ -4061,6 +4061,11 @@ static int do_mknodat(int dfd, struct filename *name, umode_t mode,
>   					  dentry, mode, 0);
>   			break;
>   	}
> +

Nit: remove empty line.


> +	if (error)
> +		goto out2;
> +
> +	security_path_post_mknod(idmap, &path, dentry, mode_stripped, dev);
>   out2:
>   	done_path_create(&path, dentry);
>   	if (retry_estale(error, lookup_flags)) {
> diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
> index 797f51da3f7d..b1634b5de98c 100644
> --- a/include/linux/lsm_hook_defs.h
> +++ b/include/linux/lsm_hook_defs.h
> @@ -93,6 +93,9 @@ 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,
> +	 const struct path *dir, struct dentry *dentry, umode_t mode,
> +	 unsigned int dev)
>   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)
> diff --git a/include/linux/security.h b/include/linux/security.h
> index 7871009d59ae..f210bd66e939 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -1842,6 +1842,9 @@ 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, const struct path *dir,
> +			      struct dentry *dentry, umode_t mode,
> +			      unsigned int dev);
>   int security_path_truncate(const struct path *path);
>   int security_path_symlink(const struct path *dir, struct dentry *dentry,
>   			  const char *old_name);
> @@ -1876,6 +1879,12 @@ 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,
> +					    const struct path *dir,
> +					    struct dentry *dentry, umode_t mode,
> +					    unsigned int dev)
> +{ }
> +
>   static inline int security_path_truncate(const struct path *path)
>   {
>   	return 0;
> diff --git a/security/security.c b/security/security.c
> index fbb58eeeea02..78aeb24efedb 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -1702,6 +1702,25 @@ int security_path_mknod(const struct path *dir, struct dentry *dentry,
>   }
>   EXPORT_SYMBOL(security_path_mknod);
>   
> +/**
> + * security_path_post_mknod() - Update inode security field after file creation
> + * @idmap: idmap of the mount
> + * @dir: parent directory
> + * @dentry: new file
> + * @mode: new file mode
> + * @dev: device number
> + *
> + * Update inode security field after a file has been created.
> + */
> +void security_path_post_mknod(struct mnt_idmap *idmap, const struct path *dir,
> +			      struct dentry *dentry, umode_t mode,
> +			      unsigned int dev)
> +{
> +	if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
> +		return;
> +	call_void_hook(path_post_mknod, idmap, dir, dentry, mode, dev);
> +}
> +
>   /**
>    * security_path_mkdir() - Check if creating a new directory is allowed
>    * @dir: parent directory


Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Mimi Zohar Oct. 13, 2023, 1:12 p.m. UTC | #2
On Mon, 2023-09-04 at 15:34 +0200, Roberto Sassu wrote:
> From: Roberto Sassu <roberto.sassu@huawei.com>
> 
> In preparation for moving IMA and EVM to the LSM infrastructure, introduce
> the path_post_mknod hook.
> 
> It is useful for IMA to let new empty files be subsequently opened for
> further modification.

(Please remove "It is useful for"  here and in other patch
descriptions.  Will not repeat this again.)

Possible wording:
IMA-appraisal requires all existing files in policy to have a file
hash/signature stored in security.ima.  An exception is made for empty
files created by mknod, by tagging them as new files.

> 
> LSMs can benefit from this hook to update the inode state after a file has
> been successfully created. 

(Please remove "LSMs can benefit from" here and in other patch
descriptions.)

Please make sure that the patch description is in sync with the LSM
hook kernel doc. 

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

(Separate paragaraph)

> 
> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
diff mbox series

Patch

diff --git a/fs/namei.c b/fs/namei.c
index 7dc4626859f0..c8c4ab26b52a 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -4061,6 +4061,11 @@  static int do_mknodat(int dfd, struct filename *name, umode_t mode,
 					  dentry, mode, 0);
 			break;
 	}
+
+	if (error)
+		goto out2;
+
+	security_path_post_mknod(idmap, &path, dentry, mode_stripped, dev);
 out2:
 	done_path_create(&path, dentry);
 	if (retry_estale(error, lookup_flags)) {
diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
index 797f51da3f7d..b1634b5de98c 100644
--- a/include/linux/lsm_hook_defs.h
+++ b/include/linux/lsm_hook_defs.h
@@ -93,6 +93,9 @@  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,
+	 const struct path *dir, struct dentry *dentry, umode_t mode,
+	 unsigned int dev)
 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)
diff --git a/include/linux/security.h b/include/linux/security.h
index 7871009d59ae..f210bd66e939 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1842,6 +1842,9 @@  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, const struct path *dir,
+			      struct dentry *dentry, umode_t mode,
+			      unsigned int dev);
 int security_path_truncate(const struct path *path);
 int security_path_symlink(const struct path *dir, struct dentry *dentry,
 			  const char *old_name);
@@ -1876,6 +1879,12 @@  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,
+					    const struct path *dir,
+					    struct dentry *dentry, umode_t mode,
+					    unsigned int dev)
+{ }
+
 static inline int security_path_truncate(const struct path *path)
 {
 	return 0;
diff --git a/security/security.c b/security/security.c
index fbb58eeeea02..78aeb24efedb 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1702,6 +1702,25 @@  int security_path_mknod(const struct path *dir, struct dentry *dentry,
 }
 EXPORT_SYMBOL(security_path_mknod);
 
+/**
+ * security_path_post_mknod() - Update inode security field after file creation
+ * @idmap: idmap of the mount
+ * @dir: parent directory
+ * @dentry: new file
+ * @mode: new file mode
+ * @dev: device number
+ *
+ * Update inode security field after a file has been created.
+ */
+void security_path_post_mknod(struct mnt_idmap *idmap, const struct path *dir,
+			      struct dentry *dentry, umode_t mode,
+			      unsigned int dev)
+{
+	if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
+		return;
+	call_void_hook(path_post_mknod, idmap, dir, dentry, mode, dev);
+}
+
 /**
  * security_path_mkdir() - Check if creating a new directory is allowed
  * @dir: parent directory