** Description changed:

  [Impact]
  
  Socket creation with the following AppArmor unconfined profile fails due
  to an AppArmor permission error:
  
  PermissionError: [Errno 13] Permission denied
  
  abi <abi/4.0>,
  profile aa-repro flags=(unconfined) {
  userns,
  }
  
  This socket_create issue does not occur with the Noble GA kernel; it
  only occurs when running Noble userland on the Noble HWE kernel or
  later.
  
- This report is similar to the pivot_root issue in bug #2067900, which
+ This report is similar to the pivot_root issue in bug 2067900, which
  shares the root cause in the AppArmor parser. This AppArmor parser bug
  is addressed in the upstream commit:
  
  
https://gitlab.com/apparmor/apparmor/-/commit/4bb134e4bb950a8c9a1f70a27eb2acd2a35df412
  
  The AppArmor parser incorrectly added mediation classes to unconfined
  profiles, including those that would affect pivot_root (and
  socket_create). The upstream fix 4bb134e landed in Resolute (and
  Stonking), but not in Noble's 4.0.1really4.0.1-0ubuntu0.24.04.7 version.
  
- In #2067900, the kernel commit dc757a645cfa82f6ac252365df20a36a9ff82760
- was reverted in the Noble GA kernel, because it had other issues with
- older versions of the AppArmor parser. This does not address the
- AppArmor parser bug, but fixed the pivot_root bug temporarily.
+ In bug 2067900, the kernel commit
+ dc757a645cfa82f6ac252365df20a36a9ff82760 was reverted in the Noble GA
+ kernel, because it had other issues with older versions of the AppArmor
+ parser. This does not address the AppArmor parser bug, but fixed the
+ pivot_root bug temporarily.
  
  The upstream fix in the AppArmor parser did initially land in Noble
  updates, but was later reverted due to an (unrelated?) regression
- according to #2067900. Since reverting dc757a6 already fixed the
- pivot_root issue on the Noble GA kernel, #2067900 has been left
+ according to bug 2067900. Since reverting dc757a6 already fixed the
+ pivot_root issue on the Noble GA kernel, bug 2067900 has been left
  inactive. This report is thus intended to backport 4bb134e to address
  this socket_create issue, in addition to the pivot_root issue.
  
  [Test Plan]
  
  I have tested the kernel behaviour under the following scenarios:
  
  1. Jammy GA kernel (5.15.0-1104-kvm) + Jammy userland (22.04.5 LTS)
  2. Jammy HWE kernel (6.8.0-136-generic) + Jammy userland (22.04.5 LTS)
  3. Noble GA kernel (6.8.0-136-generic) + Noble userland (24.04.4 LTS)
  4. Noble HWE kernel (7.0.0-28-generic) + Noble userland (24.04.4 LTS)
  5. Noble HWE kernel (7.0.0-28-generic) + Noble userland (24.04.4 LTS; with 
4bb134e)
  6. Resolute GA kernel (7.0.0-28-generic) + Resolute userland (26.04 LTS)
  7. Stonking kernel (7.0.0-14-generic) + Stonking userland (Ubuntu Stonking 
Stingray)
  
  For 5, the upstream fix 4bb134e was manually applied on ubuntu/noble-
  updates.
  
  First, set up the host and container:
  
  ~$ lxc launch ubuntu:24.04 aa-repro1 --vm -d root,size=20GB
  # Or for Stonking kernel:
  # ~$ lxc launch ubuntu-daily:stonking aa-repro3 --vm -d root,size=20GB
  ~$ lxc shell aa-repro1
  root@aa-repro1:~# snap install lxd
  root@aa-repro1:~# lxd init --minimal
  root@aa-repro1:~# lxc launch ubuntu:24.04 c1
  # Or for Stonking kernel:
  # root@aa-repro1:~# lxc launch ubuntu-daily:stonking c1
  root@aa-repro1:~# lxc shell c1
  root@c1:~# uname -r
  6.8.0-136-generic
  root@c1:~# lsb_release -a | grep Description
  Description:    Ubuntu 24.04.4 LTS
  
  Then create an unconfined AppArmor profile and test socket creation:
  
  root@c1:~# apt update && apt install -y apparmor apparmor-utils
  root@c1:~# cat >/etc/apparmor.d/aa-repro <<'EOF'
  abi <abi/4.0>,
  profile aa-repro flags=(unconfined) {
  userns,
  }
  EOF
  # Or for Jammy userland:
  # root@c1:~# cat >/etc/apparmor.d/aa-repro <<'EOF'
  # abi <abi/3.0>,
  # profile aa-repro flags=(unconfined) {
  # }
  # EOF
  root@c1:~# apparmor_parser -r /etc/apparmor.d/aa-repro
  root@c1:~# aa-exec -p aa-repro -- \
  python3 -c 'import socket; socket.socket(socket.AF_INET, socket.SOCK_STREAM); 
socket.socket(socket.AF_INET6, socket.SOCK_STREAM); print("ok")'
  ok
  
  Repeating this for 1-7, I have obtained the following results:
  
  # 1. Jammy GA kernel + Jammy userland
  root@c1:~# aa-exec -p aa-repro -- ...
  ok
  
  # 2. Jammy HWE kernel + Jammy userland
  root@c1:~# aa-exec -p aa-repro -- ...
  ok
  
  # 3. Noble GA kernel + Noble userland
  root@c1:~# aa-exec -p aa-repro -- ...
  ok
  
  # 4. Noble HWE kernel + Noble userland
  root@c1:~# aa-exec -p aa-repro -- ...
  Traceback (most recent call last):
    File "<string>", line 1, in <module>
    File "/usr/lib/python3.12/socket.py", line 233, in __init__
      _socket.socket.__init__(self, family, type, proto, fileno)
  PermissionError: [Errno 13] Permission denied
  root@c1:~# exit
  root@aa-repro1:~# journalctl -k | grep 'apparmor="DENIED"' | grep 
'class="net"'
  Jul 29 07:43:28 aa-repro1 kernel: audit: type=1400 audit(1785311008.964:621): 
apparmor="DENIED" operation="create" class="net" info="failed af match" 
error=-13 namespace="root//lxd-c1_<var-snap-lxd-common-lxd>" profile="aa-repro" 
pid=3516 comm="python3" family="inet" sock_type="stream" protocol=0 
requested="create" denied="create"
  
  # 5. Noble HWE kernel + Noble userland (with 4bb134e)
  root@c1:~# aa-exec -p aa-repro -- ...
  ok
  
  # 6. Resolute kernel + Resolute userland
  root@c1:~# aa-exec -p aa-repro -- ...
  ok
  
  # 7. Stonking kernel + Stonking userland
  root@c1:~# aa-exec -p aa-repro -- ...
  ok
  
  The AppArmor parser bug is present in Jammy and Noble userland, but not
  in Resolute userland. As shown above, the AppArmor parser in Jammy and
  Noble userland only fails on the Noble HWE kernel (or later).
  
  On another note, pivot_root succeeds for 4, which is why I believe
- justifies keeping this report separate from #2067900:
+ justifies keeping this report separate from bug 2067900:
  
  # 4. Noble HWE kernel + Noble userland
  aa-exec -p aa-repro -- unshare --mount --propagation private -- bash -c '
  mkdir -p /mnt/newroot
  mount -t tmpfs tmpfs /mnt/newroot
  mkdir -p /mnt/newroot/put_old
  cd /mnt/newroot
  pivot_root . put_old && echo ok'
  ok
  
  [Where problems could occur]
  
  I believe backporting the upstream fix 4bb134e has minimal impact
  because it only affects unconfined profiles. It also only removes
  mediation classes from the unconfined profiles, correctly excluding
  userns.
  
  [Other Info]
  
  While the root cause is the corrupted binary blob in which the AppArmor
  parser added spurious mediation classes to unconfined profiles, I have
  identified the subtle kernel behaviour that would explain:
  
  1. Why reverting dc757a6 on the Noble GA kernel temporarily fixed the issue
  2. Why Noble userland on the Noble HWE kernel fails, but not on the Noble GA 
kernel
  
  These can be explained by how these primitives work for unconfined
  profiles:
  
  1. profile_unconfined(profile) returns 1 in an LXD container process
  2. unconfined(label) returns 0 in an LXD container process, if the host 
profile is confined i.e. the profiles are stacked in a label
  3. RULE_MEDIATES(rules, AA_CLASS_XXX) (and its variants) returns 1 if the 
binary blob is corrupted
  4. label_mediates(label, AA_CLASS_XXX) returns 0 even if the binary blob is 
corrupted
  
  RULE_MEDIATES() reads from the start states of the DFA directly, which
  are compiled from the AppArmor parser. On the other hand,
  label_mediates() reads from the 'mediates' bits directly, which are left
  unset (except AA_CLASS_NS) in aa_compute_profile_mediates() if
  profile_unconfined() is 1.
  
  I have verified the above results by adding a few printk() calls to the
  kernel, triggering them in an LXD container nested in an LXD VM.
  
  The corresponding LSM hooks use the above primitives in slightly
  different ways, which I believe leads to the divergent behaviour of
  pivot_root and socket_create in an LXD container running on different
  kernel versions:
  
  1. apparmor_sb_pivotroot() on the Jammy GA kernel:
    - Same as item 3 below.
  
  2. apparmor_sb_pivotroot() on the Noble GA kernel (before reverting dc757a6):
    - The first check label_mediates(label, AA_CLASS_MOUNT) returns 1, and 
proceeds to the second check.
    - The second check !RULE_MEDIATES(rules, AA_CLASS_MOUNT) returns 0 in 
build_pivotroot(), and errors in the DFA matching.
  
  3. apparmor_sb_pivotroot() on the Noble GA kernel (after reverting dc757a6):
    - The first check !unconfined(label) returns 1, and proceeds to the second 
check.
    - The second check profile_unconfined(profile) || !RULE_MEDIATES(rules, 
AA_CLASS_MOUNT) returns 1 in build_pivotroot(), and bypasses the DFA matching.
  
  4. apparmor_sb_pivotroot() on the Resolute GA kernel:
    - Same as item 3 above.
  
  5. apparmor_socket_create() on the Jammy GA kernel:
    - The first check !(kern || unconfined(label)) returns 1, and proceeds to 
the second check.
    - The second check profile_unconfined(profile) returns 1, and bypasses the 
DFA matching.
  
  6. apparmor_socket_create() on the Noble GA kernel:
    - The first check label_mediates(label, AA_CLASS_NET) returns 0, and 
bypasses the DFA matching.
  
  7. apparmor_socket_create() on the Resolute GA kernel:
    - The first check !unconfined(label) returns 1.
    - The second check RULE_MEDIATES_NET(rule) returns 1 in 
profile_create_perm(), and errors in the DFA matching.

** Project changed: apparmor => apparmor (Ubuntu)

** Also affects: apparmor (Ubuntu Noble)
   Importance: Undecided
       Status: New

** Changed in: apparmor (Ubuntu)
       Status: New => Fix Released

** Changed in: apparmor (Ubuntu Noble)
   Importance: Undecided => Medium

** Changed in: apparmor (Ubuntu Noble)
       Status: New => In Progress

** Changed in: apparmor (Ubuntu)
   Importance: Undecided => Medium

** Changed in: apparmor (Ubuntu)
     Assignee: (unassigned) => Taichi Maeda (taichimaeda1)

** Changed in: apparmor (Ubuntu Noble)
     Assignee: (unassigned) => Taichi Maeda (taichimaeda1)

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/2162134

Title:
  Unconfined profile blocks socket_create

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/2162134/+subscriptions


-- 
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to