Activity log for bug #1772097

Date Who What changed Old value New value Message
2018-05-18 19:13:38 Jamie Strandboge bug added bug
2018-05-18 19:13:38 Jamie Strandboge attachment added linkat.tar.gz https://bugs.launchpad.net/bugs/1772097/+attachment/5141396/+files/linkat.tar.gz
2018-05-18 19:14:01 Jamie Strandboge description Qt 5.10 recently (https://github.com/qt/qtbase/commit/189e9c93d7ed42202ad51507c8944d64e9a7888d) started using something akin to the following for creating temp files: fd = open("/tmp", O_RDWR | O_DIRECTORY | O_CLOEXEC | O_TMPFILE) write(fd, "...") linkat(AT_FDCWD, "/proc/self/fd/<fd for O_TMPFILE>", AT_FDCWD, "/tmp/...", AT_SYMLINK_FOLLOW) I diagnosis was provided here: https://forum.snapcraft.io/t/qt-5-10-linkat-denials-broken-kde-snaps/5484/10 Attached is a simple reproducer that demonstrates that apparmor works fine with this for unconfined and non-attach_disconnected profiles, but using attach_disconnected breaks the above with denials that cannot be allowed with policy. Eg: $ tar -zxvf ./linkat.tar.gz linkat/ linkat/main.c linkat/test.sh linkat/profile linkat/profile_attach_disconnected linkat/test-no-snap.sh linkat/test-tmp-linkat_1.0_amd64.snap $ cd ./linkat $ ./test-no-snap.sh = Test unconfined = Running: aa-exec -p unconfined -- ./tmp-linkat /tmp prefix: /tmp opened fd: 3 [/proc/self/fd/3] writing works linkat success Running: aa-exec -p unconfined -- ./tmp-linkat /home/jamie/snap/test-tmp-linkat/common/ prefix: /home/jamie/snap/test-tmp-linkat/common/ opened fd: 3 [/proc/self/fd/3] writing works linkat success = Test confined = Loading apparmor profile for 'test' Policy for 'test' #include <tunables/global> profile test { #include <abstractions/base> /tmp/{#,okular}* rwl, @{HOME}/snap/test-tmp-linkat/common/{#,okular}* rwl, } Running: aa-exec -p test -- ./tmp-linkat /tmp prefix: /tmp opened fd: 3 [/proc/self/fd/3] writing works linkat success Running: aa-exec -p test -- ./tmp-linkat /home/jamie/snap/test-tmp-linkat/common/ prefix: /home/jamie/snap/test-tmp-linkat/common/ opened fd: 3 [/proc/self/fd/3] writing works linkat success = Test confined with attach_disconnected = Loading apparmor profile for 'test_atch_disconnected' Policy for 'test_attach_disconnected' #include <tunables/global> profile test_attach_disconnected (attach_disconnected) { #include <abstractions/base> /tmp/{#,okular}* rwl, @{HOME}/snap/test-tmp-linkat/common/{#,okular}* rwl, } Running: aa-exec -p test_attach_disconnected -- ./tmp-linkat /tmp prefix: /tmp opened fd: 3 [/proc/self/fd/3] writing works linkat failed: No such file or directory FAIL Running: aa-exec -p test_attach_disconnected -- ./tmp-linkat /home/jamie/snap/test-tmp-linkat/common/ prefix: /home/jamie/snap/test-tmp-linkat/common/ opened fd: 3 [/proc/self/fd/3] writing works linkat failed: No such file or directory FAIL FAIL: some tests failed [1] The failing test shows this in the logs: May 18 13:53:29 localhost audit[20542]: AVC apparmor="DENIED" operation="link" info="Failed name lookup - deleted entry" error=-2 profile="test_attach_disconnected" name="/tmp/#132105" pid=20542 comm="tmp-linkat" requested_mask="l" denied_mask="l" fsuid=1000 ouid=1000 May 18 13:53:29 localhost audit[20542]: AVC apparmor="DENIED" operation="link" profile="test_attach_disconnected" name="/tmp/okular_DHqFKd.ps" pid=20542 comm="tmp-linkat" requested_mask="l" denied_mask="l" fsuid=1000 ouid=1000 target="/tmp/#132105" May 18 13:53:29 localhost audit[20543]: AVC apparmor="DENIED" operation="link" info="Failed name lookup - deleted entry" error=-2 profile="test_attach_disconnected" name="/home/jamie/snap/test-tmp-linkat/common/#12871268" pid=20543 comm="tmp-linkat" requested_mask="l" denied_mask="l" fsuid=1000 ouid=1000 May 18 13:53:29 localhost audit[20543]: AVC apparmor="DENIED" operation="link" profile="test_attach_disconnected" name="/home/jamie/snap/test-tmp-linkat/common/okular_DHqFKd.ps" pid=20543 comm="tmp-linkat" requested_mask="l" denied_mask="l" fsuid=1000 ouid=1000 target="/home/jamie/snap/test-tmp-linkat/common/#12871268" Unfortunately, this breaks snaps using Qt 5.10 as there is no workaround (attach_disconnected is required due to how the snap's mountspace is setup). Eg: $ ./test.sh = Test strict mode snap (per-snap mount namespace with strict) = test-tmp-linkat 1.0 installed Grepping for relevant policy: @{SNAP_NAME}="test-tmp-linkat" profile "snap.test-tmp-linkat.test-tmp-linkat" (attach_disconnected) { owner @{HOME}/snap/@{SNAP_NAME}/common/** wl, /var/snap/@{SNAP_NAME}/common/** wl, /tmp/** mrwlkix, Running: test-tmp-linkat /tmp prefix: /tmp opened fd: 3 [/proc/self/fd/3] writing works linkat failed: No such file or directory FAIL Running: test-tmp-linkat /home/jamie/snap/test-tmp-linkat/common/ prefix: /home/jamie/snap/test-tmp-linkat/common/ opened fd: 3 [/proc/self/fd/3] writing works linkat failed: No such file or directory FAIL = Test devmode mode snap (per-snap mount namespace with complain) = test-tmp-linkat 1.0 installed Grepping for relevant policy: @{SNAP_NAME}="test-tmp-linkat" profile "snap.test-tmp-linkat.test-tmp-linkat" (attach_disconnected,complain) { owner @{HOME}/snap/@{SNAP_NAME}/common/** wl, /var/snap/@{SNAP_NAME}/common/** wl, /tmp/** mrwlkix, Running: test-tmp-linkat /tmp prefix: /tmp opened fd: 3 [/proc/self/fd/3] writing works linkat failed: No such file or directory FAIL Running: test-tmp-linkat /home/jamie/snap/test-tmp-linkat/common/ prefix: /home/jamie/snap/test-tmp-linkat/common/ opened fd: 3 [/proc/self/fd/3] writing works linkat failed: No such file or directory FAIL = Test class mode snap (global mount namespace loose with complain) = test-tmp-linkat 1.0 installed Grepping for relevant policy: @{SNAP_NAME}="test-tmp-linkat" profile "snap.test-tmp-linkat.test-tmp-linkat" (attach_disconnected,complain) { /** rwlkm, Running: test-tmp-linkat /tmp prefix: /tmp opened fd: 3 [/proc/self/fd/3] writing works linkat failed: No such file or directory FAIL Running: test-tmp-linkat /home/jamie/snap/test-tmp-linkat/common/ prefix: /home/jamie/snap/test-tmp-linkat/common/ opened fd: 3 [/proc/self/fd/3] writing works linkat failed: No such file or directory FAIL = Test unconfined = Running: aa-exec -p unconfined -- /snap/test-tmp-linkat/current/bin/tmp-linkat /tmp prefix: /tmp opened fd: 3 [/proc/self/fd/3] writing works linkat success Running: aa-exec -p unconfined -- /snap/test-tmp-linkat/current/bin/tmp-linkat /home/jamie/snap/test-tmp-linkat/common/ prefix: /home/jamie/snap/test-tmp-linkat/common/ opened fd: 3 [/proc/self/fd/3] writing works linkat success = Test confined outside of snap = Loading apparmor profile for 'test' Policy for 'test' #include <tunables/global> profile test { #include <abstractions/base> /tmp/{#,okular}* rwl, @{HOME}/snap/test-tmp-linkat/common/{#,okular}* rwl, } Running: aa-exec -p test -- /snap/test-tmp-linkat/current/bin/tmp-linkat /tmp prefix: /tmp opened fd: 3 [/proc/self/fd/3] writing works linkat success Running: aa-exec -p test -- /snap/test-tmp-linkat/current/bin/tmp-linkat /home/jamie/snap/test-tmp-linkat/common/ prefix: /home/jamie/snap/test-tmp-linkat/common/ opened fd: 3 [/proc/self/fd/3] writing works linkat success = Test confined outside of snap with attach_disconnected = Loading apparmor profile for 'test_atch_disconnected' Policy for 'test_attach_disconnected' #include <tunables/global> profile test_attach_disconnected (attach_disconnected) { #include <abstractions/base> /tmp/{#,okular}* rwl, @{HOME}/snap/test-tmp-linkat/common/{#,okular}* rwl, } Running: aa-exec -p test_attach_disconnected -- /snap/test-tmp-linkat/current/bin/tmp-linkat /tmp prefix: /tmp opened fd: 3 [/proc/self/fd/3] writing works linkat failed: No such file or directory FAIL Running: aa-exec -p test_attach_disconnected -- /snap/test-tmp-linkat/current/bin/tmp-linkat /home/jamie/snap/test-tmp-linkat/common/ prefix: /home/jamie/snap/test-tmp-linkat/common/ opened fd: 3 [/proc/self/fd/3] writing works linkat failed: No such file or directory FAIL FAIL: some tests failed [1] The reduced test case (ie, test-no-snap.sh) was confirmed to have this bug on: * Linux version 4.16.0-1-amd64 (debian-kernel@lists.debian.org) (gcc version 7.3.0 (Debian 7.3.0-17)) #1 SMP Debian 4.16.5-1 (2018-04-29) * Ubuntu 4.15.0-20.21-generic 4.15.17 * Ubuntu 4.13.0-41.46-generic 4.13.16 * Ubuntu 4.4.0-121.145-generic 4.4.117 * Ubuntu 3.13.0-147.196-generic 3.13.11-ckt39 Ubuntu 12.04 kernel does not support O_TMPFILE (it is 3.2 and O_TMPFILE was added in 3.11). Qt 5.10 recently (https://github.com/qt/qtbase/commit/189e9c93d7ed42202ad51507c8944d64e9a7888d) started using something akin to the following for creating temp files: fd = open("/tmp", O_RDWR | O_DIRECTORY | O_CLOEXEC | O_TMPFILE) write(fd, "...") linkat(AT_FDCWD, "/proc/self/fd/<fd for O_TMPFILE>", AT_FDCWD, "/tmp/...", AT_SYMLINK_FOLLOW) A diagnosis was provided here: https://forum.snapcraft.io/t/qt-5-10-linkat-denials-broken-kde-snaps/5484/10 Attached is a simple reproducer that demonstrates that apparmor works fine with this for unconfined and non-attach_disconnected profiles, but using attach_disconnected breaks the above with denials that cannot be allowed with policy. Eg: $ tar -zxvf ./linkat.tar.gz linkat/ linkat/main.c linkat/test.sh linkat/profile linkat/profile_attach_disconnected linkat/test-no-snap.sh linkat/test-tmp-linkat_1.0_amd64.snap $ cd ./linkat $ ./test-no-snap.sh = Test unconfined = Running: aa-exec -p unconfined -- ./tmp-linkat /tmp prefix: /tmp opened fd: 3 [/proc/self/fd/3] writing works linkat success Running: aa-exec -p unconfined -- ./tmp-linkat /home/jamie/snap/test-tmp-linkat/common/ prefix: /home/jamie/snap/test-tmp-linkat/common/ opened fd: 3 [/proc/self/fd/3] writing works linkat success = Test confined = Loading apparmor profile for 'test' Policy for 'test' #include <tunables/global> profile test {   #include <abstractions/base>   /tmp/{#,okular}* rwl,   @{HOME}/snap/test-tmp-linkat/common/{#,okular}* rwl, } Running: aa-exec -p test -- ./tmp-linkat /tmp prefix: /tmp opened fd: 3 [/proc/self/fd/3] writing works linkat success Running: aa-exec -p test -- ./tmp-linkat /home/jamie/snap/test-tmp-linkat/common/ prefix: /home/jamie/snap/test-tmp-linkat/common/ opened fd: 3 [/proc/self/fd/3] writing works linkat success = Test confined with attach_disconnected = Loading apparmor profile for 'test_atch_disconnected' Policy for 'test_attach_disconnected' #include <tunables/global> profile test_attach_disconnected (attach_disconnected) {   #include <abstractions/base>   /tmp/{#,okular}* rwl,   @{HOME}/snap/test-tmp-linkat/common/{#,okular}* rwl, } Running: aa-exec -p test_attach_disconnected -- ./tmp-linkat /tmp prefix: /tmp opened fd: 3 [/proc/self/fd/3] writing works linkat failed: No such file or directory FAIL Running: aa-exec -p test_attach_disconnected -- ./tmp-linkat /home/jamie/snap/test-tmp-linkat/common/ prefix: /home/jamie/snap/test-tmp-linkat/common/ opened fd: 3 [/proc/self/fd/3] writing works linkat failed: No such file or directory FAIL FAIL: some tests failed [1] The failing test shows this in the logs: May 18 13:53:29 localhost audit[20542]: AVC apparmor="DENIED" operation="link" info="Failed name lookup - deleted entry" error=-2 profile="test_attach_disconnected" name="/tmp/#132105" pid=20542 comm="tmp-linkat" requested_mask="l" denied_mask="l" fsuid=1000 ouid=1000 May 18 13:53:29 localhost audit[20542]: AVC apparmor="DENIED" operation="link" profile="test_attach_disconnected" name="/tmp/okular_DHqFKd.ps" pid=20542 comm="tmp-linkat" requested_mask="l" denied_mask="l" fsuid=1000 ouid=1000 target="/tmp/#132105" May 18 13:53:29 localhost audit[20543]: AVC apparmor="DENIED" operation="link" info="Failed name lookup - deleted entry" error=-2 profile="test_attach_disconnected" name="/home/jamie/snap/test-tmp-linkat/common/#12871268" pid=20543 comm="tmp-linkat" requested_mask="l" denied_mask="l" fsuid=1000 ouid=1000 May 18 13:53:29 localhost audit[20543]: AVC apparmor="DENIED" operation="link" profile="test_attach_disconnected" name="/home/jamie/snap/test-tmp-linkat/common/okular_DHqFKd.ps" pid=20543 comm="tmp-linkat" requested_mask="l" denied_mask="l" fsuid=1000 ouid=1000 target="/home/jamie/snap/test-tmp-linkat/common/#12871268" Unfortunately, this breaks snaps using Qt 5.10 as there is no workaround (attach_disconnected is required due to how the snap's mountspace is setup). Eg: $ ./test.sh = Test strict mode snap (per-snap mount namespace with strict) = test-tmp-linkat 1.0 installed Grepping for relevant policy: @{SNAP_NAME}="test-tmp-linkat" profile "snap.test-tmp-linkat.test-tmp-linkat" (attach_disconnected) {   owner @{HOME}/snap/@{SNAP_NAME}/common/** wl,   /var/snap/@{SNAP_NAME}/common/** wl,   /tmp/** mrwlkix, Running: test-tmp-linkat /tmp prefix: /tmp opened fd: 3 [/proc/self/fd/3] writing works linkat failed: No such file or directory FAIL Running: test-tmp-linkat /home/jamie/snap/test-tmp-linkat/common/ prefix: /home/jamie/snap/test-tmp-linkat/common/ opened fd: 3 [/proc/self/fd/3] writing works linkat failed: No such file or directory FAIL = Test devmode mode snap (per-snap mount namespace with complain) = test-tmp-linkat 1.0 installed Grepping for relevant policy: @{SNAP_NAME}="test-tmp-linkat" profile "snap.test-tmp-linkat.test-tmp-linkat" (attach_disconnected,complain) {   owner @{HOME}/snap/@{SNAP_NAME}/common/** wl,   /var/snap/@{SNAP_NAME}/common/** wl,   /tmp/** mrwlkix, Running: test-tmp-linkat /tmp prefix: /tmp opened fd: 3 [/proc/self/fd/3] writing works linkat failed: No such file or directory FAIL Running: test-tmp-linkat /home/jamie/snap/test-tmp-linkat/common/ prefix: /home/jamie/snap/test-tmp-linkat/common/ opened fd: 3 [/proc/self/fd/3] writing works linkat failed: No such file or directory FAIL = Test class mode snap (global mount namespace loose with complain) = test-tmp-linkat 1.0 installed Grepping for relevant policy: @{SNAP_NAME}="test-tmp-linkat" profile "snap.test-tmp-linkat.test-tmp-linkat" (attach_disconnected,complain) {   /** rwlkm, Running: test-tmp-linkat /tmp prefix: /tmp opened fd: 3 [/proc/self/fd/3] writing works linkat failed: No such file or directory FAIL Running: test-tmp-linkat /home/jamie/snap/test-tmp-linkat/common/ prefix: /home/jamie/snap/test-tmp-linkat/common/ opened fd: 3 [/proc/self/fd/3] writing works linkat failed: No such file or directory FAIL = Test unconfined = Running: aa-exec -p unconfined -- /snap/test-tmp-linkat/current/bin/tmp-linkat /tmp prefix: /tmp opened fd: 3 [/proc/self/fd/3] writing works linkat success Running: aa-exec -p unconfined -- /snap/test-tmp-linkat/current/bin/tmp-linkat /home/jamie/snap/test-tmp-linkat/common/ prefix: /home/jamie/snap/test-tmp-linkat/common/ opened fd: 3 [/proc/self/fd/3] writing works linkat success = Test confined outside of snap = Loading apparmor profile for 'test' Policy for 'test' #include <tunables/global> profile test {   #include <abstractions/base>   /tmp/{#,okular}* rwl,   @{HOME}/snap/test-tmp-linkat/common/{#,okular}* rwl, } Running: aa-exec -p test -- /snap/test-tmp-linkat/current/bin/tmp-linkat /tmp prefix: /tmp opened fd: 3 [/proc/self/fd/3] writing works linkat success Running: aa-exec -p test -- /snap/test-tmp-linkat/current/bin/tmp-linkat /home/jamie/snap/test-tmp-linkat/common/ prefix: /home/jamie/snap/test-tmp-linkat/common/ opened fd: 3 [/proc/self/fd/3] writing works linkat success = Test confined outside of snap with attach_disconnected = Loading apparmor profile for 'test_atch_disconnected' Policy for 'test_attach_disconnected' #include <tunables/global> profile test_attach_disconnected (attach_disconnected) {   #include <abstractions/base>   /tmp/{#,okular}* rwl,   @{HOME}/snap/test-tmp-linkat/common/{#,okular}* rwl, } Running: aa-exec -p test_attach_disconnected -- /snap/test-tmp-linkat/current/bin/tmp-linkat /tmp prefix: /tmp opened fd: 3 [/proc/self/fd/3] writing works linkat failed: No such file or directory FAIL Running: aa-exec -p test_attach_disconnected -- /snap/test-tmp-linkat/current/bin/tmp-linkat /home/jamie/snap/test-tmp-linkat/common/ prefix: /home/jamie/snap/test-tmp-linkat/common/ opened fd: 3 [/proc/self/fd/3] writing works linkat failed: No such file or directory FAIL FAIL: some tests failed [1] The reduced test case (ie, test-no-snap.sh) was confirmed to have this bug on: * Linux version 4.16.0-1-amd64 (debian-kernel@lists.debian.org) (gcc version 7.3.0 (Debian 7.3.0-17)) #1 SMP Debian 4.16.5-1 (2018-04-29) * Ubuntu 4.15.0-20.21-generic 4.15.17 * Ubuntu 4.13.0-41.46-generic 4.13.16 * Ubuntu 4.4.0-121.145-generic 4.4.117 * Ubuntu 3.13.0-147.196-generic 3.13.11-ckt39 Ubuntu 12.04 kernel does not support O_TMPFILE (it is 3.2 and O_TMPFILE was added in 3.11).
2018-05-21 22:58:56 Jamie Strandboge apparmor: status New Confirmed
2018-05-21 22:59:04 Jamie Strandboge apparmor: importance High Medium