diff --git a/Justfile b/Justfile index e434586c4..2c4c0e8d4 100644 --- a/Justfile +++ b/Justfile @@ -49,44 +49,44 @@ c := "--connect=qemu:///system" # VM prefix prefix := "aa-" -[doc('Show this help message')] +# Show this help message help: @just --list --unsorted @printf "\n%s\n" "See https://apparmor.pujol.io/development/ for more information." +# Build the go programs [group('build')] -[doc('Build the go programs')] build: @go build -o {{build}}/ ./cmd/aa-log @go build -o {{build}}/ ./cmd/prebuild +# Prebuild the profiles in enforced mode [group('build')] -[doc('Prebuild the profiles in enforced mode')] enforce: build @./{{build}}/prebuild --buildir {{build}} +# Prebuild the profiles in complain mode [group('build')] -[doc('Prebuild the profiles in complain mode')] complain: build ./{{build}}/prebuild --buildir {{build}} --complain +# Prebuild the profiles in FSP mode [group('build')] -[doc('Prebuild the profiles in FSP mode')] fsp: build @./{{build}}/prebuild --buildir {{build}} --full +# Prebuild the profiles in FSP mode (complain) [group('build')] -[doc('Prebuild the profiles in FSP mode (complain)')] fsp-complain: build @./{{build}}/prebuild --buildir {{build}} --complain --full +# Prebuild the profiles in FSP mode (debug) [group('build')] -[doc('Prebuild the profiles in FSP mode (debug)')] fsp-debug: build @./{{build}}/prebuild --buildir {{build}} --complain --full --debug +# Install prebuild profiles [group('install')] -[doc('Install prebuild profiles')] install: #!/usr/bin/env bash set -eu -o pipefail @@ -113,8 +113,8 @@ install: install -Dm0644 "$file" "{{destdir}}/usr/lib/systemd/user/$service.d/apparmor.conf" done +# Locally install prebuild profiles [group('install')] -[doc('Locally install prebuild profiles')] local +names: #!/usr/bin/env bash set -eu -o pipefail @@ -135,39 +135,39 @@ local +names: done; systemctl restart apparmor || sudo journalctl -xeu apparmor.service +# Prebuild, install, and load a dev profile [group('install')] -[doc('Prebuild, install, and load a dev profile')] dev name: go run ./cmd/prebuild --complain --file `find apparmor.d -iname {{name}}` sudo install -Dm644 {{build}}/apparmor.d/{{name}} /etc/apparmor.d/{{name}} sudo systemctl restart apparmor || sudo journalctl -xeu apparmor.service +# Build & install apparmor.d on Arch based systems [group('packages')] -[doc('Build & install apparmor.d on Arch based systems')] pkg: @makepkg --syncdeps --install --cleanbuild --force --noconfirm +# Build & install apparmor.d on Debian based systems [group('packages')] -[doc('Build & install apparmor.d on Debian based systems')] dpkg: @bash dists/build.sh dpkg @sudo dpkg -i {{pkgdest}}/{{pkgname}}_*.deb +# Build & install apparmor.d on OpenSUSE based systems [group('packages')] -[doc('Build & install apparmor.d on OpenSUSE based systems')] rpm: @bash dists/build.sh rpm @sudo rpm -ivh --force {{pkgdest}}/{{pkgname}}-*.rpm +# Run the unit tests [group('tests')] -[doc('Run the unit tests')] tests: @go test ./cmd/... -v -cover -coverprofile=coverage.out @go test ./pkg/... -v -cover -coverprofile=coverage.out @go tool cover -func=coverage.out +# Run the linters [group('linter')] -[doc('Run the linters')] lint: golangci-lint run packer fmt tests/packer/ @@ -177,34 +177,34 @@ lint: tests/packer/init.sh tests/packer/src/aa-update tests/packer/clean.sh \ debian/{{pkgname}}.postinst debian/{{pkgname}}.postrm +# Run style checks on the profiles [group('linter')] -[doc('Run style checks on the profiles')] check: @bash tests/check.sh +# Generate the man pages [group('docs')] -[doc('Generate the man pages')] man: @pandoc -t man -s -o share/man/man8/aa-log.8 share/man/man8/aa-log.md +# Build the documentation [group('docs')] -[doc('Build the documentation')] docs: @ENABLED_GIT_REVISION_DATE=false MKDOCS_OFFLINE=true mkdocs build --strict +# Serve the documentation [group('docs')] -[doc('Serve the documentation')] serve: @ENABLED_GIT_REVISION_DATE=false MKDOCS_OFFLINE=false mkdocs serve -[doc('Remove all build artifacts')] +# Remove all build artifacts clean: @rm -rf \ debian/.debhelper debian/debhelper* debian/*.debhelper debian/{{pkgname}} \ {{pkgdest}}/{{pkgname}}* {{build}} coverage.out +# Build the package in a clean OCI container [group('packages')] -[doc('Build the package in a clean OCI container')] package dist: #!/usr/bin/env bash set -eu -o pipefail @@ -219,8 +219,8 @@ package dist: fi bash dists/docker.sh $dist $version +# Build the VM image [group('vm')] -[doc('Build the VM image')] img dist flavor: (package dist) @mkdir -p {{base_dir}} packer build -force \ @@ -237,8 +237,8 @@ img dist flavor: (package dist) -var output_dir={{output_dir}} \ tests/packer/ +# Create the machine [group('vm')] -[doc('Create the machine')] create dist flavor: @cp -f {{base_dir}}/{{prefix}}{{dist}}-{{flavor}}.qcow2 {{vm}}/{{prefix}}{{dist}}-{{flavor}}.qcow2 @virt-install {{c}} \ @@ -257,53 +257,53 @@ create dist flavor: --sound model=ich9 \ --noautoconsole +# Start a machine [group('vm')] -[doc('Start a machine')] up dist flavor: @virsh {{c}} start {{prefix}}{{dist}}-{{flavor}} +# Stops the machine [group('vm')] -[doc('Stops the machine')] halt dist flavor: @virsh {{c}} shutdown {{prefix}}{{dist}}-{{flavor}} +# Reboot the machine [group('vm')] -[doc('Reboot the machine')] reboot dist flavor: @virsh {{c}} reboot {{prefix}}{{dist}}-{{flavor}} +# Destroy the machine [group('vm')] -[doc('Destroy the machine')] destroy dist flavor: @virsh {{c}} destroy {{prefix}}{{dist}}-{{flavor}} || true @virsh {{c}} undefine {{prefix}}{{dist}}-{{flavor}} --nvram @rm -fv {{vm}}/{{prefix}}{{dist}}-{{flavor}}.qcow2 +# Connect to the machine [group('vm')] -[doc('Connect to the machine')] ssh dist flavor: @ssh {{sshopt}} {{username}}@`just _get_ip {{dist}} {{flavor}}` +# Mount the shared directory on the machine [group('vm')] -[doc('Mount the shared directory on the machine')] mount dist flavor: @ssh {{sshopt}} {{username}}@`just _get_ip {{dist}} {{flavor}}` \ sh -c 'mount | grep 0a31bc478ef8e2461a4b1cc10a24cc4 || sudo mount 0a31bc478ef8e2461a4b1cc10a24cc4' +# Unmout the shared directory on the machine [group('vm')] -[doc('Unmout the shared directory on the machine')] umount dist flavor: @ssh {{sshopt}} {{username}}@`just _get_ip {{dist}} {{flavor}}` \ sh -c 'true; sudo umount /home/{{username}}/Projects/apparmor.d || true' +# List the machines [group('vm')] -[doc('List the machines')] list: @printf "{{BOLD}} %-4s %-22s %s{{NORMAL}}\n" "Id" "Distribution-Flavor" "State" @virsh {{c}} list --all | grep {{prefix}} | sed 's/{{prefix}}//g' +# List the VM images [group('vm')] -[doc('List the VM images')] images: #!/usr/bin/env bash set -eu -o pipefail @@ -320,8 +320,8 @@ images: } ' +# List the VM images that can be created [group('vm')] -[doc('List the VM images that can be created')] available: #!/usr/bin/env bash set -eu -o pipefail @@ -337,36 +337,36 @@ available: } ' +# Install dependencies for the integration tests [group('tests')] -[doc('Install dependencies for the integration tests')] init: @bash tests/requirements.sh +# Run the integration tests [group('tests')] -[doc('Run the integration tests')] integration name="": bats --recursive --timing --print-output-on-failure tests/integration/{{name}} +# Install dependencies for the integration tests (machine) [group('tests')] -[doc('Install dependencies for the integration tests (machine)')] tests-init dist flavor: @ssh {{sshopt}} {{username}}@`just _get_ip {{dist}} {{flavor}}` \ just --justfile /home/{{username}}/Projects/apparmor.d/Justfile init +# Synchronize the integration tests (machine) [group('tests')] -[doc('Synchronize the integration tests (machine)')] tests-sync dist flavor: @ssh {{sshopt}} {{username}}@`just _get_ip {{dist}} {{flavor}}` \ rsync -a --delete /home/{{username}}/Projects/apparmor.d/tests/ /home/{{username}}/Projects/tests/ +# Re-synchronize the integration tests (machine) [group('tests')] -[doc('Re-synchronize the integration tests (machine)')] tests-resync dist flavor: (mount dist flavor) \ (tests-sync dist flavor) \ (umount dist flavor) +# Run the integration tests (machine) [group('tests')] -[doc('Run the integration tests (machine)')] tests-run dist flavor name="": (tests-resync dist flavor) ssh {{sshopt}} {{username}}@`just _get_ip {{dist}} {{flavor}}` \ bats --recursive --pretty --timing --print-output-on-failure \ diff --git a/PKGBUILD b/PKGBUILD index dfbb46735..a68ba817d 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -3,8 +3,15 @@ # Warning: for development only, use https://aur.archlinux.org/packages/apparmor.d-git for production use. -pkgname=apparmor.d -pkgver=0.001 +pkgbase=apparmor.d +pkgname=( + apparmor.d + # apparmor.d.enforced + # apparmor.d.fsp apparmor.d.fsp.enforced + # apparmor.d.server apparmor.d.server.enforced + # apparmor.d.server.fsp apparmor.d.server.fsp.enforced +) +pkgver=0.0001 pkgrel=1 pkgdesc="Full set of apparmor profiles" arch=('x86_64' 'armv6h' 'armv7h' 'aarch64') @@ -12,10 +19,9 @@ url="https://github.com/roddhjav/apparmor.d" license=('GPL-2.0-only') depends=('apparmor>=4.1.0' 'apparmor<5.0.0') makedepends=('go' 'git' 'rsync' 'just') -conflicts=("$pkgname-git") pkgver() { - cd "$srcdir/$pkgname" + cd "$srcdir/$pkgbase" echo "0.$(git rev-list --count HEAD)" } @@ -24,17 +30,104 @@ prepare() { } build() { - cd "$srcdir/$pkgname" + cd "$srcdir/$pkgbase" export CGO_CPPFLAGS="${CPPFLAGS}" export CGO_CFLAGS="${CFLAGS}" export CGO_CXXFLAGS="${CXXFLAGS}" export CGO_LDFLAGS="${LDFLAGS}" + export GOPATH="${srcdir}" export GOFLAGS="-buildmode=pie -trimpath -ldflags=-linkmode=external -mod=readonly -modcacherw" export DISTRIBUTION=arch - just complain + local -A modes=( + # Mapping of modes to just build target. + [default]=complain + # [enforced]=enforce + # [fsp]=fsp-complain + # [fsp.enforced]=fsp + # [server]=server-complain + # [server.enforced]=server + # [server.fsp]=server-fsp-complain + # [server.fsp.enforced]=server-fsp + ) + for mode in "${!modes[@]}"; do + just build=".build/$mode" "${modes[$mode]}" + done } -package() { - cd "$srcdir/$pkgname" - just destdir="$pkgdir" install +_conflicts() { + local mode="$1" + local pattern=".$mode" + if [[ "$mode" == "default" ]]; then + pattern="" + else + echo "$pkgbase" + fi + for pkg in "${pkgname[@]}"; do + if [[ "$pkg" == "${pkgbase}${pattern}" ]]; then + continue + fi + echo "$pkg" + done +} + +_install() { + local mode="${1:?}" + cd "$srcdir/$pkgbase" + just build=".build/$mode" destdir="$pkgdir" install +} + +package_apparmor.d() { + mode=default + pkgdesc="$pkgdesc (complain mode)" + mapfile -t conflicts < <(_conflicts $mode) + _install $mode +} + +package_apparmor.d.enforced() { + mode=enforced + pkgdesc="$pkgdesc (enforced mode)" + mapfile -t conflicts < <(_conflicts $mode) + _install $mode +} + +package_apparmor.d.fsp() { + mode="fsp" + pkgdesc="$pkgdesc (FSP mode)" + mapfile -t conflicts < <(_conflicts $mode) + _install $mode +} + +package_apparmor.d.fsp.enforced() { + mode="fsp.enforced" + pkgdesc="$pkgdesc (FSP enforced mode)" + mapfile -t conflicts < <(_conflicts $mode) + _install $mode +} + +package_apparmor.d.server() { + mode="server" + pkgdesc="$pkgdesc (server complain mode)" + mapfile -t conflicts < <(_conflicts $mode) + _install $mode +} + +package_apparmor.d.server.enforced() { + mode="server.enforced" + pkgdesc="$pkgdesc (server enforced mode)" + mapfile -t conflicts < <(_conflicts $mode) + _install $mode +} + +package_apparmor.d.server.fsp() { + mode="server.fsp" + pkgdesc="$pkgdesc (server FSP complain mode)" + mapfile -t conflicts < <(_conflicts $mode) + _install $mode +} + +package_apparmor.d.server.fsp.enforced() { + mode="server.fsp.enforced" + pkgdesc="$pkgdesc (server FSP enforced mode)" + mapfile -t conflicts < <(_conflicts $mode) + _install $mode } diff --git a/apparmor.d/abstractions/app/chromium b/apparmor.d/abstractions/app/chromium index f08a096ca..725b57fca 100644 --- a/apparmor.d/abstractions/app/chromium +++ b/apparmor.d/abstractions/app/chromium @@ -30,6 +30,7 @@ include include include + include include include include @@ -44,7 +45,6 @@ include include include - include network inet dgram, network inet6 dgram, diff --git a/apparmor.d/abstractions/camera b/apparmor.d/abstractions/camera new file mode 100644 index 000000000..0f5cff363 --- /dev/null +++ b/apparmor.d/abstractions/camera @@ -0,0 +1,35 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allows access to all cameras + + abi , + + # Allow detection of cameras. Leaks plugged in USB device info + @{sys}/bus/usb/devices/ r, + @{sys}/devices/@{pci}/usb@{int}/**/busnum r, + @{sys}/devices/@{pci}/usb@{int}/**/devnum r, + @{sys}/devices/@{pci}/usb@{int}/**/idProduct r, + @{sys}/devices/@{pci}/usb@{int}/**/idVendor r, + @{sys}/devices/@{pci}/usb@{int}/**/interface r, + @{sys}/devices/@{pci}/usb@{int}/**/modalias r, + @{sys}/devices/@{pci}/usb@{int}/**/speed r, + + @{sys}/class/video4linux/ r, + @{sys}/devices/**/video4linux/** r, + @{sys}/devices/**/video4linux/video@{int}/ r, + @{sys}/devices/**/video4linux/video@{int}/uevent r, + + @{run}/udev/data/+usb:* r, # Identifies all USB devices + @{run}/udev/data/c81:@{int} r, # For video4linux + + # VideoCore cameras (shared device with VideoCore/EGL) + /dev/vchiq rw, + + # Access to video /dev devices + /dev/video@{int} rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/common/app b/apparmor.d/abstractions/common/app index 5072cadfd..d0b36188b 100644 --- a/apparmor.d/abstractions/common/app +++ b/apparmor.d/abstractions/common/app @@ -16,6 +16,7 @@ include include include + include include include include @@ -30,7 +31,6 @@ include include include - include dbus bus=accessibility, dbus bus=session, diff --git a/apparmor.d/abstractions/kde-strict b/apparmor.d/abstractions/kde-strict index a06a29da4..b448c542d 100644 --- a/apparmor.d/abstractions/kde-strict +++ b/apparmor.d/abstractions/kde-strict @@ -46,7 +46,7 @@ owner @{user_config_dirs}/kdeglobals r, owner @{user_config_dirs}/kwinrc r, owner @{user_config_dirs}/session/ rw, - owner @{user_config_dirs}/session/*_@{hex}_@{int}_@{int} rwlk, + owner @{user_config_dirs}/session/*_* rwlk, owner @{user_config_dirs}/session/#@{int} rw, owner @{user_config_dirs}/trashrc r, diff --git a/apparmor.d/abstractions/media-control b/apparmor.d/abstractions/media-control new file mode 100644 index 000000000..1cdcf66f2 --- /dev/null +++ b/apparmor.d/abstractions/media-control @@ -0,0 +1,20 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2021 Canonical Ltd +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allows access to media controller such as microphones, and video capture hardware. +# See: https://www.kernel.org/doc/Documentation/userspace-api/media/mediactl/media-controller-intro.rst + + abi , + + # Control of media devices + /dev/media@{int} rwk, + + # Access to V4L subnodes configuration + # See https://www.kernel.org/doc/html/v4.12/media/uapi/v4l/dev-subdev.html + /dev/v4l-subdev@{int} rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/tpm b/apparmor.d/abstractions/tpm new file mode 100644 index 000000000..ef7b30a2b --- /dev/null +++ b/apparmor.d/abstractions/tpm @@ -0,0 +1,16 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2016-2017 Canonical Ltd +# Copyright (C) 2021-2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Communication to the system TPM chip over /dev/tpm@{int} and kernel TPM +# resource manager /dev/tpmrm@{int} + + abi , + + /dev/tpm@{int} rw, + /dev/tpmrm@{int} rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/wine b/apparmor.d/abstractions/wine index 28d15cf76..145cd763a 100644 --- a/apparmor.d/abstractions/wine +++ b/apparmor.d/abstractions/wine @@ -9,9 +9,9 @@ owner @{user_share_dirs}/applications/wine/ rw, owner @{user_share_dirs}/applications/wine/**/ rw, - owner @{tmp}/.wine-@{uid}/ rw, - owner @{tmp}/.wine-@{uid}/** rwk, - owner @{tmp}/.wine-@{uid}/server-fd@{int2}-@{hex}/tmpmap-@{hex8} m, + owner @{att}/@{tmp}/.wine-@{uid}/ rw, + owner @{att}/@{tmp}/.wine-@{uid}/** rwk, + owner @{att}/@{tmp}/.wine-@{uid}/server-fd@{int2}-@{hex}/tmpmap-@{hex8} m, owner /dev/shm/wine-@{hex6}-fsync rw, owner /dev/shm/wine-@{hex6}@{h}-fsync rw, diff --git a/apparmor.d/groups/browsers/epiphany b/apparmor.d/groups/browsers/epiphany index 86b293e8d..45a32868e 100644 --- a/apparmor.d/groups/browsers/epiphany +++ b/apparmor.d/groups/browsers/epiphany @@ -12,6 +12,7 @@ profile epiphany @{exec_path} flags=(attach_disconnected) { include include include + include include include include @@ -61,8 +62,6 @@ profile epiphany @{exec_path} flags=(attach_disconnected) { deny @{user_share_dirs}/gvfs-metadata/* r, - /dev/video@{int} rw, - include if exists } diff --git a/apparmor.d/groups/cups/cups-backend-pdf b/apparmor.d/groups/cups/cups-backend-pdf index 6f658b064..21da6bf93 100644 --- a/apparmor.d/groups/cups/cups-backend-pdf +++ b/apparmor.d/groups/cups/cups-backend-pdf @@ -25,7 +25,7 @@ profile cups-backend-pdf @{exec_path} { @{sh_path} rix, @{bin}/cp rix, - @{bin}/gs rix, + @{bin}/gs{,.bin} rix, @{bin}/gsc rix, @{lib}/ghostscript/** mr, diff --git a/apparmor.d/groups/cups/cupsd b/apparmor.d/groups/cups/cupsd index acae9b7a1..642d7ef5c 100644 --- a/apparmor.d/groups/cups/cupsd +++ b/apparmor.d/groups/cups/cupsd @@ -62,7 +62,7 @@ profile cupsd @{exec_path} flags=(attach_disconnected) { @{bin}/chmod rix, @{bin}/cp rix, @{bin}/{,e}grep rix, - @{bin}/gs rix, + @{bin}/gs{,.bin} rix, @{bin}/gsc rix, @{bin}/hostname rix, @{bin}/ippfind rix, diff --git a/apparmor.d/groups/firewall/ufw-init b/apparmor.d/groups/firewall/ufw-init index aae80b87d..fcb9d8b6c 100644 --- a/apparmor.d/groups/firewall/ufw-init +++ b/apparmor.d/groups/firewall/ufw-init @@ -11,8 +11,10 @@ profile ufw-init @{exec_path} { include include + capability dac_override, capability dac_read_search, capability net_admin, + capability net_raw, network inet dgram, network inet raw, @@ -27,12 +29,29 @@ profile ufw-init @{exec_path} { @{sbin}/sysctl rCx -> sysctl, @{sbin}/xtables-legacy-multi rix, @{sbin}/xtables-nft-multi rix, + @{bin}/kmod rCx -> kmod, /etc/default/ufw r, /etc/ufw/* r, + @{run}/xtables.lock rwk, + @{PROC}/@{pid}/net/ip_tables_names r, - # @{PROC}/sys/net/ipv{4,6}/** rw, + @{PROC}/sys/kernel/modprobe r, + + profile kmod { + include + include + + capability sys_module, + + @{run}/xtables.lock r, + + @{sys}/module/compression r, + @{sys}/module/x_tables/initstate r, + + include if exists + } profile sysctl { include diff --git a/apparmor.d/groups/freedesktop/pipewire b/apparmor.d/groups/freedesktop/pipewire index 02a370cdc..04b08ecc4 100644 --- a/apparmor.d/groups/freedesktop/pipewire +++ b/apparmor.d/groups/freedesktop/pipewire @@ -14,8 +14,9 @@ profile pipewire @{exec_path} flags=(attach_disconnected) { include include include + include + include include - include capability sys_ptrace, @@ -66,8 +67,6 @@ profile pipewire @{exec_path} flags=(attach_disconnected) { owner @{PROC}/@{pid}/attr/apparmor/current r, owner @{PROC}/@{pid}/task/@{tid}/comm rw, - /dev/media@{int} rw, - include if exists } diff --git a/apparmor.d/groups/freedesktop/pipewire-media-session b/apparmor.d/groups/freedesktop/pipewire-media-session index af6f30e9c..83ee32baa 100644 --- a/apparmor.d/groups/freedesktop/pipewire-media-session +++ b/apparmor.d/groups/freedesktop/pipewire-media-session @@ -14,9 +14,9 @@ profile pipewire-media-session @{exec_path} { include include include + include include include - include network bluetooth raw, network bluetooth seqpacket, diff --git a/apparmor.d/groups/freedesktop/pulseaudio b/apparmor.d/groups/freedesktop/pulseaudio index 05e4c3ec2..5c7c49c3d 100644 --- a/apparmor.d/groups/freedesktop/pulseaudio +++ b/apparmor.d/groups/freedesktop/pulseaudio @@ -18,6 +18,7 @@ profile pulseaudio @{exec_path} { include include include + include include include include @@ -25,6 +26,7 @@ profile pulseaudio @{exec_path} { include include include + include include ptrace (trace) peer=@{profile_name}, @@ -105,7 +107,6 @@ profile pulseaudio @{exec_path} { @{sys}/devices/**/sound/**/{uevent,pcm_class} r, @{sys}/devices/virtual/dmi/id/{bios_vendor,board_vendor,sys_vendor} r, - @{sys}/devices/virtual/video4linux/video@{int}/uevent r, deny @{sys}/module/apparmor/parameters/enabled r, @@ -113,9 +114,6 @@ profile pulseaudio @{exec_path} { owner @{PROC}/@{pids}/stat r, owner @{PROC}/@{pids}/cmdline r, - /dev/media@{int} r, - /dev/video@{int} rw, - # file_inherit owner /dev/tty@{int} rw, diff --git a/apparmor.d/groups/freedesktop/wireplumber b/apparmor.d/groups/freedesktop/wireplumber index aefdc339d..aa78d9667 100644 --- a/apparmor.d/groups/freedesktop/wireplumber +++ b/apparmor.d/groups/freedesktop/wireplumber @@ -16,9 +16,10 @@ profile wireplumber @{exec_path} { include include include + include include + include include - include network bluetooth raw, network bluetooth seqpacket, @@ -65,13 +66,11 @@ profile wireplumber @{exec_path} { @{run}/systemd/users/@{uid} r, @{run}/udev/data/c14:@{int} r, # Open Sound System (OSS) - @{run}/udev/data/c81:@{int} r, # For video4linux @{run}/udev/data/c116:@{int} r, # For ALSA @{run}/udev/data/c@{dynamic}:@{int} r, # For dynamic assignment range 234 to 254, 384 to 511 @{sys}/bus/ r, @{sys}/bus/media/devices/ r, - @{sys}/devices/@{pci}/video4linux/video@{int}/uevent r, @{sys}/devices/**/device:*/{,**/}path r, @{sys}/devices/**/sound/**/pcm_class r, @{sys}/devices/**/sound/**/uevent r, @@ -87,7 +86,6 @@ profile wireplumber @{exec_path} { owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/task/@{tid}/comm rw, - /dev/media@{int} rw, /dev/udmabuf rw, include if exists diff --git a/apparmor.d/groups/freedesktop/xdg-settings b/apparmor.d/groups/freedesktop/xdg-settings index cb7edf822..840500c52 100644 --- a/apparmor.d/groups/freedesktop/xdg-settings +++ b/apparmor.d/groups/freedesktop/xdg-settings @@ -8,7 +8,7 @@ abi , include @{exec_path} = @{bin}/xdg-settings -profile xdg-settings @{exec_path} { +profile xdg-settings @{exec_path} flags=(attach_disconnected) { include include include diff --git a/apparmor.d/groups/gnome/gnome-boxes b/apparmor.d/groups/gnome/gnome-boxes index 1447715b7..cd46dd069 100644 --- a/apparmor.d/groups/gnome/gnome-boxes +++ b/apparmor.d/groups/gnome/gnome-boxes @@ -13,10 +13,12 @@ profile gnome-boxes @{exec_path} { include include include + include include include include include + include include include include @@ -80,9 +82,6 @@ profile gnome-boxes @{exec_path} { owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/stat r, - /dev/media@{int} rw, - /dev/video@{int} rw, - deny owner @{user_share_dirs}/gvfs-metadata/{,*} r, profile virsh { diff --git a/apparmor.d/groups/gnome/gnome-calculator b/apparmor.d/groups/gnome/gnome-calculator index 4e83bfb76..2f1cc0e89 100644 --- a/apparmor.d/groups/gnome/gnome-calculator +++ b/apparmor.d/groups/gnome/gnome-calculator @@ -7,7 +7,7 @@ abi , include @{exec_path} = @{bin}/gnome-calculator -profile gnome-calculator @{exec_path} { +profile gnome-calculator @{exec_path} flags=(attach_disconnected) { include include include diff --git a/apparmor.d/groups/gnome/gnome-control-center b/apparmor.d/groups/gnome/gnome-control-center index 111facf64..10f310232 100644 --- a/apparmor.d/groups/gnome/gnome-control-center +++ b/apparmor.d/groups/gnome/gnome-control-center @@ -17,11 +17,13 @@ profile gnome-control-center @{exec_path} flags=(attach_disconnected) { include include include + include include include include include include + include include include include @@ -191,8 +193,6 @@ profile gnome-control-center @{exec_path} flags=(attach_disconnected) { owner @{PROC}/@{pid}/task/*/comm rw, /dev/ r, - /dev/media@{int} r, - /dev/video@{int} rw, deny owner @{user_share_dirs}/gvfs-metadata/{,*} r, diff --git a/apparmor.d/groups/gnome/gnome-shell b/apparmor.d/groups/gnome/gnome-shell index 0876b90d1..7344b735b 100644 --- a/apparmor.d/groups/gnome/gnome-shell +++ b/apparmor.d/groups/gnome/gnome-shell @@ -32,18 +32,19 @@ profile gnome-shell @{exec_path} flags=(attach_disconnected,mediate_deleted) { include include include + include include include include include include include + include include include include include include - include capability sys_nice, capability sys_ptrace, @@ -321,7 +322,6 @@ profile gnome-shell @{exec_path} flags=(attach_disconnected,mediate_deleted) { @{run}/udev/data/+acpi:* r, # Exposes ACPI objects (power buttons, batteries, thermal) @{run}/udev/data/+pci:* r, # Identifies all PCI devices (CPU, GPU, Network, Disks, USB, etc.) @{run}/udev/data/+sound:card@{int} r, # for sound card - @{run}/udev/data/+usb:* r, # Identifies all USB devices @{run}/udev/data/+i2c:* r, # For Inter-Integrated Circuit, low-speed peripherals (sensors, EEPROMs, etc.) @{run}/udev/data/+hid:* r, # For Human Interface Device (mice, controllers, drawing tablets, scanners) @{run}/udev/data/c10:@{int} r, # for non-serial mice, misc features @@ -379,7 +379,6 @@ profile gnome-shell @{exec_path} flags=(attach_disconnected,mediate_deleted) { owner @{PROC}/@{pid}/task/@{tid}/comm rw, owner @{PROC}/@{pid}/task/@{tid}/stat r, - /dev/media@{int} rw, /dev/tty@{int} rw, @{att}/dev/dri/card@{int} rw, @{att}/dev/input/event@{int} rw, diff --git a/apparmor.d/groups/gnome/localsearch b/apparmor.d/groups/gnome/localsearch index 049b3c402..d5700db7c 100644 --- a/apparmor.d/groups/gnome/localsearch +++ b/apparmor.d/groups/gnome/localsearch @@ -68,9 +68,6 @@ profile localsearch @{exec_path} flags=(attach_disconnected) { owner @{PROC}/@{pid}/mounts r, owner @{PROC}/@{pid}/task/@{tid}/comm rw, - /dev/media@{int} rw, - /dev/video@{int} rw, - include if exists } diff --git a/apparmor.d/groups/gnome/org.gnome.NautilusPreviewer b/apparmor.d/groups/gnome/org.gnome.NautilusPreviewer index f084e7b12..e1bde2238 100644 --- a/apparmor.d/groups/gnome/org.gnome.NautilusPreviewer +++ b/apparmor.d/groups/gnome/org.gnome.NautilusPreviewer @@ -10,14 +10,15 @@ include profile org.gnome.NautilusPreviewer @{exec_path} flags=(attach_disconnected) { include include + include include include include include include + include include include - include network netlink raw, @@ -52,8 +53,6 @@ profile org.gnome.NautilusPreviewer @{exec_path} flags=(attach_disconnected) { owner @{PROC}/@{pid}/task/@{tid}/comm w, owner @{PROC}/@{pid}/task/@{tid}/stat r, - /dev/media@{int} r, - include if exists } diff --git a/apparmor.d/groups/kde/dolphin b/apparmor.d/groups/kde/dolphin index 2d3b099d7..022c0beec 100644 --- a/apparmor.d/groups/kde/dolphin +++ b/apparmor.d/groups/kde/dolphin @@ -25,7 +25,11 @@ profile dolphin @{exec_path} { network netlink raw, - signal (send) set=(term) peer=kioworker, + signal send set=hup peer=@{p_systemd}, + signal send set=term peer=kioworker, + + ptrace read peer=@{p_systemd}, + ptrace read peer=okular, @{exec_path} mr, @@ -109,10 +113,11 @@ profile dolphin @{exec_path} { owner @{PROC}/@{pid}/cmdline r, owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/mounts r, + owner @{PROC}/@{pid}/stat r, @{sys}/devices/virtual/block/dm-@{int}/uevent r, - /dev/tty r, + /dev/tty rw, include if exists } diff --git a/apparmor.d/groups/kde/kioworker b/apparmor.d/groups/kde/kioworker index 71465df97..0fc81a764 100644 --- a/apparmor.d/groups/kde/kioworker +++ b/apparmor.d/groups/kde/kioworker @@ -41,7 +41,7 @@ profile kioworker @{exec_path} { @{lib}/libheif/*.so* rm, @{bin}/wrestool rPUx, - @{bin}/gs rix, + @{bin}/gs{,.bin} rix, #aa:exec kio_http_cache_cleaner diff --git a/apparmor.d/groups/kde/kwin_x11 b/apparmor.d/groups/kde/kwin_x11 index f4f955a4f..ac80b3b18 100644 --- a/apparmor.d/groups/kde/kwin_x11 +++ b/apparmor.d/groups/kde/kwin_x11 @@ -41,6 +41,7 @@ profile kwin_x11 @{exec_path} { /usr/share/kwin-x11/{,**} r, /usr/share/kwin/{,**} r, /usr/share/plasma/desktoptheme/{,**} r, + /usr/share/sounds/*/stereo/*.oga r, /etc/machine-id r, /etc/xdg/plasmarc r, diff --git a/apparmor.d/groups/kde/okular b/apparmor.d/groups/kde/okular index acd9b7430..a2ffad26f 100644 --- a/apparmor.d/groups/kde/okular +++ b/apparmor.d/groups/kde/okular @@ -23,6 +23,8 @@ profile okular @{exec_path} { network netlink raw, + ptrace read peer=@{p_systemd}, + signal send set=term peer=kioworker, @{exec_path} mr, @@ -69,7 +71,7 @@ profile okular @{exec_path} { owner @{user_state_dirs}/#@{int} rw, owner @{user_state_dirs}/okularstaterc rw, - owner @{user_state_dirs}/okularstaterc.@{rand6} rwl -> @{user_state_dirs}/#@{int}, + owner @{user_state_dirs}/okularstaterc.@{rand6} rwlk -> @{user_state_dirs}/#@{int}, owner @{user_state_dirs}/okularstaterc.lock rwk, owner @{tmp}/#@{int} rw, @@ -82,6 +84,7 @@ profile okular @{exec_path} { owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/mounts r, + owner @{PROC}/@{pid}/stat r, profile gpg { include diff --git a/apparmor.d/groups/procps/pgrep b/apparmor.d/groups/procps/pgrep index 489f55bd7..d10c1e772 100644 --- a/apparmor.d/groups/procps/pgrep +++ b/apparmor.d/groups/procps/pgrep @@ -7,7 +7,7 @@ abi , include @{exec_path} = @{bin}/pgrep -profile pgrep @{exec_path} { +profile pgrep @{exec_path} flags=(attach_disconnected) { include include include diff --git a/apparmor.d/groups/systemd/systemd-logind b/apparmor.d/groups/systemd/systemd-logind index 271354633..05c812b18 100644 --- a/apparmor.d/groups/systemd/systemd-logind +++ b/apparmor.d/groups/systemd/systemd-logind @@ -136,7 +136,7 @@ profile systemd-logind @{exec_path} flags=(attach_disconnected) { @{PROC}/sysvipc/{shm,sem,msg} r, owner @{PROC}/@{pid}/fdinfo/@{int} r, - /dev/dri/card@{int} rw, + @{att}/dev/dri/card@{int} rw, /dev/input/event@{int} rw, # Input devices (keyboard, mouse, etc) /dev/mqueue/ r, /dev/tty@{int} rw, diff --git a/apparmor.d/groups/utils/su b/apparmor.d/groups/utils/su index 866da3d6a..e5293021c 100644 --- a/apparmor.d/groups/utils/su +++ b/apparmor.d/groups/utils/su @@ -8,7 +8,7 @@ abi , include @{exec_path} = @{bin}/su -profile su @{exec_path} { +profile su @{exec_path} flags=(attach_disconnected) { include include include diff --git a/apparmor.d/groups/xfce/xfce-clipman b/apparmor.d/groups/xfce/xfce-clipman new file mode 100644 index 000000000..270f7266f --- /dev/null +++ b/apparmor.d/groups/xfce/xfce-clipman @@ -0,0 +1,31 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2024 Alexandre Pujol +# Copyright (C) 2025 Sighy Brantler +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/xfce4-clipman +profile xfce-clipman @{exec_path} { + include + include + include + include + + @{exec_path} mr, + + /etc/xdg/xfce4/panel/xfce4-clipman-actions.xml r, + + owner @{user_cache_dirs}/xfce4/clipman/ r, + owner @{user_cache_dirs}/xfce4/clipman/* rw, + + owner @{user_config_dirs}/autostart/ r, + owner @{user_config_dirs}/autostart/xfce4-clipman-plugin-autostart.desktop rw, + owner @{user_config_dirs}/autostart/xfce4-clipman-plugin-autostart.desktop.@{rand6} rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-a-f/cheese b/apparmor.d/profiles-a-f/cheese index b89fa42f2..33b933be2 100644 --- a/apparmor.d/profiles-a-f/cheese +++ b/apparmor.d/profiles-a-f/cheese @@ -11,10 +11,12 @@ include profile cheese @{exec_path} { include include + include include include include include + include include include @@ -49,9 +51,6 @@ profile cheese @{exec_path} { owner @{PROC}/@{pid}/task/@{tid}/comm rw, - /dev/media@{int} rw, - /dev/video@{int} rw, - include if exists } diff --git a/apparmor.d/profiles-a-f/fwupd b/apparmor.d/profiles-a-f/fwupd index d7a72c236..8447bff3e 100644 --- a/apparmor.d/profiles-a-f/fwupd +++ b/apparmor.d/profiles-a-f/fwupd @@ -20,6 +20,7 @@ profile fwupd @{exec_path} flags=(attach_disconnected,complain) { include include include + include capability dac_override, capability dac_read_search, @@ -133,8 +134,6 @@ profile fwupd @{exec_path} flags=(attach_disconnected,complain) { /dev/mei@{int} rw, /dev/mem r, /dev/mtd@{int} rw, - /dev/tpm@{int} rw, - /dev/tpmrm@{int} rw, /dev/wmi/* r, profile gpg flags=(attach_disconnected,complain) { diff --git a/apparmor.d/profiles-g-l/git b/apparmor.d/profiles-g-l/git index 0538f5da0..01b491b98 100644 --- a/apparmor.d/profiles-g-l/git +++ b/apparmor.d/profiles-g-l/git @@ -65,6 +65,7 @@ profile git @{exec_path} flags=(attach_disconnected) { @{pager_path} rPx -> child-pager, + @{bin}/gh rPUx, @{bin}/man rPx, @{bin}/meld rPUx, @{lib}/code/extensions/git/dist/askpass.sh rPx, diff --git a/apparmor.d/profiles-g-l/kdestroy b/apparmor.d/profiles-g-l/kdestroy new file mode 100644 index 000000000..ccc0a2b25 --- /dev/null +++ b/apparmor.d/profiles-g-l/kdestroy @@ -0,0 +1,26 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Zane Zakraisek +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/kdestroy +profile kdestroy @{exec_path} { + include + include + + #Allow root to destroy other users' creds cache + capability dac_override, + + @{exec_path} mr, + + #Credentials cache + /tmp/krb5cc_* rwk, + /tmp/tkt* rwk, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-g-l/kinit b/apparmor.d/profiles-g-l/kinit new file mode 100644 index 000000000..706a11c10 --- /dev/null +++ b/apparmor.d/profiles-g-l/kinit @@ -0,0 +1,33 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Zane Zakraisek +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/kinit +profile kinit @{exec_path} { + include + include + include + + network inet dgram, + network inet6 dgram, + network inet stream, + network inet6 stream, + network netlink raw, + + @{exec_path} mr, + + #User keytab file + /var/lib/krb5/user/@{uid}/client.keytab r, + + #Credentials cache + /tmp/krb5cc_* rwk, + /tmp/tkt* rwk, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-g-l/klist b/apparmor.d/profiles-g-l/klist new file mode 100644 index 000000000..f21f34295 --- /dev/null +++ b/apparmor.d/profiles-g-l/klist @@ -0,0 +1,30 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Zane Zakraisek +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/klist +profile klist @{exec_path} { + include + include + + #Allow root to list other users' creds cache + capability dac_override, + capability dac_read_search, + + @{exec_path} mr, + + #User keytab file + /var/lib/krb5/user/@{uid}/client.keytab rk, + + #Credentials cache + /tmp/krb5cc_* rk, + /tmp/tkt* rk, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-g-l/libreoffice b/apparmor.d/profiles-g-l/libreoffice index dfb9361f3..de1c4a856 100644 --- a/apparmor.d/profiles-g-l/libreoffice +++ b/apparmor.d/profiles-g-l/libreoffice @@ -78,21 +78,24 @@ profile libreoffice @{exec_path} { /usr/share/mythes/{,**} r, /usr/share/thumbnailers/{,**} r, + /etc/cups/ppd/*.ppd r, /etc/java{,-}{,@{version}}-openjdk/{,**} r, /etc/libreoffice/{,**} r, - /etc/paperspecs r, /etc/papersize r, + /etc/paperspecs r, /etc/xdg/* r, /var/tmp/ r, owner /var/spool/libreoffice/uno_packages/cache/stamp.sys w, owner @{user_cache_dirs}/libreoffice/{,**} rw, + + owner @{user_config_dirs}/kservicemenurc r, owner @{user_config_dirs}/libreoffice/ rw, owner @{user_config_dirs}/libreoffice/** rwk, - owner @{user_config_dirs}/soffice.*.lock rwk, owner @{user_config_dirs}/plasma_workspace.notifyrc r, - owner @{user_config_dirs}/kservicemenurc r, + owner @{user_config_dirs}/soffice.*.lock rwk, + owner @{user_config_dirs}/soffice.binrc r, owner @{user_share_dirs}/#@{int} rw, owner @{user_share_dirs}/user-places.xbel r, diff --git a/apparmor.d/profiles-s-z/sbctl b/apparmor.d/profiles-s-z/sbctl index ef007a32c..a4fdbac88 100644 --- a/apparmor.d/profiles-s-z/sbctl +++ b/apparmor.d/profiles-s-z/sbctl @@ -9,6 +9,7 @@ include @{exec_path} = @{bin}/sbctl profile sbctl @{exec_path} { include + include capability dac_read_search, capability linux_immutable, @@ -34,9 +35,6 @@ profile sbctl @{exec_path} { @{sys}/firmware/efi/efivars/SecureBoot-@{uuid} r, @{sys}/firmware/efi/efivars/SetupMode-@{uuid} r, - /dev/pts/@{int} rw, - /dev/tpmrm@{int} rw, - # File Inherit deny network inet stream, deny network inet6 stream, diff --git a/apparmor.d/profiles-s-z/signal-desktop b/apparmor.d/profiles-s-z/signal-desktop index 001f8605a..4abe053f6 100644 --- a/apparmor.d/profiles-s-z/signal-desktop +++ b/apparmor.d/profiles-s-z/signal-desktop @@ -19,6 +19,7 @@ profile signal-desktop @{exec_path} flags=(attach_disconnected) { include include include + include include include include diff --git a/apparmor.d/profiles-s-z/v4l2-ctl b/apparmor.d/profiles-s-z/v4l2-ctl index e398049de..ddb86b9a2 100644 --- a/apparmor.d/profiles-s-z/v4l2-ctl +++ b/apparmor.d/profiles-s-z/v4l2-ctl @@ -9,14 +9,12 @@ include @{exec_path} = @{bin}/v4l2-ctl profile v4l2-ctl @{exec_path} { include + include include - include + include @{exec_path} mr, - /dev/media@{int} rw, - /dev/video@{int} rw, - include if exists } diff --git a/apparmor.d/profiles-s-z/virt-manager b/apparmor.d/profiles-s-z/virt-manager index 8a1b5f355..f820d2953 100644 --- a/apparmor.d/profiles-s-z/virt-manager +++ b/apparmor.d/profiles-s-z/virt-manager @@ -16,12 +16,14 @@ profile virt-manager @{exec_path} flags=(attach_disconnected) { include include include + include include include include include include include + include include include include @@ -101,9 +103,6 @@ profile virt-manager @{exec_path} flags=(attach_disconnected) { owner @{PROC}/@{pid}/mounts r, owner @{PROC}/@{pid}/stat r, - /dev/media@{int} r, - /dev/video@{int} rw, - # Silence the noise deny /usr/share/virt-manager/{,**} w, deny owner @{user_share_dirs}/gvfs-metadata/{,*} r, diff --git a/apparmor.d/profiles-s-z/vlc b/apparmor.d/profiles-s-z/vlc index ccf1abb61..3a3a77313 100644 --- a/apparmor.d/profiles-s-z/vlc +++ b/apparmor.d/profiles-s-z/vlc @@ -17,6 +17,7 @@ profile vlc @{exec_path} { include include include + include include include include @@ -85,7 +86,6 @@ profile vlc @{exec_path} { /dev/shm/#@{int} rw, /dev/snd/ r, /dev/tty r, - /dev/video@{int} rw, owner /dev/tty@{int} rw, # Silencer diff --git a/cmd/prebuild/main.go b/cmd/prebuild/main.go index 5eb1ab2f2..455621e5b 100644 --- a/cmd/prebuild/main.go +++ b/cmd/prebuild/main.go @@ -49,6 +49,9 @@ func init() { case "noble": prebuild.ABI = 4 prebuild.Version = 4.0 + case "questing": + prebuild.ABI = 4 + prebuild.Version = 5.0 } case "debian": diff --git a/cmd/prebuild/main_test.go b/cmd/prebuild/main_test.go deleted file mode 100644 index d3c28f025..000000000 --- a/cmd/prebuild/main_test.go +++ /dev/null @@ -1,56 +0,0 @@ -// apparmor.d - Full set of apparmor profiles -// Copyright (C) 2023-2024 Alexandre Pujol -// SPDX-License-Identifier: GPL-2.0-only - -package main - -import ( - "os" - "os/exec" - "testing" - - "github.com/roddhjav/apparmor.d/pkg/prebuild" -) - -func chdirGitRoot() { - cmd := exec.Command("git", "rev-parse", "--show-toplevel") - out, err := cmd.Output() - if err != nil { - panic(err) - } - root := string(out[0 : len(out)-1]) - if err := os.Chdir(root); err != nil { - panic(err) - } -} - -func Test_main(t *testing.T) { - tests := []struct { - name string - dist string - }{ - { - name: "Build for Archlinux", - dist: "arch", - }, - { - name: "Build for Ubuntu", - dist: "ubuntu", - }, - { - name: "Build for Debian", - dist: "debian", - }, - { - name: "Build for OpenSUSE Tumbleweed", - dist: "opensuse", - }, - } - chdirGitRoot() - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - prebuild.Distribution = tt.dist - main() - }) - } -} diff --git a/debian/apparmor.d.postinst b/debian/apparmor.d.postinst index 361af7b91..840f3196b 100644 --- a/debian/apparmor.d.postinst +++ b/debian/apparmor.d.postinst @@ -8,6 +8,6 @@ set -e #DEBHELPER# apparmor_parser --purge-cache || true -deb-systemd-invoke reload apparmor.service +deb-systemd-invoke reload apparmor.service || true exit 0 diff --git a/debian/apparmor.d.postrm b/debian/apparmor.d.postrm index 361af7b91..840f3196b 100644 --- a/debian/apparmor.d.postrm +++ b/debian/apparmor.d.postrm @@ -8,6 +8,6 @@ set -e #DEBHELPER# apparmor_parser --purge-cache || true -deb-systemd-invoke reload apparmor.service +deb-systemd-invoke reload apparmor.service || true exit 0 diff --git a/dists/build.sh b/dists/build.sh index 9b9f9e765..e33c48695 100644 --- a/dists/build.sh +++ b/dists/build.sh @@ -16,7 +16,7 @@ readonly VERSION main() { case "$COMMAND" in pkg) - PKGDEST="$OUTPUT" makepkg --syncdeps --force --cleanbuild --noconfirm --noprogressbar + PKGDEST="$OUTPUT" BUILDDIR=/tmp/makepkg makepkg --syncdeps --force --cleanbuild --noconfirm --noprogressbar ;; dpkg) diff --git a/dists/docker.sh b/dists/docker.sh index 2e581883c..45191adb8 100644 --- a/dists/docker.sh +++ b/dists/docker.sh @@ -25,7 +25,7 @@ readonly VERSION PACKAGER _start() { local img="$1" - docker start "$img" + docker start "$img" || return 1 } _is_running() { @@ -65,7 +65,7 @@ build_in_docker_makepkg() { --env PKGDEST="$BUILDIR" --env PACKAGER="$PACKAGER" \ --env BUILDDIR=/tmp/build \ "$BASEIMAGE/$dist" - docker exec "$img" sudo pacman -Syu --noconfirm --noprogressbar + docker exec "$img" sudo pacman -Sy --noconfirm --noprogressbar fi docker exec --workdir="$BUILDIR/$PKGNAME" "$img" bash dists/build.sh pkg diff --git a/dists/flags/main.flags b/dists/flags/main.flags index 057c7c298..cd9a0e5a6 100644 --- a/dists/flags/main.flags +++ b/dists/flags/main.flags @@ -185,6 +185,7 @@ kconf_update complain kde-powerdevil attach_disconnected,mediate_deleted,complain kde-systemd-start-condition complain kded complain +kdestroy complain kdump_mem_estimator complain kdump-config attach_disconnected,complain kdump-tools-init complain,attach_disconnected @@ -193,9 +194,11 @@ kernel-install complain kernel-postinst-kdump complain keyboxd complain kglobalacceld complain +kinit complain kio_http_cache_cleaner complain kiod complain kioworker complain +klist complain konsole attach_disconnected,mediate_deleted,complain kscreen_backend_launcher complain kscreen_osd_service complain @@ -230,7 +233,7 @@ lvmdump complain lvmpolld complain man complain mate-notification-daemon complain -mdadm complain +mdadm attach_disconnected,complain mdadm-mkconf complain ModemManager attach_disconnected,complain mount attach_disconnected,complain @@ -327,7 +330,7 @@ systemd-generator-ds-identify attach_disconnected,complain systemd-generator-environment-arch complain systemd-generator-environment-flatpak complain systemd-generator-environment-snapd attach_disconnected,complain -systemd-generator-friendly-recover attach_disconnected,complain +systemd-generator-friendly-recovery attach_disconnected,complain systemd-generator-fstab attach_disconnected,complain systemd-generator-getty attach_disconnected,complain systemd-generator-gpt-auto attach_disconnected,complain diff --git a/dists/flags/ubuntu.flags b/dists/flags/ubuntu.flags index 7339702a2..125575ce1 100644 --- a/dists/flags/ubuntu.flags +++ b/dists/flags/ubuntu.flags @@ -8,6 +8,7 @@ apt-helper complain check-new-release-gtk complain do-release-upgrade complain dpkg-genbuildinfo complain +esm_cache complain fanctl attach_disconnected,complain hwe-support-status complain list-oem-metapackages complain diff --git a/docs/development/abstractions.md b/docs/development/abstractions.md index f1ac6e18e..cd82f5d21 100644 --- a/docs/development/abstractions.md +++ b/docs/development/abstractions.md @@ -217,6 +217,14 @@ Minimal set of rules for sandboxed programs using `bwrap`. A profile using this A minimal set of rules for chromium based application. Handle access for internal sandbox. +It works as a *function* and requires some variables to be provided as *arguments* and set in the header of the calling profile: + +!!! note "" + + [apparmor.d/profile-s-z/spotify](https://github.com/roddhjav/apparmor.d/blob/main/apparmor.d/groups/steam/steam#L24-L25) + ``` sh linenums="24" + @{domain} = org.chromium.Chromium + ``` ### **`common/electron`** @@ -227,6 +235,7 @@ A minimal set of rules for all electron based UI applications. It works as a *fu [apparmor.d/profile-s-z/spotify](https://github.com/roddhjav/apparmor.d/blob/7d1380530aa56f31589ccc6a360a8144f3601731/apparmor.d/profiles-s-z/spotify#L10-L13) ``` sh linenums="10" @{name} = spotify + @{domain} = org.chromium.Chromium @{lib_dirs} = /opt/@{name} @{config_dirs} = @{user_config_dirs}/@{name} @{cache_dirs} = @{user_cache_dirs}/@{name} diff --git a/docs/development/build.md b/docs/development/build.md index eaa2487a2..b767e4e4e 100644 --- a/docs/development/build.md +++ b/docs/development/build.md @@ -10,18 +10,22 @@ go run ./cmd/prebuild -h ``` ``` -aa-prebuild [-h] [--complain | --enforce] [--full] [--abi 3|4] +aa-prebuild [-h] [--complain | --enforce] [--full] [--server] [--abi 3|4] [--version V] [--file FILE] Prebuild apparmor.d profiles for a given distribution and apply internal built-in directives. Options: - -h, --help Show this help message and exit. - -c, --complain Set complain flag on all profiles. - -e, --enforce Set enforce flag on all profiles. - -a, --abi ABI Target apparmor ABI. - -f, --full Set AppArmor for full system policy. - -F, --file Only prebuild a given file. + -h, --help Show this help message and exit. + -c, --complain Set complain flag on all profiles. + -e, --enforce Set enforce flag on all profiles. + -a, --abi ABI Target apparmor ABI. + -v, --version V Target apparmor version. + -f, --full Set AppArmor for full system policy. + -s, --server Set AppArmor for server. + -b, --buildir DIR Root build directory. + -F, --file Only prebuild a given file. + --debug Enable debug mode. Prepare tasks: configure - Set distribution specificities @@ -31,21 +35,27 @@ Prepare tasks: overwrite - Overwrite dummy upstream profiles synchronise - Initialize a new clean apparmor.d build directory ignore - Ignore profiles and files from: + server - Configure AppArmor for server systemd-default - Configure systemd unit drop in files to a profile for some units systemd-early - Configure systemd unit drop in files to ensure some service start after apparmor + attach - Configure tunable for re-attached path Build tasks: - abi3 - Convert all profiles from abi 4.0 to abi 3.0 - attach - Re-attach disconnected path - complain - Set complain flag on all profiles - enforce - All profiles have been enforced - fsp - Prevent unconfined transitions in profile rules - hotfix - Temporary fix for #74, #80 & #235 - userspace - Resolve variable in profile attachments + userspace - Fix: resolve variable in profile attachments + abi3 - Build: convert all profiles from abi 4.0 to abi 3.0 + attach - Feat: re-attach disconnected path + base-strict - Feat: use 'base-strict' as base abstraction + complain - Build: set complain flag on all profiles + debug - Build: debug mode enabled + enforce - Build: all profiles have been enforced + fsp - Feat: prevent unconfined transitions in profile rules + hotfix - Fix: temporary solution for #74, #80 & #235 + stacked-dbus - Fix: resolve peer label variable in dbus rules Directive: #aa:dbus own bus= name= [interface=AARE] [path=AARE] #aa:dbus talk bus= name= label= [interface=AARE] [path=AARE] + #aa:dbus common bus= name= label= #aa:exec [P|U|p|u|PU|pu|] profiles... #aa:only filters... #aa:exclude filters... @@ -66,6 +76,12 @@ Ignore profiles and files as defined in the `dist/ignore` directory. See [workfl *Enabled by default. Can be disabled in `cmd/prebuild/main.go`* +### **`server`** + +Configure AppArmor for server. Desktop related groups and profiles that use desktop abstraction are not included. [hotfix](#hotfix) is also disabled, as it is only needed on desktop system. It is mostly intended to be used on server with FSP enabled. E.g: [the play machine](https://github.com/roddhjav/play). + +*Enable with the `--server` option in the prebuild command.* + ### **`merge`** Merge profiles from `apparmor.d/group/`, `apparmor.d/profiles-*-*/` to a unified directory in `.build/apparmor.d` that AppArmor can parse. diff --git a/docs/development/roadmap.md b/docs/development/roadmap.md index 2585208e5..379241a49 100644 --- a/docs/development/roadmap.md +++ b/docs/development/roadmap.md @@ -6,11 +6,18 @@ title: Roadmap This is the current list of features that must be implemented to get to a stable release -- [x] **Play machine** +- [x] **[Play machine](https://github.com/roddhjav/play)** -- [ ] **[Sub packages](https://github.com/roddhjav/apparmor.d/issues/464)** - - [x] Move most profiles into groups such that - - [ ] New simplified build system to generate the packages with profile dependencies check +- [ ] **[Sub packages](https://github.com/roddhjav/apparmor.d/issues/464)** + - [x] Move most profiles into groups + - [ ] Provide complain/enforced packages version + - [ ] normal/FSP/server packages variants + +- [ ] **Build system** + - [ ] Continuous release on the main branch, ~2 releases per week + - [ ] Provide packages repo for ubuntu/debian + - [x] Add a `just` target to install the profiles in the right place + - [x] Fully drop the Makefile in favor of `just` - [ ] **Tests** - [x] Tests VM for all supported targets (see [tests/vm](vm.md)) @@ -22,14 +29,26 @@ This is the current list of features that must be implemented to get to a stable - [ ] **General improvements** - [ ] Provide a proper fix for [#74](https://github.com/roddhjav/apparmor.d/issues/74), [#80](https://github.com/roddhjav/apparmor.d/issues/80) & [#235](https://github.com/roddhjav/apparmor.d/issues/235) - - [x] The apt/dpkg profiles needs to be reworked -- [ ] Build system - - [ ] Continuous release on the main branch, ~2 releases per week - - [ ] Provide packages repo for ubuntu/debian - - [ ] Provide complain/enforced packages version - - [x] Add a `just` target to install the profiles in the right place - - [x] Fully drop the Makefile in favor of `just` +- [ ] **Abstractions** + - [ ] Document all abstractions + - [ ] Split and reorganize some big abs into set of smaller abstractions. + Strictly follow the new abstractions guidelines (layer 0, layer 1, etc.) + - [ ] Abstraction based profiles: + Most of the accesses needed by GUI based application are commons. As such 80-90% of the profile content should be handled by abstractions (internally they will have conditions). + - [ ] Test new interface like abstractions + - notifications + - audio-bluetooth + - secrets-service + - media-keys + - ... + - [ ] Rewrite the desktop abstraction to only contains other abs. No direct rules in it. + - [ ] Rewrite the DE specific abstraction to be a layer 1 abs + +- [ ] **Security improvements** + - [ ] Limit the use of `abstractions/common/systemd` + - [ ] Ensure systemctl restart/stop/reload is always confined and filtered by unit (dbus only) + - [ ] Revisit the usae of `systemd-tty-ask-password-agent` ## Next features @@ -45,8 +64,16 @@ This is the current list of features that must be implemented to get to a stable - [ ] Debug tool to show the profiles transition tree, and ensure no profile is missing - [x] Remove the `default` profile +- [ ] **Define roles** + - [ ] Unrestricted shell role without FSP enabled + - [ ] Define the roles when FSP is enabled + ## Done +**General improvements** + +- [x] The apt/dpkg profiles has been rewritten + **Abstractions** - [x] New `audio-client` and `audio-server` abstractions diff --git a/docs/issues.md b/docs/issues.md index 1db3b195a..2f38f4c5a 100644 --- a/docs/issues.md +++ b/docs/issues.md @@ -6,6 +6,19 @@ title: Known issues Known bugs are tracked on the meta issue **[#75](https://github.com/roddhjav/apparmor.d/issues/74)**. +## Ubuntu + +### Dbus + +Ubuntu fully supports dbus mediation with apparmor. If it is a value added by Ubuntu from other distributions, it can also lead to some breakage if you enforce some profiles. *Do not enforce the rules on Ubuntu Desktop.* + +Note: Ubuntu server has been more tested and will work without issues with enforced rules. + +### Snap + +Apparmor.d needs to be fully integrated with snap, otherwise your snap applications may not work properly. As of today, it is a work in progress. + + ## Complain mode A profile in *complain* mode cannot break the program it confines. However, there are some **major exceptions**: @@ -14,20 +27,3 @@ A profile in *complain* mode cannot break the program it confines. However, ther 2. `attach_disconnected` (and `mediate_deleted`) will break the program if they are required and missing in the profile, 3. If AppArmor does not find the profile to transition `rPx`. -## Pacman "could not get current working directory" - -```sh -$ sudo pacman -Syu -... -error: could not get current working directory -:: Processing package changes... -... -``` - -This is **a feature, not a bug!** It can safely be ignored. Pacman tries to get your current directory. You will only get this error when you run pacman in your home directory. - -According to the Arch Linux guideline, on Arch Linux, packages cannot install files under `/home/`. Therefore, the [`pacman`][pacman] profile purposely does not allow access of your home directory. - -This provides a basic protection against some packages (on the AUR) that may have rogue install script. - -[pacman]: https://github.com/roddhjav/apparmor.d/blob/main/apparmor.d/groups/pacman/pacman diff --git a/pkg/prebuild/builder/attach.go b/pkg/prebuild/builder/attach.go index 66ef18aef..1ec5e06b1 100644 --- a/pkg/prebuild/builder/attach.go +++ b/pkg/prebuild/builder/attach.go @@ -31,6 +31,9 @@ func init() { func (b ReAttach) Apply(opt *Option, profile string) (string, error) { var insert string var origin = "profile " + opt.Name + if opt.File.HasSuffix("attached/base") { + return profile, nil // Do not re-attach twice + } if strings.Contains(profile, "attach_disconnected") { insert = "@{att} = /att/" + opt.Name + "/\n" @@ -42,13 +45,17 @@ func (b ReAttach) Apply(opt *Option, profile string) (string, error) { "include ", "include ", ) + profile = strings.ReplaceAll(profile, + "include ", + "include ", + ) profile = strings.ReplaceAll(profile, "include ", "include ", ) } else { - insert = "@{att} = /\n" + insert = "@{att} = \"\"\n" } diff --git a/pkg/prebuild/builder/core_test.go b/pkg/prebuild/builder/core_test.go index 06ceb1d28..6bcf74647 100644 --- a/pkg/prebuild/builder/core_test.go +++ b/pkg/prebuild/builder/core_test.go @@ -231,10 +231,80 @@ func TestBuilder_Apply(t *testing.T) { want: "", wantErr: true, }, + { + name: "stacked-dbus-1", + b: Builders["stacked-dbus"], + profile: ` +profile foo { + dbus send bus=session path=/org/freedesktop/DBus + interface=org.freedesktop.DBus + member={Hello,AddMatch,RemoveMatch,GetNameOwner,NameHasOwner,StartServiceByName} + peer=(name=org.freedesktop.DBus, label="@{p_dbus_session}"), + +}`, + want: ` +profile foo { +dbus send bus=session path=/org/freedesktop/DBus + interface=org.freedesktop.DBus + member={Hello,AddMatch,RemoveMatch,GetNameOwner,NameHasOwner,StartServiceByName} + peer=(name=org.freedesktop.DBus, label=dbus-session), +dbus send bus=session path=/org/freedesktop/DBus + interface=org.freedesktop.DBus + member={Hello,AddMatch,RemoveMatch,GetNameOwner,NameHasOwner,StartServiceByName} + peer=(name=org.freedesktop.DBus, label=dbus-session//&unconfined), + +}`, + }, + { + name: "base-strict-1", + b: Builders["base-strict"], + profile: ` +profile foo { + include +}`, + want: ` +profile foo { + include +}`, + }, + { + name: "attach-1", + b: Builders["attach"], + profile: ` +profile attach-1 flags=(attach_disconnected) { + include + include + include +}`, + want: ` +@{att} = /att/attach-1/ +profile attach-1 flags=(attach_disconnected,attach_disconnected.path=@{att}) { + include + include + include +}`, + }, + { + name: "attach-2", + b: Builders["attach"], + profile: ` +profile attach-2 flags=(complain) { + include + include + include +}`, + want: ` +@{att} = "" +profile attach-2 flags=(complain) { + include + include + include +}`, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - opt := &Option{File: prebuild.RootApparmord.Join(tt.name)} + opt := &Option{File: prebuild.RootApparmord.Join(tt.name), Name: tt.name} got, err := tt.b.Apply(opt, tt.profile) if (err != nil) != tt.wantErr { t.Errorf("Builder.Apply() error = %v, wantErr %v", err, tt.wantErr) diff --git a/pkg/prebuild/builder/stacked-dbus.go b/pkg/prebuild/builder/stacked-dbus.go index e33ecf4b7..eca8122c6 100644 --- a/pkg/prebuild/builder/stacked-dbus.go +++ b/pkg/prebuild/builder/stacked-dbus.go @@ -72,7 +72,7 @@ func (b StackedDbus) Apply(opt *Option, profile string) (string, error) { toResolve = append(toResolve, k) } - rulesByParagraph, paragraphs, err := parse(kind, profile) // + rulesByParagraph, paragraphs, err := parse(kind, profile) if err != nil { return "", err } diff --git a/pkg/prebuild/cli/cli.go b/pkg/prebuild/cli/cli.go index 8abfb4323..bf768c050 100644 --- a/pkg/prebuild/cli/cli.go +++ b/pkg/prebuild/cli/cli.go @@ -7,6 +7,8 @@ package cli import ( "flag" "fmt" + "os" + "slices" "strings" "github.com/roddhjav/apparmor.d/pkg/logging" @@ -20,7 +22,7 @@ import ( const ( nilABI = 0 nilVer = 0.0 - usage = `aa-prebuild [-h] [--complain | --enforce] [--full] [--abi 3|4] [--version V] [--file FILE] + usage = `aa-prebuild [-h] [--complain | --enforce] [--full] [--server] [--abi 3|4] [--version V] [--file FILE] Prebuild apparmor.d profiles for a given distribution and apply internal built-in directives. @@ -32,7 +34,8 @@ Options: -a, --abi ABI Target apparmor ABI. -v, --version V Target apparmor version. -f, --full Set AppArmor for full system policy. - -b, --buildir DIR Root build directory. + -s, --server Set AppArmor for server. + -b, --buildir DIR Root build directory. -F, --file Only prebuild a given file. --debug Enable debug mode. ` @@ -43,6 +46,7 @@ var ( complain bool enforce bool full bool + server bool debug bool abi int version float64 @@ -55,6 +59,8 @@ func init() { flag.BoolVar(&help, "help", false, "Show this help message and exit.") flag.BoolVar(&full, "f", false, "Set AppArmor for full system policy.") flag.BoolVar(&full, "full", false, "Set AppArmor for full system policy.") + flag.BoolVar(&server, "s", false, "Set AppArmor for server.") + flag.BoolVar(&server, "server", false, "Set AppArmor for server.") flag.BoolVar(&complain, "c", false, "Set complain flag on all profiles.") flag.BoolVar(&complain, "complain", false, "Set complain flag on all profiles.") flag.BoolVar(&enforce, "e", false, "Set enforce flag on all profiles.") @@ -81,7 +87,22 @@ func Configure() { flag.Parse() if help { flag.Usage() - return + os.Exit(0) + } + + if server { + idx := slices.Index(prepare.Prepares, prepare.Tasks["merge"]) + if idx == -1 { + prepare.Register("server") + } else { + prepare.Prepares = slices.Insert(prepare.Prepares, idx, prepare.Tasks["server"]) + } + + // Remove hotfix task as it is not needed on server + idx = slices.Index(prepare.Prepares, prepare.Tasks["hotfix"]) + if idx != -1 { + prepare.Prepares = slices.Delete(prepare.Prepares, idx, idx+1) + } } if full && paths.New("apparmor.d/groups/_full").Exist() { @@ -118,8 +139,11 @@ func Configure() { builder.Register("stacked-dbus") } else { + if !prebuild.DownStream { + prepare.Register("attach") + } builder.Register("attach") - prepare.Register("attach") + } default: diff --git a/pkg/prebuild/directive/dbus.go b/pkg/prebuild/directive/dbus.go index 891eb9e1d..4862597bb 100644 --- a/pkg/prebuild/directive/dbus.go +++ b/pkg/prebuild/directive/dbus.go @@ -135,7 +135,7 @@ func (d Dbus) own(rules map[string]string) aa.Rules { } res = append(res, - // DBus.Properties + // DBus.Properties: reply to properties request from anyone &aa.Dbus{ Access: []string{"send", "receive"}, Bus: rules["bus"], Path: rules["path"], Interface: "org.freedesktop.DBus.Properties", @@ -143,7 +143,7 @@ func (d Dbus) own(rules map[string]string) aa.Rules { PeerName: `"{@{busname},org.freedesktop.DBus}"`, }, - // DBus.Introspectable + // DBus.Introspectable: allow clients to introspect the service &aa.Dbus{ Access: []string{"receive"}, Bus: rules["bus"], Path: rules["path"], Interface: "org.freedesktop.DBus.Introspectable", @@ -151,7 +151,7 @@ func (d Dbus) own(rules map[string]string) aa.Rules { PeerName: `"@{busname}"`, }, - // DBus.ObjectManager + // DBus.ObjectManager: allow clients to enumerate sources &aa.Dbus{ Access: []string{"receive"}, Bus: rules["bus"], Path: rules["path"], Interface: "org.freedesktop.DBus.ObjectManager", @@ -170,7 +170,14 @@ func (d Dbus) own(rules map[string]string) aa.Rules { func (d Dbus) talk(rules map[string]string) aa.Rules { interfaces := getInterfaces(rules) - res := aa.Rules{} + res := aa.Rules{ + &aa.Unix{ + Type: "stream", + Address: "none", + PeerLabel: rules["label"], + PeerAddr: "none", + }, + } // Interfaces for _, iface := range interfaces { @@ -198,7 +205,7 @@ func (d Dbus) talk(rules map[string]string) aa.Rules { PeerName: `"{@{busname},` + rules["name"] + `}"`, PeerLabel: rules["label"], }, - // DBus.ObjectManager + // DBus.ObjectManager: allow clients to enumerate sources &aa.Dbus{ Access: []string{"send"}, Bus: rules["bus"], Path: rules["path"], Interface: "org.freedesktop.DBus.ObjectManager", diff --git a/pkg/prebuild/directive/dbus_test.go b/pkg/prebuild/directive/dbus_test.go index 0844fd745..d6e90bb99 100644 --- a/pkg/prebuild/directive/dbus_test.go +++ b/pkg/prebuild/directive/dbus_test.go @@ -8,7 +8,7 @@ import ( "testing" ) -const dbusOwnSystemd1 = ` include +const dbusOwnSystemd1 = ` include dbus bind bus=system name=org.freedesktop.systemd1{,.*}, dbus receive bus=system path=/org/freedesktop/systemd1{,/**} @@ -73,7 +73,7 @@ func TestDbus_Apply(t *testing.T) { Raw: " #aa:dbus own bus=session name=com.rastersoft.ding interface+=org.gtk.Actions", }, profile: " #aa:dbus own bus=session name=com.rastersoft.ding interface+=org.gtk.Actions", - want: ` include + want: ` include dbus bind bus=session name=com.rastersoft.ding{,.*}, dbus receive bus=session path=/com/rastersoft/ding{,/**} @@ -120,7 +120,9 @@ func TestDbus_Apply(t *testing.T) { Raw: " #aa:dbus talk bus=system name=org.freedesktop.Accounts label=accounts-daemon", }, profile: " #aa:dbus talk bus=system name=org.freedesktop.Accounts label=accounts-daemon", - want: ` dbus (send receive) bus=system path=/org/freedesktop/Accounts{,/**} + want: ` unix type=stream addr=none peer=(label=accounts-daemon, addr=none), + + dbus (send receive) bus=system path=/org/freedesktop/Accounts{,/**} interface=org.freedesktop.Accounts{,.*} peer=(name="{@{busname},org.freedesktop.Accounts{,.*}}", label=accounts-daemon), dbus (send receive) bus=system path=/org/freedesktop/Accounts{,/**} diff --git a/pkg/prebuild/directories.go b/pkg/prebuild/directories.go index 37cbc69bc..201d8c841 100644 --- a/pkg/prebuild/directories.go +++ b/pkg/prebuild/directories.go @@ -13,6 +13,9 @@ var ( // AppArmor version Version = 4.0 + // Tells the build we are a downstream project using apparmor.d as dependency + DownStream = false + // Either or not RBAC is enabled RBAC = false diff --git a/pkg/prebuild/files.go b/pkg/prebuild/files.go index 504f05c1c..d9879570b 100644 --- a/pkg/prebuild/files.go +++ b/pkg/prebuild/files.go @@ -11,9 +11,12 @@ import ( ) // Hide is the default content of debian/apparmor.d.hide. Whonix has special addition. -var Hide = `# This file is generated by "make", all edit will be lost. +var Hide = `# This file is generated by "just", all edit will be lost. /etc/apparmor.d/usr.bin.firefox +/etc/apparmor.d/usr.bin.swtpm +/etc/apparmor.d/usr.bin.wsdd +/etc/apparmor.d/usr.libexec.geoclue /etc/apparmor.d/usr.sbin.cups-browsed /etc/apparmor.d/usr.sbin.cupsd /etc/apparmor.d/usr.sbin.rsyslogd diff --git a/pkg/prebuild/prepare/server.go b/pkg/prebuild/prepare/server.go new file mode 100644 index 000000000..fb9a1f602 --- /dev/null +++ b/pkg/prebuild/prepare/server.go @@ -0,0 +1,108 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2021-2024 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package prepare + +import ( + "fmt" + "strings" + + "github.com/roddhjav/apparmor.d/pkg/paths" + "github.com/roddhjav/apparmor.d/pkg/prebuild" +) + +var ( + serverIgnorePatterns = []string{ + "include ", + "include ", + "include ", + "include ", + "include ", + "include ", + "include ", + "include ", + "include ", + "include ", + "include ", + "include ", + "include ", + "include ", + } + serverIgnoreGroups = []string{ + "akonadi", + "avahi", + "bluetooth", + "browsers", + "cosmic", + "cups", + "display-manager", + "flatpak", + "freedesktop", + "gnome", + "gvfs", + "hyprland", + "kde", + "lxqt", + "steam", + "xfce", + "zed", + } +) + +type Server struct { + prebuild.Base +} + +func init() { + RegisterTask(&Server{ + Base: prebuild.Base{ + Keyword: "server", + Msg: "Configure AppArmor for server", + }, + }) +} + +func (p Server) Apply() ([]string, error) { + res := []string{} + + // Ignore desktop related groups + groupNb := 0 + for _, group := range serverIgnoreGroups { + path := prebuild.RootApparmord.Join("groups", group) + if path.IsDir() { + if err := path.RemoveAll(); err != nil { + return res, err + } + groupNb++ + } else { + res = append(res, fmt.Sprintf("Group %s not found, ignoring", path)) + } + } + + // Ignore profiles using a desktop related abstraction + fileNb := 0 + files, _ := prebuild.RootApparmord.ReadDirRecursiveFiltered(nil, paths.FilterOutDirectories()) + for _, file := range files { + if !file.Exist() { + continue + } + profile, err := file.ReadFileAsString() + if err != nil { + return res, err + } + for _, pattern := range serverIgnorePatterns { + if strings.Contains(profile, pattern) { + if err := file.RemoveAll(); err != nil { + return res, err + } + fileNb++ + break + } + } + } + + res = append(res, fmt.Sprintf("%d groups ignored", groupNb)) + res = append(res, fmt.Sprintf("%d profiles ignored", fileNb)) + return res, nil +} diff --git a/tests/check.sh b/tests/check.sh index 60e23c694..b54bc157a 100644 --- a/tests/check.sh +++ b/tests/check.sh @@ -11,9 +11,13 @@ set -eu -o pipefail RES=$(mktemp) echo "false" >"$RES" MAX_JOBS=$(nproc) +APPARMORD=${CHECK_APPARMORD:-apparmor.d} +SBIN_LIST=${CHECK_SBIN_LIST:-tests/sbin.list} declare WITH_CHECK declare _check_is_disabled -readonly RES MAX_JOBS APPARMORD="apparmor.d" +declare _check_is_disabled_global +_FILE_IGNORE_ALL=false +readonly APPARMORD SBIN_LIST RES MAX_JOBS readonly reset="\033[0m" fgRed="\033[0;31m" fgYellow="\033[0;33m" fgWhite="\033[0;37m" BgWhite="\033[1;37m" _msg() { printf '%b%s%b\n' "$BgWhite" "$*" "$reset"; } _warn() { @@ -42,6 +46,11 @@ _in_array() { _is_enabled() { local check="$1" if _in_array "$check" "${WITH_CHECK[@]}"; then + if [[ -n "${_check_is_disabled_global+x}" && ${#_check_is_disabled_global[@]} -gt 0 ]]; then + if _in_array "$check" "${_check_is_disabled_global[@]}"; then + return 1 + fi + fi if [[ -z "${_check_is_disabled+x}" || ${#_check_is_disabled[@]} -eq 0 ]]; then return 0 fi @@ -68,10 +77,18 @@ _ignore_lint() { local checks line="$1" if [[ "$line" =~ ^[[:space:]]*$_IGNORE_LINT=.*$ ]]; then - # Start of an ignore block - _IGNORE_LINT_BLOCK=true + # Start of an ignore block (or file-wide if in header) checks="${line#*"$_IGNORE_LINT="}" - read -ra _check_is_disabled <<<"${checks//,/ }" + read -ra _parsed <<<"${checks//,/ }" + if (( line_number <= 10 )); then + # Treat as file-wide ignore + _check_is_disabled_global=("${_parsed[@]}") + _FILE_IGNORE_ALL=true + _IGNORE_LINT_BLOCK=false + return 0 + fi + _IGNORE_LINT_BLOCK=true + _check_is_disabled=("${_parsed[@]}") elif [[ $_IGNORE_LINT_BLOCK == true && "$line" =~ ^[[:space:]]*$ ]]; then # New paragraph, end of block @@ -79,22 +96,33 @@ _ignore_lint() { _check_is_disabled=() elif [[ $_IGNORE_LINT_BLOCK == true ]]; then - # Nothing to do, we are in a block + # Nothing to do, we are in a block/paragraph return 0 elif [[ "$line" == *"$_IGNORE_LINT="* ]]; then - # Inline ignore + # Inline ignore (or file-wide if in header) checks="${line#*"$_IGNORE_LINT="}" - read -ra _check_is_disabled <<<"${checks//,/ }" + read -ra _parsed <<<"${checks//,/ }" + if (( line_number <= 10 )); then + _check_is_disabled_global=("${_parsed[@]}") + _FILE_IGNORE_ALL=true + return 0 + fi + _check_is_disabled=("${_parsed[@]}") else - _check_is_disabled=() + # Do not clear if file-wide ignore is set + if ! $_FILE_IGNORE_ALL; then + _check_is_disabled=() + fi fi } _check() { local file="$1" - local line_number=0 + line_number=0 + _FILE_IGNORE_ALL=false + _check_is_disabled_global=() while IFS= read -r line; do line_number=$((line_number + 1)) @@ -193,6 +221,7 @@ declare -A EQUIVALENTS=( ["awk"]="{m,g,}awk" ["gawk"]="{m,g,}awk" ["grep"]="{,e}grep" + ["gs"]="gs{,.bin}" ["which"]="which{,.debianutils}" ) _check_equivalent() { @@ -500,14 +529,14 @@ _check_udev() { check_sbin() { local file name jobs - mapfile -t sbin