[SRU][J/N/P][PATCH 1/2] apparmor: shift ouid when mediating hard links in userns
John Johansen
john.johansen at canonical.com
Tue Aug 26 19:15:53 UTC 2025
On 8/26/25 11:05, Wesley Hershberger wrote:
> From: Gabriel Totev <gabriel.totev at zetier.com>
>
> BugLink: https://bugs.launchpad.net/bugs/2121257
>
> 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>
> (cherry picked from commit c5bf96d20fd787e4909b755de4705d52f3458836)
> Signed-off-by: Wesley Hershberger <wesley.hershberger at canonical.com>
From the AppArmor side
Acked-by: John Johansen <john.johansen 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 3e080bd3b470..e96615e26dfd 100644
> --- a/security/apparmor/file.c
> +++ b/security/apparmor/file.c
> @@ -577,9 +577,11 @@ int aa_path_link(const struct cred *subj_cred,
> {
> 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);
> + vfsuid_t vfsuid = i_uid_into_vfsuid(mnt_idmap(target.mnt), inode);
> struct path_cond cond = {
> - d_backing_inode(old_dentry)->i_uid,
> - d_backing_inode(old_dentry)->i_mode
> + .uid = vfsuid_into_kuid(vfsuid),
> + .mode = inode->i_mode,
> };
> char *buffer = NULL, *buffer2 = NULL;
> struct aa_profile *profile;
More information about the kernel-team
mailing list