From: Roberto Sassu <roberto.sassu@xxxxxxxxxx> 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@xxxxxxxxxx> --- 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; } + + 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 -- 2.34.1