[SRU][J][PATCH v2 1/2] apparmor: shift ouid when mediating hard links in userns

Wesley Hershberger wesley.hershberger at canonical.com
Thu Oct 30 14:27:28 UTC 2025


From: Gabriel Totev <gabriel.totev at zetier.com>

When using AppArmor profiles inside an unprivileged container,
the link operation observes an unshifted ouid.
(tested with LXD and Incus)

For example, root inside container and uid 1000000 outside, with
`owner /root/link l,` profile entry for ln:

/root$ touch chain && ln chain link
==> dmesg
apparmor="DENIED" operation="link" class="file"
namespace="root//lxd-feet_<var-snap-lxd-common-lxd>" profile="linkit"
name="/root/link" pid=1655 comm="ln" requested_mask="l" denied_mask="l"
fsuid=1000000 ouid=0 [<== should be 1000000] target="/root/chain"

Fix by mapping inode uid of old_dentry in aa_path_link() rather than
using it directly, similarly to how it's mapped in __file_path_perm()
later in the file.

Signed-off-by: Gabriel Totev <gabriel.totev at zetier.com>
Signed-off-by: John Johansen <john.johansen at canonical.com>
(backported from commit c5bf96d20fd787e4909b755de4705d52f3458836)
[whershberger:
 i_uid_into_vfsuid => i_uid_into_mnt: 234a3113f28d02973ecf501f83d,
 mnt_idmap => mnt_user_ns: 256c8aed2b420a7c57ed6469fbb0f8310f5aeec9]
Signed-off-by: Wesley Hershberger <wesley.hershberger at canonical.com>
---
 security/apparmor/file.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/security/apparmor/file.c b/security/apparmor/file.c
index d6fc6fbe3d71..18b7980288b4 100644
--- a/security/apparmor/file.c
+++ b/security/apparmor/file.c
@@ -462,9 +462,11 @@ int aa_path_link(struct aa_label *label, struct dentry *old_dentry,
 {
 	struct path link = { .mnt = new_dir->mnt, .dentry = new_dentry };
 	struct path target = { .mnt = new_dir->mnt, .dentry = old_dentry };
+	struct inode *inode = d_backing_inode(old_dentry);
+	kuid_t vfsuid = i_uid_into_mnt(mnt_user_ns(target.mnt), inode);
 	struct path_cond cond = {
-		d_backing_inode(old_dentry)->i_uid,
-		d_backing_inode(old_dentry)->i_mode
+		.uid = vfsuid,
+		.mode = inode->i_mode,
 	};
 	char *buffer = NULL, *buffer2 = NULL;
 	struct aa_profile *profile;
-- 
2.34.1




More information about the kernel-team mailing list