diff mbox series

[2/2] apparmor: shift uid when mediating af_unix in userns

Message ID 20250416224209.904863-2-gabriel.totev@zetier.com (mailing list archive)
State New
Headers show
Series [1/2] apparmor: shift ouid when mediating hard links in userns | expand

Commit Message

Gabriel Totev April 16, 2025, 10:42 p.m. UTC
Avoid unshifted ouids for socket file operations as observed when using
AppArmor profiles in unprivileged containers with LXD or Incus.

For example, root inside container and uid 1000000 outside, with
`owner /root/sock rw,` profile entry for nc:

/root$ nc -lkU sock & nc -U sock
==> dmesg
apparmor="DENIED" operation="connect" class="file"
namespace="root//lxd-podia_<var-snap-lxd-common-lxd>" profile="sockit"
name="/root/sock" pid=3924 comm="nc" requested_mask="wr" denied_mask="wr"
fsuid=1000000 ouid=0 [<== should be 1000000]

Fix by performing uid mapping as per common_perm_cond() in lsm.c

Signed-off-by: Gabriel Totev <gabriel.totev@zetier.com>
---
The example above was taken from an Ubuntu Noble 6.8.0 kernel, which has
a different af_unix.c file, which nevertheless contains an identical
section that I patched identically and verified the connect operation
saw the correctly shifted ouid.

I was not able to verify this fix on the mainline kernel as it does not
appear to mediate af_unix (due to dcd7a559411e "gate... behind v9 abi"?)
and I don't know how to make it do so.

I am also not sure how this change should be propagated to the Ubuntu
kernel and its differing af_unix.c

First time patch mailer so please excuse my ignorance or blunders.

 security/apparmor/af_unix.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/security/apparmor/af_unix.c b/security/apparmor/af_unix.c
index ed4b34b88e38..a1c2b8516681 100644
--- a/security/apparmor/af_unix.c
+++ b/security/apparmor/af_unix.c
@@ -12,6 +12,7 @@ 
  * License.
  */
 
+#include <linux/fs.h>
 #include <net/tcp_states.h>
 
 #include "include/audit.h"
@@ -45,8 +46,11 @@  static int unix_fs_perm(const char *op, u32 mask, const struct cred *subj_cred,
 	 */
 	if (u->path.dentry) {
 		/* the sunpath may not be valid for this ns so use the path */
-		struct path_cond cond = { u->path.dentry->d_inode->i_uid,
-					  u->path.dentry->d_inode->i_mode
+		struct inode *inode = u->path.dentry->d_inode;
+		vfsuid_t vfsuid = i_uid_into_vfsuid(mnt_idmap(u->path.mnt), inode);
+		struct path_cond cond = {
+			.uid = vfsuid_into_kuid(vfsuid),
+			.mode = inode->i_mode,
 		};
 
 		return aa_path_perm(op, subj_cred, label, &u->path,