[PATCH 2/2] apparmor: shift uid when mediating af_unix in userns
Gabriel Totev
gabriel.totev at zetier.com
Wed Apr 16 22:42:09 UTC 2025
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 at 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 --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,
--
2.34.1
More information about the Linux-security-module-archive
mailing list