[PATCH 0/3] Apparmor: Add profiles for hypervisor daemons

This series is a first attempt at creating apparmor profiles for the modular daemons. It introduces profiles for virt{lxc,qemu,xen}d, which AFAIK are the only hypervisors supported by apparmor. The profiles are copies of the libvirtd profile, with all the non hypervisor-specific rules removed. E.g. qemu related rules removed from the virtxend profile and vice versa. Likely more rules could be trimmed from the xen and lxc profiles. I'll need to investigate how the apparmor tools can help identify such rules. So far things look okay with apparmor and modular daemons. One issue I have yet to resolve is interaction between dnsmasq and libvirt_leaseshelper. Trying to start e.g. the default network results in the following apparmor denial type=AVC msg=audit(1623791662.885:655): apparmor="DENIED" operation="exec" profile="/usr/sbin/dnsmasq" name="/usr/lib/libvirt_leaseshelper" pid=8154 comm="sh" requested_mask="x" denied_mask="x" fsuid=0 ouid=0 Perhaps some apparmor experts can make better sense of that error than me :-). It would be nice to avoid adjusting the dnsmasq profile, which is not in the libvirt project, if possible. I noticed a few more denial messages that I _think_ are unrelated to modular daemons, which also need further investigation type=AVC msg=audit(1623797296.856:593): apparmor="DENIED" operation="open" profile="virt-aa-helper" name="/etc/ssl/openssl.cnf" pid=6511 comm="virt-aa-helper" requested_mask="r" denied_mask="r" fsuid=0 ouid=0 type=AVC msg=audit(1623797296.856:594): apparmor="DENIED" operation="open" profile="virt-aa-helper" name="/etc/libnl/classid" pid=6511 comm="virt-aa-helper" requested_mask="r" denied_mask="r" fsuid=0 ouid=0 t type=AVC msg=audit(1623797297.732:623): apparmor="DENIED" operation="open" profile="libvirt-481c2d22-76d5-404b-a4b0-dc2069c7e19e" name="/etc/libnl/classid" pid=6539 comm="qemu-system-x86" requested_mask="r" denied_mask="r" fsuid=107 ouid=0 Jim Fehlig (3): Apparmor: Add profile for virtqemud Apparmor: Add profile for virtlxcd Apparmor: Add profile for virtxend src/security/apparmor/libvirt-lxc | 4 +- src/security/apparmor/libvirt-qemu | 6 + src/security/apparmor/meson.build | 3 + src/security/apparmor/usr.sbin.virtlxcd.in | 89 +++++++++++++ src/security/apparmor/usr.sbin.virtqemud.in | 135 ++++++++++++++++++++ src/security/apparmor/usr.sbin.virtxend.in | 78 +++++++++++ 6 files changed, 314 insertions(+), 1 deletion(-) create mode 100644 src/security/apparmor/usr.sbin.virtlxcd.in create mode 100644 src/security/apparmor/usr.sbin.virtqemud.in create mode 100644 src/security/apparmor/usr.sbin.virtxend.in -- 2.31.1

A new apparmor profile derived from the libvirtd profile, with non-QEMU related rules removed. Adopt the libvirt-qemu abstraction to work with the new profile. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/security/apparmor/libvirt-qemu | 6 + src/security/apparmor/meson.build | 1 + src/security/apparmor/usr.sbin.virtqemud.in | 135 ++++++++++++++++++++ 3 files changed, 142 insertions(+) diff --git a/src/security/apparmor/libvirt-qemu b/src/security/apparmor/libvirt-qemu index 85c9e61d6c..990bb0b2ba 100644 --- a/src/security/apparmor/libvirt-qemu +++ b/src/security/apparmor/libvirt-qemu @@ -16,9 +16,13 @@ ptrace (readby, tracedby) peer=libvirtd, ptrace (readby, tracedby) peer=/usr/sbin/libvirtd, + ptrace (readby, tracedby) peer=virtqemud, + ptrace (readby, tracedby) peer=/usr/sbin/virtqemud, signal (receive) peer=libvirtd, signal (receive) peer=/usr/sbin/libvirtd, + signal (receive) peer=virtqemud, + signal (receive) peer=/usr/sbin/virtqemud, /dev/kvm rw, /dev/net/tun rw, @@ -221,6 +225,8 @@ # allow connect with openGraphicsFD to work unix (send, receive) type=stream addr=none peer=(label=libvirtd), unix (send, receive) type=stream addr=none peer=(label=/usr/sbin/libvirtd), + unix (send, receive) type=stream addr=none peer=(label=virtqemud), + unix (send, receive) type=stream addr=none peer=(label=/usr/sbin/virtqemud), # for gathering information about available host resources /sys/devices/system/cpu/ r, diff --git a/src/security/apparmor/meson.build b/src/security/apparmor/meson.build index af43780211..56f308bf3a 100644 --- a/src/security/apparmor/meson.build +++ b/src/security/apparmor/meson.build @@ -1,6 +1,7 @@ apparmor_gen_profiles = [ 'usr.lib.libvirt.virt-aa-helper', 'usr.sbin.libvirtd', + 'usr.sbin.virtqemud', ] apparmor_gen_profiles_conf = configuration_data() diff --git a/src/security/apparmor/usr.sbin.virtqemud.in b/src/security/apparmor/usr.sbin.virtqemud.in new file mode 100644 index 0000000000..b986241c74 --- /dev/null +++ b/src/security/apparmor/usr.sbin.virtqemud.in @@ -0,0 +1,135 @@ +#include <tunables/global> +@{LIBVIRT}="libvirt" + +profile virtqemud @sbindir@/virtqemud flags=(attach_disconnected) { + #include <abstractions/base> + #include <abstractions/dbus> + + capability kill, + capability net_admin, + capability net_raw, + capability setgid, + capability sys_admin, + capability sys_module, + capability sys_ptrace, + capability sys_pacct, + capability sys_nice, + capability sys_chroot, + capability setuid, + capability dac_override, + capability dac_read_search, + capability fowner, + capability chown, + capability setpcap, + capability mknod, + capability fsetid, + capability audit_write, + capability ipc_lock, + capability sys_rawio, + capability bpf, + capability perfmon, + + # Needed for vfio + capability sys_resource, + + mount options=(rw,rslave) -> /, + mount options=(rw, nosuid) -> /{var/,}run/libvirt/qemu/*.dev/, + umount /{var/,}run/libvirt/qemu/*.dev/, + + # libvirt provides any mounts under /dev to qemu namespaces + mount options=(rw, move) /dev/ -> /{,var/}run/libvirt/qemu/*.dev/, + mount options=(rw, move) /dev/** -> /{,var/}run/libvirt/qemu/*{,/}, + mount options=(rw, move) /{,var/}run/libvirt/qemu/*.dev/ -> /dev/, + mount options=(rw, move) /{,var/}run/libvirt/qemu/*{,/} -> /dev/**, + + network inet stream, + network inet dgram, + network inet6 stream, + network inet6 dgram, + network netlink raw, + network packet dgram, + network packet raw, + + # for --p2p migrations + unix (send, receive) type=stream addr=none peer=(label=unconfined addr=none), + + ptrace (read,trace) peer=unconfined, + ptrace (read,trace) peer=@{profile_name}, + ptrace (read,trace) peer=dnsmasq, + ptrace (read,trace) peer=/usr/sbin/dnsmasq, + ptrace (read,trace) peer=libvirt-*, + + signal (send) peer=dnsmasq, + signal (send) peer=/usr/sbin/dnsmasq, + signal (read, send) peer=libvirt-*, + signal (send) set=("kill", "term") peer=unconfined, + + # For communication/control to qemu-bridge-helper + unix (send, receive) type=stream addr=none peer=(label=libvirtd//qemu_bridge_helper), + signal (send) set=("term") peer=libvirtd//qemu_bridge_helper, + + # allow connect with openGraphicsFD, direction reversed in newer versions + unix (send, receive) type=stream addr=none peer=(label=libvirt-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*), + # unconfined also required if guests run without security module + unix (send, receive) type=stream addr=none peer=(label=unconfined), + + # required if guests run unconfined seclabel type='none' but libvirtd is confined + signal (read, send) peer=unconfined, + + # Very lenient profile for libvirtd since we want to first focus on confining + # the guests. Guests will have a very restricted profile. + / r, + /** rwmkl, + + /bin/* PUx, + /sbin/* PUx, + /usr/bin/* PUx, + @sbindir@/virtlogd pix, + @sbindir@/* PUx, + /{usr/,}lib/udev/scsi_id PUx, + /usr/{lib,lib64,lib/qemu,libexec}/vhost-user-gpu PUx, + /usr/{lib,lib64,lib/qemu,libexec}/virtiofsd PUx, + + # Required by nwfilter_ebiptables_driver.c:ebiptablesWriteToTempFile() to + # read and run an ebtables script. + /var/lib/libvirt/virtd* ixr, + + # force the use of virt-aa-helper + audit deny /{usr/,}sbin/apparmor_parser rwxl, + audit deny /etc/apparmor.d/libvirt/** wxl, + audit deny /sys/kernel/security/apparmor/features rwxl, + audit deny /sys/kernel/security/apparmor/matching rwxl, + audit deny /sys/kernel/security/apparmor/.* rwxl, + /sys/kernel/security/apparmor/profiles r, + @libexecdir@/* PUxr, + @libexecdir@/libvirt_parthelper ix, + @libexecdir@/libvirt_iohelper ix, + /etc/libvirt/hooks/** rmix, + + # allow changing to our UUID-based named profiles + change_profile -> @{LIBVIRT}-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*, + + /usr/{lib,lib64,lib/qemu,libexec}/qemu-bridge-helper Cx -> qemu_bridge_helper, + # child profile for bridge helper process + profile qemu_bridge_helper { + #include <abstractions/base> + + capability setuid, + capability setgid, + capability setpcap, + capability net_admin, + + network inet stream, + + # For communication/control from libvirtd + unix (send, receive) type=stream addr=none peer=(label=libvirtd), + signal (receive) set=("term") peer=/usr/sbin/libvirtd, + signal (receive) set=("term") peer=libvirtd, + + /dev/net/tun rw, + /etc/qemu/** r, + owner @{PROC}/*/status r, + + /usr/{lib,lib64,lib/qemu,libexec}/qemu-bridge-helper rmix, + } +} -- 2.31.1

Hello, [I'm not subscribed to the libvirt list, please CC me in replies] Am Mittwoch, 16. Juni 2021, 05:41:02 CEST schrieb Jim Fehlig:
diff --git a/src/security/apparmor/libvirt-qemu b/src/security/apparmor/libvirt-qemu index 85c9e61d6c..990bb0b2ba 100644 --- a/src/security/apparmor/libvirt-qemu +++ b/src/security/apparmor/libvirt-qemu [...]
You only need to add
+ ptrace (readby, tracedby) peer=virtqemud,
The following rule
+ ptrace (readby, tracedby) peer=/usr/sbin/virtqemud,
is superfluous and can be removed. Technical background: the reason why there are rules for libvirtd and /usr/sbin/libvirtd is backwards compability to the old /usr/sbin/libvirtd { profile before it became profile libvirtd /usr/sbin/libvirtd { You don't need that for a new profile that is profile virtqumud /usr/sbin/virtquemud { from the beginning. This also applies to your 2/3 and 3/3 patches.
signal (receive) peer=libvirtd, signal (receive) peer=/usr/sbin/libvirtd, + signal (receive) peer=virtqemud, + signal (receive) peer=/usr/sbin/virtqemud,
Same here - the rule with peer=/usr/sbin/virtquemud is superfluous. [...]
+ unix (send, receive) type=stream addr=none peer=(label=virtqemud), + unix (send, receive) type=stream addr=none peer=(label=/usr/sbin/ virtqemud),
And again ;-) [...]
diff --git a/src/security/apparmor/usr.sbin.virtqemud.in b/src/security/apparmor/usr.sbin.virtqemud.in new file mode 100644 index 0000000000..b986241c74 --- /dev/null +++ b/src/security/apparmor/usr.sbin.virtqemud.in @@ -0,0 +1,135 @@ +#include <tunables/global> +@{LIBVIRT}="libvirt" + +profile virtqemud @sbindir@/virtqemud flags=(attach_disconnected) { + #include <abstractions/base> + #include <abstractions/dbus> + + capability kill, + capability net_admin, + capability net_raw, + capability setgid, + capability sys_admin, + capability sys_module, + capability sys_ptrace, + capability sys_pacct, + capability sys_nice, + capability sys_chroot, + capability setuid, + capability dac_override, + capability dac_read_search, + capability fowner, + capability chown, + capability setpcap, + capability mknod, + capability fsetid, + capability audit_write, + capability ipc_lock, + capability sys_rawio, + capability bpf, + capability perfmon, + + # Needed for vfio + capability sys_resource, [...]
Just wondering - do the new profiles (in all 3 patches) reallly need all the capabilities and the other broad rules? (See my 0/3 reply how to find out ;-) Regards, Christian Boltz -- Let's hope the best and praise the Gecko! [Hans-Peter Jansen in opensuse-factory]

On 6/16/21 11:23 AM, Christian Boltz wrote:
Hello,
[I'm not subscribed to the libvirt list, please CC me in replies]
Am Mittwoch, 16. Juni 2021, 05:41:02 CEST schrieb Jim Fehlig:
diff --git a/src/security/apparmor/libvirt-qemu b/src/security/apparmor/libvirt-qemu index 85c9e61d6c..990bb0b2ba 100644 --- a/src/security/apparmor/libvirt-qemu +++ b/src/security/apparmor/libvirt-qemu [...]
You only need to add
+ ptrace (readby, tracedby) peer=virtqemud,
The following rule
+ ptrace (readby, tracedby) peer=/usr/sbin/virtqemud,
is superfluous and can be removed.
Technical background: the reason why there are rules for libvirtd and /usr/sbin/libvirtd is backwards compability to the old /usr/sbin/libvirtd { profile before it became profile libvirtd /usr/sbin/libvirtd {
You don't need that for a new profile that is profile virtqumud /usr/sbin/virtquemud { from the beginning.
Understood.
This also applies to your 2/3 and 3/3 patches.
Will fix in V2.
signal (receive) peer=libvirtd, signal (receive) peer=/usr/sbin/libvirtd, + signal (receive) peer=virtqemud, + signal (receive) peer=/usr/sbin/virtqemud,
Same here - the rule with peer=/usr/sbin/virtquemud is superfluous.
[...]
+ unix (send, receive) type=stream addr=none peer=(label=virtqemud), + unix (send, receive) type=stream addr=none peer=(label=/usr/sbin/ virtqemud),
And again ;-)
[...]
diff --git a/src/security/apparmor/usr.sbin.virtqemud.in b/src/security/apparmor/usr.sbin.virtqemud.in new file mode 100644 index 0000000000..b986241c74 --- /dev/null +++ b/src/security/apparmor/usr.sbin.virtqemud.in @@ -0,0 +1,135 @@ +#include <tunables/global> +@{LIBVIRT}="libvirt" + +profile virtqemud @sbindir@/virtqemud flags=(attach_disconnected) { + #include <abstractions/base> + #include <abstractions/dbus> + + capability kill, + capability net_admin, + capability net_raw, + capability setgid, + capability sys_admin, + capability sys_module, + capability sys_ptrace, + capability sys_pacct, + capability sys_nice, + capability sys_chroot, + capability setuid, + capability dac_override, + capability dac_read_search, + capability fowner, + capability chown, + capability setpcap, + capability mknod, + capability fsetid, + capability audit_write, + capability ipc_lock, + capability sys_rawio, + capability bpf, + capability perfmon, + + # Needed for vfio + capability sys_resource, [...]
Just wondering - do the new profiles (in all 3 patches) reallly need all the capabilities and the other broad rules?
I'll try to figure that out before posting V2
(See my 0/3 reply how to find out ;-)
... using your tips! Regards, Jim

A new apparmor profile derived from the libvirtd profile, with non-LXC related rules removed. Adopt the libvirt-lxc abstraction to work with the new profile. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/security/apparmor/libvirt-lxc | 4 +- src/security/apparmor/meson.build | 1 + src/security/apparmor/usr.sbin.virtlxcd.in | 89 ++++++++++++++++++++++ 3 files changed, 93 insertions(+), 1 deletion(-) diff --git a/src/security/apparmor/libvirt-lxc b/src/security/apparmor/libvirt-lxc index 0c8b812743..331f43fbbc 100644 --- a/src/security/apparmor/libvirt-lxc +++ b/src/security/apparmor/libvirt-lxc @@ -1,8 +1,10 @@ #include <abstractions/base> - # Allow receiving signals from libvirtd + # Allow receiving signals from libvirtd and virtlxcd signal (receive) peer=libvirtd, signal (receive) peer=/usr/sbin/libvirtd, + signal (receive) peer=virtlxcd, + signal (receive) peer=/usr/sbin/virtlxcd, umount, diff --git a/src/security/apparmor/meson.build b/src/security/apparmor/meson.build index 56f308bf3a..64db8fdde6 100644 --- a/src/security/apparmor/meson.build +++ b/src/security/apparmor/meson.build @@ -1,6 +1,7 @@ apparmor_gen_profiles = [ 'usr.lib.libvirt.virt-aa-helper', 'usr.sbin.libvirtd', + 'usr.sbin.virtlxcd', 'usr.sbin.virtqemud', ] diff --git a/src/security/apparmor/usr.sbin.virtlxcd.in b/src/security/apparmor/usr.sbin.virtlxcd.in new file mode 100644 index 0000000000..73a87ca37a --- /dev/null +++ b/src/security/apparmor/usr.sbin.virtlxcd.in @@ -0,0 +1,89 @@ +#include <tunables/global> +@{LIBVIRT}="libvirt" + +profile virtlxcd @sbindir@/virtlxcd flags=(attach_disconnected) { + #include <abstractions/base> + #include <abstractions/dbus> + + capability kill, + capability net_admin, + capability net_raw, + capability setgid, + capability sys_admin, + capability sys_module, + capability sys_ptrace, + capability sys_pacct, + capability sys_nice, + capability sys_chroot, + capability setuid, + capability dac_override, + capability dac_read_search, + capability fowner, + capability chown, + capability setpcap, + capability mknod, + capability fsetid, + capability audit_write, + capability ipc_lock, + capability sys_rawio, + capability bpf, + capability perfmon, + + mount options=(rw,rslave) -> /, + + network inet stream, + network inet dgram, + network inet6 stream, + network inet6 dgram, + network netlink raw, + network packet dgram, + network packet raw, + + ptrace (read,trace) peer=unconfined, + ptrace (read,trace) peer=@{profile_name}, + ptrace (read,trace) peer=dnsmasq, + ptrace (read,trace) peer=/usr/sbin/dnsmasq, + ptrace (read,trace) peer=libvirt-*, + + signal (send) peer=dnsmasq, + signal (send) peer=/usr/sbin/dnsmasq, + signal (read, send) peer=libvirt-*, + signal (send) set=("kill", "term") peer=unconfined, + + # unconfined also required if guests run without security module + unix (send, receive) type=stream addr=none peer=(label=unconfined), + + # required if guests run unconfined seclabel type='none' but libvirtd is confined + signal (read, send) peer=unconfined, + + # Very lenient profile for libvirtd since we want to first focus on confining + # the guests. Guests will have a very restricted profile. + / r, + /** rwmkl, + + /bin/* PUx, + /sbin/* PUx, + /usr/bin/* PUx, + @sbindir@/virtlogd pix, + @sbindir@/* PUx, + /{usr/,}lib/udev/scsi_id PUx, + + # Required by nwfilter_ebiptables_driver.c:ebiptablesWriteToTempFile() to + # read and run an ebtables script. + /var/lib/libvirt/virtd* ixr, + + # force the use of virt-aa-helper + audit deny /{usr/,}sbin/apparmor_parser rwxl, + audit deny /etc/apparmor.d/libvirt/** wxl, + audit deny /sys/kernel/security/apparmor/features rwxl, + audit deny /sys/kernel/security/apparmor/matching rwxl, + audit deny /sys/kernel/security/apparmor/.* rwxl, + /sys/kernel/security/apparmor/profiles r, + @libexecdir@/* PUxr, + @libexecdir@/libvirt_parthelper ix, + @libexecdir@/libvirt_iohelper ix, + /etc/libvirt/hooks/** rmix, + + # allow changing to our UUID-based named profiles + change_profile -> @{LIBVIRT}-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*-[0-9a-f]*, +} -- 2.31.1

A new apparmor profile derived from the libvirtd profile, with non-Xen related rules removed. Signed-off-by: Jim Fehlig <jfehlig@suse.com> --- src/security/apparmor/meson.build | 1 + src/security/apparmor/usr.sbin.virtxend.in | 78 ++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/src/security/apparmor/meson.build b/src/security/apparmor/meson.build index 64db8fdde6..aca0c46881 100644 --- a/src/security/apparmor/meson.build +++ b/src/security/apparmor/meson.build @@ -3,6 +3,7 @@ apparmor_gen_profiles = [ 'usr.sbin.libvirtd', 'usr.sbin.virtlxcd', 'usr.sbin.virtqemud', + 'usr.sbin.virtxend', ] apparmor_gen_profiles_conf = configuration_data() diff --git a/src/security/apparmor/usr.sbin.virtxend.in b/src/security/apparmor/usr.sbin.virtxend.in new file mode 100644 index 0000000000..9472d99afb --- /dev/null +++ b/src/security/apparmor/usr.sbin.virtxend.in @@ -0,0 +1,78 @@ +#include <tunables/global> + +profile virtxend @sbindir@/virtxend flags=(attach_disconnected) { + #include <abstractions/base> + #include <abstractions/dbus> + + capability kill, + capability net_admin, + capability net_raw, + capability setgid, + capability sys_admin, + capability sys_module, + capability sys_ptrace, + capability sys_pacct, + capability sys_nice, + capability sys_chroot, + capability setuid, + capability dac_override, + capability dac_read_search, + capability fowner, + capability chown, + capability setpcap, + capability mknod, + capability fsetid, + capability audit_write, + capability ipc_lock, + capability sys_rawio, + capability bpf, + capability perfmon, + + network inet stream, + network inet dgram, + network inet6 stream, + network inet6 dgram, + network netlink raw, + network packet dgram, + network packet raw, + + # for --p2p migrations + unix (send, receive) type=stream addr=none peer=(label=unconfined addr=none), + + ptrace (read,trace) peer=unconfined, + ptrace (read,trace) peer=dnsmasq, + ptrace (read,trace) peer=/usr/sbin/dnsmasq, + + signal (send) peer=dnsmasq, + signal (send) peer=/usr/sbin/dnsmasq, + signal (send) set=("kill", "term") peer=unconfined, + + # Very lenient profile for libvirtd since we want to first focus on confining + # the guests. Guests will have a very restricted profile. + / r, + /** rwmkl, + + /bin/* PUx, + /sbin/* PUx, + /usr/bin/* PUx, + @sbindir@/virtlogd pix, + @sbindir@/* PUx, + /{usr/,}lib/udev/scsi_id PUx, + /usr/{lib,lib64}/xen-common/bin/xen-toolstack PUx, + /usr/{lib,lib64}/xen/bin/* Ux, + /usr/{lib,libexec}/xen-*/bin/libxl-save-helper PUx, + /usr/{lib,libexec}/xen-*/bin/pygrub PUx, + + # force the use of virt-aa-helper + audit deny /{usr/,}sbin/apparmor_parser rwxl, + audit deny /etc/apparmor.d/libvirt/** wxl, + audit deny /sys/kernel/security/apparmor/features rwxl, + audit deny /sys/kernel/security/apparmor/matching rwxl, + audit deny /sys/kernel/security/apparmor/.* rwxl, + /sys/kernel/security/apparmor/profiles r, + @libexecdir@/* PUxr, + @libexecdir@/libvirt_parthelper ix, + @libexecdir@/libvirt_iohelper ix, + /etc/libvirt/hooks/** rmix, + /etc/xen/scripts/** rmix, +} -- 2.31.1

Hello, [I'm not subscribed to the libvirt list, please CC me in replies] Am Mittwoch, 16. Juni 2021, 05:41:01 CEST schrieb Jim Fehlig:
This series is a first attempt at creating apparmor profiles for the modular daemons. It introduces profiles for virt{lxc,qemu,xen}d, which AFAIK are the only hypervisors supported by apparmor. The profiles are copies of the libvirtd profile, with all the non hypervisor-specific rules removed. E.g. qemu related rules removed from the virtxend profile and vice versa. Likely more rules could be trimmed from the xen and lxc profiles. I'll need to investigate how the apparmor tools can help identify such rules.
There are two ways to do this: - prefix the rules with "audit" (for example "audit capability sys_admin,"), reload and use the profile, and check your audit.log for AUDIT events mentioning it. (Note: the aa-* tools won't help you with AUDIT events.) - remove the rules in question and optionally set the profile to complain mode, then reload and use the profile. Afterwards, check the audit.log or use aa-logprof. Note: aa-logprof doesn't support adding unix, mount and pivot_root rules yet, so you'll have to add those manually.
So far things look okay with apparmor and modular daemons. One issue I have yet to resolve is interaction between dnsmasq and libvirt_leaseshelper. Trying to start e.g. the default network results in the following apparmor denial
type=AVC msg=audit(1623791662.885:655): apparmor="DENIED" operation="exec" profile="/usr/sbin/dnsmasq" name="/usr/lib/libvirt_leaseshelper" pid=8154 comm="sh" requested_mask="x" denied_mask="x" fsuid=0 ouid=0
The dnsmasq profile already has # libvirt lease helper /usr/lib{,64}/libvirt/libvirt_leaseshelper Cx -> libvirt_leaseshelper, /usr/libexec/libvirt_leaseshelper Cx -> libvirt_leaseshelper, /usr/lib/libvirt_leaseshelper looks like yet another path. Did libvirt_leaseshelp move? (I still have it as /usr/lib64/libvirt/libvirt_leaseshelper on openSUSE Tumbleweed.) Technically, the dnsmasq profile will need two additions for the new path: - a Cx rule in the main profile - a m rule inside the libvirt_leaseshelper child profile
Perhaps some apparmor experts can make better sense of that error than me :-). It would be nice to avoid adjusting the dnsmasq profile, which is not in the libvirt project, if possible.
This will be a change to the dnsmasq profile, but that's not a real problem.
I noticed a few more denial messages that I _think_ are unrelated to modular daemons, which also need further investigation
type=AVC msg=audit(1623797296.856:593): apparmor="DENIED" operation="open" profile="virt-aa-helper" name="/etc/ssl/openssl.cnf" pid=6511 comm="virt-aa-helper" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
include <abstractions/openssl>
type=AVC msg=audit(1623797296.856:594): apparmor="DENIED" operation="open" profile="virt-aa-helper" name="/etc/libnl/classid" pid=6511 comm="virt-aa-helper" requested_mask="r" denied_mask="r" fsuid=0 ouid=0 type=AVC msg=audit(1623797297.732:623): apparmor="DENIED" operation="open" profile="libvirt-481c2d22-76d5-404b-a4b0-dc2069c7e19e" name="/etc/libnl/classid" pid=6539 comm="qemu-system-x86" requested_mask="r" denied_mask="r" fsuid=107 ouid=0
I don't know what libnl is/does, but allowing read permissions to this file doesn't look too critical. BTW: The dnsmasq libvirt_leaseshelper child profile and abstractions/nameservice have /etc/libnl-3/classid r, Note the slightly different path, git blame says it's a Debian path added to the profile in 2016. (I don't remember any denial for /etc/libnl/classid on openSUSE, therefore I'm not sure if we should add that path to the upstream dnsmasq profile and/or abstractions/nameservice. Feedback welcome ;-) ) Also note that abstractions/nameservice allows a lot, so even if the path would match, please don't add it just because you need read permissions for a single file. Regards, Christian Boltz -- <cboltz> I wonder if I should add "sponsored by Aspirin" ;-) <jjohansen> you could have a nice little side business if Asprin was sponsoring all the bugs you find [from #apparmor]

On 6/16/21 11:21 AM, Christian Boltz wrote:
Hello,
[I'm not subscribed to the libvirt list, please CC me in replies]
Am Mittwoch, 16. Juni 2021, 05:41:01 CEST schrieb Jim Fehlig:
This series is a first attempt at creating apparmor profiles for the modular daemons. It introduces profiles for virt{lxc,qemu,xen}d, which AFAIK are the only hypervisors supported by apparmor. The profiles are copies of the libvirtd profile, with all the non hypervisor-specific rules removed. E.g. qemu related rules removed from the virtxend profile and vice versa. Likely more rules could be trimmed from the xen and lxc profiles. I'll need to investigate how the apparmor tools can help identify such rules.
There are two ways to do this: - prefix the rules with "audit" (for example "audit capability sys_admin,"), reload and use the profile, and check your audit.log for AUDIT events mentioning it. (Note: the aa-* tools won't help you with AUDIT events.) - remove the rules in question and optionally set the profile to complain mode, then reload and use the profile. Afterwards, check the audit.log or use aa-logprof. Note: aa-logprof doesn't support adding unix, mount and pivot_root rules yet, so you'll have to add those manually.
Thanks for the tips!
So far things look okay with apparmor and modular daemons. One issue I have yet to resolve is interaction between dnsmasq and libvirt_leaseshelper. Trying to start e.g. the default network results in the following apparmor denial
type=AVC msg=audit(1623791662.885:655): apparmor="DENIED" operation="exec" profile="/usr/sbin/dnsmasq" name="/usr/lib/libvirt_leaseshelper" pid=8154 comm="sh" requested_mask="x" denied_mask="x" fsuid=0 ouid=0
The dnsmasq profile already has
# libvirt lease helper /usr/lib{,64}/libvirt/libvirt_leaseshelper Cx -> libvirt_leaseshelper, /usr/libexec/libvirt_leaseshelper Cx -> libvirt_leaseshelper,
/usr/lib/libvirt_leaseshelper looks like yet another path. Did libvirt_leaseshelp move? (I still have it as /usr/lib64/libvirt/libvirt_leaseshelper on openSUSE Tumbleweed.)
Facepalm!! I didn't notice the "incorrect" path! I got distracted thinking it was an issue with virtnetworkd permissions. And no, the path has not changed. The path in my snippet is from a test system where I was experimenting with the openSUSE libexecdir change and mistakenly left the meson configuration with --libexecdir=/usr/lib :-(. Do you think it still makes sense to add a /usr/lib{,64}/libvit_leaseshelper rule? The only complaint thus far is from a developer with a misconfigured system :-).
Technically, the dnsmasq profile will need two additions for the new path: - a Cx rule in the main profile - a m rule inside the libvirt_leaseshelper child profile
Perhaps some apparmor experts can make better sense of that error than me :-). It would be nice to avoid adjusting the dnsmasq profile, which is not in the libvirt project, if possible.
This will be a change to the dnsmasq profile, but that's not a real problem.
I noticed a few more denial messages that I _think_ are unrelated to modular daemons, which also need further investigation
type=AVC msg=audit(1623797296.856:593): apparmor="DENIED" operation="open" profile="virt-aa-helper" name="/etc/ssl/openssl.cnf" pid=6511 comm="virt-aa-helper" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
include <abstractions/openssl>
type=AVC msg=audit(1623797296.856:594): apparmor="DENIED" operation="open" profile="virt-aa-helper" name="/etc/libnl/classid" pid=6511 comm="virt-aa-helper" requested_mask="r" denied_mask="r" fsuid=0 ouid=0 type=AVC msg=audit(1623797297.732:623): apparmor="DENIED" operation="open" profile="libvirt-481c2d22-76d5-404b-a4b0-dc2069c7e19e" name="/etc/libnl/classid" pid=6539 comm="qemu-system-x86" requested_mask="r" denied_mask="r" fsuid=107 ouid=0
I don't know what libnl is/does, but allowing read permissions to this file doesn't look too critical.
According to the package description The libnl suite is a collection of libraries providing APIs to netlink protocol based Linux kernel interfaces. Regardless, it is safe to say these are unrelated to modular daemons.
BTW: The dnsmasq libvirt_leaseshelper child profile and abstractions/nameservice have /etc/libnl-3/classid r,
Note the slightly different path, git blame says it's a Debian path added to the profile in 2016. (I don't remember any denial for /etc/libnl/classid on openSUSE, therefore I'm not sure if we should add that path to the upstream dnsmasq profile and/or abstractions/nameservice. Feedback welcome ;-) )
I only see the denial on SLE, and only from virt-aa-helper and per-VM profiles. No need to add it to the dnsmasq profile IMO.
Also note that abstractions/nameservice allows a lot, so even if the path would match, please don't add it just because you need read permissions for a single file.
Thanks again for the review and all the information! Regards, Jim
participants (2)
-
Christian Boltz
-
Jim Fehlig