[PATCH 1/2] lsm: expose mount idmaps to inode hooks
Daan De Meyer via B4 Relay <[email protected]>
| Newsgroups | org.kernel.vger.linux-security-module,org.kernel.feeds.b4-sent,org.kernel.vger.linux-fsdevel |
|---|---|
| Message-ID | <[email protected]> |
From: Daan De Meyer <[email protected]> Pass the mount idmap through the create, link, symlink, mkdir, mknod, and permission hooks. Update the in-tree security implementations and non-VFS callers accordingly. --- fs/cachefiles/security.c | 4 +-- fs/namei.c | 18 +++++++------- include/linux/lsm_hook_defs.h | 23 +++++++++-------- include/linux/security.h | 58 +++++++++++++++++++++++++------------------ security/security.c | 40 +++++++++++++++++------------ security/selinux/hooks.c | 19 +++++++++----- security/smack/smack_lsm.c | 9 ++++--- 7 files changed, 100 insertions(+), 71 deletions(-) diff --git a/fs/cachefiles/security.c b/fs/cachefiles/security.c index fc6611886b3b..eefe5453b904 100644 --- a/fs/cachefiles/security.c +++ b/fs/cachefiles/security.c @@ -51,14 +51,14 @@ static int cachefiles_check_cache_dir(struct cachefiles_cache *cache, { int ret; - ret = security_inode_mkdir(d_backing_inode(root), root, 0); + ret = security_inode_mkdir(&nop_mnt_idmap, d_backing_inode(root), root, 0); if (ret < 0) { pr_err("Security denies permission to make dirs: error %d", ret); return ret; } - ret = security_inode_create(d_backing_inode(root), root, 0); + ret = security_inode_create(&nop_mnt_idmap, d_backing_inode(root), root, 0); if (ret < 0) pr_err("Security denies permission to create files: error %d", ret); diff --git a/fs/namei.c b/fs/namei.c index 20a6534ea3ef..99f894f3f7e1 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -658,7 +658,7 @@ int inode_permission(struct mnt_idmap *idmap, if (unlikely(retval)) return retval; - return security_inode_permission(inode, mask); + return security_inode_permission(idmap, inode, mask); } EXPORT_SYMBOL(inode_permission); @@ -695,7 +695,7 @@ static __always_inline int lookup_inode_permission_may_exec(struct mnt_idmap *id if (unlikely(((inode->i_mode & 0111) != 0111) || !no_acl_inode(inode))) return inode_permission(idmap, inode, mask); - return security_inode_permission(inode, mask); + return security_inode_permission(idmap, inode, mask); } /** @@ -4188,7 +4188,7 @@ int vfs_create(struct mnt_idmap *idmap, struct dentry *dentry, umode_t mode, return -EACCES; /* shouldn't it be ENOSYS? */ mode = vfs_prepare_mode(idmap, dir, mode, S_IALLUGO, S_IFREG); - error = security_inode_create(dir, dentry, mode); + error = security_inode_create(idmap, dir, dentry, mode); if (error) return error; error = try_break_deleg(dir, LEASE_BREAK_DIR_CREATE, di); @@ -4212,7 +4212,7 @@ int vfs_mkobj(struct dentry *dentry, umode_t mode, mode &= S_IALLUGO; mode |= S_IFREG; - error = security_inode_create(dir, dentry, mode); + error = security_inode_create(&nop_mnt_idmap, dir, dentry, mode); if (error) return error; error = f(dentry, mode, arg); @@ -4328,7 +4328,7 @@ static int may_o_create(struct mnt_idmap *idmap, if (error) return error; - return security_inode_create(dir->dentry->d_inode, dentry, mode); + return security_inode_create(idmap, dir->dentry->d_inode, dentry, mode); } /** @@ -5258,7 +5258,7 @@ int vfs_mknod(struct mnt_idmap *idmap, struct inode *dir, if (error) return error; - error = security_inode_mknod(dir, dentry, mode, dev); + error = security_inode_mknod(idmap, dir, dentry, mode, dev); if (error) return error; @@ -5395,7 +5395,7 @@ struct dentry *vfs_mkdir(struct mnt_idmap *idmap, struct inode *dir, goto err; mode = vfs_prepare_mode(idmap, dir, mode, S_IRWXUGO | S_ISVTX, S_IFDIR); - error = security_inode_mkdir(dir, dentry, mode); + error = security_inode_mkdir(idmap, dir, dentry, mode); if (error) goto err; @@ -5783,7 +5783,7 @@ int vfs_symlink(struct mnt_idmap *idmap, struct inode *dir, if (!dir->i_op->symlink) return -EPERM; - error = security_inode_symlink(dir, dentry, oldname); + error = security_inode_symlink(idmap, dir, dentry, oldname); if (error) return error; @@ -5907,7 +5907,7 @@ int vfs_link(struct dentry *old_dentry, struct mnt_idmap *idmap, if (S_ISDIR(inode->i_mode)) return -EPERM; - error = security_inode_link(old_dentry, dir, new_dentry); + error = security_inode_link(idmap, old_dentry, dir, new_dentry); if (error) return error; diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 65c9609ec207..9e49a5bc9ff3 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -120,26 +120,27 @@ LSM_HOOK(int, -EOPNOTSUPP, inode_init_security, struct inode *inode, int *xattr_count) LSM_HOOK(int, 0, inode_init_security_anon, struct inode *inode, const struct qstr *name, const struct inode *context_inode) -LSM_HOOK(int, 0, inode_create, struct inode *dir, struct dentry *dentry, - umode_t mode) +LSM_HOOK(int, 0, inode_create, struct mnt_idmap *idmap, struct inode *dir, + struct dentry *dentry, umode_t mode) LSM_HOOK(void, LSM_RET_VOID, inode_post_create_tmpfile, struct mnt_idmap *idmap, struct inode *inode) -LSM_HOOK(int, 0, inode_link, struct dentry *old_dentry, struct inode *dir, - struct dentry *new_dentry) +LSM_HOOK(int, 0, inode_link, struct mnt_idmap *idmap, + struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) LSM_HOOK(int, 0, inode_unlink, struct inode *dir, struct dentry *dentry) -LSM_HOOK(int, 0, inode_symlink, struct inode *dir, struct dentry *dentry, - const char *old_name) -LSM_HOOK(int, 0, inode_mkdir, struct inode *dir, struct dentry *dentry, - umode_t mode) +LSM_HOOK(int, 0, inode_symlink, struct mnt_idmap *idmap, struct inode *dir, + struct dentry *dentry, const char *old_name) +LSM_HOOK(int, 0, inode_mkdir, struct mnt_idmap *idmap, struct inode *dir, + struct dentry *dentry, umode_t mode) LSM_HOOK(int, 0, inode_rmdir, struct inode *dir, struct dentry *dentry) -LSM_HOOK(int, 0, inode_mknod, struct inode *dir, struct dentry *dentry, - umode_t mode, dev_t dev) +LSM_HOOK(int, 0, inode_mknod, struct mnt_idmap *idmap, struct inode *dir, + struct dentry *dentry, umode_t mode, dev_t dev) LSM_HOOK(int, 0, inode_rename, struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) LSM_HOOK(int, 0, inode_readlink, struct dentry *dentry) LSM_HOOK(int, 0, inode_follow_link, struct dentry *dentry, struct inode *inode, bool rcu) -LSM_HOOK(int, 0, inode_permission, struct inode *inode, int mask) +LSM_HOOK(int, 0, inode_permission, struct mnt_idmap *idmap, + struct inode *inode, int mask) LSM_HOOK(int, 0, inode_setattr, struct mnt_idmap *idmap, struct dentry *dentry, struct iattr *attr) LSM_HOOK(void, LSM_RET_VOID, inode_post_setattr, struct mnt_idmap *idmap, diff --git a/include/linux/security.h b/include/linux/security.h index 153e9043058f..0f5f20ac1050 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -404,24 +404,28 @@ int security_inode_init_security(struct inode *inode, struct inode *dir, int security_inode_init_security_anon(struct inode *inode, const struct qstr *name, const struct inode *context_inode); -int security_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode); +int security_inode_create(struct mnt_idmap *idmap, struct inode *dir, + struct dentry *dentry, umode_t mode); void security_inode_post_create_tmpfile(struct mnt_idmap *idmap, struct inode *inode); -int security_inode_link(struct dentry *old_dentry, struct inode *dir, - struct dentry *new_dentry); +int security_inode_link(struct mnt_idmap *idmap, struct dentry *old_dentry, + struct inode *dir, struct dentry *new_dentry); int security_inode_unlink(struct inode *dir, struct dentry *dentry); -int security_inode_symlink(struct inode *dir, struct dentry *dentry, - const char *old_name); -int security_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode); +int security_inode_symlink(struct mnt_idmap *idmap, struct inode *dir, + struct dentry *dentry, const char *old_name); +int security_inode_mkdir(struct mnt_idmap *idmap, struct inode *dir, + struct dentry *dentry, umode_t mode); int security_inode_rmdir(struct inode *dir, struct dentry *dentry); -int security_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev); +int security_inode_mknod(struct mnt_idmap *idmap, struct inode *dir, + struct dentry *dentry, umode_t mode, dev_t dev); int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry, unsigned int flags); int security_inode_readlink(struct dentry *dentry); int security_inode_follow_link(struct dentry *dentry, struct inode *inode, bool rcu); -int security_inode_permission(struct inode *inode, int mask); +int security_inode_permission(struct mnt_idmap *idmap, struct inode *inode, + int mask); int security_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry, struct iattr *attr); void security_inode_post_setattr(struct mnt_idmap *idmap, struct dentry *dentry, @@ -902,9 +906,10 @@ static inline int security_inode_init_security_anon(struct inode *inode, return 0; } -static inline int security_inode_create(struct inode *dir, - struct dentry *dentry, - umode_t mode) +static inline int security_inode_create(struct mnt_idmap *idmap, + struct inode *dir, + struct dentry *dentry, + umode_t mode) { return 0; } @@ -913,9 +918,10 @@ static inline void security_inode_post_create_tmpfile(struct mnt_idmap *idmap, struct inode *inode) { } -static inline int security_inode_link(struct dentry *old_dentry, - struct inode *dir, - struct dentry *new_dentry) +static inline int security_inode_link(struct mnt_idmap *idmap, + struct dentry *old_dentry, + struct inode *dir, + struct dentry *new_dentry) { return 0; } @@ -926,16 +932,18 @@ static inline int security_inode_unlink(struct inode *dir, return 0; } -static inline int security_inode_symlink(struct inode *dir, - struct dentry *dentry, - const char *old_name) +static inline int security_inode_symlink(struct mnt_idmap *idmap, + struct inode *dir, + struct dentry *dentry, + const char *old_name) { return 0; } -static inline int security_inode_mkdir(struct inode *dir, - struct dentry *dentry, - int mode) +static inline int security_inode_mkdir(struct mnt_idmap *idmap, + struct inode *dir, + struct dentry *dentry, + int mode) { return 0; } @@ -946,9 +954,10 @@ static inline int security_inode_rmdir(struct inode *dir, return 0; } -static inline int security_inode_mknod(struct inode *dir, - struct dentry *dentry, - int mode, dev_t dev) +static inline int security_inode_mknod(struct mnt_idmap *idmap, + struct inode *dir, + struct dentry *dentry, + int mode, dev_t dev) { return 0; } @@ -974,7 +983,8 @@ static inline int security_inode_follow_link(struct dentry *dentry, return 0; } -static inline int security_inode_permission(struct inode *inode, int mask) +static inline int security_inode_permission(struct mnt_idmap *idmap, + struct inode *inode, int mask) { return 0; } diff --git a/security/security.c b/security/security.c index 2ee276ab15c5..a9190da3341d 100644 --- a/security/security.c +++ b/security/security.c @@ -1614,6 +1614,7 @@ int security_path_chroot(const struct path *path) /** * security_inode_create() - Check if creating a file is allowed + * @idmap: idmap of the mount * @dir: the parent directory * @dentry: the file being created * @mode: requested file mode @@ -1622,12 +1623,12 @@ int security_path_chroot(const struct path *path) * * Return: Returns 0 if permission is granted. */ -int security_inode_create(struct inode *dir, struct dentry *dentry, - umode_t mode) +int security_inode_create(struct mnt_idmap *idmap, struct inode *dir, + struct dentry *dentry, umode_t mode) { if (unlikely(IS_PRIVATE(dir))) return 0; - return call_int_hook(inode_create, dir, dentry, mode); + return call_int_hook(inode_create, idmap, dir, dentry, mode); } EXPORT_SYMBOL_GPL(security_inode_create); @@ -1648,6 +1649,7 @@ void security_inode_post_create_tmpfile(struct mnt_idmap *idmap, /** * security_inode_link() - Check if creating a hard link is allowed + * @idmap: idmap of the mount * @old_dentry: existing file * @dir: new parent directory * @new_dentry: new link @@ -1656,12 +1658,12 @@ void security_inode_post_create_tmpfile(struct mnt_idmap *idmap, * * Return: Returns 0 if permission is granted. */ -int security_inode_link(struct dentry *old_dentry, struct inode *dir, - struct dentry *new_dentry) +int security_inode_link(struct mnt_idmap *idmap, struct dentry *old_dentry, + struct inode *dir, struct dentry *new_dentry) { if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)))) return 0; - return call_int_hook(inode_link, old_dentry, dir, new_dentry); + return call_int_hook(inode_link, idmap, old_dentry, dir, new_dentry); } /** @@ -1682,6 +1684,7 @@ int security_inode_unlink(struct inode *dir, struct dentry *dentry) /** * security_inode_symlink() - Check if creating a symbolic link is allowed + * @idmap: idmap of the mount * @dir: parent directory * @dentry: symbolic link * @old_name: existing filename @@ -1690,16 +1693,17 @@ int security_inode_unlink(struct inode *dir, struct dentry *dentry) * * Return: Returns 0 if permission is granted. */ -int security_inode_symlink(struct inode *dir, struct dentry *dentry, - const char *old_name) +int security_inode_symlink(struct mnt_idmap *idmap, struct inode *dir, + struct dentry *dentry, const char *old_name) { if (unlikely(IS_PRIVATE(dir))) return 0; - return call_int_hook(inode_symlink, dir, dentry, old_name); + return call_int_hook(inode_symlink, idmap, dir, dentry, old_name); } /** * security_inode_mkdir() - Check if creating a new directory is allowed + * @idmap: idmap of the mount * @dir: parent directory * @dentry: new directory * @mode: new directory mode @@ -1709,11 +1713,12 @@ int security_inode_symlink(struct inode *dir, struct dentry *dentry, * * Return: Returns 0 if permission is granted. */ -int security_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) +int security_inode_mkdir(struct mnt_idmap *idmap, struct inode *dir, + struct dentry *dentry, umode_t mode) { if (unlikely(IS_PRIVATE(dir))) return 0; - return call_int_hook(inode_mkdir, dir, dentry, mode); + return call_int_hook(inode_mkdir, idmap, dir, dentry, mode); } EXPORT_SYMBOL_GPL(security_inode_mkdir); @@ -1735,6 +1740,7 @@ int security_inode_rmdir(struct inode *dir, struct dentry *dentry) /** * security_inode_mknod() - Check if creating a special file is allowed + * @idmap: idmap of the mount * @dir: parent directory * @dentry: new file * @mode: new file mode @@ -1747,12 +1753,12 @@ int security_inode_rmdir(struct inode *dir, struct dentry *dentry) * * Return: Returns 0 if permission is granted. */ -int security_inode_mknod(struct inode *dir, struct dentry *dentry, - umode_t mode, dev_t dev) +int security_inode_mknod(struct mnt_idmap *idmap, struct inode *dir, + struct dentry *dentry, umode_t mode, dev_t dev) { if (unlikely(IS_PRIVATE(dir))) return 0; - return call_int_hook(inode_mknod, dir, dentry, mode, dev); + return call_int_hook(inode_mknod, idmap, dir, dentry, mode, dev); } /** @@ -1823,6 +1829,7 @@ int security_inode_follow_link(struct dentry *dentry, struct inode *inode, /** * security_inode_permission() - Check if accessing an inode is allowed + * @idmap: idmap of the mount * @inode: inode * @mask: access mask * @@ -1835,11 +1842,12 @@ int security_inode_follow_link(struct dentry *dentry, struct inode *inode, * * Return: Returns 0 if permission is granted. */ -int security_inode_permission(struct inode *inode, int mask) +int security_inode_permission(struct mnt_idmap *idmap, struct inode *inode, + int mask) { if (unlikely(IS_PRIVATE(inode))) return 0; - return call_int_hook(inode_permission, inode, mask); + return call_int_hook(inode_permission, idmap, inode, mask); } /** diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 035aaf113d1d..967984d0af30 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3074,12 +3074,14 @@ static int selinux_inode_init_security_anon(struct inode *inode, &ad); } -static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode) +static int selinux_inode_create(struct mnt_idmap *idmap, struct inode *dir, + struct dentry *dentry, umode_t mode) { return may_create(dir, dentry, SECCLASS_FILE); } -static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) +static int selinux_inode_link(struct mnt_idmap *idmap, struct dentry *old_dentry, + struct inode *dir, struct dentry *new_dentry) { return may_link(dir, old_dentry, MAY_LINK); } @@ -3089,12 +3091,14 @@ static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry) return may_link(dir, dentry, MAY_UNLINK); } -static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name) +static int selinux_inode_symlink(struct mnt_idmap *idmap, struct inode *dir, + struct dentry *dentry, const char *name) { return may_create(dir, dentry, SECCLASS_LNK_FILE); } -static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask) +static int selinux_inode_mkdir(struct mnt_idmap *idmap, struct inode *dir, + struct dentry *dentry, umode_t mask) { return may_create(dir, dentry, SECCLASS_DIR); } @@ -3104,7 +3108,8 @@ static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry) return may_link(dir, dentry, MAY_RMDIR); } -static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev) +static int selinux_inode_mknod(struct mnt_idmap *idmap, struct inode *dir, + struct dentry *dentry, umode_t mode, dev_t dev) { return may_create(dir, dentry, inode_mode_to_security_class(mode)); } @@ -3236,13 +3241,15 @@ static inline void task_avdcache_update(struct task_security_struct *tsec, /** * selinux_inode_permission - Check if the current task can access an inode + * @idmap: idmap of the mount * @inode: the inode that is being accessed * @requested: the accesses being requested * * Check if the current task is allowed to access @inode according to * @requested. Returns 0 if allowed, negative values otherwise. */ -static int selinux_inode_permission(struct inode *inode, int requested) +static int selinux_inode_permission(struct mnt_idmap *idmap, + struct inode *inode, int requested) { int mask; u32 perms; diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 8e88ac65fd7f..a45819d13c0d 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -1089,14 +1089,15 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, /** * smack_inode_link - Smack check on link + * @idmap: idmap of the mount * @old_dentry: the existing object * @dir: unused * @new_dentry: the new object * * Returns 0 if access is permitted, an error code otherwise */ -static int smack_inode_link(struct dentry *old_dentry, struct inode *dir, - struct dentry *new_dentry) +static int smack_inode_link(struct mnt_idmap *idmap, struct dentry *old_dentry, + struct inode *dir, struct dentry *new_dentry) { struct smack_known *isp; struct smk_audit_info ad; @@ -1226,6 +1227,7 @@ static int smack_inode_rename(struct inode *old_inode, /** * smack_inode_permission - Smack version of permission() + * @idmap: idmap of the mount * @inode: the inode in question * @mask: the access requested * @@ -1233,7 +1235,8 @@ static int smack_inode_rename(struct inode *old_inode, * * Returns 0 if access is permitted, an error code otherwise */ -static int smack_inode_permission(struct inode *inode, int mask) +static int smack_inode_permission(struct mnt_idmap *idmap, struct inode *inode, + int mask) { struct superblock_smack *sbsp = smack_superblock(inode->i_sb); struct smk_audit_info ad; -- 2.54.0