Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

apparmor: handle idmapped mounts

The i_uid and i_gid are mostly used when logging for AppArmor. This is
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.

Link: https://lore.kernel.org/r/20210121131959.646623-26-christian.brauner@ubuntu.com
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>

+24 -10
+6 -3
security/apparmor/domain.c
··· 10 10 11 11 #include <linux/errno.h> 12 12 #include <linux/fdtable.h> 13 + #include <linux/fs.h> 13 14 #include <linux/file.h> 14 15 #include <linux/mount.h> 15 16 #include <linux/syscalls.h> 16 17 #include <linux/tracehook.h> 17 18 #include <linux/personality.h> 18 19 #include <linux/xattr.h> 20 + #include <linux/user_namespace.h> 19 21 20 22 #include "include/audit.h" 21 23 #include "include/apparmorfs.h" ··· 860 858 const char *info = NULL; 861 859 int error = 0; 862 860 bool unsafe = false; 861 + kuid_t i_uid = i_uid_into_mnt(file_mnt_user_ns(bprm->file), 862 + file_inode(bprm->file)); 863 863 struct path_cond cond = { 864 - file_inode(bprm->file)->i_uid, 864 + i_uid, 865 865 file_inode(bprm->file)->i_mode 866 866 }; 867 867 ··· 971 967 error = fn_for_each(label, profile, 972 968 aa_audit_file(profile, &nullperms, OP_EXEC, MAY_EXEC, 973 969 bprm->filename, NULL, new, 974 - file_inode(bprm->file)->i_uid, info, 975 - error)); 970 + i_uid, info, error)); 976 971 aa_put_label(new); 977 972 goto done; 978 973 }
+3 -1
security/apparmor/file.c
··· 11 11 #include <linux/tty.h> 12 12 #include <linux/fdtable.h> 13 13 #include <linux/file.h> 14 + #include <linux/fs.h> 15 + #include <linux/mount.h> 14 16 15 17 #include "include/apparmor.h" 16 18 #include "include/audit.h" ··· 511 509 struct aa_profile *profile; 512 510 struct aa_perms perms = {}; 513 511 struct path_cond cond = { 514 - .uid = file_inode(file)->i_uid, 512 + .uid = i_uid_into_mnt(file_mnt_user_ns(file), file_inode(file)), 515 513 .mode = file_inode(file)->i_mode 516 514 }; 517 515 char *buffer;
+15 -6
security/apparmor/lsm.c
··· 224 224 */ 225 225 static int common_perm_cond(const char *op, const struct path *path, u32 mask) 226 226 { 227 - struct path_cond cond = { d_backing_inode(path->dentry)->i_uid, 228 - d_backing_inode(path->dentry)->i_mode 227 + struct user_namespace *mnt_userns = mnt_user_ns(path->mnt); 228 + struct path_cond cond = { 229 + i_uid_into_mnt(mnt_userns, d_backing_inode(path->dentry)), 230 + d_backing_inode(path->dentry)->i_mode 229 231 }; 230 232 231 233 if (!path_mediated_fs(path->dentry)) ··· 268 266 struct dentry *dentry, u32 mask) 269 267 { 270 268 struct inode *inode = d_backing_inode(dentry); 269 + struct user_namespace *mnt_userns = mnt_user_ns(dir->mnt); 271 270 struct path_cond cond = { }; 272 271 273 272 if (!inode || !path_mediated_fs(dentry)) 274 273 return 0; 275 274 276 - cond.uid = inode->i_uid; 275 + cond.uid = i_uid_into_mnt(mnt_userns, inode); 277 276 cond.mode = inode->i_mode; 278 277 279 278 return common_perm_dir_dentry(op, dir, dentry, mask, &cond); ··· 364 361 365 362 label = begin_current_label_crit_section(); 366 363 if (!unconfined(label)) { 364 + struct user_namespace *mnt_userns = mnt_user_ns(old_dir->mnt); 367 365 struct path old_path = { .mnt = old_dir->mnt, 368 366 .dentry = old_dentry }; 369 367 struct path new_path = { .mnt = new_dir->mnt, 370 368 .dentry = new_dentry }; 371 - struct path_cond cond = { d_backing_inode(old_dentry)->i_uid, 372 - d_backing_inode(old_dentry)->i_mode 369 + struct path_cond cond = { 370 + i_uid_into_mnt(mnt_userns, d_backing_inode(old_dentry)), 371 + d_backing_inode(old_dentry)->i_mode 373 372 }; 374 373 375 374 error = aa_path_perm(OP_RENAME_SRC, label, &old_path, 0, ··· 425 420 426 421 label = aa_get_newest_cred_label(file->f_cred); 427 422 if (!unconfined(label)) { 423 + struct user_namespace *mnt_userns = file_mnt_user_ns(file); 428 424 struct inode *inode = file_inode(file); 429 - struct path_cond cond = { inode->i_uid, inode->i_mode }; 425 + struct path_cond cond = { 426 + i_uid_into_mnt(mnt_userns, inode), 427 + inode->i_mode 428 + }; 430 429 431 430 error = aa_path_perm(OP_OPEN, label, &file->f_path, 0, 432 431 aa_map_file_to_perms(file), &cond);