The i_uid and i_gid are only ever used when logging for AppArmor. This is already broken in a bunch of places where the global root id is reported instead of the i_uid or i_gid of the file. Nonetheless, be kind and log the mapped inode if we're coming from an idmapped mount. If the initial user namespace is passed nothing changes so non-idmapped mounts will see identical behavior as before. Signed-off-by: Christian Brauner <christian.brauner@xxxxxxxxxx> --- /* v2 */ unchanged /* v3 */ unchanged /* v4 */ - Serge Hallyn <serge@xxxxxxxxxx>: - Use "mnt_userns" to refer to a vfsmount's userns everywhere to make terminology consistent. --- security/apparmor/domain.c | 9 ++++++--- security/apparmor/file.c | 5 ++++- security/apparmor/lsm.c | 12 ++++++++---- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c index 16f184bc48de..890aa0b43bab 100644 --- a/security/apparmor/domain.c +++ b/security/apparmor/domain.c @@ -10,12 +10,14 @@ #include <linux/errno.h> #include <linux/fdtable.h> +#include <linux/fs.h> #include <linux/file.h> #include <linux/mount.h> #include <linux/syscalls.h> #include <linux/tracehook.h> #include <linux/personality.h> #include <linux/xattr.h> +#include <linux/user_namespace.h> #include "include/audit.h" #include "include/apparmorfs.h" @@ -858,8 +860,10 @@ int apparmor_bprm_creds_for_exec(struct linux_binprm *bprm) const char *info = NULL; int error = 0; bool unsafe = false; + struct user_namespace *mnt_userns = mnt_user_ns(bprm->file->f_path.mnt); + kuid_t i_uid = i_uid_into_mnt(mnt_userns, file_inode(bprm->file)); struct path_cond cond = { - file_inode(bprm->file)->i_uid, + i_uid, file_inode(bprm->file)->i_mode }; @@ -967,8 +971,7 @@ int apparmor_bprm_creds_for_exec(struct linux_binprm *bprm) error = fn_for_each(label, profile, aa_audit_file(profile, &nullperms, OP_EXEC, MAY_EXEC, bprm->filename, NULL, new, - file_inode(bprm->file)->i_uid, info, - error)); + i_uid, info, error)); aa_put_label(new); goto done; } diff --git a/security/apparmor/file.c b/security/apparmor/file.c index 92acf9a49405..d70d09a5ce7d 100644 --- a/security/apparmor/file.c +++ b/security/apparmor/file.c @@ -11,6 +11,8 @@ #include <linux/tty.h> #include <linux/fdtable.h> #include <linux/file.h> +#include <linux/fs.h> +#include <linux/mount.h> #include "include/apparmor.h" #include "include/audit.h" @@ -508,8 +510,9 @@ static int __file_path_perm(const char *op, struct aa_label *label, { struct aa_profile *profile; struct aa_perms perms = {}; + struct user_namespace *mnt_userns = mnt_user_ns(file->f_path.mnt); struct path_cond cond = { - .uid = file_inode(file)->i_uid, + .uid = i_uid_into_mnt(mnt_userns, file_inode(file)), .mode = file_inode(file)->i_mode }; char *buffer; diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index ffeaee5ed968..03260983b471 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -224,7 +224,8 @@ static int common_perm(const char *op, const struct path *path, u32 mask, */ static int common_perm_cond(const char *op, const struct path *path, u32 mask) { - struct path_cond cond = { d_backing_inode(path->dentry)->i_uid, + struct user_namespace *mnt_userns = mnt_user_ns(path->mnt); + struct path_cond cond = { i_uid_into_mnt(mnt_userns, d_backing_inode(path->dentry)), d_backing_inode(path->dentry)->i_mode }; @@ -266,12 +267,13 @@ static int common_perm_rm(const char *op, const struct path *dir, struct dentry *dentry, u32 mask) { struct inode *inode = d_backing_inode(dentry); + struct user_namespace *mnt_userns = mnt_user_ns(dir->mnt); struct path_cond cond = { }; if (!inode || !path_mediated_fs(dentry)) return 0; - cond.uid = inode->i_uid; + cond.uid = i_uid_into_mnt(mnt_userns, inode); cond.mode = inode->i_mode; return common_perm_dir_dentry(op, dir, dentry, mask, &cond); @@ -361,11 +363,12 @@ static int apparmor_path_rename(const struct path *old_dir, struct dentry *old_d label = begin_current_label_crit_section(); if (!unconfined(label)) { + struct user_namespace *mnt_userns = mnt_user_ns(old_dir->mnt); struct path old_path = { .mnt = old_dir->mnt, .dentry = old_dentry }; struct path new_path = { .mnt = new_dir->mnt, .dentry = new_dentry }; - struct path_cond cond = { d_backing_inode(old_dentry)->i_uid, + struct path_cond cond = { i_uid_into_mnt(mnt_userns, d_backing_inode(old_dentry)), d_backing_inode(old_dentry)->i_mode }; @@ -420,8 +423,9 @@ static int apparmor_file_open(struct file *file) label = aa_get_newest_cred_label(file->f_cred); if (!unconfined(label)) { + struct user_namespace *mnt_userns = mnt_user_ns(file->f_path.mnt); struct inode *inode = file_inode(file); - struct path_cond cond = { inode->i_uid, inode->i_mode }; + struct path_cond cond = { i_uid_into_mnt(mnt_userns, inode), inode->i_mode }; error = aa_path_perm(OP_OPEN, label, &file->f_path, 0, aa_map_file_to_perms(file), &cond); -- 2.29.2