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 <[email protected]>
---
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


Reply via email to