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

apparmor: Fix regression in mount mediation

commit 2db154b3ea8e ("vfs: syscall: Add move_mount(2) to move mounts around")

introduced a new move_mount(2) system call and a corresponding new LSM
security_move_mount hook but did not implement this hook for any
existing LSM. This creates a regression for AppArmor mediation of
mount. This patch provides a base mapping of the move_mount syscall to
the existing mount mediation. In the future we may introduce
additional mediations around the new mount calls.

Fixes: 2db154b3ea8e ("vfs: syscall: Add move_mount(2) to move mounts around")
CC: stable@vger.kernel.org
Reported-by: Andreas Steinmetz <anstein99@googlemail.com>
Signed-off-by: John Johansen <john.johansen@canonical.com>

+51 -22
+5 -2
security/apparmor/include/mount.h
··· 38 38 struct aa_label *label, const struct path *path, 39 39 unsigned long flags); 40 40 41 + int aa_move_mount_old(const struct cred *subj_cred, 42 + struct aa_label *label, const struct path *path, 43 + const char *old_name); 41 44 int aa_move_mount(const struct cred *subj_cred, 42 - struct aa_label *label, const struct path *path, 43 - const char *old_name); 45 + struct aa_label *label, const struct path *from_path, 46 + const struct path *to_path); 44 47 45 48 int aa_new_mount(const struct cred *subj_cred, 46 49 struct aa_label *label, const char *dev_name,
+18 -2
security/apparmor/lsm.c
··· 722 722 error = aa_mount_change_type(current_cred(), label, 723 723 path, flags); 724 724 else if (flags & MS_MOVE) 725 - error = aa_move_mount(current_cred(), label, path, 726 - dev_name); 725 + error = aa_move_mount_old(current_cred(), label, path, 726 + dev_name); 727 727 else 728 728 error = aa_new_mount(current_cred(), label, dev_name, 729 729 path, type, flags, data); 730 730 } 731 + __end_current_label_crit_section(label); 732 + 733 + return error; 734 + } 735 + 736 + static int apparmor_move_mount(const struct path *from_path, 737 + const struct path *to_path) 738 + { 739 + struct aa_label *label; 740 + int error = 0; 741 + 742 + label = __begin_current_label_crit_section(); 743 + if (!unconfined(label)) 744 + error = aa_move_mount(current_cred(), label, from_path, 745 + to_path); 731 746 __end_current_label_crit_section(label); 732 747 733 748 return error; ··· 1391 1376 LSM_HOOK_INIT(capget, apparmor_capget), 1392 1377 LSM_HOOK_INIT(capable, apparmor_capable), 1393 1378 1379 + LSM_HOOK_INIT(move_mount, apparmor_move_mount), 1394 1380 LSM_HOOK_INIT(sb_mount, apparmor_sb_mount), 1395 1381 LSM_HOOK_INIT(sb_umount, apparmor_sb_umount), 1396 1382 LSM_HOOK_INIT(sb_pivotroot, apparmor_sb_pivotroot),
+28 -18
security/apparmor/mount.c
··· 483 483 } 484 484 485 485 int aa_move_mount(const struct cred *subj_cred, 486 - struct aa_label *label, const struct path *path, 487 - const char *orig_name) 486 + struct aa_label *label, const struct path *from_path, 487 + const struct path *to_path) 488 488 { 489 489 struct aa_profile *profile; 490 - char *buffer = NULL, *old_buffer = NULL; 491 - struct path old_path; 490 + char *to_buffer = NULL, *from_buffer = NULL; 492 491 int error; 493 492 494 493 AA_BUG(!label); 495 - AA_BUG(!path); 494 + AA_BUG(!from_path); 495 + AA_BUG(!to_path); 496 + 497 + to_buffer = aa_get_buffer(false); 498 + from_buffer = aa_get_buffer(false); 499 + error = -ENOMEM; 500 + if (!to_buffer || !from_buffer) 501 + goto out; 502 + error = fn_for_each_confined(label, profile, 503 + match_mnt(subj_cred, profile, to_path, to_buffer, 504 + from_path, from_buffer, 505 + NULL, MS_MOVE, NULL, false)); 506 + out: 507 + aa_put_buffer(to_buffer); 508 + aa_put_buffer(from_buffer); 509 + 510 + return error; 511 + } 512 + 513 + int aa_move_mount_old(const struct cred *subj_cred, struct aa_label *label, 514 + const struct path *path, const char *orig_name) 515 + { 516 + struct path old_path; 517 + int error; 496 518 497 519 if (!orig_name || !*orig_name) 498 520 return -EINVAL; 499 - 500 521 error = kern_path(orig_name, LOOKUP_FOLLOW, &old_path); 501 522 if (error) 502 523 return error; 503 524 504 - buffer = aa_get_buffer(false); 505 - old_buffer = aa_get_buffer(false); 506 - error = -ENOMEM; 507 - if (!buffer || !old_buffer) 508 - goto out; 509 - error = fn_for_each_confined(label, profile, 510 - match_mnt(subj_cred, profile, path, buffer, &old_path, 511 - old_buffer, 512 - NULL, MS_MOVE, NULL, false)); 513 - out: 514 - aa_put_buffer(buffer); 515 - aa_put_buffer(old_buffer); 525 + error = aa_move_mount(subj_cred, label, &old_path, path); 516 526 path_put(&old_path); 517 527 518 528 return error;