2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-31 14:25:52 +00:00

Compare commits

...

19 Commits

Author SHA1 Message Date
John Johansen
a635a86e1d Prepare for AppArmor 4.0 release
- update version file

Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-04-11 20:55:33 -07:00
John Johansen
c8e25e4689 Merge parser: add network inet mediation documentation to apparmor.d
This updates the man page for the recent inet mediation patch.

This is an extension of MR 1202, it adds a patch that changes the anonymous ip address anon to be ip address none which is a better fit.

This patch adds documentation of the recent network changes which extended all network rules to support access permissions, and added address and port matching for inet and inet6 families.

Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1213
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit ab9e6311f3)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-04-11 20:54:23 -07:00
John Johansen
68dd052873 Merge parser: inet conditionals should only generate rules for inet family
When a family is specified in the network rules, we have to make sure
the conditionals match the family. A netlink rule should not be able
to specify ip and port for local and remote (peer) sockets, for example.

When type or protocol is specified in network rules along with inet
conditionals, we should only generate rules for the families that
support those conditionals.

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/384
Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>

Closes #384
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1210
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>

(cherry picked from commit a0acf7785d)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-04-11 20:53:41 -07:00
John Johansen
4cef932170 Merge profiles: add unconfined wike profile
Wike (deb package/compiled version) does not run in Ubuntu 24.04
due to some interference between apparmor and webkit.

Fixes: https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/2060810
Signed-off-by: John Johansen <john.johansen@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1212
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit 3c43c314dc)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-04-11 20:53:30 -07:00
John Johansen
8108a217a3 Merge profiles: add unconfined foliate profile
Foliate is using user namespaces via bwrap. For now add an unconfined
profile to support it.

Fixes: https://github.com/johnfactotum/foliate/issues/1271
Fixes: https://bugs.launchpad.net/bugs/2060767
Signed-off-by: John Johansen <john.johansen@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1209
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit 0aa689dbf7)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-04-11 20:53:10 -07:00
John Johansen
2284e99613 Merge Updates to the chromium_browser profile
This is a retargeting of [my MR in apparmor-profiles](https://gitlab.com/apparmor/apparmor-profiles/-/merge_requests/58).

The most significant change is the addition of a `crashpad_handler` subprofile, to factor out some permissions that the browser proper does not need. The remainder is mostly updates from my normal usage monitoring.

I have recorded below examples of the AppArmor log messages that motivated the updates. They are listed in the order in which they appear in the overall diff:

#### +abstractions/fonts
`Jun 30 16:45:42 testvm kernel: [ 4956.877581] audit: type=1400 audit(1688157942.647:127): apparmor="DENIED" operation="mknod" profile="chromium_browser" name="/home/username/.cache/fontconfig/af531e44-9f34-43fa-a244-e0ea9a6dc5f1-le64.cache-7.TMP-VbjHEy" pid=2136 comm="chromium" requested_mask="c" denied_mask="c" fsuid=1000 ouid=1000`

#### +abstractions/mesa
`May 30 21:08:36 testvm kernel: [ 9893.605107] audit: type=1400 audit(1685495316.380:1708): apparmor="ALLOWED" operation="file_lock" profile="chromium_browser" name="/home/username/.cache/mesa_shader_cache/6b/ce9f90908044cb4d4dabc34d81bf24b2fbda0a.tmp" pid=5879 comm="chromiu:disk$0" requested_mask="k" denied_mask="k" fsuid=1000 ouid=1000`

#### +abstractions/vulcan
`May 30 22:35:36 testvm kernel: [1544761.278181] audit: type=1400 audit(1685500536.387:22272): apparmor="DENIED" operation="open" profile="chromium_browser" name="/sys/devices/pci0000:00/0000:00:02.0/drm/card0/gt_min_freq_mhz" pid=963194 comm="chromium" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0`

#### -deny dbus path=/org/freedesktop/hostname1
`Jun 13 19:16:35 image-ubuntu64 kernel: [78978.711877] audit: type=1107 audit(1686698195.982:2339): pid=540 uid=102 auid=4294967295 ses=4294967295 subj=unconfined msg='apparmor="DENIED" operation="dbus_method_call"  bus="system" path="/org/freedesktop/hostname1" interface="org.freedesktop.DBus.Properties" member="GetAll" mask="send" name=":1.369" pid=17766 label="chromium_browser" peer_pid=17975 peer_label="unconfined"`

#### +dbus path=/org/freedesktop/login1
`Jun 12 21:45:36 testvm kernel: [ 1518.318643] audit: type=1107 audit(1686620736.127:67): pid=540 uid=102 auid=4294967295 ses=4294967295 subj=unconfined msg='apparmor="DENIED" operation="dbus_signal"  bus="system" path="/org/freedesktop/login1" interface="org.freedesktop.login1.Manager" member="SessionNew" name=":1.1" mask="receive" pid=3378 label="chromium_browser" peer_pid=565 peer_label="unconfined"`

`Jun 12 21:40:03 testvm kernel: [ 1185.247117] audit: type=1107 audit(1686620403.059:66): pid=540 uid=102 auid=4294967295 ses=4294967295 subj=unconfined msg='apparmor="DENIED" operation="dbus_signal"  bus="system" path="/org/freedesktop/login1" interface="org.freedesktop.login1.Manager" member="SessionRemoved" name=":1.1" mask="receive" pid=3378 label="chromium_browser" peer_pid=565 peer_label="unconfined"`

#### +dbus path=/org/freedesktop/DBus
`Jun  2 00:02:39 image-ubuntu64 dbus-daemon[10113]: apparmor="ALLOWED" operation="dbus_method_call"  bus="session" path="/org/freedesktop/DBus" interface="org.freedesktop.DBus" member="AddMatch" mask="send" name="org.freedesktop.DBus" pid=34637 label="chromium_browser" peer_label="unconfined"`

`Jun  2 00:02:39 image-ubuntu64 dbus-daemon[10113]: apparmor="ALLOWED" operation="dbus_method_call"  bus="session" path="/org/freedesktop/DBus" interface="org.freedesktop.DBus" member="GetNameOwner" mask="send" name="org.freedesktop.DBus" pid=34637 label="chromium_browser" peer_label="unconfined"`

`Jun  2 00:02:39 image-ubuntu64 dbus-daemon[10113]: apparmor="ALLOWED" operation="dbus_method_call"  bus="session" path="/org/freedesktop/DBus" interface="org.freedesktop.DBus" member="Hello" mask="send" name="org.freedesktop.DBus" pid=34637 label="chromium_browser" peer_label="unconfined"`

`Jun  2 00:02:39 image-ubuntu64 dbus-daemon[10113]: apparmor="ALLOWED" operation="dbus_method_call"  bus="session" path="/org/freedesktop/DBus" interface="org.freedesktop.DBus" member="NameHasOwner" mask="send" name="org.freedesktop.DBus" pid=34637 label="chromium_browser" peer_label="unconfined"`

`Jun  2 00:02:39 image-ubuntu64 dbus-daemon[10113]: apparmor="ALLOWED" operation="dbus_method_call"  bus="session" path="/org/freedesktop/DBus" interface="org.freedesktop.DBus" member="RemoveMatch" mask="send" name="org.freedesktop.DBus" pid=34637 label="chromium_browser" peer_label="unconfined"`

`Jun  2 00:02:39 image-ubuntu64 dbus-daemon[10113]: apparmor="ALLOWED" operation="dbus_method_call"  bus="session" path="/org/freedesktop/DBus" interface="org.freedesktop.DBus" member="StartServiceByName" mask="send" name="org.freedesktop.DBus" pid=34637 label="chromium_browser" peer_label="unconfined"`

#### +dbus path=/org/freedesktop/portal/desktop
`Jun  2 00:02:39 testvm dbus-daemon[10113]: apparmor="ALLOWED" operation="dbus_method_call"  bus="session" path="/org/freedesktop/portal/desktop" interface="org.freedesktop.DBus.Properties" member="Get" mask="send" name="org.freedesktop.portal.Desktop" pid=34637 label="chromium_browser" peer_pid=10595 peer_label="unconfined"`

#### +dbus path=/org/freedesktop/Notifications
`Jun  2 00:02:39 testvm dbus-daemon[10113]: apparmor="ALLOWED" operation="dbus_method_call"  bus="session" path="/org/freedesktop/Notifications" interface="org.freedesktop.Notifications" member="GetCapabilities" mask="send" name="org.freedesktop.Notifications" pid=34637 label="chromium_browser" peer_pid=10438 peer_label="unconfined"`

`Jun  2 00:02:39 testvm dbus-daemon[10113]: apparmor="ALLOWED" operation="dbus_method_call"  bus="session" path="/org/freedesktop/Notifications" interface="org.freedesktop.Notifications" member="GetServerInformation" mask="send" name="org.freedesktop.Notifications" pid=34637 label="chromium_browser" peer_pid=10438 peer_label="unconfined"`

#### +dbus path=/org/gtk/vfs/mounttracker
`Jun  2 00:02:39 testvm dbus-daemon[10113]: apparmor="ALLOWED" operation="dbus_method_call"  bus="session" path="/org/gtk/vfs/mounttracker" interface="org.gtk.vfs.MountTracker" member="ListMountableInfo" mask="send" name=":1.9" pid=34637 label="chromium_browser" peer_pid=10331 peer_label="unconfined"`

#### +/etc/fstab
`Jun 19 00:12:34 testvm kernel: [3192175.541293] audit: type=1400 audit(1687147954.193:127452): apparmor="DENIED" operation="open" profile="chromium_browser" name="/etc/fstab" pid=1541844 comm="chromium" requested_mask="r" denied_mask="r" fsuid=1002 ouid=0`

#### +~/.cache/thumbnails
`Jun 28 14:31:34 testvm kernel: [4021314.484388] audit: type=1400 audit(1687977094.903:128621): apparmor="DENIED" operation="open" profile="chromium_browser" name="/home/username/.cache/thumbnails/normal/5ff3c24d6d3b35a6ea92e12c71c487f9.png" pid=1781421 comm="pool-chromium" requested_mask="r" denied_mask="r" fsuid=1002 ouid=1002`

`Jun 28 14:31:34 testvm kernel: [4021314.484975] audit: type=1400 audit(1687977094.903:128622): apparmor="DENIED" operation="open" profile="chromium_browser" name="/home/username/.cache/thumbnails/normal/5ff3c24d6d3b35a6ea92e12c71c487f9.png" pid=1781421 comm="chromium" requested_mask="r" denied_mask="r" fsuid=1002 ouid=1002`

#### -/proc/$PID/fd/
This rule appears to have been used by the crash handler, so I've moved it to the new `crashpad_handler` subprofile. I have not observed the normal browser process(es) attempting this access.

#### +/proc/pressure/{cpu,io,memory}
`May 30 22:44:26 testvm kernel: [1545291.245886] audit: type=1400 audit(1685501066.352:22355): apparmor="DENIED" operation="open" profile="chromium_browser" name="/proc/pressure/cpu" pid=741817 comm="ThreadPoolForeg" requested_mask="r" denied_mask="r" fsuid=1002 ouid=0`

`May 30 22:44:26 testvm kernel: [1545291.245903] audit: type=1400 audit(1685501066.352:22356): apparmor="DENIED" operation="open" profile="chromium_browser" name="/proc/pressure/io" pid=741817 comm="ThreadPoolForeg" requested_mask="r" denied_mask="r" fsuid=1002 ouid=0`

`May 30 22:44:26 testvm kernel: [1545291.245912] audit: type=1400 audit(1685501066.352:22357): apparmor="DENIED" operation="open" profile="chromium_browser" name="/proc/pressure/memory" pid=741817 comm="ThreadPoolForeg" requested_mask="r" denied_mask="r" fsuid=1002 ouid=0`

#### +/proc/$PID/clear_refs
`May 30 18:32:55 testvm kernel: [  552.316554] audit: type=1400 audit(1685485975.161:305): apparmor="ALLOWED" operation="open" profile="chromium_browser" name="/proc/1950/clear_refs" pid=1950 comm="MemoryInfra" requested_mask="w" denied_mask="w" fsuid=1000 ouid=1000`

#### +/proc/$PID/mountinfo
`Jun 19 00:12:34 testvm kernel: [3192175.541221] audit: type=1400 audit(1687147954.193:127451): apparmor="DENIED" operation="open" profile="chromium_browser" name="/proc/1541844/mountinfo" pid=1541844 comm="gmain" requested_mask="r" denied_mask="r" fsuid=1002 ouid=1002`

#### +/proc/sys/fs/inotify/max_user_watches
`May 30 18:32:26 testvm kernel: [  523.274479] audit: type=1400 audit(1685485946.109:288): apparmor="ALLOWED" operation="open" profile="chromium_browser" name="/proc/sys/fs/inotify/max_user_watches" pid=1972 comm="chromium" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0`

#### +/sys/devices/system/cpu/{kernel_max,possible,present}
`May 30 18:32:26 testvm kernel: [  523.287063] audit: type=1400 audit(1685485946.125:290): apparmor="ALLOWED" operation="open" profile="chromium_browser" name="/sys/devices/system/cpu/kernel_max" pid=1971 comm="chromium" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0`

`May 30 18:32:26 testvm kernel: [  523.287107] audit: type=1400 audit(1685485946.125:291): apparmor="ALLOWED" operation="open" profile="chromium_browser" name="/sys/devices/system/cpu/possible" pid=1971 comm="chromium" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0`

`May 30 18:32:26 testvm kernel: [  523.287607] audit: type=1400 audit(1685485946.125:297): apparmor="ALLOWED" operation="open" profile="chromium_browser" name="/sys/devices/system/cpu/present" pid=1972 comm="chromium" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0`

#### +/sys/devices/pci[0-9]*/**/{bConfigurationValue,boot_vga,busnum}
`2023-07-03T04:40:49.955727-04:00 testsys kernel: [28353.647821] audit: type=1400 audit(1688373649.948:152): apparmor="DENIED" operation="open" profile="chromium_browser" name="/sys/devices/pci0000:00/0000:00:1d.3/usb5/5-2/bConfigurationValue" pid=5585 comm="ThreadPoolForeg" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0`

`Jul  4 00:10:52 testvm kernel: [  405.584960] audit: type=1400 audit(1688443852.472:148): apparmor="DENIED" operation="open" profile="chromium_browser" name="/sys/devices/pci0000:00/0000:00:02.0/boot_vga" pid=2057 comm="chromium" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0`

`2023-07-03T04:40:49.955731-04:00 testsys kernel: [28353.647923] audit: type=1400 audit(1688373649.948:153): apparmor="DENIED" operation="open" profile="chromium_browser" name="/sys/devices/pci0000:00/0000:00:1d.3/usb5/5-2/busnum" pid=5585 comm="ThreadPoolForeg" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0`

#### +/sys/devices/pci[0-9]*/**/{descriptors,devnum}
`2023-07-02T21:29:22.067669-04:00 testsys kernel: [ 2465.760458] audit: type=1400 audit(1688347762.063:71): apparmor="DENIED" operation="open" profile="chromium_browser" name="/sys/devices/pci0000:00/0000:00:1d.0/usb2/descriptors" pid=2276 comm="ThreadPoolForeg" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0`

`2023-07-02T21:29:22.071708-04:00 testsys kernel: [ 2465.762364] audit: type=1400 audit(1688347762.067:75): apparmor="DENIED" operation="open" profile="chromium_browser" name="/sys/devices/pci0000:00/0000:00:1d.3/usb5/5-2/descriptors" pid=2276 comm="ThreadPoolForeg" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0`

`2023-07-02T21:29:22.071721-04:00 testsys kernel: [ 2465.763437] audit: type=1400 audit(1688347762.067:78): apparmor="DENIED" operation="open" profile="chromium_browser" name="/sys/devices/pci0000:00/0000:00:1d.7/usb1/1-6/1-6.3/descriptors" pid=2276 comm="ThreadPoolForeg" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0`

`2023-07-03T04:40:49.955736-04:00 testsys kernel: [28353.648042] audit: type=1400 audit(1688373649.948:154): apparmor="DENIED" operation="open" profile="chromium_browser" name="/sys/devices/pci0000:00/0000:00:1d.3/usb5/5-2/devnum" pid=5585 comm="ThreadPoolForeg" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0`

#### +/sys/devices/pci[0-9]*/**/{manufacturer,product}
`2023-07-03T04:40:49.955694-04:00 testsys kernel: [28353.647497] audit: type=1400 audit(1688373649.948:150): apparmor="DENIED" operation="open" profile="chromium_browser" name="/sys/devices/pci0000:00/0000:00:1d.3/usb5/5-2/manufacturer" pid=5585 comm="ThreadPoolForeg" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0`

`2023-07-03T04:40:49.955721-04:00 testsys kernel: [28353.647661] audit: type=1400 audit(1688373649.948:151): apparmor="DENIED" operation="open" profile="chromium_browser" name="/sys/devices/pci0000:00/0000:00:1d.3/usb5/5-2/product" pid=5585 comm="ThreadPoolForeg" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0`

#### +/sys/devices/pci[0-9]*/**/serial
(lost the log entry for this one)

#### +deny /sys/devices/virtual/dmi/id/*
`May 30 18:38:58 testvm kernel: [  915.363204] audit: type=1400 audit(1685486338.202:390): apparmor="ALLOWED" operation="open" profile="chromium_browser" name="/sys/devices/virtual/dmi/id/sys_vendor" pid=2158 comm="ThreadPoolForeg" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0`

`May 30 18:38:58 testvm kernel: [  915.363521] audit: type=1400 audit(1685486338.202:391): apparmor="ALLOWED" operation="open" profile="chromium_browser" name="/sys/devices/virtual/dmi/id/product_name" pid=2158 comm="ThreadPoolForeg" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0`

These sysfs paths yield the make and model of your system, so their access is questionable from a privacy perspective.

#### +{dev,var/run} in shm paths
Can't be replaced with `@{run}` as this does not include `/dev`.

#### +ptrace (read)
`May 31 04:47:35 testvm kernel: [1567080.438164] audit: type=1400 audit(1685522855.581:124669): apparmor="DENIED" operation="ptrace" profile="chromium_browser" pid=1145702 comm="ThreadPoolForeg" requested_mask="read" denied_mask="read" peer="chromium_browser//xdgsettings"`

Figured I'd add read access proactively to `lsb_release` as well. Holding back on adding it to self for now.

#### /etc/@{chromium}/policies/** -> /etc/@{chromium}/**
`May 30 21:25:44 testvm kernel: [10922.020981] audit: type=1400 audit(1685496344.792:2031): apparmor="ALLOWED" operation="open" profile="chromium_browser" name="/etc/chromium/master_preferences" pid=6465 comm="chromium" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0`

#### Note: "~/.pki/... denied by private-files abstraction"
`May 30 21:29:13 testvm kernel: [11130.436441] audit: type=1400 audit(1685496553.206:2105): apparmor="ALLOWED" operation="mkdir" profile="chromium_browser" name="/home/username/.pki/" pid=7344 comm="ThreadPoolForeg" requested_mask="c" denied_mask="c" fsuid=1000 ouid=1000`

`May 30 21:29:13 testvm kernel: [11130.437992] audit: type=1400 audit(1685496553.206:2106): apparmor="ALLOWED" operation="mkdir" profile="chromium_browser" name="/home/username/.pki/nssdb/" pid=7344 comm="ThreadPoolForeg" requested_mask="c" denied_mask="c" fsuid=1000 ouid=1000`

Something else will need to create these directories.

#### +Widevine
`May 31 04:46:52 testvm kernel: [1567036.849155] audit: type=1400 audit(1685522811.993:124665): apparmor="DENIED" operation="file_mmap" profile="chromium_browser" name="/home/username/.config/chromium/WidevineCdm/4.10.2557.0/_platform_specific/linux_x64/libwidevinecdm.so" pid=1145723 comm="chromium" requested_mask="m" denied_mask="m" fsuid=1002 ouid=1002`

#### +GVfs
`Jun 13 19:16:35 testvm kernel: [78978.537455] audit: type=1400 audit(1686698195.810:2337): apparmor="DENIED" operation="connect" profile="chromium_browser" name="/run/user/1000/gvfsd/socket-EpT3MyPP" pid=17766 comm="chromium" requested_mask="wr" denied_mask="wr" fsuid=1000 ouid=1000`

#### +/lib/libc.so
`May 30 18:02:25 testvm kernel: [  868.340300] audit: type=1400 audit(1685484145.031:80): apparmor="ALLOWED" operation="open" profile="chromium_browser//chromium_browser_sandbox" name="/lib/x86_64-linux-gnu/libc.so.6" pid=2405 comm="chrome-sandbox" requested_mask="r" denied_mask="r" fsuid=0 ouid=0`

`May 30 18:02:25 testvm kernel: [  868.340363] audit: type=1400 audit(1685484145.031:81): apparmor="ALLOWED" operation="file_mmap" profile="chromium_browser//chromium_browser_sandbox" name="/lib/x86_64-linux-gnu/libc.so.6" pid=2405 comm="chrome-sandbox" requested_mask="rm" denied_mask="rm" fsuid=0 ouid=0`

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1208
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit a1afe3265c)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-04-11 20:52:32 -07:00
John Johansen
f763c44cd0 Merge Add profiles for the Transmission family of Bittorrent clients
This covers the various forms of the Transmission BT client. I've tested the `-gtk` one most thoroughly, and run through an ISO download with each of the other three.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1190
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit 30a45ba82f)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-04-11 20:51:32 -07:00
John Johansen
1d36e1f196 Prepare for AppArmor 4.0 beta4 release
- update version file

Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-04-08 03:21:40 -07:00
John Johansen
22ee6c19bc Merge profiles: disable bwrap and unshare profiles by default
The bwrap and unshare profiles are special profiles in the same
vein as the unconfined profiles but they actual enforce restrictions
on the applications that are launched.

As such they have come to late in the 4.0 dev cycle to consider enabling
by default. Disable them but ship them so users or distros can easily
enable them.

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/382
Signed-off-by: John Johansen <john.johansen@canonical.com>

Closes #382
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1206
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>

(cherry picked from commit 41d4664124)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-04-08 00:17:10 -07:00
John Johansen
6198edb3d0 Merge profiles: Add profile for unshare utility
This adds an unshare profile to allow it to function on a system
with user namespace restrictions enabled.

The child task of unshare will enter into a profile without capabilities
thus preventing unshare from being able to be used to
arbitrarily by-pass the user namespace restriction.

This profile does prevent applications launch with privilege (eg.
sudo unshare ...) from functioning so it may break some use cases.

Fixes: https://bugs.launchpad.net/ubuntu/+source/pageedit/+bug/2046844
Signed-off-by: John Johansen <john.johansen@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1204
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit 2d59dc3d9b)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-04-03 22:45:10 -07:00
John Johansen
4d2a171466 Merge profiles: Add profile for bwrap utility
This adds a bwrap profile to allow it to function on a system with
user namespace restrictions enabled.

The child task of bwrap will enter into a profile without capabilities
thus preventing bwrap from being able to be used to arbitrarily
by-pass user namespace restrictions.

This profile does prevent applications launch with privilege (eg.
sudo bwrap ...) from functioning so it may break some use cases.

Note: The unpriv_bwrap profile is deliberately stacked against the
bwrap profile due to bwraps uses of no-new-privileges.

Fixes: https://bugs.launchpad.net/ubuntu/+source/pageedit/+bug/2046844
Signed-off-by: John Johansen <john.johansen@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1205
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit b6f2a3d9d2)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-04-03 22:44:49 -07:00
John Johansen
e88cf3cd02 Merge profiles: adjust unconfined firefox profile to support mozilla.org download
The version of tarball version of firefox downloaded from mozilla.org
installs to /opt/firefox/firefox. Support this location so that the
firefox from the tarball works.

Note this does not support running firefox from the users home directory
in this case the user must update the profile accordingly.

Signed-off-by: John Johansen <john.johansen@canonical.com>

Fixes: https://bugs.launchpad.net/bugs/2056297
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1203
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit 2dfe6aeec2)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-04-03 22:39:58 -07:00
John Johansen
6f856dfee3 Merge profiles/samba*: allow /etc/gnutls/config & @{HOMEDIRS}
# abstractions/samba: allow /etc/gnutls/config

Various samba components want to read it. Without it, shares cannot be accessed.

    apparmor="DENIED" operation="open" class="file" profile="nmbd" name="/etc/gnutls/config" pid=23509 comm="nmbd" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
    apparmor="DENIED" operation="open" class="file" profile="smbd" name="/etc/gnutls/config" pid=23508 comm="smbd" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
    apparmor="DENIED" operation="open" class="file" profile="samba-rpcd" name="/etc/gnutls/config" pid=24037 comm="rpcd_fsrvp" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
    apparmor="DENIED" operation="open" class="file" profile="samba-rpcd" name="/etc/gnutls/config" pid=24036 comm="rpcd_epmapper" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
    apparmor="DENIED" operation="open" class="file" profile="samba-rpcd" name="/etc/gnutls/config" pid=24038 comm="rpcd_lsad" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
    apparmor="DENIED" operation="open" class="file" profile="samba-rpcd" name="/etc/gnutls/config" pid=24041 comm="rpcd_winreg" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
    apparmor="DENIED" operation="open" class="file" profile="samba-rpcd" name="/etc/gnutls/config" pid=24039 comm="rpcd_mdssvc" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
    apparmor="DENIED" operation="open" class="file" profile="samba-rpcd-spoolss" name="/etc/gnutls/config" pid=24040 comm="rpcd_spoolss" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
    apparmor="DENIED" operation="open" class="file" profile="samba-rpcd-classic" name="/etc/gnutls/config" pid=24035 comm="rpcd_classic" requested_mask="r" denied_mask="r" fsuid=0 ouid=0

# profiles/apparmor.d/samba-rpcd-classic: allow @{HOMEDIRS}

Give access to @{HOMEDIRS}, just like in usr.sbin.smbd, so that
usershares in /home/ can be accessed.

    apparmor="DENIED" operation="open" class="file" profile="samba-rpcd-classic" name="/home/user/path/to/usershare/" pid=4781 comm="rpcd_classic" requested_mask="r" denied_mask="r" fsuid=0 ouid=1000

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/379
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1200
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit 5998a0021a)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-04-03 14:15:52 -07:00
John Johansen
a6d8171bd6 Merge parser: fix getattr and setattr perm mapping on mqueue rules
Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/377
Fixes: https://gitlab.com/apparmor/apparmor/-/issues/378
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1197
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit 88ec709aac)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-04-03 02:32:32 -07:00
John Johansen
26e7249f44 Merge tests: fix inet tests
Fixes: https://gitlab.com/apparmor/apparmor/-/issues/376
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1192
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit 01fcce41dc)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-04-03 02:30:59 -07:00
John Johansen
117d0cc444 Merge usr.sbin.sshd: Add new permissions needed on Ubuntu 24.04
Testing on noble turned these up:

`2024-03-27T00:10:28.929314-04:00 image-ubuntu64 kernel: audit: type=1400 audit(1711512628.920:155): apparmor="DENIED" operation="bind" class="net" profile="/usr/sbin/sshd" pid=1290 comm="sshd" family="unix" sock_type="stream" protocol=0 requested_mask="bind" denied_mask="bind" addr="@63cf34db7fbab75f/bus/sshd/system"`

`2024-03-27T00:41:09.791826-04:00 image-ubuntu64 kernel: audit: type=1107 audit(1711514469.771:333907): pid=703 uid=101 auid=4294967295 ses=4294967295 subj=unconfined msg='apparmor="DENIED" operation="dbus_method_call"  bus="system" path="/org/freedesktop/login1" interface="org.freedesktop.login1.Manager" member="CreateSessionWithPIDFD" mask="send" name="org.freedesktop.login1" pid=4528 label="/usr/sbin/sshd" peer_pid=688 peer_label="unconfined"`

Fixes: https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/2060100
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1196
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit 3aa40249cf)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-04-03 02:29:31 -07:00
Georgia Garcia
1c7127d30d Merge utils: allow mount destination globbing
The abstraction lxc/start-container shipped by the liblxc-common
package uses the following mount rule which was not allowed by our
regexes:

  mount options=(rw, make-slave) -> **,
  mount options=(rw, make-rslave) -> **,

Since in AppArmor regex ** includes '/' but * by itself doesn't, I'm
adding explicit support for **.

Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/381
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1195
Approved-by: Christian Boltz <apparmor@cboltz.de>
Merged-by: Georgia Garcia <georgia.garcia@canonical.com>
(cherry picked from commit e96fdc0f5b)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-04-03 02:23:43 -07:00
Christian Boltz
d111ddcc21 Merge firefox: allow locking of *.sqlite-shm files in user cache area
Noticed a bunch of these after a Firefox 124.0 upgrade:

`Mar 25 22:08:27 darkstar kernel: [598271.991739] audit: type=1400 audit(1711418907.493:27323): apparmor="DENIED" operation="file_lock" profile="firefox" name="/home/username/.cache/mozilla/firefox/deadbeef.default/suggest.sqlite-shm" pid=2855447 comm=4267494F5468727E6F6C2023333530 requested_mask="k" denied_mask="k" fsuid=1000 ouid=1000`

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/380
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1193
Approved-by: Christian Boltz <apparmor@cboltz.de>
Merged-by: Christian Boltz <apparmor@cboltz.de>
(cherry picked from commit 14572d9581)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-04-03 02:18:24 -07:00
John Johansen
fa26623e6d Merge Move pam-related permissions to abstractions/authentication
... instead of keeping them in the smbd profile.

For details, see c09f58a364 and
https://bugzilla.opensuse.org/show_bug.cgi?id=1220032#c12

Also replace /usr/etc/ with @{etc_ro} to that also /etc/ is covered.

Fixes: https://bugzilla.opensuse.org/show_bug.cgi?id=1220032#c12
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1191
Approved-by: John Johansen <john@jjmx.net>
Merged-by: John Johansen <john@jjmx.net>
(cherry picked from commit f334884787)
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-04-03 02:14:16 -07:00
42 changed files with 962 additions and 328 deletions

4
.gitignore vendored
View File

@@ -266,8 +266,8 @@ tests/regression/apparmor/mmap
tests/regression/apparmor/mount
tests/regression/apparmor/move_mount
tests/regression/apparmor/named_pipe
tests/regression/apparmor/net_finegrained_rcv
tests/regression/apparmor/net_finegrained_snd
tests/regression/apparmor/net_inet_rcv
tests/regression/apparmor/net_inet_snd
tests/regression/apparmor/net_raw
tests/regression/apparmor/open
tests/regression/apparmor/openat

View File

@@ -1 +1 @@
4.0.0~beta3
4.0.0

View File

@@ -148,7 +148,14 @@ B<CAPABILITY LIST> = ( I<CAPABILITY> )+
B<CAPABILITY> = (lowercase capability name without 'CAP_' prefix; see
capabilities(7))
B<NETWORK RULE> = [ I<QUALIFIERS> ] 'network' [ I<DOMAIN> ] [ I<TYPE> | I<PROTOCOL> ]
B<NETWORK RULE> = [ I<QUALIFIERS> ] 'network' [ I<NETWORK ACCESS EXPR> ] [ I<DOMAIN> ] [ I<TYPE> | I<PROTOCOL> ] [ I<NETWORK LOCAL EXPR> ] [ I<NETWORK PEER EXPR> ]
B<NETWORK ACCESS EXPR> = ( I<NETWORK ACCESS> | I<NETWORK ACCESS LIST> )
B<NETWORK ACCESS> = ( 'create' | 'bind' | 'listen' | 'accept' | 'connect' | 'shutdown' | 'getattr' | 'setattr' | 'getopt' | 'setopt' | 'send' | 'receive' | 'r' | 'w' | 'rw' )
Some access modes are incompatible with some rules.
B<NETWORK ACCESS LIST> = '(' I<NETWORK ACCESS> ( [','] I<NETWORK ACCESS> )* ')'
B<DOMAIN> = ( 'unix' | 'inet' | 'ax25' | 'ipx' | 'appletalk' | 'netrom' | 'bridge' | 'atmpvc' | 'x25' | 'inet6' | 'rose' | 'netbeui' | 'security' | 'key' | 'netlink' | 'packet' | 'ash' | 'econet' | 'atmsvc' | 'rds' | 'sna' | 'irda' | 'pppox' | 'wanpipe' | 'llc' | 'ib' | 'mpls' | 'can' | 'tipc' | 'bluetooth' | 'iucv' | 'rxrpc' | 'isdn' | 'phonet' | 'ieee802154' | 'caif' | 'alg' | 'nfc' | 'vsock' | 'kcm' | 'qipcrtr' | 'smc' | 'xdp' | 'mctp' ) ','
@@ -156,6 +163,22 @@ B<TYPE> = ( 'stream' | 'dgram' | 'seqpacket' | 'rdm' | 'raw' | 'packet' )
B<PROTOCOL> = ( 'tcp' | 'udp' | 'icmp' )
B<NETWORK LOCAL EXPR> = ( I<NETWORK IP COND> | I<NETWORK PORT COND> )*
Each cond can appear at most once.
B<NETWORK PEER EXPR> = 'peer' '=' '(' ( I<NETWORK IP COND> | I<NETWORK PORT COND> )+ ')'
Each cond can appear at most once.
B<NETWORK IP COND> = 'ip' '=' ( 'none' | I<NETWORK IPV4> | I<NETWORK IPV6> )
B<NETWORK PORT COND> = 'port' '=' ( I<NETWORK PORT> )
B<NETWORK IPV4> = IPv4, represented by four 8-bit decimal numbers separated by '.'
B<NETWORK IPV6> = IPv6, represented by eight groups of four hexadecimal numbers separated by ':'. Shortened representation of contiguous zeros is allowed by using '::'
B<NETWORK PORT> = 16-bit number ranging from 0 to 65535
B<MOUNT RULE> = ( I<MOUNT> | I<REMOUNT> | I<UMOUNT> )
B<MOUNT> = [ I<QUALIFIERS> ] 'mount' [ I<MOUNT CONDITIONS> ] [ I<SOURCE FILEGLOB> ] [ '-E<gt>' [ I<MOUNTPOINT FILEGLOB> ]
@@ -912,11 +935,10 @@ and other operations that are typically reserved for the root user.
=head2 Network Rules
AppArmor supports simple coarse grained network mediation. The network
rule restrict all socket(2) based operations. The mediation done is
a coarse-grained check on whether a socket of a given type and family
can be created, read, or written. There is no mediation based of port
number or protocol beyond tcp, udp, and raw. Network netlink(7) rules may
AppArmor supports simple coarse grained network mediation. The
network rule restrict all socket(2) based operations. The mediation
done is a coarse-grained check on whether a socket of a given type and
family can be created, read, or written. Network netlink(7) rules may
only specify type 'dgram' and 'raw'.
AppArmor network rules are accumulated so that the granted network
@@ -933,6 +955,48 @@ eg.
network inet6 tcp, #allow access to tcp only for inet6 addresses
network netlink raw, #allow access to AF_NETLINK SOCK_RAW
=head3 Network permissions
Network rule permissions are implied when a rule does not explicitly
state an access list. By default if a rule does not have an access
list all permissions that are compatible with the specified set of
local and peer conditionals are implied.
The create, bind, listen, shutdown, getattr, setattr, getopt, and
setopt permissions are local socket permissions. They are only applied
to the local socket and can't be specified in rules that have a peer
conditional. The accept permission applies to the combination of a
local and peer socket. The connect, send, and receive permissions are
peer socket permissions.
=head3 Mediation of inet/inet6 family
AppArmor supports fine grained mediation of the inet and inet6
families by using the ip and port conditionals. The ip conditional
accepts both IPv4 and IPv6 using the regular representation of four
octets separated by '.' for IPv4 and eight groups of four hexadecimal
numbers separated by ':' for IPv6. Contiguous leading zeros can be
replaced by '::' once. On a connected socket, the sender and receiver
don't need to be specified in the recvfrom and sendto system calls. In
that case, and with unbounded sockets, the IP address is none, or
unknown. Unknown or Unbound IP addresses are represented in policy by the
'none' keyword. When the ip conditional is omitted, then all IP
addresses will be allowed: IPv4, IPv6 and none. If INADDR_ANY or
in6addr_any is used, then the ip conditional can be omitted or they
can be represented by:
network ip=::, #allow in6addr_any
network ip=0.0.0.0; #allow INADDR_ANY
The network rules support the specification of local and remote IP
addresses and ports.
network ip=127.0.0.1 port=8080,
network peer=(ip=10.139.15.23 port=8081),
network ip=fd74:1820:b03a:b361::cf32 peer=(ip=fd74:1820:b03a:b361::a0f9),
network port=8080 peer=(port=8081),
network ip=127.0.0.1 port=8080 peer=(ip=10.139.15.23 port=8081),
=head2 Mount Rules
AppArmor supports mount mediation and allows specifying filesystem types and

View File

@@ -231,10 +231,10 @@ int mqueue_rule::gen_policy_re(Profile &prof)
/* store perms at name match so label doesn't need
* to be checked
*/
if (!label && !prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, perms, audit == AUDIT_FORCE ? perms : 0, 1, vec, parseopts, false))
if (!label && !prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, map_mqueue_perms(perms), audit == AUDIT_FORCE ? map_mqueue_perms(perms) : 0, 1, vec, parseopts, false))
goto fail;
/* also provide label match with perm */
if (!prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, perms, audit == AUDIT_FORCE ? perms : 0, size, vec, parseopts, false))
if (!prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, map_mqueue_perms(perms), audit == AUDIT_FORCE ? map_mqueue_perms(perms) : 0, size, vec, parseopts, false))
goto fail;
}
}
@@ -266,10 +266,10 @@ int mqueue_rule::gen_policy_re(Profile &prof)
}
if (perms & AA_VALID_SYSV_MQ_PERMS) {
if (!label && !prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, perms, audit == AUDIT_FORCE ? perms : 0, 1, vec, parseopts, false))
if (!label && !prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, map_mqueue_perms(perms), audit == AUDIT_FORCE ? map_mqueue_perms(perms) : 0, 1, vec, parseopts, false))
goto fail;
/* also provide label match with perm */
if (!prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, perms, audit == AUDIT_FORCE ? perms : 0, size, vec, parseopts, false))
if (!prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, map_mqueue_perms(perms), audit == AUDIT_FORCE ? map_mqueue_perms(perms) : 0, size, vec, parseopts, false))
goto fail;
}
}

View File

@@ -52,13 +52,13 @@
* kernel doesn't allow for us to control
* - posix
* - notify
* - getattr/setattr
* - labels at anything other than mqueue label, via mqueue inode.
*/
#define AA_VALID_POSIX_MQ_PERMS (AA_MQUEUE_WRITE | AA_MQUEUE_READ | \
AA_MQUEUE_CREATE | AA_MQUEUE_DELETE | \
AA_MQUEUE_OPEN)
AA_MQUEUE_OPEN | \
AA_MQUEUE_SETATTR | AA_MQUEUE_GETATTR)
/* TBD - for now make it wider than posix */
#define AA_VALID_SYSV_MQ_PERMS (AA_MQUEUE_WRITE | AA_MQUEUE_READ | \
@@ -78,6 +78,11 @@ typedef enum mqueue_type {
mqueue_sysv
} mqueue_type;
static inline uint32_t map_mqueue_perms(uint32_t mask)
{
return (mask & 0x7f) |
((mask & (AA_MQUEUE_GETATTR | AA_MQUEUE_SETATTR)) << (AA_OTHER_SHIFT - 8));
}
int parse_mqueue_perms(const char *str_perms, perms_t *perms, int fail);

View File

@@ -360,8 +360,8 @@ bool network_rule::parse_port(ip_conds &entry)
bool network_rule::parse_address(ip_conds &entry)
{
if (strcmp(entry.sip, "anon") == 0) {
entry.is_anonymous = true;
if (strcmp(entry.sip, "none") == 0) {
entry.is_none = true;
return true;
}
entry.is_ip = true;
@@ -405,17 +405,31 @@ network_rule::network_rule(perms_t perms_p, struct cond_entry *conds,
struct cond_entry *peer_conds):
dedup_perms_rule_t(AA_CLASS_NETV8), label(NULL)
{
size_t family_index;
for (family_index = AF_UNSPEC; family_index < get_af_max(); family_index++) {
network_map[family_index].push_back({ family_index, 0xFFFFFFFF, 0xFFFFFFFF });
set_netperm(family_index, 0xFFFFFFFF, 0xFFFFFFFF);
}
size_t family_index, i;
move_conditionals(conds, local);
move_conditionals(peer_conds, peer);
free_cond_list(conds);
free_cond_list(peer_conds);
if (has_local_conds() || has_peer_conds()) {
const char *family[] = { "inet", "inet6" };
for (i = 0; i < sizeof(family)/sizeof(family[0]); i++) {
const struct network_tuple *mapping = NULL;
while ((mapping = net_find_mapping(mapping, family[i], NULL, NULL))) {
network_map[mapping->family].push_back({ mapping->family, mapping->type, mapping->protocol });
set_netperm(mapping->family, mapping->type, mapping->protocol);
}
}
} else {
for (family_index = AF_UNSPEC; family_index < get_af_max(); family_index++) {
network_map[family_index].push_back({ family_index, 0xFFFFFFFF, 0xFFFFFFFF });
set_netperm(family_index, 0xFFFFFFFF, 0xFFFFFFFF);
}
}
if (perms_p) {
perms = perms_p;
if (perms & ~AA_VALID_NET_PERMS)
@@ -433,13 +447,34 @@ network_rule::network_rule(perms_t perms_p, const char *family, const char *type
dedup_perms_rule_t(AA_CLASS_NETV8), label(NULL)
{
const struct network_tuple *mapping = NULL;
move_conditionals(conds, local);
move_conditionals(peer_conds, peer);
free_cond_list(conds);
free_cond_list(peer_conds);
while ((mapping = net_find_mapping(mapping, family, type, protocol))) {
/* if inet conds and family are specified, fail if
* family is not af_inet or af_inet6
*/
if ((has_local_conds() || has_peer_conds()) &&
mapping->family != AF_INET && mapping->family != AF_INET6) {
yyerror("network family does not support local or peer conditionals\n");
}
network_map[mapping->family].push_back({ mapping->family, mapping->type, mapping->protocol });
set_netperm(mapping->family, mapping->type, mapping->protocol);
}
if (type == NULL && network_map.empty()) {
while ((mapping = net_find_mapping(mapping, type, family, protocol))) {
/* if inet conds and type/protocol are
* specified, only add rules for af_inet and
* af_inet6
*/
if ((has_local_conds() || has_peer_conds()) &&
mapping->family != AF_INET && mapping->family != AF_INET6)
continue;
network_map[mapping->family].push_back({ mapping->family, mapping->type, mapping->protocol });
set_netperm(mapping->family, mapping->type, mapping->protocol);
}
@@ -448,11 +483,6 @@ network_rule::network_rule(perms_t perms_p, const char *family, const char *type
if (network_map.empty())
yyerror(_("Invalid network entry."));
move_conditionals(conds, local);
move_conditionals(peer_conds, peer);
free_cond_list(conds);
free_cond_list(peer_conds);
if (perms_p) {
perms = perms_p;
if (perms & ~AA_VALID_NET_PERMS)
@@ -585,13 +615,13 @@ std::string gen_port_cond(uint16_t port)
std::list<std::ostringstream> gen_all_ip_options(std::ostringstream &oss) {
std::list<std::ostringstream> all_streams;
std::ostringstream anon, ipv4, ipv6;
std::ostringstream none, ipv4, ipv6;
int i;
anon << oss.str();
none << oss.str();
ipv4 << oss.str();
ipv6 << oss.str();
anon << "\\x" << std::setfill('0') << std::setw(2) << std::hex << ANON_SIZE;
none << "\\x" << std::setfill('0') << std::setw(2) << std::hex << NONE_SIZE;
/* add a byte containing the size of the following ip */
ipv4 << "\\x" << std::setfill('0') << std::setw(2) << std::hex << IPV4_SIZE;
@@ -603,7 +633,7 @@ std::list<std::ostringstream> gen_all_ip_options(std::ostringstream &oss) {
for (i = 0; i < 16; ++i)
ipv6 << ".";
all_streams.push_back(std::move(anon));
all_streams.push_back(std::move(none));
all_streams.push_back(std::move(ipv4));
all_streams.push_back(std::move(ipv6));
@@ -627,7 +657,7 @@ bool network_rule::gen_ip_conds(Profile &prof, std::list<std::ostringstream> &st
std::list<std::ostringstream> ip_streams;
for (auto &oss : streams) {
if (entry.is_port && !(entry.is_ip && entry.is_anonymous)) {
if (entry.is_port && !(entry.is_ip && entry.is_none)) {
/* encode port type (privileged - 1, remote - 2, unprivileged - 0) */
if (!is_peer && perms & AA_NET_BIND && entry.port < IPPORT_RESERVED)
oss << "\\x01";
@@ -650,8 +680,8 @@ bool network_rule::gen_ip_conds(Profile &prof, std::list<std::ostringstream> &st
if (entry.is_ip) {
oss << gen_ip_cond(entry.ip);
streams.push_back(std::move(oss));
} else if (entry.is_anonymous) {
oss << "\\x" << std::setfill('0') << std::setw(2) << std::hex << ANON_SIZE;
} else if (entry.is_none) {
oss << "\\x" << std::setfill('0') << std::setw(2) << std::hex << NONE_SIZE;
streams.push_back(std::move(oss));
} else {
streams.splice(streams.end(), gen_all_ip_options(oss));
@@ -898,7 +928,7 @@ static int cmp_ip_conds(ip_conds const &lhs, ip_conds const &rhs)
res = null_strcmp(lhs.sport, rhs.sport);
if (res)
return res;
return lhs.is_anonymous - rhs.is_anonymous;
return lhs.is_none - rhs.is_none;
}
static int cmp_network_map(std::unordered_map<unsigned int, std::pair<unsigned int, unsigned int>> lhs,

View File

@@ -80,7 +80,7 @@
#define CMD_LISTEN 2
#define CMD_OPT 4
#define ANON_SIZE 0
#define NONE_SIZE 0
#define IPV4_SIZE 1
#define IPV6_SIZE 2
@@ -132,7 +132,7 @@ public:
uint16_t port;
struct ip_address ip;
bool is_anonymous = false;
bool is_none = false;
void free_conds() {
if (sip)

View File

@@ -0,0 +1,9 @@
#
#=Description test globbed destination MR 1195
#=EXRESULT PASS
/usr/bin/foo {
mount options=(rw, make-slave) -> **,
mount options=(rw) foo -> **,
mount fstype=tmpfs options=(rw) foo -> **,
mount -> **,
}

View File

@@ -0,0 +1,8 @@
#
#=DESCRIPTION invalid family for inet conditionals
#=EXRESULT FAIL
#
/usr/bin/foo {
network unix ip=127.0.0.1 port=1234 peer=(ip=127.0.0.1 port=1234),
}

View File

@@ -0,0 +1,8 @@
#
#=DESCRIPTION invalid family for inet conditionals
#=EXRESULT FAIL
#
/usr/bin/foo {
network netlink ip=127.0.0.1,
}

View File

@@ -0,0 +1,8 @@
#
#=DESCRIPTION invalid family for inet conditionals
#=EXRESULT FAIL
#
/usr/bin/foo {
network packet peer=(port=1234),
}

View File

@@ -5,5 +5,7 @@
/usr/bin/foo {
network inet ip=10.0.2.1 peer=(ip=10.0.2.1),
network inet tcp ip=192.168.2.254 peer=(ip=192.168.2.254),
network stream ip=192.168.2.254 peer=(ip=192.168.2.254),
network raw ip=10.0.2.1 peer=(ip=10.0.2.1),
}

View File

@@ -0,0 +1,11 @@
#
#=DESCRIPTION network none ip conditional test
#=EXRESULT PASS
#
/usr/bin/foo {
network ip=none,
network peer=(ip=none),
network inet ip=none peer=(ip=none),
network inet tcp ip=none peer=(ip=none),
}

View File

@@ -35,6 +35,13 @@
owner /proc/@{pid}/loginuid r,
/{,usr/}{,s}bin/unix_chkpwd Px,
# pam_env
@{etc_ro}/environment r,
# pam_limit
@{etc_ro}/security/limits.d/ r,
@{etc_ro}/security/limits.d/*.conf r,
# gssapi
@{etc_ro}/gss/mech r,
@{etc_ro}/gss/mech.d/ r,

View File

@@ -12,6 +12,7 @@
abi <abi/4.0>,
/etc/samba/* r,
/etc/gnutls/config r,
/usr/lib*/ldb/*.so mr,
/usr/lib*/ldb2/*.so mr,
/usr/lib*/ldb2/modules/ldb/*.so mr,

View File

@@ -0,0 +1,153 @@
# vim:syntax=apparmor
# LOGPROF-SUGGEST: no
# Author: Daniel Richard G. <skunk@iSKUNK.ORG>
include <abstractions/base>
include <abstractions/freedesktop.org>
include <abstractions/nameservice>
include <abstractions/openssl>
network inet dgram,
network inet6 dgram,
network netlink dgram,
network inet stream,
network inet6 stream,
dbus (bind)
bus=session
name=com.transmissionbt.Transmission,
dbus (bind)
bus=session
name=com.transmissionbt.transmission_*,
dbus (receive)
bus=session
path=/ca/desrt/dconf/Writer/user
interface=ca.desrt.dconf.Writer
member=Notify,
dbus (send)
bus=session
path=/ca/desrt/dconf/Writer/user
interface=ca.desrt.dconf.Writer
member=Change
peer=(name=ca.desrt.dconf),
dbus (receive)
bus=accessibility
path=/org/a11y/atspi/accessible/root
interface=org.freedesktop.DBus.Properties
member=Set,
dbus (send)
bus=accessibility
path=/org/a11y/atspi/accessible/root
interface=org.a11y.atspi.Socket
member=Embed
peer=(name=org.a11y.atspi.Registry),
dbus (send)
bus=accessibility
path=/org/a11y/atspi/registry
interface=org.a11y.atspi.Registry
member=GetRegisteredEvents
peer=(name=org.a11y.atspi.Registry),
dbus (send)
bus=accessibility
path=/org/a11y/atspi/registry/deviceeventcontroller
interface=org.a11y.atspi.DeviceEventController
member={GetDeviceEventListeners,GetKeystrokeListeners}
peer=(name=org.a11y.atspi.Registry),
dbus (send)
bus={accessibility,session}
path=/org/freedesktop/DBus
interface=org.freedesktop.DBus
member={AddMatch,GetNameOwner,Hello,ReleaseName,RemoveMatch,RequestName,StartServiceByName}
peer=(name=org.freedesktop.DBus),
dbus (send)
bus=session
interface=org.freedesktop.DBus.Introspectable
path=/StatusNotifierWatcher
member=Introspect
peer=(name=org.kde.StatusNotifierWatcher),
dbus (send)
bus=session
interface=org.freedesktop.DBus.Properties
path=/StatusNotifierWatcher
member=Get
peer=(name=org.kde.StatusNotifierWatcher),
dbus (send)
bus=session
interface=org.freedesktop.DBus.Properties
path=/org/a11y/bus
member=Get
peer=(name=org.a11y.Bus),
dbus (send)
bus=system
interface=org.freedesktop.DBus.Properties
path=/org/freedesktop/hostname1
member=GetAll,
dbus (send)
bus=session
interface=org.freedesktop.Notifications
path=/org/freedesktop/Notifications
member={GetCapabilities,Notify},
dbus (send)
bus=session
path=/org/gtk/Private/RemoteVolumeMonitor
interface=org.gtk.Private.RemoteVolumeMonitor
member={IsSupported,List},
dbus (send)
bus=session
path=/org/gtk/vfs/Daemon
interface=org.gtk.vfs.Daemon
member={GetConnection,ListMonitorImplementations},
dbus (send)
bus=session
path=/org/gtk/vfs/mount/[1-9]*
interface=org.gtk.vfs.Mount
member={CreateFileMonitor,Enumerate,QueryInfo},
dbus (receive)
bus=session
path=/org/gtk/vfs/mounttracker
interface=org.gtk.vfs.MountTracker
member=Mounted,
dbus (send)
bus=session
path=/org/gtk/vfs/mounttracker
interface=org.gtk.vfs.MountTracker
member={ListMountableInfo,ListMounts2,LookupMount},
@{PROC}/sys/kernel/random/uuid r,
owner @{PROC}/@{pid}/mountinfo r,
owner @{PROC}/@{pid}/mounts r,
owner @{run}/user/@{uid}/gvfsd/socket-* rw,
@{etc_ro}/fstab r,
@{system_share_dirs}/hwdata/** r,
@{system_share_dirs}/lxqt/** r,
owner /tmp/tr_session_id_* rwk,
# allow a top-level directory listing
@{HOME}/ r,
owner @{HOME}/.cache/transmission/ w,
owner @{HOME}/.cache/transmission/** rw,
owner @{HOME}/.config/transmission/ w,
owner @{HOME}/.config/transmission/** rw,
owner @{HOME}/.config/lxqt/lxqt.conf r,
owner @{HOME}/@{XDG_DOWNLOAD_DIR}/ r,
owner @{HOME}/@{XDG_DOWNLOAD_DIR}/** rw,
# exclude these for now
deny /usr/share/thumbnailers/ r,
deny @{HOME}/.local/share/gvfs-metadata/** r,
deny @{HOME}/.config/lxqt/** rw,
include if exists <abstractions/transmission-common.d>

View File

@@ -4,7 +4,7 @@
abi <abi/4.0>,
include <tunables/global>
profile firefox /usr/lib/firefox{,-esr,-beta,-devedition,-nightly}/firefox{,-esr,-bin} flags=(unconfined) {
profile firefox /{usr/lib/firefox{,-esr,-beta,-devedition,-nightly},opt/firefox}/firefox{,-esr,-bin} flags=(unconfined) {
userns,
# Site-specific additions and overrides. See local/README for details.

View File

@@ -0,0 +1,12 @@
# This profile allows everything and only exists to give the
# application a name instead of having the label "unconfined"
abi <abi/4.0>,
include <tunables/global>
profile foliate /usr/bin/foliate flags=(unconfined) {
userns,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/foliate>
}

View File

@@ -19,6 +19,8 @@ profile samba-rpcd-classic /usr/lib*/samba/{,samba/}rpcd_classic {
/usr/lib*/samba/{,samba/}rpcd_classic mr,
@{HOMEDIRS}/** lrwk,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/samba-rpcd-classic>
}

View File

@@ -0,0 +1,76 @@
# vim:syntax=apparmor
# Author: Daniel Richard G. <skunk@iSKUNK.ORG>
abi <abi/4.0>,
include <tunables/global>
profile transmission-daemon /usr/bin/transmission-daemon flags=(complain) {
# Don't use abstractions/transmission-common here, as the
# access needed is narrower than the user applications
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/openssl>
network inet dgram,
network inet6 dgram,
network inet stream,
network inet6 stream,
owner @{PROC}/@{pid}/mounts r,
@{PROC}/sys/kernel/random/uuid r,
@{run}/systemd/notify w,
/etc/transmission-daemon/** r,
owner /etc/transmission-daemon/settings.json{,.tmp.*} rw,
owner /tmp/tr_session_id_* rwk,
/usr/share/transmission/web/** r,
owner /var/lib/transmission-daemon/.config/transmission-daemon/** rw,
owner /var/lib/transmission-daemon/downloads/** rw,
owner /var/lib/transmission-daemon/info/** rw,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/transmission>
include if exists <local/transmission-daemon>
}
profile transmission-cli /usr/bin/transmission-cli flags=(complain) {
include <abstractions/transmission-common>
include <abstractions/consoles>
# Site-specific additions and overrides. See local/README for details.
include if exists <local/transmission>
include if exists <local/transmission-cli>
}
profile transmission-gtk /usr/bin/transmission-gtk flags=(complain) {
include <abstractions/transmission-common>
include <abstractions/dbus-session-strict>
include <abstractions/dconf>
include <abstractions/gnome>
owner @{run}/user/*/dconf/user w,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/transmission>
include if exists <local/transmission-gtk>
}
profile transmission-qt /usr/bin/transmission-qt flags=(complain) {
include <abstractions/transmission-common>
include <abstractions/dbus-accessibility-strict>
include <abstractions/dbus-network-manager-strict>
include <abstractions/dbus-session-strict>
include <abstractions/fonts>
include <abstractions/X>
include <abstractions/qt5>
include <abstractions/qt5-settings-write>
# Site-specific additions and overrides. See local/README for details.
include if exists <local/transmission>
include if exists <local/transmission-qt>
}

View File

@@ -32,9 +32,6 @@ profile smbd /usr/{bin,sbin}/smbd {
/etc/samba/* rwk,
@{PROC}/@{pid}/mounts r,
@{PROC}/sys/kernel/core_pattern r,
/usr/etc/environment r,
/usr/etc/security/limits.d/ r,
/usr/etc/security/limits.d/*.conf r,
/usr/lib*/samba/vfs/*.so mr,
/usr/lib*/samba/auth/*.so mr,
/usr/lib*/samba/charset/*.so mr,

View File

@@ -0,0 +1,68 @@
# This profile allows almost everything and only exists to allow
# bwrap to work on a system with user namespace restrictions
# being enforced.
# bwrap is allowed access to user namespaces and capabilities
# within the user namespace, but its children do not have
# capabilities, blocking bwrap from being able to be used to
# arbitrarily by-pass the user namespace restrictions.
#
# Note: the bwrap child is stacked against the bwrap profile due to
# bwraps use of no-new-privs
# disabled by default as it can break some use cases on a system that
# doesn't have or has disable user namespace restrictions for unconfined
# use aa-enforce to enable it
abi <abi/4.0>,
include <tunables/global>
profile bwrap /usr/bin/bwrap flags=(attach_disconnected) {
allow capability,
# not allow all, to allow for pix stack
# sadly we have to allow m every where to allow children to work under
# stacking.
allow file rwlkm /{**,},
allow network,
allow unix,
allow ptrace,
allow signal,
allow mqueue,
allow io_uring,
allow userns,
allow mount,
allow umount,
allow pivot_root,
allow dbus,
allow px /** -> bwrap//&unpriv_bwrap,
# the local include should not be used without understanding the userns
# restriction.
# Site-specific additions and overrides. See local/README for details.
include if exists <local/bwrap-userns-restrict>
}
profile unpriv_bwrap flags=(attach_disconnected) {
# not allow all, to allow for pix stack
allow file rwlkm /{**,},
allow network,
allow unix,
allow ptrace,
allow signal,
allow mqueue,
allow io_uring,
allow userns,
allow mount,
allow umount,
allow pivot_root,
allow dbus,
allow pix /** -> &unpriv_bwrap,
audit deny capability,
# the local include should not be used without understanding the userns
# restriction.
# Site-specific additions and overrides. See local/README for details.
include if exists <local/unpriv_bwrap>
}

View File

@@ -12,7 +12,7 @@
abi <abi/4.0>,
#include <tunables/global>
include <tunables/global>
@{chromium} = chromium{,-browser}
@@ -22,10 +22,13 @@ profile chromium_browser /usr/lib/@{chromium}/@{chromium} flags=(attach_disconne
include <abstractions/cups-client>
include <abstractions/dbus-session>
include <abstractions/dbus-strict>
include <abstractions/fonts>
include <abstractions/gnome>
include <abstractions/ibus>
include <abstractions/mesa>
include <abstractions/nameservice>
include <abstractions/user-tmp>
include <abstractions/vulkan>
# This include specifies which ubuntu-browsers.d abstractions to use. Eg, if
# you want access to productivity applications, adjust the following file
@@ -57,14 +60,48 @@ profile chromium_browser /usr/lib/@{chromium}/@{chromium} flags=(attach_disconne
member={EnumerateDevices,GetDisplayDevice}
peer=(label=unconfined),
# ???
deny dbus (send)
dbus (send)
bus=system
path=/org/freedesktop/hostname1
interface=org.freedesktop.DBus.Properties
member=GetAll
peer=(label=unconfined),
dbus (receive)
bus=system
path=/org/freedesktop/login1
interface=org.freedesktop.login1.Manager
member={SessionNew,SessionRemoved}
peer=(label=unconfined),
dbus (send)
bus=session
path=/org/freedesktop/DBus
interface=org.freedesktop.DBus
member={AddMatch,GetNameOwner,Hello,NameHasOwner,RemoveMatch,StartServiceByName}
peer=(name=org.freedesktop.DBus),
dbus (send)
bus=session
path=/org/freedesktop/portal/desktop
interface=org.freedesktop.DBus.Properties
member=Get
peer=(name=org.freedesktop.portal.Desktop),
dbus (send)
bus=session
path=/org/freedesktop/Notifications
interface=org.freedesktop.Notifications
member={GetCapabilities,GetServerInformation}
peer=(name=org.freedesktop.Notifications),
dbus (send)
bus=session
path=/org/gtk/vfs/mounttracker
interface=org.gtk.vfs.MountTracker
member=ListMountableInfo
peer=(label=unconfined),
# Networking
network inet stream,
network inet6 stream,
@@ -72,30 +109,35 @@ profile chromium_browser /usr/lib/@{chromium}/@{chromium} flags=(attach_disconne
@{PROC}/@{pid}/net/ipv6_route r,
# Should maybe be in abstractions
/etc/fstab r,
/etc/mime.types r,
/etc/mailcap r,
/etc/mtab r,
/etc/xdg/xubuntu/applications/defaults.list r,
owner @{HOME}/.cache/thumbnails/** r,
owner @{HOME}/.local/share/applications/defaults.list r,
owner @{HOME}/.local/share/applications/mimeinfo.cache r,
/tmp/.X[0-9]*-lock r,
@{PROC}/self/exe ixr,
@{PROC}/@{pid}/fd/ r,
@{PROC}/filesystems r,
@{PROC}/pressure/{cpu,io,memory} r,
@{PROC}/vmstat r,
@{PROC}/ r,
@{PROC}/@{pid}/task/@{tid}/stat r,
owner @{PROC}/@{pid}/task/@{tid}/stat r,
owner @{PROC}/@{pid}/clear_refs w,
owner @{PROC}/@{pid}/cmdline r,
owner @{PROC}/@{pid}/io r,
owner @{PROC}/@{pid}/mountinfo r,
owner @{PROC}/@{pid}/setgroups w,
owner @{PROC}/@{pid}/{uid,gid}_map w,
@{PROC}/@{pid}/smaps r,
owner @{PROC}/@{pid}/smaps r,
@{PROC}/@{pid}/stat r,
@{PROC}/@{pid}/statm r,
@{PROC}/@{pid}/status r,
owner @{PROC}/@{pid}/status r,
owner @{PROC}/@{pid}/task/@{tid}/status r,
deny @{PROC}/@{pid}/oom_{,score_}adj w,
@{PROC}/sys/fs/inotify/max_user_watches r,
@{PROC}/sys/kernel/yama/ptrace_scope r,
@{PROC}/sys/net/ipv4/tcp_fastopen r,
@@ -105,13 +147,24 @@ profile chromium_browser /usr/lib/@{chromium}/@{chromium} flags=(attach_disconne
/sys/devices/**/uevent r,
/sys/devices/system/cpu/cpufreq/policy*/cpuinfo_max_freq r,
/sys/devices/system/cpu/cpu*/cpufreq/cpuinfo_max_freq r,
/sys/devices/system/cpu/kernel_max r,
/sys/devices/system/cpu/possible r,
/sys/devices/system/cpu/present r,
/sys/devices/system/node/node*/meminfo r,
/sys/devices/pci[0-9]*/**/bConfigurationValue r,
/sys/devices/pci[0-9]*/**/boot_vga r,
/sys/devices/pci[0-9]*/**/busnum r,
/sys/devices/pci[0-9]*/**/class r,
/sys/devices/pci[0-9]*/**/config r,
/sys/devices/pci[0-9]*/**/descriptors r,
/sys/devices/pci[0-9]*/**/device r,
/sys/devices/pci[0-9]*/**/devnum r,
/sys/devices/pci[0-9]*/**/irq r,
/sys/devices/pci[0-9]*/**/manufacturer r,
/sys/devices/pci[0-9]*/**/product r,
/sys/devices/pci[0-9]*/**/resource r,
/sys/devices/pci[0-9]*/**/revision r,
/sys/devices/pci[0-9]*/**/serial r,
/sys/devices/pci[0-9]*/**/subsystem_device r,
/sys/devices/pci[0-9]*/**/subsystem_vendor r,
/sys/devices/pci[0-9]*/**/vendor r,
@@ -122,6 +175,7 @@ profile chromium_browser /usr/lib/@{chromium}/@{chromium} flags=(attach_disconne
/sys/devices/virtual/tty/tty*/active r,
# This is requested, but doesn't seem to actually be needed so deny for now
deny /run/udev/data/** r,
deny /sys/devices/virtual/dmi/id/* r,
# Needed for the crash reporter
owner @{PROC}/@{pid}/auxv r,
@@ -132,13 +186,13 @@ profile chromium_browser /usr/lib/@{chromium}/@{chromium} flags=(attach_disconne
/usr/share/fonts/**/*.pfb m,
/usr/share/mime/mime.cache m,
/usr/share/icons/**/*.cache m,
owner /{dev,run}/shm/pulse-shm* m,
owner /{dev,run,var/run}/shm/pulse-shm* m,
owner @{HOME}/.local/share/mime/mime.cache m,
owner /tmp/** m,
@{PROC}/sys/kernel/shmmax r,
owner /{dev,run}/shm/{,.}org.chromium.* mrw,
owner /{,var/}run/shm/shmfd-* mrw,
owner /{dev,run,var/run}/shm/{,.}org.chromium.* mrw,
owner /{dev,run,var/run}/shm/shmfd-* mrw,
/usr/lib/@{chromium}/*.pak mr,
/usr/lib/@{chromium}/locales/* mr,
@@ -149,8 +203,8 @@ profile chromium_browser /usr/lib/@{chromium}/@{chromium} flags=(attach_disconne
# Allow ptracing ourselves and our helpers
ptrace (trace) peer=@{profile_name},
ptrace (trace) peer=@{profile_name}//xdgsettings,
ptrace (trace) peer=lsb_release,
ptrace (read, trace) peer=@{profile_name}//xdgsettings,
ptrace (read, trace) peer=lsb_release,
# Make browsing directories work
/ r,
@@ -183,10 +237,9 @@ profile chromium_browser /usr/lib/@{chromium}/@{chromium} flags=(attach_disconne
/etc/firefox/profile/bookmarks.html r,
owner @{HOME}/.mozilla/** k,
# Chromium Policies
/etc/@{chromium}/policies/** r,
# Chromium configuration
/etc/@{chromium}/** r,
# Note: "~/.pki/{,nssdb/} w" is denied by private-files abstraction
owner @{HOME}/.pki/nssdb/* rwk,
owner @{HOME}/.cache/chromium/ rw,
owner @{HOME}/.cache/chromium/** rw,
@@ -197,12 +250,18 @@ profile chromium_browser /usr/lib/@{chromium}/@{chromium} flags=(attach_disconne
owner @{HOME}/.config/chromium/Dictionaries/*.bdic mr,
owner @{HOME}/.config/chromium/**/Dictionaries/*.bdic mr,
# Allow transitions to ourself and our sandbox
# Widevine CDM plugin
owner @{HOME}/.config/chromium/WidevineCdm/*/_platform_specific/*/libwidevinecdm.so mr,
# Allow transitions to ourself, our sandbox, and crash handler
/usr/lib/@{chromium}/@{chromium} ix,
/usr/lib/@{chromium}/chrome-sandbox cx -> sandbox,
/usr/lib/@{chromium}/chrome_crashpad_handler Cxr -> crashpad_handler,
# Allow communicating with sandbox
# Allow communicating with sandbox and crash handler
unix (receive, send) peer=(label=@{profile_name}//sandbox),
unix (receive, send) peer=(label=@{profile_name}//crashpad_handler),
signal (receive) set=(cont) peer=@{profile_name}//crashpad_handler,
/{usr/,}bin/ps Uxr,
/usr/lib/@{chromium}/xdg-settings Cxr -> xdgsettings,
@@ -210,10 +269,13 @@ profile chromium_browser /usr/lib/@{chromium}/@{chromium} flags=(attach_disconne
/usr/bin/lsb_release Pxr -> lsb_release,
# GSettings
owner /{,var/}run/user/*/dconf/ rw,
owner /{,var/}run/user/*/dconf/user rw,
owner @{run}/user/[0-9]*/dconf/ rw,
owner @{run}/user/[0-9]*/dconf/user rw,
owner @{HOME}/.config/dconf/user r,
# GVfs
owner @{run}/user/[0-9]*/gvfsd/socket-* rw,
# Magnet links
/usr/bin/gio ixr,
@@ -230,7 +292,7 @@ profile chromium_browser /usr/lib/@{chromium}/@{chromium} flags=(attach_disconne
/etc/ld.so.cache r,
/etc/xdg/** r,
/usr/bin/xdg-settings r,
/{usr/,}lib{,32,64}/@{chromium}/xdg-settings r,
/usr/lib/@{chromium}/xdg-settings r,
/usr/share/applications/*.desktop r,
/usr/share/applications/*.list r,
@@ -266,6 +328,8 @@ profile chromium_browser /usr/lib/@{chromium}/@{chromium} flags=(attach_disconne
/{usr/,}lib/@{multiarch}/libpthread-*.so* mr,
/{usr/,}lib{,32,64}/libatomic.so* mr,
/{usr/,}lib/@{multiarch}/libatomic.so* mr,
/{usr/,}lib{,32,64}/libc.so.* mr,
/{usr/,}lib/@{multiarch}/libc.so.* mr,
/{usr/,}lib{,32,64}/libc-*.so* mr,
/{usr/,}lib/@{multiarch}/libc-*.so* mr,
/{usr/,}lib{,32,64}/libdl-*.so* mr,
@@ -326,6 +390,32 @@ profile chromium_browser /usr/lib/@{chromium}/@{chromium} flags=(attach_disconne
owner /tmp/** rw,
}
profile crashpad_handler {
include <abstractions/base>
capability sys_ptrace,
ptrace (read, trace) peer=chromium_browser,
signal (send) set=(cont) peer=chromium_browser,
unix (receive, send) peer=(label=chromium_browser),
/usr/lib/@{chromium}/chrome_crashpad_handler ixr,
/sys/devices/system/cpu/cpufreq/policy[0-9]*/scaling_{cur,max}_freq r,
@{PROC}/sys/kernel/yama/ptrace_scope r,
owner @{PROC}/@{pid}/fd/ r,
owner @{PROC}/@{pid}/mem r,
owner @{PROC}/@{pid}/stat r,
owner @{PROC}/@{pid}/task/ r,
owner @{PROC}/@{pid}/task/@{tid}/comm r,
owner @{HOME}/.config/chromium/Crash?Reports/** rwk,
}
# Site-specific additions and overrides. See local/README for details.
include if exists <local/chromium_browser>
}

View File

@@ -241,7 +241,7 @@ profile firefox @{MOZ_LIBDIR}/@{MOZ_APP_NAME}{,*[^s][^h]} {
owner @{HOME}/.gnome2/firefox* rwk,
owner @{HOME}/.cache/mozilla/{,@{MOZ_APP_NAME}/} rw,
owner @{HOME}/.cache/mozilla/@{MOZ_APP_NAME}/** rw,
owner @{HOME}/.cache/mozilla/@{MOZ_APP_NAME}/**/*.sqlite k,
owner @{HOME}/.cache/mozilla/@{MOZ_APP_NAME}/**/*.sqlite{,-shm} k,
owner @{HOME}/.config/gtk-3.0/bookmarks r,
owner @{HOME}/.config/dconf/user w,
owner @{run}/user/[0-9]*/dconf/ w,

View File

@@ -0,0 +1,65 @@
# This profile allows almost everything and only exists to allow
# unshare to work on a system with user namespace restrictions
# being enforced.
# unshare is allowed access to user namespaces and capabilities
# within the user namespace, but its children do not have
# capabilities, blocking unshare from being able to be used to
# arbitrarily by-pass the user namespace restrictions.
# We restrict x mapping of any code that is unknown while unshare
# has privilige within the namespace. To help ensure unshare can't
# be used to attack the kernel.
#
# disabled by default as it can break some use cases on a system that
# doesn't have or has disable user namespace restrictions for unconfined
# use aa-enforce to enable it
abi <abi/4.0>,
include <tunables/global>
profile unshare /usr/bin/unshare flags=(attach_disconnected) {
# not allow all, to allow for cix transition
# and to limit executable mapping to just unshare
allow capability,
allow file rwlk /{**,},
allow network,
allow unix,
allow ptrace,
allow signal,
allow mqueue,
allow io_uring,
allow userns,
allow mount,
allow umount,
allow pivot_root,
allow dbus,
audit allow cx /** -> unpriv,
allow file m /usr/lib/@{multiarch}/libc.so.6,
allow file m /usr/bin/unshare,
# the local include should not be used without understanding the userns
# restriction.
# Site-specific additions and overrides. See local/README for details.
include if exists <local/unshare-userns-restrict>
profile unpriv flags=(attach_disconnected) {
# not allow all, to allow for pix stack
allow file rwlkm /{**,},
allow network,
allow unix,
allow ptrace,
allow signal,
allow mqueue,
allow io_uring,
allow userns,
allow mount,
allow umount,
allow pivot_root,
allow dbus,
allow pix /** -> &unshare//unpriv,
audit deny capability,
}
}

View File

@@ -50,6 +50,15 @@ include <tunables/global>
# needed when /proc is mounted with hidepid>=1
ptrace (read,trace) peer="unconfined",
unix (bind) type=stream addr="@*/bus/sshd/system",
dbus (send)
bus=system
path=/org/freedesktop/login1
interface=org.freedesktop.login1.Manager
member=CreateSessionWithPIDFD
peer=(label=unconfined),
/dev/ptmx rw,
/dev/pts/[0-9]* rw,
/dev/urandom r,

12
profiles/apparmor/wike Normal file
View File

@@ -0,0 +1,12 @@
# This profile allows everything and only exists to give the
# application a name instead of having the label "unconfined"
abi <abi/4.0>,
include <tunables/global>
profile wike /usr/bin/wike flags=(unconfined) {
userns,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/wike>
}

View File

@@ -111,8 +111,8 @@ SRC=access.c \
mount.c \
move_mount.c \
named_pipe.c \
net_finegrained_rcv.c \
net_finegrained_snd.c \
net_inet_rcv.c \
net_inet_snd.c \
net_raw.c \
open.c \
openat.c \
@@ -364,10 +364,10 @@ unix_fd_client: unix_fd_client.c unix_fd_common.o
attach_disconnected: attach_disconnected.c unix_fd_common.o
${CC} ${CFLAGS} ${LDFLAGS} $^ -o $@ ${LDLIBS}
userns: userns.c userns.h
userns: userns.c pipe_helper.h
${CC} ${CFLAGS} ${LDFLAGS} $^ -o $@ ${LDLIBS}
userns_setns: userns_setns.c userns.h
userns_setns: userns_setns.c pipe_helper.h
${CC} ${CFLAGS} ${LDFLAGS} $^ -o $@ ${LDLIBS}
mount: mount.c

View File

@@ -6,9 +6,9 @@
#published by the Free Software Foundation, version 2 of the
#License.
#=NAME posix_mq
#=NAME net_inet
#=DESCRIPTION
# This test verifies if mediation of posix message queues is working
# This test verifies if finegrained inet mediation is working
#=END
pwd=`dirname $0`
@@ -18,13 +18,13 @@ bin=$pwd
. $bin/prologue.inc
#requires_kernel_features network_v8/finegrained
requires_kernel_features network_v8/af_inet
requires_parser_support "network ip=::1,"
settest net_finegrained_rcv
settest net_inet_rcv
sender="$bin/net_finegrained_snd"
receiver="$bin/net_finegrained_rcv"
sender="$bin/net_inet_snd"
receiver="$bin/net_inet_rcv"
# local ipv6 address generated according to https://www.rfc-editor.org/rfc/rfc4193.html
#ipv6_subnet=fd74:1820:b03a:b361::/64
@@ -47,7 +47,7 @@ do_onexit="cleanup"
do_test()
{
local desc="FINEGRAINED NETWORK ($1)"
local desc="NETWORK INET ($1)"
shift
runchecktest "$desc" "$@"
}
@@ -65,12 +65,11 @@ do_tests()
protocol=$8
generate_profile=$9
settest net_finegrained_rcv
settest net_inet_rcv
$generate_profile
do_test "$prefix - root" $expect_rcv --bind_ip $bind_ip --bind_port $bind_port --remote_ip $remote_ip --remote_port $remote_port --protocol $protocol --timeout 5 --sender $sender
settest -u "foo" net_finegrained_rcv
settest -u "foo" net_inet_rcv
$generate_profile
do_test "$prefix - user" $expect_rcv --bind_ip $bind_ip --bind_port $bind_port --remote_ip $remote_ip --remote_port $remote_port --protocol $protocol --timeout 5 --sender $sender
@@ -97,7 +96,7 @@ do_tests "ipv4 udp no conds" pass pass $bind_ipv4 $bind_port $remote_ipv4 $remot
generate_profile="genprofile network $sender:px -- image=$sender network"
do_tests "ipv4 tcp no conds" pass pass $bind_ipv4 $bind_port $remote_ipv4 $remote_port tcp "$generate_profile"
setsockopt_rules="network;(setopt,getopt);ip=0.0.0.0;port=0"
setsockopt_rules="network;(setopt,getopt);ip=0.0.0.0;port=0" # INADDR_ANY
rcv_rules="network;ip=$bind_ipv4;peer=(ip=anon)"
snd_rules="network;ip=$remote_ipv4;peer=(ip=anon)"
@@ -126,7 +125,7 @@ do_tests "ipv6 udp no conds" pass pass $bind_ipv6 $bind_port $remote_ipv6 $remot
generate_profile="genprofile network $sender:px -- image=$sender network"
do_tests "ipv6 tcp no conds" pass pass $bind_ipv6 $bind_port $remote_ipv6 $remote_port tcp "$generate_profile"
setsockopt_rules="network;(setopt,getopt);ip=::0;port=0"
setsockopt_rules="network;(setopt,getopt);ip=::0;port=0" # IN6ADDR_ANY_INIT
rcv_rules="network;ip=$bind_ipv6;peer=(ip=anon)"
snd_rules="network;ip=$remote_ipv6;peer=(ip=anon)"
@@ -135,5 +134,3 @@ do_tests "ipv6 udp generic perms" pass pass $bind_ipv6 $bind_port $remote_ipv6 $
generate_profile="genprofile network;ip=$bind_ipv6;port=$bind_port;peer=(ip=$remote_ipv6,port=$remote_port) $setsockopt_rules $rcv_rules $sender:px -- image=$sender network;ip=$remote_ipv6;port=$remote_port;peer=(ip=$bind_ipv6,port=$bind_port) $setsockopt_rules $snd_rules"
do_tests "ipv6 tcp generic perms" pass pass $bind_ipv6 $bind_port $remote_ipv6 $remote_port tcp "$generate_profile"

View File

@@ -9,7 +9,13 @@
#include <string.h>
#include <getopt.h>
#include <sys/stat.h>
#include "net_finegrained.h"
#include "net_inet.h"
enum protocol {
UDP,
TCP,
ICMP
};
struct connection_info {
char *bind_ip;
@@ -17,17 +23,72 @@ struct connection_info {
char *remote_ip;
char *remote_port;
char *protocol;
enum protocol prot;
int timeout;
} net_info;
int receive_udp()
int receive_bind()
{
int sock;
char *buf;
struct sockaddr_in local;
struct sockaddr_in6 local6;
struct ip_address bind_addr;
if (!parse_ip(net_info.bind_ip, net_info.bind_port, &bind_addr)) {
fprintf(stderr, "FAIL - could not parse bind ip address\n");
return -1;
}
switch(net_info.prot) {
case UDP:
sock = socket(bind_addr.family, SOCK_DGRAM, 0);
break;
case TCP:
sock = socket(bind_addr.family, SOCK_STREAM, 0);
break;
case ICMP:
sock = socket(bind_addr.family, SOCK_DGRAM, IPPROTO_ICMP);
break;
}
if (sock < 0) {
perror("FAIL - Socket error: ");
return -1;
}
const int enable = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &enable, sizeof(int)) < 0)
perror("FAIL - setsockopt(SO_REUSEADDR) failed");
if (bind_addr.family == AF_INET) {
local = convert_to_sockaddr_in(bind_addr);
if (bind(sock, (struct sockaddr *) &local, sizeof(local)) < 0) {
perror("FAIL - Bind error: ");
return -1;
}
} else {
local6 = convert_to_sockaddr_in6(bind_addr);
if (bind(sock, (struct sockaddr *) &local6, sizeof(local6)) < 0) {
perror("FAIL - Bind error: ");
return -1;
}
}
if (net_info.prot == TCP) {
if (listen(sock, 5) == -1) {
perror("FAIL - Could not listen: ");
return -1;
}
}
return sock;
}
int receive_udp(int sock)
{
char *buf;
int ret = -1;
int select_return;
@@ -37,38 +98,6 @@ int receive_udp()
buf = (char *) malloc(255);
memset(buf, '\0', 255);
struct ip_address bind_addr;
if (!parse_ip(net_info.bind_ip, net_info.bind_port, &bind_addr)) {
fprintf(stderr, "FAIL - could not parse bind ip address\n");
return -1;
}
if ((sock = socket(bind_addr.family, SOCK_DGRAM, 0)) < 0) {
perror("FAIL - Socket error: ");
return(-1);
}
const int enable = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &enable, sizeof(int)) < 0)
perror("FAIL - setsockopt(SO_REUSEADDR) failed");
if (bind_addr.family == AF_INET) {
local = convert_to_sockaddr_in(bind_addr);
if (bind(sock, (struct sockaddr *) &local, sizeof(local)) < 0)
{
perror("FAIL - Bind error: ");
return(-1);
}
} else {
local6 = convert_to_sockaddr_in6(bind_addr);
if (bind(sock, (struct sockaddr *) &local6, sizeof(local6)) < 0)
{
printf("errno %d\n", errno);
perror("FAIL - Bind error: ");
return(-1);
}
}
FD_ZERO(&read_set);
FD_SET(sock, &read_set);
FD_ZERO(&err_set);
@@ -77,39 +106,30 @@ int receive_udp()
timeout.tv_usec = 0;
select_return = select(sock + 1, &read_set, NULL, &err_set, &timeout);
if (select_return < 0)
{
if (select_return < 0) {
perror("FAIL - Select error: ");
ret = -1;
}
if ((select_return > 0) && (FD_ISSET(sock, &read_set)) && (!FD_ISSET(sock, &err_set)))
{
if (recvfrom(sock, buf, 255, 0, (struct sockaddr *)0, (unsigned int *)0) >= 1)
{
} else if (select_return == 0) {
printf("FAIL - select timeout\n");
} else if (select_return > 0 && FD_ISSET(sock, &read_set) && !FD_ISSET(sock, &err_set)) {
if (recvfrom(sock, buf, 255, 0, NULL, NULL) >= 1) {
//printf("MESSAGE: %s\n", buf);
ret = 0;
}
else
{
} else {
printf("FAIL - recvfrom failed\n");
ret = -1;
}
}
free(buf);
return(ret);
}
int receive_tcp()
int receive_tcp(int sock)
{
int sock, cli_sock;
int cli_sock;
char *buf;
struct sockaddr_in local;
struct sockaddr_in6 local6;
int ret = -1;
int select_return;
@@ -119,44 +139,6 @@ int receive_tcp()
buf = (char *) malloc(255);
memset(buf, '\0', 255);
struct ip_address bind_addr;
if (!parse_ip(net_info.bind_ip, net_info.bind_port, &bind_addr)) {
fprintf(stderr, "FAIL - could not parse bind ip address\n");
return -1;
}
if ((sock = socket(bind_addr.family, SOCK_STREAM, 0)) < 0)
{
perror("FAIL - Socket error:");
return(-1);
}
const int enable = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &enable, sizeof(int)) < 0)
perror("FAIL - setsockopt(SO_REUSEADDR) failed");
if (bind_addr.family == AF_INET) {
local = convert_to_sockaddr_in(bind_addr);
if (bind(sock, (struct sockaddr *) &local, sizeof(local)) < 0)
{
perror("FAIL - Bind error: ");
return(-1);
}
} else {
local6 = convert_to_sockaddr_in6(bind_addr);
if (bind(sock, (struct sockaddr *) &local6, sizeof(local6)) < 0)
{
perror("FAIL - Bind error: ");
return(-1);
}
}
if (listen(sock, 5) == -1)
{
perror("FAIL - Could not listen: ");
return(-1);
}
FD_ZERO(&read_set);
FD_SET(sock, &read_set);
FD_ZERO(&err_set);
@@ -165,48 +147,33 @@ int receive_tcp()
timeout.tv_usec = 0;
select_return = select(sock + 1, &read_set, NULL, &err_set, &timeout);
if (select_return < 0)
{
if (select_return < 0) {
perror("FAIL - Select failed: ");
ret = -1;
}
if ((select_return > 0) && (FD_ISSET(sock, &read_set)) && (!FD_ISSET(sock, &err_set)))
{
if ((cli_sock = accept(sock, NULL, NULL)) < 0)
{
} else if (select_return == 0) {
printf("FAIL - select timeout\n");
} else if (select_return > 0 && FD_ISSET(sock, &read_set) && !FD_ISSET(sock, &err_set)) {
if ((cli_sock = accept(sock, NULL, NULL)) < 0) {
perror("FAIL - Accept failed: ");
ret = -1;
}
else
{
if (recv(cli_sock, buf, 255, 0) >= 1)
{
} else {
if (recv(cli_sock, buf, 255, 0) >= 1) {
//printf("MESSAGE: %s\n", buf);
ret = 0;
}
else
{
} else {
perror("FAIL - recv failure: ");
ret = -1;
}
}
}
else
{
perror("FAIL - There were select failures: ");
ret = -1;
}
free(buf);
return(ret);
}
int receive_icmp()
int receive_icmp(int sock)
{
int sock;
char *buf;
struct sockaddr_in local;
int ret = -1;
int select_return;
@@ -215,25 +182,6 @@ int receive_icmp()
buf = (char *) malloc(255);
memset(buf, '\0', 255);
if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP)) < 0)
{
perror("FAIL - Socket error: ");
return(-1);
}
const int enable = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &enable, sizeof(int)) < 0)
perror("FAIL - setsockopt(SO_REUSEADDR) failed");
local.sin_family = AF_INET;
local.sin_port = htons(atoi(net_info.bind_port));
inet_aton(net_info.bind_ip, &local.sin_addr);
if (bind(sock, (struct sockaddr *) &local, sizeof(local)) < 0)
{
perror("FAIL - Bind error: ");
return(-1);
}
FD_ZERO(&read_set);
FD_SET(sock, &read_set);
@@ -243,28 +191,21 @@ int receive_icmp()
timeout.tv_usec = 0;
select_return = select(sock + 1, &read_set, NULL, &err_set, &timeout);
if (select_return < 0)
{
if (select_return < 0) {
perror("FAIL - Select error: ");
ret = -1;
}
if ((select_return > 0) && (FD_ISSET(sock, &read_set)) && (!FD_ISSET(sock, &err_set)))
{
if (recvfrom(sock, buf, 255, 0, (struct sockaddr *)0, (unsigned int *)0) >= 1)
{
} else if (select_return == 0) {
printf("FAIL - select timeout\n");
} else if (select_return > 0 && FD_ISSET(sock, &read_set) && !FD_ISSET(sock, &err_set)) {
if (recvfrom(sock, buf, 255, 0, NULL, NULL) >= 1) {
//printf("MESSAGE: %s\n", buf);
ret = 0;
}
else
{
} else {
printf("FAIL - recvfrom failed\n");
ret = -1;
}
}
free(buf);
return(ret);
@@ -302,7 +243,7 @@ int main(int argc, char *argv[])
{"protocol", required_argument, 0, 'p' },
{"timeout", required_argument, 0, 't' },
{"sender", required_argument, 0, 's' },
{0, 0, 0, 0 }
{0, 0, 0, 0 }
};
while ((opt = getopt_long(argc, argv,"i:o:r:e:p:t:s:", long_options, 0)) != -1) {
@@ -321,6 +262,14 @@ int main(int argc, char *argv[])
break;
case 'p':
net_info.protocol = optarg;
if (strcmp(net_info.protocol, "udp") == 0)
net_info.prot = UDP;
else if (strcmp(net_info.protocol, "tcp") == 0)
net_info.prot = TCP;
else if (strcmp(net_info.protocol, "icmp") == 0)
net_info.prot = ICMP;
else
printf("FAIL - Unknown protocol.\n");
break;
case 't':
net_info.timeout = atoi(optarg);
@@ -333,6 +282,13 @@ int main(int argc, char *argv[])
}
}
/* get the server to bind/listen, so the child has something
* to connect to if it wins the race. */
int sockfd = receive_bind();
if (sockfd == -1) {
exit(1);
}
/* exec the sender */
pid = fork();
if (pid == -1) {
@@ -357,22 +313,23 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
if (strcmp(net_info.protocol, "udp") == 0)
ret = receive_udp(net_info);
else if (strcmp(net_info.protocol, "tcp") == 0)
ret = receive_tcp(net_info);
else if (strcmp(net_info.protocol, "icmp") == 0)
ret = receive_icmp(net_info);
else
printf("FAIL - Unknown protocol.\n");
switch(net_info.prot) {
case UDP:
ret = receive_udp(sockfd);
break;
case TCP:
ret = receive_tcp(sockfd);
break;
case ICMP:
ret = receive_icmp(sockfd);
break;
}
if (ret == -1)
{
if (ret == -1) {
printf("FAIL - Receive message failed.\n");
exit(1);
}
printf("PASS\n");
return 0;
}

View File

@@ -12,7 +12,7 @@
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
#include "net_finegrained.h"
#include "net_inet.h"
struct connection_info {
char *bind_ip;
@@ -40,8 +40,7 @@ int send_udp(char *message)
return -1;
}
if ((sock = socket(bind_addr.family, SOCK_DGRAM, 0)) < 0)
{
if ((sock = socket(bind_addr.family, SOCK_DGRAM, 0)) < 0) {
perror("FAIL SND - Could not open socket: ");
return(-1);
}
@@ -53,15 +52,13 @@ int send_udp(char *message)
if (bind_addr.family == AF_INET) {
local = convert_to_sockaddr_in(bind_addr);
if (bind(sock, (struct sockaddr *) &local, sizeof(local)) < 0)
{
if (bind(sock, (struct sockaddr *) &local, sizeof(local)) < 0) {
perror("FAIL SND - Bind error: ");
return(-1);
}
} else {
local6 = convert_to_sockaddr_in6(bind_addr);
if (bind(sock, (struct sockaddr *) &local6, sizeof(local6)) < 0)
{
if (bind(sock, (struct sockaddr *) &local6, sizeof(local6)) < 0) {
perror("FAIL SND - Bind error: ");
return(-1);
}
@@ -70,22 +67,19 @@ int send_udp(char *message)
if (remote_addr.family == AF_INET) {
remote = convert_to_sockaddr_in(remote_addr);
//printf("Sending \"%s\"\n", message);
if (sendto(sock, message, strlen(message), 0, (struct sockaddr *) &remote, sizeof(remote)) <= 0)
{
if (sendto(sock, message, strlen(message), 0, (struct sockaddr *) &remote, sizeof(remote)) <= 0) {
perror("FAIL SND - Send failed: ");
return(-1);
}
} else {
remote6 = convert_to_sockaddr_in6(remote_addr);
//printf("Sending \"%s\"\n", message);
if (sendto(sock, message, strlen(message), 0, (struct sockaddr *) &remote6, sizeof(remote6)) <= 0)
{
if (sendto(sock, message, strlen(message), 0, (struct sockaddr *) &remote6, sizeof(remote6)) <= 0) {
perror("FAIL SND - Send failed: ");
return(-1);
}
}
close(sock);
return(0);
@@ -121,15 +115,13 @@ int send_tcp(char *message)
if (bind_addr.family == AF_INET) {
local = convert_to_sockaddr_in(bind_addr);
if (bind(sock, (struct sockaddr *) &local, sizeof(local)) < 0)
{
if (bind(sock, (struct sockaddr *) &local, sizeof(local)) < 0) {
perror("FAIL SND - Bind error: ");
return(-1);
}
} else {
local6 = convert_to_sockaddr_in6(bind_addr);
if (bind(sock, (struct sockaddr *) &local6, sizeof(local6)) < 0)
{
if (bind(sock, (struct sockaddr *) &local6, sizeof(local6)) < 0) {
perror("FAIL SND - Bind error: ");
return(-1);
}
@@ -138,24 +130,21 @@ int send_tcp(char *message)
if (remote_addr.family == AF_INET) {
remote = convert_to_sockaddr_in(remote_addr);
//printf("Sending \"%s\"\n", message);
if (connect(sock, (struct sockaddr *) &remote, sizeof(remote)) < 0)
{
if (connect(sock, (struct sockaddr *) &remote, sizeof(remote)) < 0) {
perror("FAIL SND - Could not connect: ");
return(-1);
}
} else {
remote6 = convert_to_sockaddr_in6(remote_addr);
//printf("Sending \"%s\"\n", message);
if (connect(sock, (struct sockaddr *) &remote6, sizeof(remote6)) < 0)
{
if (connect(sock, (struct sockaddr *) &remote6, sizeof(remote6)) < 0) {
perror("FAIL SND - Could not connect: ");
return(-1);
}
}
//printf("Sending \"%s\"\n", message);
if (send(sock, message, strlen(message), 0) <= 0)
{
if (send(sock, message, strlen(message), 0) <= 0) {
perror("FAIL SND - Send failed: ");
return(-1);
}
@@ -171,8 +160,7 @@ int send_icmp(char *message)
char packetdata[sizeof(icmp_hdr) + 4];
if ((sock = socket(AF_INET | AF_INET6, SOCK_DGRAM, IPPROTO_ICMP)) < 0)
{
if ((sock = socket(AF_INET | AF_INET6, SOCK_DGRAM, IPPROTO_ICMP)) < 0) {
perror("FAIL SND - Could not open socket: ");
return(-1);
}
@@ -199,8 +187,7 @@ int send_icmp(char *message)
memcpy(packetdata, &icmp_hdr, sizeof(icmp_hdr));
memcpy(packetdata + sizeof(icmp_hdr), message, strlen(message));
if (bind(sock, (struct sockaddr *) &local, sizeof(local)) < 0)
{
if (bind(sock, (struct sockaddr *) &local, sizeof(local)) < 0) {
perror("FAIL SND - Could not bind: ");
return(-1);
}
@@ -208,8 +195,7 @@ int send_icmp(char *message)
//printf("Sending \"%s\"\n", message);
// Send the packet
if(sendto(sock, packetdata, sizeof(packetdata), 0, (struct sockaddr*) &remote, sizeof(remote)) < 0)
{
if(sendto(sock, packetdata, sizeof(packetdata), 0, (struct sockaddr*) &remote, sizeof(remote)) < 0) {
perror("FAIL SND - Send failed: ");
close(sock);
return(-1);
@@ -231,8 +217,7 @@ int main(int argc, char *argv[])
{
int send_ret;
if (argc < 6)
{
if (argc < 6) {
printf("Usage: %s bind_ip bind_port remote_ip remote_port proto\n", argv[0]);
exit(1);
}
@@ -253,8 +238,7 @@ int main(int argc, char *argv[])
else
printf("FAIL SND - Unknown protocol.\n");
if (send_ret == -1)
{
if (send_ret == -1) {
printf("FAIL SND - Send message failed.\n");
exit(1);
}

View File

@@ -12,6 +12,7 @@
#define QNAME "/testmq"
#define SHM_PATH "/unnamedsemtest"
#define SEM_PATH "/namedsemtest"
#define PIPENAME "/tmp/mqueuepipe";
#define OBJ_PERMS (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
#define BUF_SIZE 1024

View File

@@ -27,6 +27,7 @@ sender="$bin/posix_mq_snd"
receiver="$bin/posix_mq_rcv"
queuename="/queuename"
queuename2="/queuename2"
pipe="/tmp/mqueuepipe"
user="foo"
adduser --gecos "First Last,RoomNumber,WorkPhone,HomePhone" --no-create-home --disabled-password $user >/dev/null
@@ -41,6 +42,7 @@ cleanup()
{
rm -f /dev/mqueue/$queuename
rm -f /dev/mqueue/$queuename2
rm -f $pipe
deluser foo >/dev/null
}
do_onexit="cleanup"
@@ -66,7 +68,7 @@ do_tests()
do_test "$prefix" "$expect_send" $sender "$expect_recv" -c $sender -k $queuename "${rest_args[@]}"
# notify requires netlink permissions
do_test "$prefix : mq_notify" "$expect_send" $sender "$expect_recv" -c $sender -k $queuename -n mq_notify "${rest_args[@]}"
do_test "$prefix : mq_notify" "$expect_send" $sender "$expect_recv" -c $sender -k $queuename -n mq_notify -p $pipe "${rest_args[@]}"
do_test "$prefix : select" "$expect_open" -c $sender -k $queuename -n select "${rest_args[@]}"
@@ -86,11 +88,11 @@ for username in "root" "$userid" ; do
do_tests "unconfined $username" pass pass pass pass $usercmd
# No mqueue perms
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "$sender:px" -- image=$sender
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "$sender:px" "$pipe:rw" -- image=$sender "$pipe:rw"
do_tests "confined $username - no perms" fail fail fail fail $usercmd
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "deny:mqueue" "$sender:px" -- image=$sender "deny mqueue"
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "deny:mqueue" "$sender:px" "$pipe:rw" -- image=$sender "deny mqueue" "$pipe:rw"
do_tests "confined $username - deny perms" fail fail fail fail $usercmd
@@ -102,46 +104,46 @@ for username in "root" "$userid" ; do
# apparmor when doing "root" username tests
# * if doing the $userid set of tests and you see
# Permission denied in the test output
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue" "$sender:px" -- image=$sender "mqueue"
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue" "$sender:px" "$pipe:rw" -- image=$sender "mqueue" "$pipe:rw"
do_tests "confined $username - mqueue" pass pass pass pass $usercmd
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:type=posix" "$sender:px" -- image=$sender "mqueue:type=posix"
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:type=posix" "$sender:px" "$pipe:rw" -- image=$sender "mqueue:type=posix" "$pipe:rw"
do_tests "confined $username - mqueue type=posix" pass pass pass pass $usercmd
# queue name
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:$queuename" "$sender:px" -- image=$sender "mqueue:$queuename"
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:$queuename" "$sender:px" "$pipe:rw" -- image=$sender "mqueue:$queuename" "$pipe:rw"
do_tests "confined $username - mqueue /name 1" pass pass pass pass $usercmd
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue" "$sender:px" -- image=$sender "mqueue:$queuename"
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue" "$sender:px" "$pipe:rw" -- image=$sender "mqueue:$queuename" "$pipe:rw"
do_tests "confined $username - mqueue /name 2" pass pass pass pass $usercmd
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:$queuename" "$sender:px" -- image=$sender "mqueue"
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:$queuename" "$sender:px" "$pipe:rw" -- image=$sender "mqueue" "$pipe:rw"
do_tests "confined $username - mqueue /name 3" pass pass pass pass $usercmd
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:$queuename" "$sender:px" -- image=$sender "mqueue:$queuename2"
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:$queuename" "$sender:px" "$pipe:rw" -- image=$sender "mqueue:$queuename2" "$pipe:rw"
do_tests "confined $username - mqueue /name 4" fail fail fail fail $usercmd -t 1
# specific permissions
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(create,read,delete,getattr,setattr)" "$sender:px" -- image=$sender "mqueue:write"
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(create,read,delete,getattr,setattr)" "$sender:px" "$pipe:rw" -- image=$sender "mqueue:write" "$pipe:rw"
do_tests "confined $username - specific 1" pass pass pass pass $usercmd
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(read,delete,getattr,setattr)" "$sender:px" -- image=$sender "mqueue:write"
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(read,delete,getattr,setattr)" "$sender:px" "$pipe:rw" -- image=$sender "mqueue:write" "$pipe:rw"
do_tests "confined $username - specific 2" fail fail fail fail $usercmd -t 1
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(create,delete,getattr,setattr)" "$sender:px" -- image=$sender "mqueue:write"
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(create,delete,getattr,setattr)" "$sender:px" "$pipe:rw" -- image=$sender "mqueue:write" "$pipe:rw"
do_tests "confined $username - specific 3" fail fail fail fail $usercmd -t 1
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(create,read,getattr,setattr)" "$sender:px" -- image=$sender "mqueue:write"
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(create,read,getattr,setattr)" "$sender:px" "$pipe:rw" -- image=$sender "mqueue:write" "$pipe:rw"
do_tests "confined $username - specific 4" fail fail fail fail $usercmd -t 1
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(create,read,delete,setattr)" "$sender:px" -- image=$sender "mqueue:write"
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(create,read,delete,setattr)" "$sender:px" "$pipe:rw" -- image=$sender "mqueue:write" "$pipe:rw"
do_tests "confined $username - specific 5" pass pass pass pass $usercmd
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(create,read,delete,getattr)" "$sender:px" -- image=$sender "mqueue:write"
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(create,read,delete,getattr)" "$sender:px" "$pipe:rw" -- image=$sender "mqueue:write" "$pipe:rw"
do_tests "confined $username - specific 6" pass pass pass pass $usercmd
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(create,read,delete,getattr,setattr)" "$sender:px" -- image=$sender "mqueue:read"
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(create,read,delete,getattr,setattr)" "$sender:px" "$pipe:rw" -- image=$sender "mqueue:read" "$pipe:rw"
do_tests "confined $username - specific 7" fail fail fail fail $usercmd -t 1
# unconfined receiver
@@ -150,17 +152,17 @@ for username in "root" "$userid" ; do
# unconfined sender
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue" "$sender:ux"
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue" "$sender:ux" "$pipe:rw"
do_tests "confined receiver $username - unconfined sender" pass pass pass pass $usercmd
# queue label
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:label=$receiver" "$sender:px" -- image=$sender "mqueue:label=$receiver"
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:label=$receiver" "$sender:px" "$pipe:rw" -- image=$sender "mqueue:label=$receiver" "$pipe:rw"
do_tests "confined $username - mqueue label 1" xpass xpass xpass xpass $usercmd
# queue name and label
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(create,read,delete):type=posix:label=$receiver:$queuename" "$sender:px" -- image=$sender "mqueue:(open,write):type=posix:label=$receiver:$queuename"
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(create,read,delete):type=posix:label=$receiver:$queuename" "$sender:px" "$pipe:rw" -- image=$sender "mqueue:(open,write):type=posix:label=$receiver:$queuename" "$pipe:rw"
do_tests "confined $username - mqueue label 2" xpass xpass xpass xpass $usercmd
# ensure we are cleaned up for next pass

View File

@@ -1,3 +1,4 @@
#define _GNU_SOURCE
#include <mqueue.h>
#include <stdlib.h>
#include <signal.h>
@@ -6,9 +7,11 @@
#include <time.h>
#include "posix_mq.h"
#include "pipe_helper.h"
int timeout = 5; //seconds
char *queuename = QNAME;
char *pipepath = PIPENAME;
enum notify_options {
DO_NOT_NOTIFY,
@@ -18,10 +21,13 @@ enum notify_options {
EPOLL
};
enum notify_options notify = DO_NOT_NOTIFY;
int receive_message(mqd_t mqd, char needs_timeout) {
ssize_t nbytes;
struct mq_attr attr;
char *buf = NULL;
int ret = EXIT_FAILURE;
if (mq_getattr(mqd, &attr) == -1) {
perror("FAIL - could not mq_getattr");
@@ -62,20 +68,24 @@ int receive_message(mqd_t mqd, char needs_timeout) {
}
printf("PASS\n");
ret = EXIT_SUCCESS;
out:
free(buf);
if (mq_close(mqd) == (mqd_t) -1) {
perror("FAIL - could not close mq");
exit(EXIT_FAILURE);
ret = EXIT_FAILURE;
}
if (mq_unlink(queuename) == (mqd_t) -1) {
perror("FAIL - could unlink mq");
exit(EXIT_FAILURE);
perror("FAIL - could not unlink mq");
ret = EXIT_FAILURE;
}
exit(EXIT_SUCCESS);
if (notify == MQ_NOTIFY && unlink(pipepath) == -1) {
perror("FAIL - could not remove pipe");
ret = EXIT_FAILURE;
}
exit(ret);
}
static void handle_signal(union sigval sv) {
@@ -96,6 +106,7 @@ static void usage(char *prog_name, char *msg)
fprintf(stderr, "-c path of the client binary\n");
fprintf(stderr, "-u run test as specified UID\n");
fprintf(stderr, "-t timeout in seconds\n");
fprintf(stderr, "-p named pipe path. used by mq_notify\n");
exit(EXIT_FAILURE);
}
@@ -108,9 +119,15 @@ void receive_mq_notify(mqd_t mqd)
sev.sigev_value.sival_ptr = &mqd;
if (mq_notify(mqd, &sev) == -1) {
perror(" FAIL - could not mq_notify");
exit(EXIT_FAILURE);
perror("FAIL - could not mq_notify");
return;
}
if (write_to_pipe(pipepath) == -1) { // let sender know mq_notify is ready
fprintf(stderr, "FAIL - could not write to pipe\n");
return;
}
sleep(timeout);
fprintf(stderr, "FAIL - could not mq_notify: Connection timed out\n");
}
@@ -127,7 +144,7 @@ void receive_select(mqd_t mqd)
if (select(mqd + 1, &read_fds, NULL, NULL, &tv) == -1) {
perror("FAIL - could not select");
exit(EXIT_FAILURE);
return;
} else {
if (FD_ISSET(mqd, &read_fds))
receive_message(mqd, 0);
@@ -142,7 +159,7 @@ void receive_poll(mqd_t mqd)
if (poll(fds, 1, timeout * 1000) == -1) {
perror("FAIL - could not poll");
exit(EXIT_FAILURE);
return;
} else {
if (fds[0].revents & POLLIN)
receive_message(mqd, 0);
@@ -154,7 +171,7 @@ void receive_epoll(mqd_t mqd)
int epfd = epoll_create(1);
if (epfd == -1) {
perror("FAIL - could not create epoll");
exit(EXIT_FAILURE);
return;
}
struct epoll_event ev, rev[1];
@@ -162,12 +179,12 @@ void receive_epoll(mqd_t mqd)
ev.data.fd = mqd;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, mqd, &ev) == -1) {
perror("FAIL - could not add mqd to epoll");
exit(EXIT_FAILURE);
return;
}
if (epoll_wait(epfd, rev, 1, timeout * 1000) == -1) {
perror("FAIL - could not epoll_wait");
exit(EXIT_FAILURE);
return;
} else {
if (rev[0].data.fd == mqd && rev[0].events & EPOLLIN)
receive_message(mqd, 0);
@@ -198,17 +215,17 @@ void receive(enum notify_options notify, mqd_t mqd)
int main(int argc, char *argv[])
{
int opt = 0;
enum notify_options notify = DO_NOT_NOTIFY;
mqd_t mqd;
char *client = NULL;
int uid;
int pipefd;
struct mq_attr attr;
attr.mq_flags = 0;
attr.mq_maxmsg = 10;
attr.mq_msgsize = BUF_SIZE;
attr.mq_curmsgs = 0;
while ((opt = getopt(argc, argv, "n:k:c:u:t:")) != -1) {
while ((opt = getopt(argc, argv, "n:k:c:u:t:p:")) != -1) {
switch (opt) {
case 'n':
if (strcmp(optarg, "mq_notify") == 0)
@@ -258,6 +275,9 @@ int main(int argc, char *argv[])
case 't':
timeout = atoi(optarg);
break;
case 'p':
pipepath = optarg;
break;
default:
usage(argv[0], "Unrecognized option\n");
}
@@ -269,11 +289,24 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
if (notify == MQ_NOTIFY) {
if (mkfifo(pipepath, 0666) == -1) {
perror("FAIL - could not mkfifo");
goto nopipeout;
}
pipefd = open_read_pipe(pipepath);
if (pipefd == -1) {
fprintf(stderr, "FAIL - couldn't open pipe\n");
goto out;
}
}
/* exec the client */
int pid = fork();
if (pid == -1) {
perror("FAIL - could not fork");
exit(EXIT_FAILURE);
goto out;
} else if (!pid) {
if (client == NULL) {
usage(argv[0], "client not specified");
@@ -282,25 +315,30 @@ int main(int argc, char *argv[])
* in case the client will be manually executed
*/
}
execl(client, client, queuename, NULL);
printf("FAIL %d - execlp %s %s- %m\n", getuid(), client, queuename);
if (notify == MQ_NOTIFY) {
char strpipefd[12];
sprintf(strpipefd, "%d", pipefd);
execl(client, client, queuename, strpipefd, NULL);
printf("FAIL %d - execlp %s %s %s- %m\n", getuid(), client, queuename, strpipefd);
} else {
execl(client, client, queuename, NULL);
printf("FAIL %d - execlp %s %s- %m\n", getuid(), client, queuename);
}
exit(EXIT_FAILURE);
}
receive(notify, mqd);
/* when the notification fails because of timeout, it ends up here
* so, clean up the mqueue
* so, clean up the mqueue and exit_failure
*/
if (mq_close(mqd) == (mqd_t) -1) {
out:
if (notify == MQ_NOTIFY && unlink(pipepath) == -1)
perror("FAIL - could not remove pipe");
nopipeout:
if (mq_close(mqd) == (mqd_t) -1)
perror("FAIL - could not close mq");
exit(EXIT_FAILURE);
}
if (mq_unlink(queuename) == (mqd_t) -1) {
if (mq_unlink(queuename) == (mqd_t) -1)
perror("FAIL - could unlink mq");
exit(EXIT_FAILURE);
}
return 0;
return EXIT_FAILURE;
}

View File

@@ -1,16 +1,27 @@
#define _GNU_SOURCE
#include <mqueue.h>
#include <stdlib.h>
#include "posix_mq.h"
#include "pipe_helper.h"
int main(int argc, char * argv[])
{
mqd_t mqd;
char *queuename = QNAME;
int pipefd;
if (argc > 1) {
queuename = argv[1];
}
if (argc > 2) {
pipefd = atoi(argv[2]);
if (read_from_pipe(pipefd) == -1) { // wait for receiver to mq_notify
fprintf(stderr, "FAIL - could not read from pipe\n");
return 1;
}
}
mqd = mq_open(queuename, O_WRONLY);
if (mqd == (mqd_t) -1) {
perror("FAIL sender - could not open mq");

View File

@@ -23,7 +23,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/limits.h>
#include "userns.h"
#include "pipe_helper.h"
static void usage(char *pname)
{

View File

@@ -6,7 +6,7 @@
#include <fcntl.h>
#include <unistd.h>
#include "userns.h"
#include "pipe_helper.h"
int main(int argc, char *argv[])
{

View File

@@ -15,7 +15,7 @@ import re
from apparmor.common import AppArmorBug, AppArmorException
from apparmor.regex import RE_PROFILE_MOUNT, RE_PROFILE_PATH_OR_VAR, strip_parenthesis
from apparmor.regex import RE_PROFILE_MOUNT, strip_parenthesis
from apparmor.rule import AARE
from apparmor.rule import BaseRule, BaseRuleset, parse_modifiers, logprof_value_or_all, check_and_split_list
@@ -34,7 +34,7 @@ valid_fs = [
'securityfs', 'sockfs', 'bpf', 'npipefs', 'ramfs', 'hugetlbfs', 'devpts', 'ext3', 'ext2', 'ext4', 'squashfs',
'vfat', 'ecryptfs', 'fuseblk', 'fuse', 'fusectl', 'efivarfs', 'mqueue', 'store', 'autofs', 'binfmt_misc', 'overlay',
'none', 'bdev', 'proc', 'pipefs', 'pstore', 'btrfs', 'xfs', '9p', 'resctrl', 'zfs', 'iso9660', 'udf', 'ntfs3',
'nfs', 'cifs',
'nfs', 'cifs', 'overlayfs', 'aufs', 'rpc_pipefs', 'msdos', 'nfs4',
]
flags_keywords = [
@@ -72,9 +72,13 @@ mount_condition_pattern = rf'({fs_type_pattern})?\s*({option_pattern})?'
# - A filesystem : sysfs (sudo mount -t tmpfs tmpfs /tmp/bar)
# - Any label : mntlabel (sudo mount -t tmpfs mntlabel /tmp/bar)
# Thus we cannot use directly RE_PROFILE_PATH_OR_VAR
# Destination can also be
# - A path : /foo
# - A globbed Path : **
source_fileglob_pattern = r'(\s*(?P<source_file>([/{]\S*|"[/{][^"]*"|@{\S+}\S*|"@{\S+}[^"]*")|\w+))'
dest_fileglob_pattern = r'(\s*' + RE_PROFILE_PATH_OR_VAR % 'dest_file' + r')'
glob_pattern = r'(\s*(?P<%s>(([/{]|\*\*)\S*|"([/{]|\*\*)[^"]*"|@{\S+}\S*|"@{\S+}[^"]*")|\w+))'
source_fileglob_pattern = glob_pattern % 'source_file'
dest_fileglob_pattern = glob_pattern % 'dest_file'
RE_MOUNT_DETAILS = re.compile(r'^\s*' + mount_condition_pattern + rf'(\s+{source_fileglob_pattern})?' + rf'(\s+->\s+{dest_fileglob_pattern})?\s*' + r'$')
RE_UMOUNT_DETAILS = re.compile(r'^\s*' + mount_condition_pattern + rf'(\s+{dest_fileglob_pattern})?\s*' + r'$')
@@ -142,7 +146,7 @@ class MountRule(BaseRule):
if self.operation == 'mount' and not self.all_source and not self.all_options and flags_forbidden_with_source & self.options != set():
raise AppArmorException(f'Operation {flags_forbidden_with_source & self.options} cannot have a source. Source = {self.source}')
self.dest, self.all_dest = self._aare_or_all(dest, 'dest', is_path=True, log_event=log_event)
self.dest, self.all_dest = self._aare_or_all(dest, 'dest', is_path=False, log_event=log_event)
self.can_glob = not self.all_source and not self.all_dest and not self.all_options

View File

@@ -29,6 +29,8 @@ class MountTestParse(AATest):
tests = (
# Rule Operation Filesystem Options Source Destination Audit Deny Allow Comment
('mount -> **,', MountRule('mount', MountRule.ALL, MountRule.ALL, MountRule.ALL, '**', False, False, False, '' )),
('mount options=(rw, shared) -> **,', MountRule('mount', MountRule.ALL, ('=', ('rw', 'shared')), MountRule.ALL, '**', False, False, False, '' )),
('mount fstype=bpf options=rw bpf -> /sys/fs/bpf/,', MountRule('mount', ('=', ('bpf')), ('=', ('rw')), 'bpf', '/sys/fs/bpf/', False, False, False, '' )),
('mount fstype=fuse.obex* options=rw bpf -> /sys/fs/bpf/,', MountRule('mount', ('=', ('fuse.obex*')), ('=', ('rw')), 'bpf', '/sys/fs/bpf/', False, False, False, '' )),
('mount fstype=fuse.* options=rw bpf -> /sys/fs/bpf/,', MountRule('mount', ('=', ('fuse.*')), ('=', ('rw')), 'bpf', '/sys/fs/bpf/', False, False, False, '' )),

View File

@@ -492,6 +492,7 @@ syntax_failure = (
'network/network_ok_41.sd',
'network/network_ok_42.sd',
'network/network_ok_43.sd',
'network/network_ok_44.sd',
'network/perms/ok_accept_1.sd',
'network/perms/ok_accept_2.sd',
'network/perms/ok_attr_1.sd',