diff --git a/.github/local/needrestart b/.github/local/needrestart deleted file mode 100644 index 33b23e0148..0000000000 --- a/.github/local/needrestart +++ /dev/null @@ -1,2 +0,0 @@ - - /var/lib/waagent/** r, diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 166840b447..3a0f2261db 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -9,9 +9,14 @@ jobs: - name: Check out repository code uses: actions/checkout@v4 + - name: Install linter dependencies + run: | + pipx install rust-just + echo "$HOME/.local/bin" >> $GITHUB_PATH + - name: Run basic profile linter check run: | - make check + just check build: runs-on: ${{ matrix.os }} @@ -21,10 +26,6 @@ jobs: include: - os: ubuntu-24.04 mode: default - - os: ubuntu-24.04 - mode: full-system-policy - - os: ubuntu-22.04 - mode: default steps: - name: Check out repository code uses: actions/checkout@v4 @@ -35,32 +36,23 @@ jobs: sudo apt-get install -y \ devscripts debhelper config-package-dev \ auditd apparmor-profiles apparmor-utils + pipx install rust-just + echo "$HOME/.local/bin" >> $GITHUB_PATH sudo rm /etc/apparmor.d/usr.lib.snapd.snap-confine.real - name: Build the apparmor.d package run: | - if [[ ${{ matrix.mode }} == full-system-policy ]]; then - echo -e "\noverride_dh_auto_build:\n\tmake full" >> debian/rules - fi - if [[ ${{ matrix.os }} == ubuntu-24.04 ]] && [[ ${{ matrix.mode }} == default ]]; then - # Test with Re-attach disconnected path - sed -e 's;// builder.Register("attach");builder.Register("attach");' -i pkg/prebuild/cli/cli.go - sed -e '/@{att}/d' -i apparmor.d/tunables/multiarch.d/system - fi - bash dists/build.sh dpkg + just build-dpkg - name: Install apparmor.d run: sudo dpkg --install .pkg/apparmor.d_*_amd64.deb || true - name: Reload AppArmor run: | - sudo systemctl restart apparmor.service || true - sudo systemctl status apparmor.service - - - name: Ensure compatibility with some AppArmor userspace tools - if: matrix.os != 'ubuntu-24.04' - run: | - sudo aa-enforce /etc/apparmor.d/aa-notify + if ! sudo systemctl restart apparmor.service; then + sudo journalctl -xeu apparmor.service + exit 1 + fi - name: Show AppArmor log and rules run: | @@ -81,6 +73,7 @@ jobs: tests: runs-on: ubuntu-24.04 needs: build + if: github.ref_name == 'dev' || github.event_name == 'workflow_dispatch' steps: - name: Check out repository code uses: actions/checkout@v4 @@ -100,7 +93,8 @@ jobs: sudo apt-get install -y \ apparmor-profiles apparmor-utils \ bats bats-support - sudo install -Dm0644 .github/local/needrestart /etc/apparmor.d/local/needrestart + pipx install rust-just + echo "$HOME/.local/bin" >> $GITHUB_PATH - name: Install apparmor.d run: | @@ -132,11 +126,12 @@ jobs: - name: Install integration dependencies run: | - bash tests/requirements.sh + just init + find /usr/sbin/ -type f - name: Run the integration tests run: | - make integration + just integration - name: Show final AppArmor logs if: always() diff --git a/.gitignore b/.gitignore index d888d6d5cf..276eeaa59c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,17 @@ # Build .build .logs +.pkg +.tree +.snapd +/snap +snapd.backup tests/tldr tests/tldr.tar.gz +tests/bats_dirty # mkdocs +__pycache__ .cache public site @@ -13,11 +20,12 @@ site *.deb *.buildinfo *.changes -debian/hardened debian/.debhelper debian/*.debhelper # Debian build packages +debian/apparmor.d.*/ +debian/apparmor.d-*/ debian/apparmor.d.displace debian/apparmor.d.substvars debian/apparmor.d/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f697637faf..c21d51baec 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,9 +1,7 @@ --- -include: - - template: Security/SAST.gitlab-ci.yml - variables: + PKGNAME: apparmor.d PKGDEST: $CI_PROJECT_DIR/.pkg PACKAGER: 'Alexandre Pujol ' @@ -23,8 +21,9 @@ bash: image: koalaman/shellcheck-alpine script: - shellcheck --shell=bash - PKGBUILD dists/build.sh dists/docker.sh tests/check.sh - tests/packer/init.sh tests/packer/src/aa-update tests/packer/clean.sh + PKGBUILD dists/*.sh tests/check.sh + tests/packer/*.sh tests/packer/src/aa-update + tests/autopkgtest/autopkgtest.sh debian/common.postinst debian/common.postrm golangci-lint: stage: lint @@ -38,12 +37,8 @@ packer: name: hashicorp/packer:latest entrypoint: [""] script: - - cd tests && - packer fmt --check packer/ && - packer validate --syntax-only packer/ - -sast: - stage: lint + - packer fmt tests/packer/ + - packer validate --syntax-only tests/packer/ # Code test @@ -62,11 +57,13 @@ tests: - go test $(go list ./pkg/... | grep -v /pkg/paths) -v -cover -coverprofile=coverage.out - go tool cover -func=coverage.out -check: +# Disabled as it is long and we reach the limit of GitLab CI minutes +# Enabled in Github Actions CI +.check: stage: test image: registry.gitlab.com/roddhjav/builders/archlinux script: - - make check + - just check # Package Build # ------------- @@ -84,14 +81,13 @@ archlinux: debian: stage: build - image: registry.gitlab.com/roddhjav/builders/debian:12 + image: registry.gitlab.com/roddhjav/builders/debian:13 script: - sudo chown -R build:build /builds/ - git config --global --add safe.directory $CI_PROJECT_DIR - mkdir -p "$PKGDEST" - - sudo apt-get update -q && sudo apt-get install -y config-package-dev lsb-release - - sudo apt-get install -y -t bookworm-backports golang-go - - bash dists/build.sh dpkg + - sudo apt-get update -q && sudo apt-get install -y config-package-dev golang-go lsb-release libdistro-info-perl + - just build-dpkg artifacts: expire_in: 1 day paths: @@ -99,14 +95,14 @@ debian: ubuntu: stage: build - image: registry.gitlab.com/roddhjav/builders/ubuntu:24.04 + image: registry.gitlab.com/roddhjav/builders/ubuntu:26.04 variables: GOFLAGS: "-buildvcs=false" script: - git config --global --add safe.directory $CI_PROJECT_DIR - mkdir -p "$PKGDEST" - - sudo apt-get update -q && sudo apt-get install -y config-package-dev golang-go lsb-release - - bash dists/build.sh dpkg + - sudo apt-get update -q && sudo apt-get install -y config-package-dev golang-go lsb-release libdistro-info-perl + - just build-dpkg artifacts: expire_in: 1 day paths: @@ -117,7 +113,7 @@ whonix: variables: DISTRIBUTION: whonix before_script: - - echo "\noverride_dh_auto_build:\n\tmake full" >> debian/rules + - sed -e "s/just complain/just fsp-complain/" -i debian/rules opensuse: stage: build @@ -125,7 +121,7 @@ opensuse: script: - mkdir -p "$PKGDEST" - sudo zypper install -y distribution-release golang-packaging apparmor-profiles - - bash dists/build.sh rpm + - just build-rpm artifacts: expire_in: 1 day paths: @@ -142,32 +138,32 @@ preprocess-archlinux: - archlinux script: - pacman -Syu --noconfirm --noprogressbar apparmor - - pacman -U --noconfirm --noprogressbar $PKGDEST/* + - pacman -U --noconfirm --noprogressbar $PKGDEST/${PKGNAME}-* - apparmor_parser --preprocess /etc/apparmor.d 1> /dev/null preprocess-debian: stage: preprocess - image: debian + image: debian:13 dependencies: - debian script: - apt-get update -q - apt-get install -y apparmor apparmor-profiles - - dpkg --install $PKGDEST/* + - dpkg --install $PKGDEST/${PKGNAME}_* - apparmor_parser --preprocess /etc/apparmor.d 1> /dev/null preprocess-ubuntu: stage: preprocess - image: ubuntu + image: ubuntu:26.04 dependencies: - ubuntu script: - apt-get update -q - apt-get install -y apparmor apparmor-profiles - - dpkg --install $PKGDEST/* + - dpkg --install $PKGDEST/${PKGNAME}_* - apparmor_parser --preprocess /etc/apparmor.d 1> /dev/null -preprocess-whonix: +.preprocess-whonix: extends: preprocess-debian dependencies: - whonix @@ -183,7 +179,7 @@ preprocess-opensuse: - apparmor_parser --preprocess /etc/apparmor.d 1> /dev/null -# Deploy the documentation +# Deploy the documentation # ------------------------ pages: @@ -195,7 +191,9 @@ pages: GIT_DEPTH: 0 script: - pip install -r requirements.txt - - mkdocs build --site-dir public + - bash dists/docstring.sh + - zensical build --strict + - mv site public artifacts: paths: - public diff --git a/.golangci.yaml b/.golangci.yaml index 6861d253d5..4a43f08035 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -1,15 +1,27 @@ --- version: "2" + linters: settings: + errcheck: + exclude-functions: + - (*os.File).Close + - (*os.File).WriteString + - (*os.Process).Kill + - (*github.com/roddhjav/apparmor.d/pkg/paths.Process).Kill + - (*bufio.Writer).Flush + - (*bufio.Writer).WriteString + - (*github.com/roddhjav/apparmor.d/pkg/paths.Path).Chmod + - (*github.com/roddhjav/apparmor.d/pkg/paths.Path).Remove + - (*github.com/roddhjav/apparmor.d/pkg/paths.Path).RemoveAll + - (*github.com/roddhjav/apparmor.d/cmd/aa-flatpak.FileWatcher).Close + - os.Remove + - path/filepath.WalkDir staticcheck: checks: - all - - -SA1019 - - -ST1000 exclusions: - paths: - - pkg/paths + paths: + - internal/ - tests/cmd/ - diff --git a/Justfile b/Justfile index 740b29cc11..0b34db17cd 100644 --- a/Justfile +++ b/Justfile @@ -2,26 +2,26 @@ # Copyright (C) 2025 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only -# Integration environment for apparmor.d -# -# Usage: -# just -# just img ubuntu24 server -# just vm ubuntu24 server -# just up ubuntu24 server -# just ssh ubuntu24 server -# just halt ubuntu24 server -# just destroy ubuntu24 server -# just list -# just images -# just available -# just clean - -# Build setings +# Usage: `just` +# See https://apparmor.pujol.io/development/ for more information. + +# Globally override any variables +set allow-duplicate-variables +import? '~/.aa.just' + +# Build settings + destdir := "/" build := ".build" -pkgdest := `pwd` / ".pkg/dist" +pkgdest := `pwd` / ".pkg" pkgname := "apparmor.d" +gpgkey := "06A26D531D56C42D66805049C5469996F0DF68EC" +sign := "false" + +# Prebuild options, only used for the `dev` install target +opt := "complain" + +# The following variables are only used for the development and test VM # Admin username username := "user" @@ -43,6 +43,13 @@ ssh_keyname := "id_ed25519" ssh_privatekey := home_dir() / ".ssh/" + ssh_keyname ssh_publickey := ssh_privatekey + ".pub" +# Path to the UEFI firmware +firmware := if path_exists("/usr/share/edk2/x64/OVMF.4m.fd") == "true" { + "/usr/share/edk2/x64/OVMF.4m.fd" +} else { + "/usr/share/ovmf/OVMF.fd" +} + # Where the VM are stored vm := home_dir() / ".vm" @@ -61,41 +68,116 @@ c := "--connect=qemu:///system" # VM prefix prefix := "aa-" -[doc('Show this help message')] +usage := " +Build variables available: + build " + BLUE + "# Build directory (default: " + build + ")" + NORMAL + " + destdir " + BLUE + "# Installation destination (default: " + destdir + ")" + NORMAL + " + pkgdest " + BLUE + "# Package output directory (default: " + pkgdest + ")" + NORMAL + " + opt " + BLUE + "# Prebuild option, only used for the dev install target (default: " + opt + ")" + NORMAL + " + +Development variables available: + username " + BLUE + "# VM username (default: " + username + ")" + NORMAL + " + password " + BLUE + "# VM password (default: " + password + ")" + NORMAL + " + disk_size " + BLUE + "# VM disk size (default: " + disk_size + ")" + NORMAL + " + vcpus " + BLUE + "# VM CPU (default: " + vcpus + ")" + NORMAL + " + ram " + BLUE + "# VM RAM (default: " + ram + ")" + NORMAL + " + +See https://apparmor.pujol.io/development/ for more information." + +# Show this help message help: - @echo -e "Integration environment helper for apparmor.d\n" @just --list --unsorted - @echo -e "\nSee https://apparmor.pujol.io/development/vm/ for more information." + @printf "%s\n" "{{usage}}" -[doc('Build the go programs')] +# Build the go programs +[group('build')] build: @go build -o {{build}}/ ./cmd/aa-log + @go build -o {{build}}/ ./cmd/aa-mode @go build -o {{build}}/ ./cmd/prebuild -[doc('Prebuild the profiles in enforced mode')] +# Build aa-flatpak +[group('build')] +build-aa-flatpak: + @go build -o {{build}}/ ./cmd/aa-flatpak + +# Prebuild the profiles +[group('build')] +prebuild: build + ./{{build}}/prebuild --buildir {{build}} --future + +# Prebuild the profiles in FSP mode +[group('build')] +prebuild-fsp: build + @./{{build}}/prebuild --buildir {{build}} --future --full + +# Prebuild the profiles in enforced mode +[group('build')] enforce: build - @./{{build}}/prebuild + @./{{build}}/prebuild --buildir {{build}} + +# Prebuild the profiles in enforce mode (test) +[group('build')] +enforce-test: build + @./{{build}}/prebuild --buildir {{build}} --test -[doc('Prebuild the profiles in complain mode')] +# Prebuild the profiles in complain mode +[group('build')] complain: build - @./{{build}}/prebuild --complain + ./{{build}}/prebuild --buildir {{build}} --complain -[doc('Prebuild the profiles in FSP mode')] -fsp: build - @./{{build}}/prebuild --complain --full +# Prebuild the profiles in complain mode (test) +[group('build')] +complain-test: build + @./{{build}}/prebuild --buildir {{build}} --complain --test -[doc('Install the profiles')] -install: +# Install base abstraction, tunable and booleans +[group('install')] +install-base: + #!/usr/bin/env bash + set -eu -o pipefail + mapfile -t files < <(find "{{build}}/apparmor.d/abstractions" -type f -printf "%P\n") + for file in "${files[@]}"; do + install -Dm0644 "{{build}}/apparmor.d/abstractions/$file" "{{destdir}}/etc/apparmor.d/abstractions/$file" + done + mapfile -t files < <(find "{{build}}/apparmor.d/tunables" -type f -printf "%P\n") + for file in "${files[@]}"; do + install -Dm0644 "{{build}}/apparmor.d/tunables/$file" "{{destdir}}/etc/apparmor.d/tunables/$file" + done + +# Install apparmor.d tools +[group('install')] +install-tools: #!/usr/bin/env bash set -eu -o pipefail install -Dm0755 {{build}}/aa-log {{destdir}}/usr/bin/aa-log - for file in $(find "{{build}}/share" -type f -not -name "*.md" -printf "%P\n"); do + install -Dm0755 {{build}}/aa-mode {{destdir}}/usr/bin/aa-mode + mapfile -t share < <(find "{{build}}/share" -type f -not -name "*.md" -not -name "*aa-flatpak*" -printf "%P\n") + for file in "${share[@]}"; do install -Dm0644 "{{build}}/share/$file" "{{destdir}}/usr/share/$file" done - for file in $(find "{{build}}/apparmor.d" -type f -printf "%P\n"); do + +# Install aa-flatpak +[group('install')] +install-aa-flatpak: + @install -Dm0755 {{build}}/aa-flatpak {{destdir}}/usr/bin/aa-flatpak + @install -Dm0644 systemd/aa-flatpak.service {{destdir}}/usr/lib/systemd/system/aa-flatpak.service + @install -Dm0644 share/bash-completion/completions/aa-flatpak {{destdir}}/usr/share/bash-completion/completions/aa-flatpak + @install -Dm0644 share/man/man1/aa-flatpak.1 {{destdir}}/usr/share/man/man1/aa-flatpak.1 + @install -Dm0644 share/zsh/site-functions/_aa-flatpak.zsh {{destdir}}/usr/share/zsh/site-functions/_aa-flatpak.zsh + +# Install prebuilt profiles +[group('install')] +install-prebuilt: + #!/usr/bin/env bash + set -eu -o pipefail + mapfile -t aa < <(find "{{build}}/apparmor.d" -type f -not -path "*/abstractions/*" -not -path "*/tunables/*" -printf "%P\n") + for file in "${aa[@]}"; do + #install -Dm0644 "{{build}}/apparmor.d/$file" "{{destdir}}/usr/share/apparmor.d/$file" install -Dm0644 "{{build}}/apparmor.d/$file" "{{destdir}}/etc/apparmor.d/$file" done - for file in $(find "{{build}}/apparmor.d" -type l -printf "%P\n"); do + mapfile -t links < <(find "{{build}}/apparmor.d" -type l -printf "%P\n") + for file in "${links[@]}"; do mkdir -p "{{destdir}}/etc/apparmor.d/disable" cp -d "{{build}}/apparmor.d/$file" "{{destdir}}/etc/apparmor.d/$file" done @@ -108,78 +190,209 @@ install: install -Dm0644 "$file" "{{destdir}}/usr/lib/systemd/user/$service.d/apparmor.conf" done -[doc('Build & install apparmor.d on Arch based systems')] -pkg: - @makepkg --syncdeps --install --cleanbuild --force --noconfirm - -[doc('Build & install apparmor.d on Debian based systems')] -dpkg: - @bash dists/build.sh dpkg - @sudo dpkg -i {{pkgdest}}/{{pkgname}}_*.deb +# Install prebuild profiles +[group('install')] +install: install-tools + #!/usr/bin/env bash + set -eu -o pipefail + mapfile -t aa < <(find "{{build}}/apparmor.d" -type f -printf "%P\n") + for file in "${aa[@]}"; do + install -Dm0644 "{{build}}/apparmor.d/$file" "{{destdir}}/etc/apparmor.d/$file" + done + mapfile -t links < <(find "{{build}}/apparmor.d" -type l -printf "%P\n") + for file in "${links[@]}"; do + mkdir -p "{{destdir}}/etc/apparmor.d/disable" + cp -d "{{build}}/apparmor.d/$file" "{{destdir}}/etc/apparmor.d/$file" + done + for file in "{{build}}/systemd/system/"*; do + service="$(basename "$file")" + install -Dm0644 "$file" "{{destdir}}/usr/lib/systemd/system/$service.d/apparmor.conf" + done + for file in "{{build}}/systemd/user/"*; do + service="$(basename "$file")" + install -Dm0644 "$file" "{{destdir}}/usr/lib/systemd/user/$service.d/apparmor.conf" + done -[doc('Build & install apparmor.d on OpenSUSE based systems')] -rpm: - @bash dists/build.sh rpm - @sudo rpm -ivh --force {{pkgdest}}/{{pkgname}}-*.rpm +# Locally install prebuild profiles +[group('install')] +local +names: + #!/usr/bin/env bash + set -eu -o pipefail + install -Dm0755 {{build}}/aa-log {{destdir}}/usr/bin/aa-log + mapfile -t abs < <(find "{{build}}/apparmor.d/abstractions" -type f -printf "%P\n") + for file in "${abs[@]}"; do + install -Dm0644 "{{build}}/apparmor.d/abstractions/$file" "{{destdir}}/etc/apparmor.d/abstractions/$file" + done; + mapfile -t tunables < <(find "{{build}}/apparmor.d/tunables" -type f -printf "%P\n") + for file in "${tunables[@]}"; do + install -Dm0644 "{{build}}/apparmor.d/tunables/$file" "{{destdir}}/etc/apparmor.d/tunables/$file" + done; + echo "Warning: profile dependencies fallback to unconfined." + for file in {{names}}; do + grep -Ei 'rPx|rpx' "{{build}}/apparmor.d/$file" || true + sed -i -e "s/rPx/rPUx/g" "{{build}}/apparmor.d/$file" + install -Dvm0644 "{{build}}/apparmor.d/$file" "{{destdir}}/etc/apparmor.d/$file" + done; + systemctl restart apparmor.service || journalctl -xeu apparmor.service + +# Prebuild, install, and load a dev profile +[group('install')] +dev +names: + go run ./cmd/prebuild --{{opt}} + for file in {{names}}; do \ + sudo install -Dm644 -v {{build}}/apparmor.d/$file /etc/apparmor.d/$file; \ + done + sudo systemctl restart apparmor.service || sudo journalctl -xeu apparmor.service -[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 +# Build the package on Arch Linux +[group('packages')] +build-pkg: (_ensure_pkgdest) + @PKGDEST={{pkgdest}} BUILDDIR=/tmp/makepkg makepkg --syncdeps --force --cleanbuild --noconfirm --noprogressbar -[doc('Run the linters')] +# Build the package on Debian +[group('packages')] +build-dpkg: (_ensure_pkgdest) + #!/usr/bin/env bash + set -eu -o pipefail + version=`just version` + suffix="" + if dpkg-vendor --is Ubuntu; then + suffix="ubuntu1~$(lsb_release -sr)" + elif dpkg-vendor --is Debian; then + if [[ "$(lsb_release -sc)" == "forky" ]]; then + suffix="1+deb14" + else + suffix="1+deb$(lsb_release -sr)" + fi + fi + dch --urgency=medium --newversion="$version-$suffix" --distribution=`lsb_release -sc` --controlmaint "Release $version-$suffix" + dpkg-buildpackage -b -d {{ if sign == "true" { "--sign-key=" + gpgkey } else { "--no-sign" } }} + lintian --color always --display-info --pedantic --tag-display-limit 0 || true + mv ../{{pkgname}}*.deb {{pkgdest}}/ + +# Build the package on OpenSUSE +[group('packages')] +build-rpm: (_ensure_pkgdest) + #!/usr/bin/env bash + set -eu -o pipefail + RPMBUILD_ROOT=$(mktemp -d /tmp/{{pkgname}}.XXXXXX) + ARCH=$(uname -m) + VERSION="$(just version)" + echo "Building {{pkgname}} version $VERSION for $ARCH architecture" + readonly RPMBUILD_ROOT ARCH VERSION + + mkdir -p "$RPMBUILD_ROOT"/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS/tmp} + cp -p "dists/{{pkgname}}.spec" "$RPMBUILD_ROOT/SPECS" + tar -czf "$RPMBUILD_ROOT/SOURCES/{{pkgname}}-$VERSION.tar.gz" --transform "s,^,{{pkgname}}-$VERSION/," ./* + + cd "$RPMBUILD_ROOT" + sed -i "s/^Version:.*/Version: $VERSION/" "SPECS/{{pkgname}}.spec" + rpmbuild -bb --define "_topdir $RPMBUILD_ROOT" "SPECS/{{pkgname}}.spec" + + find "$RPMBUILD_ROOT/RPMS" -name '*.rpm' -exec mv -t "{{pkgdest}}/" {} + + rm -rf "$RPMBUILD_ROOT" + +# Build & install apparmor.d on Arch based systems +[group('packages')] +pkg: build-pkg + @sudo pacman -U --noconfirm \ + {{pkgdest}}/{{pkgname}}-`just version`*.pkg.tar.zst \ + {{pkgdest}}/{{pkgname}}-base-`just version`*.pkg.tar.zst \ + {{pkgdest}}/{{pkgname}}-tools-`just version`*.pkg.tar.zst + +# Build & install apparmor.d on Debian based systems +[group('packages')] +dpkg name="": build-dpkg + @sudo dpkg -i \ + {{pkgdest}}/{{pkgname}}{{ if name != "" { "." + name } else { "" } }}_`just version`*.deb + +# Build & install apparmor.d on OpenSUSE based systems +[group('packages')] +rpm: build-rpm + @sudo rpm -ivh --force \ + {{pkgdest}}/{{pkgname}}-`just version`*.rpm + +# Run the linters +[group('linter')] lint: golangci-lint run packer fmt tests/packer/ packer validate --syntax-only tests/packer/ shellcheck --shell=bash \ - PKGBUILD dists/build.sh dists/docker.sh tests/check.sh \ - tests/packer/init.sh tests/packer/src/aa-update tests/packer/clean.sh \ - debian/{{pkgname}}.postinst debian/{{pkgname}}.postrm + PKGBUILD dists/*.sh tests/check.sh \ + tests/packer/*.sh tests/packer/src/aa-update \ + tests/autopkgtest/autopkgtest.sh debian/common.postinst debian/common.postrm -[doc('Run style checks on the profiles')] +# Run style checks on the profiles +[group('linter')] check: @bash tests/check.sh -[doc('Generate the man pages')] +# Generate the man pages +[group('docs')] man: + @pandoc -t man -s -o share/man/man1/aa-mode.1 share/man/man1/aa-mode.md @pandoc -t man -s -o share/man/man8/aa-log.8 share/man/man8/aa-log.md -[doc('Build the documentation')] +# Generate abstractions and tunable documentation from the source +[group('docs')] +docstring: + @bash dists/docstring.sh + +# Build the documentation +[group('docs')] docs: - @ENABLED_GIT_REVISION_DATE=false MKDOCS_OFFLINE=true mkdocs build --strict + @ENABLED_GIT_REVISION_DATE=false MKDOCS_OFFLINE=true zensical build --strict -[doc('Serve the documentation')] +# Serve the documentation +[group('docs')] serve: - @ENABLED_GIT_REVISION_DATE=false MKDOCS_OFFLINE=false mkdocs serve + @ENABLED_GIT_REVISION_DATE=false MKDOCS_OFFLINE=false zensical serve --open -[doc('Remove all build artifacts')] +# Remove all build artifacts clean: @rm -rf \ - debian/.debhelper debian/debhelper* debian/*.debhelper debian/{{pkgname}} \ - .pkg/{{pkgname}}* {{build}} coverage.out - -[doc('Build the apparmor.d package')] -package dist: + debian/.debhelper debian/debhelper* debian/*.debhelper debian/{{pkgname}}* \ + debian/*.substvars debian/*.debhelper debian/files \ + {{pkgdest}}/{{pkgname}}* {{pkgdest}}/ubuntu {{pkgdest}}/debian \ + {{pkgdest}}/archlinux {{pkgdest}}/opensuse \ + {{build}} coverage.out .logs/autopkgtest/ site .cache + +# Build the package in a clean OCI container +[group('packages')] +package dist release="" flavor="": + bash dists/docker.sh {{dist}} {{release}} {{flavor}} + +# Build all packages in a clean OCI container +[group('packages')] +packages: (clean) #!/usr/bin/env bash set -eu -o pipefail - dist="{{dist}}" - version="" - if [[ $dist =~ ubuntu([0-9]+) ]]; then - version="${BASH_REMATCH[1]}.04" - dist="ubuntu" - elif [[ $dist =~ debian([0-9]+) ]]; then - version="${BASH_REMATCH[1]}" - dist="debian" - fi - bash dists/docker.sh $dist $version + declare -A matrix=( + # ["archlinux"]="-" + ["debian"]="13" + ["ubuntu"]="24.04 25.10 26.04" + # ["opensuse"]="-" + ) + for dist in "${!matrix[@]}"; do + IFS=' ' read -r -a releases <<< "${matrix[$dist]}" + for release in "${releases[@]}"; do + echo "{{ RED + BOLD }}Building package for $dist $release{{ NORMAL }}" + bash dists/docker.sh $dist $release + done + done -[doc('Build the image')] -img dist flavor: (package dist) - @mkdir -p {{base_dir}} +# Build the VM image +[group('vm')] +img dist release flavor: (package dist release flavor) + #!/usr/bin/env bash + set -eu -o pipefail + RELEASE="{{release}}" + [[ "$RELEASE" == "-" ]] && RELEASE="" + mkdir -p {{base_dir}} packer build -force \ -var dist={{dist}} \ + -var release="$RELEASE" \ -var flavor={{flavor}} \ -var prefix={{prefix}} \ -var username={{username}} \ @@ -188,113 +401,284 @@ img dist flavor: (package dist) -var disk_size={{disk_size}} \ -var cpus={{vcpus}} \ -var ram={{ram}} \ + -var firmware={{firmware}} \ -var base_dir={{base_dir}} \ -var output_dir={{output_dir}} \ tests/packer/ -[doc('Create the machine')] -create dist flavor: - @cp -f {{base_dir}}/{{prefix}}{{dist}}-{{flavor}}.qcow2 {{vm}}/{{prefix}}{{dist}}-{{flavor}}.qcow2 +# Create the machine +[group('vm')] +create osinfo flavor: + @cp -f {{base_dir}}/{{prefix}}{{osinfo}}-{{flavor}}.qcow2 {{vm}}/{{prefix}}{{osinfo}}-{{flavor}}.qcow2 @virt-install {{c}} \ --import \ - --name {{prefix}}{{dist}}-{{flavor}} \ + --name {{prefix}}{{osinfo}}-{{flavor}} \ --vcpus {{vcpus}} \ --ram {{ram}} \ --machine q35 \ - --boot uefi \ + {{ if osinfo == "archlinux" { "" } else { "--boot uefi" } }} \ --memorybacking source.type=memfd,access.mode=shared \ - --disk path={{vm}}/{{prefix}}{{dist}}-{{flavor}}.qcow2,format=qcow2,bus=virtio \ + --disk path={{vm}}/{{prefix}}{{osinfo}}-{{flavor}}.qcow2,format=qcow2,bus=virtio \ --filesystem "`pwd`,0a31bc478ef8e2461a4b1cc10a24cc4",accessmode=passthrough,driver.type=virtiofs \ - --os-variant "`just get_osinfo {{dist}}`" \ + --os-variant "{{ if osinfo == "opensuse" { "opensusetumbleweed" } else { osinfo } }}" \ --graphics spice \ --audio id=1,type=spice \ --sound model=ich9 \ --noautoconsole -[doc('Start a machine')] -up dist flavor: - @virsh {{c}} start {{prefix}}{{dist}}-{{flavor}} - -[doc('Stops the machine')] -halt dist flavor: - @virsh {{c}} shutdown {{prefix}}{{dist}}-{{flavor}} - -[doc('Reboot the machine')] -reboot dist flavor: - @virsh {{c}} reboot {{prefix}}{{dist}}-{{flavor}} - -[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 - -[doc('Connect to the machine')] -ssh dist flavor: - @ssh {{sshopt}} {{username}}@`just get_ip {{dist}} {{flavor}}` - -[doc('List the machines')] +# Start a machine +[group('vm')] +up osinfo flavor: + @virsh {{c}} start {{prefix}}{{osinfo}}-{{flavor}} + +# Stops the machine +[group('vm')] +halt osinfo flavor: + @virsh {{c}} shutdown {{prefix}}{{osinfo}}-{{flavor}} + +# Reboot the machine +[group('vm')] +reboot osinfo flavor: + @virsh {{c}} reboot {{prefix}}{{osinfo}}-{{flavor}} + +# Destroy the machine +[group('vm')] +destroy osinfo flavor: + @virsh {{c}} destroy {{prefix}}{{osinfo}}-{{flavor}} || true + @virsh {{c}} undefine {{prefix}}{{osinfo}}-{{flavor}} --nvram + @rm -fv {{vm}}/{{prefix}}{{osinfo}}-{{flavor}}.qcow2 + +# List all snapshots for a machine +[group('vm')] +snapshots osinfo flavor: + @virsh {{c}} snapshot-list {{prefix}}{{osinfo}}-{{flavor}} + +# Snapshot a machine +[group('vm')] +snapshot osinfo flavor snapname: + @virsh {{c}} snapshot-create-as {{prefix}}{{osinfo}}-{{flavor}} --name {{snapname}} + +# Restore a machine to a specified snapshot +[group('vm')] +restore osinfo flavor snapname: + @virsh {{c}} snapshot-revert {{prefix}}{{osinfo}}-{{flavor}} {{snapname}} + +# Delete a specified snapshot from a machine +[group('vm')] +delete osinfo flavor snapname: + @virsh {{c}} snapshot-delete {{prefix}}{{osinfo}}-{{flavor}} {{snapname}} + +# Connect to the machine +[group('vm')] +ssh osinfo flavor: + @ssh {{sshopt}} {{username}}@`just _get_ip {{osinfo}} {{flavor}}` + +# Mount the shared directory on the machine +[group('vm')] +mount osinfo flavor: + @ssh {{sshopt}} {{username}}@`just _get_ip {{osinfo}} {{flavor}}` \ + sh -c 'mount | grep 0a31bc478ef8e2461a4b1cc10a24cc4 || sudo mount 0a31bc478ef8e2461a4b1cc10a24cc4' + +# Unmout the shared directory on the machine +[group('vm')] +umount osinfo flavor: + @ssh {{sshopt}} {{username}}@`just _get_ip {{osinfo}} {{flavor}}` \ + sh -c 'true; sudo umount /home/{{username}}/Projects/apparmor.d || true' + +# List the machines +[group('vm')] list: - @echo -e '\033[1m Id Distribution Flavor State\033[0m' + @printf "{{BOLD}} %-4s %-22s %s{{NORMAL}}\n" "Id" "OsInfo-Flavor" "State" @virsh {{c}} list --all | grep {{prefix}} | sed 's/{{prefix}}//g' -[doc('List the images')] +# List the VM images +[group('vm')] images: #!/usr/bin/env bash set -eu -o pipefail - ls -lh {{base_dir}} | awk ' - BEGIN { - printf("\033[1m%-18s %-10s %-5s %s\033[0m\n", "Distribution", "Flavor", "Size", "Date") - } - { - if ($9 ~ /^{{prefix}}.*\.qcow2$/) { - split($9, arr, "-|\\.") - printf("%-18s %-10s %-5s %s %s %s\n", arr[2], arr[3], $5, $6, $7, $8) - } - } - ' - -[doc('List the machine that can be created')] + mkdir -p {{base_dir}} + ( + printf "{{BOLD}}%s %s %s %s %s{{NORMAL}}\n" "OsInfo" "Flavor" "Size" "Date" + find {{base_dir}} -iname '{{prefix}}*' -type f -printf "%f %k %Tb %Td %TH:%TM\n" | sort | awk ' + { + split($1, item, "-") + split(item[3], flavor, "\\.") + if ($2>=1048576) { + printf("%s %s %.1fGB %s %s %s\n", item[2], flavor[1], $2/1048576, $3, $4, $5) + } else { + printf("%s %s %.fMB %s %s %s\n", item[2], flavor[1], $2/1024, $3, $4, $5) + } + } + ' + ) | column -t + +# List the VM images that can be created +[group('vm')] available: #!/usr/bin/env bash set -eu -o pipefail - ls -lh tests/cloud-init | awk ' - BEGIN { - printf("\033[1m%-18s %s\033[0m\n", "Distribution", "Flavor") - } - { - if ($9 ~ /^.*\.user-data.yml$/) { - split($9, arr, "-|\\.") - printf("%-18s %s\n", arr[1], arr[2]) - } - } - ' - -[doc('Run the integration tests on the machine')] -integration dist flavor: - @ssh {{sshopt}} user@`just get_ip {{dist}} {{flavor}}` \ - cp -rf /home/user/Projects/apparmor.d/tests/integration/ /home/user/Projects - @ssh {{sshopt}} user@`just get_ip {{dist}} {{flavor}}` \ - sudo umount /home/user/Projects/apparmor.d - @ssh {{sshopt}} user@`just get_ip {{dist}} {{flavor}}` \ - @bats --recursive --timing --print-output-on-failure Projects/integration/ - - - -get_ip dist flavor: - @virsh --quiet --readonly {{c}} domifaddr {{prefix}}{{dist}}-{{flavor}} | \ + ( + printf "{{BOLD}}%s %s %s{{NORMAL}}\n" "Distribution" "Release" "Flavor" + find tests/cloud-init -iname '*.user-data.yml' -type f -printf "%f\n" | sort | awk ' + { + split($1, item, "-") + match(item[1], /^([a-z]+)([0-9.]*?)$/, osinfo) + release = (osinfo[2] == "" ? "-" : osinfo[2]) + split(item[2], flavor, "\\.") + printf("%s %s %s\n", osinfo[1], release, flavor[1]) + } + ' + ) | column -t + +# Run the unit tests +[group('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 autopkgtest tests +[group('tests')] +autopkgtest osinfo: + @PREFIX='{{prefix}}' VM_DIR='{{vm}}' \ + USER='{{username}}' PASSWORD='{{password}}' SSH_OPT='{{sshopt}}' \ + bash tests/autopkgtest/autopkgtest.sh run {{osinfo}} + +# Update the apparmor.d package on the test machine +[group('tests')] +autopkgtest-update dist release: + just up {{dist}}{{release}} test || true + just package {{dist}} {{release}} test + scp {{sshopt}} {{pkgdest}}/{{pkgname}}_*.deb \ + {{username}}@`just _get_ip {{dist}}{{release}} test`:/home/{{username}}/Projects/ + ssh {{sshopt}} {{username}}@`just _get_ip {{dist}}{{release}} test` \ + sudo dpkg -i /home/{{username}}/Projects/{{pkgname}}_*.deb + just halt {{dist}}{{release}} test + +_autopkgtest-log-merge: + @mkdir -p .logs/autopkgtest + @cat .logs/autopkgtest/aa-log-* > .logs/autopkgtest/merged.log + +# Report all collected logs +[group('tests')] +autopkgtest-log: (_autopkgtest-log-merge) + @aa-log --file .logs/autopkgtest/merged.log + +# Report all generated rules +[group('tests')] +autopkgtest-rules: (_autopkgtest-log-merge) + @aa-log --rules --file .logs/autopkgtest/merged.log + +# Install dependencies for the integration tests +[group('tests')] +init: + @bash tests/requirements.sh + +# Run the integration tests +[group('tests')] +integration name="": + bats --recursive --timing --print-output-on-failure tests/integration/{{name}} + +# Install dependencies for the integration tests (machine) +[group('tests')] +tests-init osinfo flavor: + @ssh {{sshopt}} {{username}}@`just _get_ip {{osinfo}} {{flavor}}` \ + just --justfile /home/{{username}}/Projects/apparmor.d/Justfile init + +# Synchronize the integration tests (machine) +[group('tests')] +tests-sync osinfo flavor: + @ssh {{sshopt}} {{username}}@`just _get_ip {{osinfo}} {{flavor}}` \ + rsync -a --delete /home/{{username}}/Projects/apparmor.d/tests/ /home/{{username}}/Projects/tests/ + +# Re-synchronize the integration tests (machine) +[group('tests')] +tests-resync osinfo flavor: (mount osinfo flavor) \ + (tests-sync osinfo flavor) \ + (umount osinfo flavor) + +# Run the integration tests (machine) +[group('tests')] +tests-run osinfo flavor name="": (tests-resync osinfo flavor) + ssh {{sshopt}} {{username}}@`just _get_ip {{osinfo}} {{flavor}}` \ + bats --recursive --pretty --timing --print-output-on-failure \ + /home/{{username}}/Projects/tests/integration/{{name}} + +# Get the current apparmor.d release version +[group('version')] +version: + @bash -c 'source PKGBUILD && echo "${pkgver%~dev}"' + +# Create a new version number from the current release +[group('version')] +version-new: + @bash -c 'source PKGBUILD && IFS="." read -r major minor patch <<< "$pkgver" && echo "${major}.$(( minor + 1 )).0"' + +# Create a new release +[group('release')] +release: clean commit archive publish repo + +# Write the new release version to package files, commit and tag it +[group('release')] +commit: + #!/usr/bin/env bash + set -eu -o pipefail + version=`just version-new` + git restore debian/changelog + cat > debian/changelog.tmp <<-EOF + {{pkgname}} (${version}-1) stable; urgency=medium + + * Release {{pkgname}} v${version} + + -- $(git config user.name) <$(git config user.email)> $(date -R) + + EOF + cat debian/changelog >> debian/changelog.tmp + mv debian/changelog.tmp debian/changelog + sed -i "s/^pkgver=.*/pkgver=$version/" PKGBUILD + sed -i "s/^Version:.*/Version: $version/" "dists/{{pkgname}}.spec" + git add PKGBUILD "dists/{{pkgname}}.spec" debian/changelog + git commit -S -m "Release {{pkgname}} v$version" + git tag -a "v$version" -m "{{pkgname}} v$version" --local-user={{gpgkey}} + +# Create a release archive +[group('release')] +archive: + #!/usr/bin/env bash + set -eu -o pipefail + version=`just version` + mkdir -p {{pkgdest}}/release/ + git archive \ + --format=tar.gz \ + --prefix={{pkgname}}-$version/ \ + --output={{pkgdest}}/release/{{pkgname}}-$version.tar.gz \ + v$version + gpg --armor --default-key {{gpgkey}} --detach-sig {{pkgdest}}/release/{{pkgname}}-$version.tar.gz + gpg --verify {{pkgdest}}/release/{{pkgname}}-$version.tar.gz.asc + +# Publish the new release on Github +[group('release')] +publish: + #!/usr/bin/env bash + set -eu -o pipefail + owner="roddhjav" + version=`just version` + git push origin main --tags + gh release create "v$version" --notes "" --repo $owner/{{pkgname}} + gh release upload "v$version" --repo $owner/{{pkgname}} \ + {{pkgdest}}/release/{{pkgname}}-$version.tar.gz \ + {{pkgdest}}/release/{{pkgname}}-$version.tar.gz.asc + +# Create & upload new release packages to the repositories +[group('release')] +repo path="../../../Packages": + just --justfile {{path}}/pkgbuilds/Justfile publish {{pkgname}} `just version` + just --justfile {{path}}/repo.pujol.io/Justfile publish {{pkgname}} `just version` + +_ensure_pkgdest: + @mkdir -p {{pkgdest}} + +_get_ip osinfo flavor: + @virsh --quiet --readonly {{c}} domifaddr {{prefix}}{{osinfo}}-{{flavor}} | \ head -1 | \ grep -E -o '([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}' - -get_osinfo dist: - #!/usr/bin/env python3 - osinfo = { - "archlinux": "archlinux", - "debian12": "debian12", - "debian13": "debian13", - "ubuntu22": "ubuntu22.04", - "ubuntu24": "ubuntu24.04", - "ubuntu25": "ubuntu25.04", - "opensuse": "opensusetumbleweed", - } - print(osinfo.get("{{dist}}", "{{dist}}")) diff --git a/Makefile b/Makefile deleted file mode 100644 index 8bc8757bca..0000000000 --- a/Makefile +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/make -f -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2022-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - -DESTDIR ?= / -BUILD ?= .build -PKGDEST ?= ${PWD}/.pkg -PKGNAME := apparmor.d -PROFILES = $(filter-out dpkg,$(notdir $(wildcard ${BUILD}/apparmor.d/*))) - -.PHONY: all -all: build - @./${BUILD}/prebuild --complain - -.PHONY: build -build: - @go build -o ${BUILD}/ ./cmd/aa-log - @go build -o ${BUILD}/ ./cmd/prebuild - -.PHONY: enforce -enforce: build - @./${BUILD}/prebuild - -.PHONY: full -full: build - @./${BUILD}/prebuild --complain --full - -.PHONY: install -install: - @install -Dm0755 ${BUILD}/aa-log ${DESTDIR}/usr/bin/aa-log - @for file in $(shell find "${BUILD}/share" -type f -not -name "*.md" -printf "%P\n"); do \ - install -Dm0644 "${BUILD}/share/$${file}" "${DESTDIR}/usr/share/$${file}"; \ - done; - @for file in $(shell find "${BUILD}/apparmor.d" -type f -printf "%P\n"); do \ - install -Dm0644 "${BUILD}/apparmor.d/$${file}" "${DESTDIR}/etc/apparmor.d/$${file}"; \ - done; - @for file in $(shell find "${BUILD}/apparmor.d" -type l -printf "%P\n"); do \ - mkdir -p "${DESTDIR}/etc/apparmor.d/disable"; \ - cp -d "${BUILD}/apparmor.d/$${file}" "${DESTDIR}/etc/apparmor.d/$${file}"; \ - done; - @for file in ${BUILD}/systemd/system/*; do \ - service="$$(basename "$$file")"; \ - install -Dm0644 "$${file}" "${DESTDIR}/usr/lib/systemd/system/$${service}.d/apparmor.conf"; \ - done; - @for file in ${BUILD}/systemd/user/*; do \ - service="$$(basename "$$file")"; \ - install -Dm0644 "$${file}" "${DESTDIR}/usr/lib/systemd/user/$${service}.d/apparmor.conf"; \ - done - - -.PHONY: $(PROFILES) -$(PROFILES): - @install -Dm0755 ${BUILD}/aa-log ${DESTDIR}/usr/bin/aa-log - @for file in $(shell find ${BUILD}/apparmor.d/abstractions/ -type f -printf "%P\n"); do \ - install -Dm0644 "${BUILD}/apparmor.d/abstractions/$${file}" "${DESTDIR}/etc/apparmor.d/abstractions/$${file}"; \ - done; - @for file in $(shell find ${BUILD}/apparmor.d/tunables/ -type f -printf "%P\n"); do \ - install -Dm0644 "${BUILD}/apparmor.d/tunables/$${file}" "${DESTDIR}/etc/apparmor.d/tunables/$${file}"; \ - done; - @echo "Warning: profile dependencies fallback to unconfined." - @for file in ${@}; do \ - grep 'rPx' "${BUILD}/apparmor.d/$${file}"; \ - sed -i -e "s/rPx/rPUx/g" "${BUILD}/apparmor.d/$${file}"; \ - install -Dvm0644 "${BUILD}/apparmor.d/$${file}" "${DESTDIR}/etc/apparmor.d/$${file}"; \ - done; - @systemctl restart apparmor || sudo journalctl -xeu apparmor.service - -.PHONY: dev -name ?= -dev: - @go run ./cmd/prebuild --complain --file $(shell 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 - -.PHONY: pkg -pkg: - @makepkg --syncdeps --install --cleanbuild --force --noconfirm - -.PHONY: dpkg -dpkg: - @bash dists/build.sh dpkg - @sudo dpkg -i ${PKGDEST}/${PKGNAME}_*.deb - -.PHONY: rpm -rpm: - @bash dists/build.sh rpm - @sudo rpm -ivh --force ${PKGDEST}/${PKGNAME}-*.rpm - -.PHONY: check -check: - @bash tests/check.sh - -.PHONY: integration -integration: - @bats --recursive --timing --print-output-on-failure tests/integration/ diff --git a/PKGBUILD b/PKGBUILD index ca1aaa8402..f67df65505 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -3,37 +3,53 @@ # 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-base + apparmor.d-tools +) +pkgver=0.4907.0 pkgrel=1 pkgdesc="Full set of apparmor profiles" -arch=("x86_64") -url="https://github.com/roddhjav/$pkgname" +arch=('x86_64' 'armv6h' 'armv7h' 'aarch64') +url="https://github.com/roddhjav/apparmor.d" license=('GPL-2.0-only') -depends=('apparmor') -makedepends=('go' 'git' 'rsync' 'just') -conflicts=("$pkgname-git") - -pkgver() { - cd "$srcdir/$pkgname" - echo "0.$(git rev-list --count HEAD)" -} +makedepends=('go' 'rsync' 'just') prepare() { rsync -a --delete "$startdir" "$srcdir" } build() { - cd "$srcdir/$pkgname" + cd "$srcdir/$pkgbase" export CGO_CPPFLAGS="${CPPFLAGS}" export CGO_CFLAGS="${CFLAGS}" export CGO_CXXFLAGS="${CXXFLAGS}" export CGO_LDFLAGS="${LDFLAGS}" - export GOFLAGS="-buildmode=pie -trimpath -ldflags=-linkmode=external -mod=readonly -modcacherw" - DISTRIBUTION=arch just complain + export GOPATH="${srcdir}" + export GOFLAGS="-buildmode=pie -trimpath -ldflags=-linkmode=external -mod=readonly -modcacherw -tags=dev" + export DISTRIBUTION=arch + just complain +# just prebuild +} + +package_apparmor.d() { + depends=('apparmor' 'apparmor.d-base' 'apparmor.d-tools') + arch=("any") + cd "$srcdir/$pkgbase" + just destdir="$pkgdir" install-prebuilt +} + +package_apparmor.d-base() { + pkgdesc="$pkgdesc (base abstractions, tunables, and booleans)" + arch=("any") + cd "$srcdir/$pkgbase" + just destdir="$pkgdir" install-base } -package() { - cd "$srcdir/$pkgname" - just destdir="$pkgdir" install +package_apparmor.d-tools() { + pkgdesc="$pkgdesc (userland toolings)" + cd "$srcdir/$pkgbase" + just destdir="$pkgdir" install-tools } diff --git a/README.md b/README.md index a2ae8d6fb8..a64e0d900c 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # apparmor.d -[![][workflow]][action] [![][build]][project] [![][quality]][goreportcard] [![][matrix]][matrix-link] +[![][workflow]][action] [![][build]][project] [![][quality]][goreportcard] [![][matrix]][matrix-link] [![][play]][play-link] **Full set of AppArmor profiles** @@ -37,12 +37,14 @@ * XFCE (Lightdm) *(work in progress)* - [Fully tested](https://apparmor.pujol.io/development/tests/) +**Demo** + +You want to try this project, or you are curious about the advanced usage and security it can provide without installing it on your machine. You can try it online on my AppArmor play machine at https://play.pujol.io/ + > This project is originally based on the work from [Morfikov][upstream] and aims to extend it to more Linux distributions and desktop environments. ## Concepts -*One profile a day keeps the hacker away* - There are over 50000 Linux packages and even more applications. It is simply not possible to write an AppArmor profile for all of them. Therefore, a question arises: **What to confine and why?** @@ -58,6 +60,10 @@ Building the largest set of AppArmor profiles: - [Linux Security Summit North America (LSS-NA 2023)](https://events.linuxfoundation.org/linux-security-summit-north-america/) *([Slide](https://lssna2023.sched.com/event/1K7bI/building-the-largest-working-set-of-apparmor-profiles-alexandre-pujol-the-collaboratory-tudublin), [Video](https://www.youtube.com/watch?v=OzyalrOzxE8))* - [Ubuntu Summit 2023](https://events.canonical.com/event/31/) *([Slide](https://events.canonical.com/event/31/contributions/209/), [Video](https://www.youtube.com/watch?v=GK1J0TlxnFI))* +Lessons learned while making an AppArmor Play machine: + +- [Linux Security Summit North America (LSS-NA 2025)](https://events.linuxfoundation.org/linux-security-summit-north-america/) *([Slide](https://lssna2025.sched.com/event/1zalf/lessons-learned-while-making-an-apparmor-play-machine-alexandre-pujol-linagora), [Video](https://www.youtube.com/watch?v=zCSl8honRI0))* + ## Installation Please see [apparmor.pujol.io/install](https://apparmor.pujol.io/install) @@ -92,6 +98,8 @@ and thus has the same license (GPL2). [goreportcard]: https://goreportcard.com/report/github.com/roddhjav/apparmor.d [matrix]: https://img.shields.io/badge/Matrix-%23apparmor.d-blue?style=flat-square&logo=matrix [matrix-link]: https://matrix.to/#/#apparmor.d:matrix.org +[play]: https://img.shields.io/badge/Live_Demo-play.pujol.io-blue?style=flat-square +[play-link]: https://play.pujol.io [android_model]: https://arxiv.org/pdf/1904.05572 [clipos]: https://clip-os.org/en/ diff --git a/apparmor.d/abstractions/X-strict b/apparmor.d/abstractions/X-strict index 4c506da69c..2415bc0677 100644 --- a/apparmor.d/abstractions/X-strict +++ b/apparmor.d/abstractions/X-strict @@ -4,25 +4,25 @@ abi , - # The unix socket to use to connect to the display - unix (connect, receive, send) type=stream peer=(addr="@/tmp/.X11-unix/X[0-9]*"), - unix (connect, receive, send) type=stream peer=(addr="@/tmp/.ICE-unix/[0-9]*"), - unix type=stream addr="@/tmp/.ICE-unix/[0-9]*", - unix type=stream addr="@/tmp/.X11-unix/X[0-9]*", + unix (connect, receive, send) type=stream peer=(addr=@/tmp/.ICE-unix/@{int}), + unix (connect, receive, send) type=stream peer=(addr=@/tmp/.X11-unix/X@{int}), + unix type=stream addr=@/tmp/.ICE-unix/@{int}, + unix type=stream addr=@/tmp/.X11-unix/X@{int}, /usr/share/X11/{,**} r, /usr/share/xsessions/{,*.desktop} r, # Available Xsessions + /usr/share/xkeyboard-config-2/{,**} r, /etc/X11/cursors/{,**} r, - owner @{HOME}/.ICEauthority rw, # ICEauthority files required for X authentication, per user + owner @{HOME}/.ICEauthority r, # ICEauthority files required for X authentication, per user owner @{HOME}/.Xauthority rw, # Xauthority files required for X connections, per user owner @{HOME}/.xsession-errors rw, - /tmp/.ICE-unix/* rw, + /tmp/.ICE-unix/@{int} rw, /tmp/.X@{int}-lock rw, - /tmp/.X11-unix/* rw, + /tmp/.X11-unix/X@{int}{,_} rw, owner @{tmp}/xauth_@{rand6} rl -> @{tmp}/#@{int}, owner @{run}/user/@{uid}/.mutter-Xwaylandauth.@{rand6} rw, # Xwayland @@ -30,7 +30,7 @@ owner @{run}/user/@{uid}/iceauth_@{rand6} r, owner @{run}/user/@{uid}/ICEauthority r, owner @{run}/user/@{uid}/X11/Xauthority r, - owner @{run}/user/@{uid}/xauth_@{rand6} rl -> @{run}/user/@{uid}/#@{int}, + owner @{run}/user/@{uid}/xauth_@{rand6} rl, include if exists diff --git a/apparmor.d/abstractions/accessibility b/apparmor.d/abstractions/accessibility new file mode 100644 index 0000000000..894ee467e4 --- /dev/null +++ b/apparmor.d/abstractions/accessibility @@ -0,0 +1,15 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow communication with Assistive Technology Service Provider Interface (AT-SPI) + + abi , + + include + include + include + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/accounts-observe b/apparmor.d/abstractions/accounts-observe new file mode 100644 index 0000000000..41d371c832 --- /dev/null +++ b/apparmor.d/abstractions/accounts-observe @@ -0,0 +1,63 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2021 Canonical Ltd +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow communication with accounts-daemon. This is used by gnome-shell's agent +# implementation to display user information in the authorisation dialog. + + abi , + + # DBus.Properties: read properties from the interface + + dbus send bus=system path=/org/freedesktop/Accounts + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name="{@{busname},org.freedesktop.Accounts}", label="@{p_accounts_daemon}"), + + dbus send bus=system path=/org/freedesktop/Accounts/User@{int} + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name="{@{busname},org.freedesktop.Accounts}", label="@{p_accounts_daemon}"), + + # DBus.Properties: receive property changed events + + dbus receive bus=system path=/org/freedesktop/Accounts/User@{int} + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name=@{busname}, label="@{p_accounts_daemon}"), + + # DBus.Introspectable: allow clients to introspect the service + + dbus send bus=system path=/org/freedesktop/Accounts + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(label="@{p_accounts_daemon}"), + + # org.freedesktop.Accounts + + dbus send bus=system path=/org/freedesktop/Accounts + interface=org.freedesktop.Accounts + member={FindUserById,FindUserByName} + peer=(name="{@{busname},org.freedesktop.Accounts}", label="@{p_accounts_daemon}"), + + dbus send bus=system path=/org/freedesktop/Accounts + interface=org.freedesktop.Accounts + member={ListCachedUsers,GetUsersLanguages} + peer=(name=@{busname}, label="@{p_accounts_daemon}"), + + dbus receive bus=system path=/org/freedesktop/Accounts + interface=org.freedesktop.Accounts + member={UserAdded,UserDeleted} + peer=(name=@{busname}, label="@{p_accounts_daemon}"), + + # org.freedesktop.Accounts.User + + dbus receive bus=system path=/org/freedesktop/Accounts/User@{int} + interface=org.freedesktop.Accounts.User + member=Changed + peer=(name=@{busname}, label="@{p_accounts_daemon}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/amdgpu b/apparmor.d/abstractions/amdgpu new file mode 100644 index 0000000000..5c39d9b1c9 --- /dev/null +++ b/apparmor.d/abstractions/amdgpu @@ -0,0 +1,33 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Kernel Fusion Driver for AMD GPUs + + abi , + + /opt/rocm/lib/{,**} mr, + + @{sys}/devices/virtual/kfd/kfd/topology/nodes/@{int}/ r, + @{sys}/devices/virtual/kfd/kfd/topology/nodes/@{int}/properties r, + + @{sys}/devices/virtual/kfd/kfd/dev r, + @{sys}/devices/virtual/kfd/kfd/topology/ r, + @{sys}/devices/virtual/kfd/kfd/topology/generation_id r, + @{sys}/devices/virtual/kfd/kfd/topology/nodes/ r, + @{sys}/devices/virtual/kfd/kfd/topology/nodes/@{int}/ r, + @{sys}/devices/virtual/kfd/kfd/topology/nodes/@{int}/caches/ r, + @{sys}/devices/virtual/kfd/kfd/topology/nodes/@{int}/caches/@{int}/properties r, + @{sys}/devices/virtual/kfd/kfd/topology/nodes/@{int}/gpu_id r, + @{sys}/devices/virtual/kfd/kfd/topology/nodes/@{int}/io_links/@{int}/properties r, + @{sys}/devices/virtual/kfd/kfd/topology/nodes/@{int}/mem_banks/@{int}/properties r, + @{sys}/devices/virtual/kfd/kfd/topology/nodes/@{int}/properties r, + @{sys}/devices/virtual/kfd/kfd/topology/system_properties r, + @{sys}/devices/virtual/kfd/kfd/uevent r, + @{sys}/module/amdgpu/initstate r, + + /dev/kfd rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/ansible b/apparmor.d/abstractions/ansible new file mode 100644 index 0000000000..5797830964 --- /dev/null +++ b/apparmor.d/abstractions/ansible @@ -0,0 +1,11 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + owner @{HOME}/.ansible/tmp/ansible-tmp-*/* rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/app-indicator b/apparmor.d/abstractions/app-indicator new file mode 100644 index 0000000000..6e85a202f9 --- /dev/null +++ b/apparmor.d/abstractions/app-indicator @@ -0,0 +1,14 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# App Indicator, modern systray icons + + abi , + + include + include + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/app-launcher-root b/apparmor.d/abstractions/app-launcher-root index 5d2f743638..7f7e2a673c 100644 --- a/apparmor.d/abstractions/app-launcher-root +++ b/apparmor.d/abstractions/app-launcher-root @@ -5,14 +5,12 @@ abi , + include + @{bin}/** PUx, + @{sbin}/** PUx, /usr/local/{s,}bin/** PUx, - @{bin}/ r, - / r, - /usr/ r, - /usr/local/{s,}bin/ r, - include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/app-launcher-user b/apparmor.d/abstractions/app-launcher-user index 800de5106d..3f35d5882a 100644 --- a/apparmor.d/abstractions/app-launcher-user +++ b/apparmor.d/abstractions/app-launcher-user @@ -5,6 +5,8 @@ abi , + include + @{bin}/** PUx, /opt/*/** PUx, /usr/share/** PUx, @@ -18,13 +20,7 @@ @{thunderbird_path} Px, @{offices_path} PUx, - @{bin}/ r, - / r, - /usr/ r, - /usr/local/bin/ r, - - @{user_bin_dirs}/ r, - @{user_bin_dirs}/** PUx, + @{user_bin_dirs}/** PUx, include if exists diff --git a/apparmor.d/abstractions/app-open b/apparmor.d/abstractions/app-open index 73b2e45805..a9ea3ea5ef 100644 --- a/apparmor.d/abstractions/app-open +++ b/apparmor.d/abstractions/app-open @@ -2,9 +2,9 @@ # Copyright (C) 2023-2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only -# Instead of allowing the run of all software in @{bin}/, @{lib} the purpose of +# Instead of allowing the run of all software in `@{bin}/`, `@{lib}` the purpose of # this abstraction is to list all GUI program that can open resources. - +# # Ultimately, only sandbox manager such as like bwrap, snap, flatpak, firejail # should be present here. Until this day, this profile will be a controlled mess. @@ -18,6 +18,7 @@ # Labeled programs @{archive_viewers_path} PUx, + @{backup_path} PUx, @{browsers_path} Px, @{document_viewers_path} PUx, @{emails_path} PUx, @@ -25,6 +26,7 @@ @{help_path} Px, @{image_viewers_path} PUx, @{offices_path} PUx, + @{terminal_path} PUx, @{text_editors_path} PUx, # Others @@ -33,17 +35,20 @@ @{bin}/discord{,-ptb} Px, @{bin}/draw.io PUx, @{bin}/dropbox Px, + @{bin}/ebook-edit PUx, @{bin}/element-desktop Px, @{bin}/extension-manager Px, @{bin}/filezilla Px, @{bin}/flameshot Px, - @{bin}/gimp{,3} Px, + @{bin}/gimp{,-3.0} Px, @{bin}/gnome-calculator Px, @{bin}/gnome-disk-image-mounter Px, @{bin}/gnome-disks Px, + @{bin}/gnome-session-quit Px, @{bin}/gnome-software Px, @{bin}/gwenview PUx, - @{bin}/kgx Px, + @{bin}/keepassxc Px, + @{bin}/mpv Px, @{bin}/qbittorrent Px, @{bin}/qpdfview Px, @{bin}/smplayer Px, @@ -57,9 +62,6 @@ #aa:only opensuse @{lib}/YaST2/** PUx, - # Backup - @{lib}/deja-dup/deja-dup-monitor PUx, - include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/app/bus b/apparmor.d/abstractions/app/bus index 8c7e6e98bc..fa87d9911a 100644 --- a/apparmor.d/abstractions/app/bus +++ b/apparmor.d/abstractions/app/bus @@ -3,14 +3,14 @@ # SPDX-License-Identifier: GPL-2.0-only # LOGPROF-SUGGEST: no -# Minimal set of rules for dbus-send/dbus-launch. +# Minimal set of rules for `dbus-send` or `dbus-launch`. abi , include include - @{bin}/dbus-launch mix, + @{bin}/dbus-launch mrix, @{bin}/dbus-send mrix, @{bin}/dbus-daemon Px -> dbus-session, diff --git a/apparmor.d/abstractions/app/bwrap-glycin b/apparmor.d/abstractions/app/bwrap-glycin new file mode 100644 index 0000000000..0b2165c88e --- /dev/null +++ b/apparmor.d/abstractions/app/bwrap-glycin @@ -0,0 +1,47 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + +# Base set of rules for glycin-loaders sandboxed with bwrap. +# +# - It is very safe to use when used like in the glycin profile. +# - It is **not** safe to use when used by a profile stacking glycin +# +# See https://github.com/roddhjav/apparmor.d/issues/881 for more details. + + abi , + + include + include + + unix type=stream, + + signal (send receive) set=kill peer=@{profile_name}, + signal (send receive) set=kill peer=@{profile_name}//&glycin, + signal (send receive) set=kill peer=glycin, + + ptrace read peer=@{profile_name}, + ptrace read peer=@{profile_name}//&glycin, + ptrace read peer=glycin, + + @{bin}/bwrap mr, + + # To test sandbox functionalities + # See; https://gitlab.gnome.org/GNOME/glycin/-/blob/main/glycin/src/sandbox.rs#L676 + @{bin}/true ix, + + /usr/share/glycin-loaders/{,**} r, + + /usr/share/gtksourceview-2.0/{,**} r, + /usr/share/gtksourceview-3.0/{,**} r, + /usr/share/gtksourceview-4/{,**} r, + /usr/share/gtksourceview-5/{,**} r, + + owner @{tmp}/gdk-pixbuf-glycin-tmp.@{rand6} rw, + + owner @{PROC}/@{pid}/mountinfo r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/app/chromium b/apparmor.d/abstractions/app/chromium index 666387d0ae..a73c22db43 100644 --- a/apparmor.d/abstractions/app/chromium +++ b/apparmor.d/abstractions/app/chromium @@ -2,57 +2,58 @@ # Copyright (C) 2022-2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only # LOGPROF-SUGGEST: no +# NEEDS-VARIABLE: name +# NEEDS-VARIABLE: domain +# NEEDS-VARIABLE: lib_dirs +# NEEDS-VARIABLE: config_dirs +# NEEDS-VARIABLE: cache_dirs -# Full set of rules for all chromium based browsers. It works as a *function* +# A full set of rules for all chromium based browsers. It works as a *function* # and requires some variables to be provided as *arguments* and set in the -# header of the calling profile. Example: +# header of the calling profile. # -# @{name} = chromium -# @{domain} = org.chromium.Chromium -# @{lib_dirs} = @{lib}/chromium -# @{config_dirs} = @{user_config_dirs}/chromium -# @{cache_dirs} = @{user_cache_dirs}/chromium +# !!! quote "[apparmor.d/groups/browsers/chromium](https://github.com/roddhjav/apparmor.d/blob/e979fe05b06f525e5a65c767b4eabe5600147355/apparmor.d/groups/browsers/chromium#L10-L14)" # -# If your application requires chromium to run use abstractions/common/chromium -# or abstractions/common/electron instead. +# ``` +# @{name} = chromium +# @{domain} = org.chromium.Chromium +# @{lib_dirs} = @{lib}/chromium +# @{config_dirs} = @{user_config_dirs}/chromium +# @{cache_dirs} = @{user_cache_dirs}/chromium +# ``` # +# If your application requires chromium to run use [`common/chromium`](#commonchromium) +# or [`common/electron`](#commonelectron) instead. abi , include - include - include - include - include - include - include - include - include - include - include - include - include - include + include + include + include + include + include + include + include + include include include - include + include + include include - include + include + include include + include + include + include + include include include include + include include include - include - - userns, - - capability setgid, - capability setuid, - capability sys_admin, - capability sys_chroot, - capability sys_ptrace, network inet dgram, network inet6 dgram, @@ -60,53 +61,47 @@ network inet6 stream, network netlink raw, - signal (receive) peer=@{profile_name}-crashpad-handler, - signal (send) set=(term, kill) peer=@{profile_name}-sandbox, - signal (send) set=(term, kill) peer=keepassxc-proxy, + signal send set=(term, kill) peer=keepassxc-proxy, + signal receive peer=@{profile_name}//&@{profile_name}//crashpad_handler, + + ptrace trace peer=@{profile_name}, - ptrace (read) peer=browserpass, - ptrace (read) peer=chrome-gnome-shell, - ptrace (read) peer=gnome-browser-connector-host, - ptrace (read) peer=keepassxc-proxy, - ptrace (read) peer=lsb_release, - ptrace (read) peer=plasma-browser-integration-host, - ptrace (read) peer=xdg-settings, - ptrace (trace) peer=@{profile_name}, + ptrace read peer=browserpass, + ptrace read peer=chrome-gnome-shell, + ptrace read peer=gnome-browser-connector-host, + ptrace read peer=keepassxc-proxy, + ptrace read peer=lsb_release, + ptrace read peer=plasma-browser-integration-host, + ptrace read peer=xdg-settings, + ptrace read peer=kwin_wayland_wrapper, @{lib_dirs}/{,**} r, @{lib_dirs}/*.so* mr, - @{lib_dirs}/chrome-sandbox rPx, + @{lib_dirs}/WidevineCdm/_platform_specific/linux_*/libwidevinecdm.so mr, # Desktop integration - @{bin}/lsb_release rPx -> lsb_release, - @{bin}/xdg-desktop-menu rPx, - @{bin}/xdg-email rPx, - @{bin}/xdg-icon-resource rPx, - @{bin}/xdg-mime rPx, - @{bin}/xdg-open rPx -> child-open, - @{bin}/xdg-settings rPx, - - # Installing/removing extensions & applications - @{bin}/{,e}grep rix, - @{bin}/basename rix, - @{bin}/cat rix, - @{bin}/cut rix, - @{bin}/mkdir rix, - @{bin}/mktemp rix, - @{bin}/rm rix, - @{bin}/sed rix, - @{bin}/touch rix, + @{bin}/lsb_release Px, + @{bin}/xdg-desktop-menu ix, + @{bin}/xdg-email Px, + @{bin}/xdg-icon-resource ix, + @{bin}/xdg-mime rix, + @{bin}/xdg-open Px -> child-open-any, + @{bin}/xdg-settings rix, + + # Installing/removing extensions, applications, and stacked xdg menus + @{sh_path} rix, + @{coreutils_path} ix, # For storing passwords externally @{bin}/keepassxc-proxy rix, # as a temporary solution - see issue #128 - @{bin}/browserpass rPx, + @{bin}/browserpass Px, # Gnome shell integration - @{bin}/chrome-gnome-shell rPx, - @{bin}/gnome-browser-connector-host rPx, + @{bin}/chrome-gnome-shell Px, + @{bin}/gnome-browser-connector-host Px, # Plasma integration - @{bin}/plasma-browser-integration-host rPx, + @{bin}/plasma-browser-integration-host Px, /usr/share/@{name}/{,**} r, /usr/share/chromium/extensions/{,**} r, @@ -115,33 +110,28 @@ /etc/@{name}/{,**} r, /etc/fstab r, - /etc/{,opensc/}opensc.conf r, - - /var/lib/dbus/machine-id r, - /etc/machine-id r, / r, owner @{HOME}/ r, - owner @{HOME}/.pki/ rw, - owner @{HOME}/.pki/nssdb/ rw, - owner @{HOME}/.pki/nssdb/pkcs11.txt rw, - owner @{HOME}/.pki/nssdb/{cert9,key4}.db rwk, - owner @{HOME}/.pki/nssdb/{cert9,key4}.db-journal rw, - - owner @{user_config_dirs}/gtk-3.0/servers r, - owner @{user_share_dirs}/.@{domain}.@{rand6} rw, owner @{user_cache_dirs}/gtk-3.0/**/*.cache r, + owner @{user_config_dirs}/gtk-3.0/servers r, + + owner @{user_share_dirs}/icons/hicolor/.xdg-icon-resource-dummy w, owner @{config_dirs}/ rw, owner @{config_dirs}/** rwk, owner @{config_dirs}/WidevineCdm/*/_platform_specific/linux_*/libwidevinecdm.so mrw, - owner @{cache_dirs}/{,**} rw, + owner @{cache_dirs}/ rw, + owner @{cache_dirs}/** rwk, owner @{user_config_dirs}/kioslaverc r, owner @{user_config_dirs}/menus/applications-merged/ r, - owner @{user_config_dirs}/menus/applications-merged/xdg-desktop-menu-dummy.menu r, + owner @{user_config_dirs}/menus/applications-merged/*.menu rw, + owner @{user_config_dirs}/mimeapps.list{,.new} rw, + owner @{user_share_dirs}/icons/hicolor/.icon-theme.cache w, + owner @{user_share_dirs}/icons/hicolor/icon-theme.cache w, # For importing data (bookmarks, cookies, etc) from Firefox # owner @{HOME}/.mozilla/firefox/profiles.ini r, @@ -155,10 +145,12 @@ /tmp/ r, /var/tmp/ r, - owner @{tmp}/.@{domain}.@{rand6} rw, - owner @{tmp}/.@{domain}.@{rand6}/{,**} rw, + owner @{tmp}/{,.}@{domain}.*/{,**} rw, owner @{tmp}/@{name}-crashlog-@{int}-@{int}.txt rw, + owner @{tmp}/cache/Default/ rw, + owner @{tmp}/cache/Default/** rwk, owner @{tmp}/scoped_dir@{rand6}/{,**} rw, + owner @{tmp}/tmp.@{rand10} rw, owner @{tmp}/tmp.@{rand6} rw, owner @{tmp}/tmp.@{rand6}/ rw, owner @{tmp}/tmp.@{rand6}/** rwk, @@ -166,56 +158,141 @@ owner @{run}/user/@{uid}/app/org.keepassxc.KeePassXC/org.keepassxc.KeePassXC.BrowserServer rw, owner @{run}/user/@{uid}/org.keepassxc.KeePassXC.BrowserServer rw, - /dev/shm/ r, - owner /dev/shm/.@{domain}.@{rand6} rw, - @{run}/udev/data/c13:@{int} r, # for /dev/input/* @{sys}/bus/ r, @{sys}/bus/**/devices/ r, @{sys}/class/**/ r, - @{sys}/devices/@{pci}/{in_intensity_sampling_frequency,in_intensity_scale,in_illuminance_raw} r, - @{sys}/devices/@{pci}/boot_vga r, - @{sys}/devices/@{pci}/report_descriptor r, @{sys}/devices/**/uevent r, - @{sys}/devices/system/cpu/kernel_max r, - @{sys}/devices/virtual/**/report_descriptor r, - @{sys}/devices/virtual/dmi/id/{sys_vendor,product_name} r, - @{sys}/devices/virtual/tty/tty@{int}/active r, + @{sys}/devices/system/cpu/cpu@{int}/microcode/version r, - @{PROC}/ r, - @{PROC}/@{pid}/fd/ r, - @{PROC}/@{pid}/stat r, - @{PROC}/@{pid}/statm r, - @{PROC}/@{pid}/task/@{tid}/status r, - @{PROC}/pressure/{memory,cpu,io} r, - @{PROC}/sys/fs/inotify/max_user_watches r, - @{PROC}/sys/kernel/yama/ptrace_scope r, - @{PROC}/vmstat r, + # List processes in /proc + @{PROC}/ r, + + # Allow reading the memory map of any processes for introspection and debugging + @{PROC}/@{pid}/maps r, + + # Process status in one line (pid, state, ppid, CPU time, threads, etc.) + @{PROC}/@{pid}/stat r, + + # Memory usage in pages (total, resident, shared, text, data) + @{PROC}/@{pid}/statm r, + + # Human-readable process status (name, state, UIDs, memory, capabilities) + @{PROC}/@{pid}/status r, + + # Pressure Stall Information interface + @{PROC}/pressure/cpu r, + @{PROC}/pressure/io r, + @{PROC}/pressure/memory r, + + # Human-readable thread status + @{PROC}/@{pid}/task/@{tid}/status r, + + # Limits for how many inotify instances, watches, and pending events a user can have. + @{PROC}/sys/fs/inotify/max_queued_events r, + @{PROC}/sys/fs/inotify/max_user_instances r, + @{PROC}/sys/fs/inotify/max_user_watches r, + + # Get the ptrace restrictions level + @{PROC}/sys/kernel/yama/ptrace_scope r, + + # Exposes virtual memory statistics (page faults, swap activity, allocation counts) + @{PROC}/vmstat r, + + # Allow reading cgroup membership information for process introspection + owner @{PROC}/@{pid}/cgroup r, + + # Clearing the referenced bits in a process's page table entries provides a method to + # measure approximately how much memory a process is using. owner @{PROC}/@{pid}/clear_refs w, + + # Allow reading command line arguments for process identification owner @{PROC}/@{pid}/cmdline r, + owner @{PROC}/@{pid}/comm r, + + # Allow reading our own environment variables owner @{PROC}/@{pid}/environ r, - owner @{PROC}/@{pid}/gid_map w, + + # Allow listing file descriptors + @{PROC}/@{pid}/fd/ r, + owner @{PROC}/@{pid}/fd/ r, + + # Chromium content api unfortunately needs these for normal operation + owner @{PROC}/@{pid}/fd/@{int} w, + + # Shows the process's current resource limits (soft/hard), the ulimit value. owner @{PROC}/@{pid}/limits r, + + # Allow reading info about the physical mapping of virtual pages owner @{PROC}/@{pid}/mem r, - owner @{PROC}/@{pid}/mountinfo r, + + # This is an information leak but disallowing it leads to developer confusion + # when using the chromium content api file chooser due to a (harmless) glib + # warning and the noisy AppArmor denial. owner @{PROC}/@{pid}/mounts r, - owner @{PROC}/@{pid}/oom_{,score_}adj rw, - owner @{PROC}/@{pid}/setgroups w, - owner @{PROC}/@{pid}/task/ r, + owner @{PROC}/@{pid}/mountinfo r, + + # Allow reading of smaps_rollup, which is a summary of the memory use of a process + owner @{PROC}/@{pid}/smaps_rollup r, + + # Reads of oom_adj and oom_score_adj are safe + owner @{PROC}/@{pid}/oom_adj r, + owner @{PROC}/@{pid}/oom_score_adj r, + + # This allows raising the OOM score of other processes owned by the user. + owner @{PROC}/@{pid}/oom_score_adj w, + + # Per man(5) proc, the kernel enforces that a thread may only modify its comm + # value or those in its thread group. owner @{PROC}/@{pid}/task/@{tid}/comm rw, + + # Provide statistical information about our own processes/threads + owner @{PROC}/@{pid}/task/ r, owner @{PROC}/@{pid}/task/@{tid}/stat r, - owner @{PROC}/@{pid}/uid_map w, + owner @{PROC}/@{pid}/task/@{tid}/status r, /dev/ r, - /dev/hidraw@{int} rw, /dev/tty rw, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, # Silencer deny @{lib_dirs}/** w, deny @{user_share_dirs}/gvfs-metadata/* r, + profile crashpad_handler flags=(attach_disconnected) { + include + include + + capability sys_ptrace, + + signal send peer=@{name}, + + ptrace read peer=@{name}, + ptrace trace peer=@{name}, + + unix (send receive) type=seqpacket peer=(label=@{name}), + + @{lib_dirs}/chrome_crashpad_handler mrix, + @{lib_dirs}/@{name}_crashpad_handler mrix, + + owner "@{config_dirs}/{,*/}Crash Reports/**" rwk, + + @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_cur_freq r, + @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_max_freq r, + + @{PROC}/@{pid}/maps r, + @{PROC}/@{pid}/status r, + @{PROC}/sys/kernel/yama/ptrace_scope r, + owner @{PROC}/@{pid}/fd/ r, + owner @{PROC}/@{pid}/mem r, + owner @{PROC}/@{pid}/stat r, + owner @{PROC}/@{pid}/task/ r, + owner @{PROC}/@{pid}/task/@{tid}/comm r, + + include if exists + } + include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/app/code-extension b/apparmor.d/abstractions/app/code-extension new file mode 100644 index 0000000000..a92e909d83 --- /dev/null +++ b/apparmor.d/abstractions/app/code-extension @@ -0,0 +1,28 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no +# NEEDS-VARIABLE: lib_dirs +# NEEDS-VARIABLE: config_dirs + + abi , + + network netlink raw, + + signal receive peer=code, + + unix type=seqpacket peer=(label=code), + unix (send receive) type=stream peer=(label=code), + + @{lib_dirs}/** mr, + + # Allow writting logs to vscode + owner @{config_dirs}/logs/{,**} w, + + # file_inherit + deny /usr/share/code/*.bin r, + deny owner /dev/shm/.org.chromium.Chromium.@{rand6} rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/app/editor b/apparmor.d/abstractions/app/editor index 3992fb7b03..bcf3dd65ae 100644 --- a/apparmor.d/abstractions/app/editor +++ b/apparmor.d/abstractions/app/editor @@ -10,31 +10,30 @@ include @{sh_path} rix, - @{bin}/nvim mix, - @{bin}/sensible-editor mr, - @{bin}/vim{,.*} mrix, - @{bin}/which{,.debianutils} ix, + @{editor_path} mrix, + @{bin}/which{,.debianutils} rix, - /usr/share/nvim/{,**} r, + /usr/share/doc/{,**} r, + /usr/share/@{editor_names}/{,**} r, /usr/share/terminfo/** r, - /usr/share/vim/{,**} r, - /etc/vim/{,**} r, - /etc/vimrc r, - /etc/xdg/nvim/* r, + /etc/@{editor_names}/{,**} r, + /etc/@{editor_names}rc r, + /etc/xdg/@{editor_names}/* r, owner @{HOME}/.selected_editor r, - owner @{HOME}/.viminf@{c}{,.tmp} rw, - owner @{HOME}/.vimrc r, + owner @{HOME}/.vim/{after/,}spell/{,**} rw, + owner @{HOME}/.@{editor_names}/** r, + owner @{HOME}/.@{editor_names}{,.tmp} rw, + owner @{HOME}/.@{editor_names}rc r, owner @{HOME}/ r, owner @{user_cache_dirs}/ r, - owner @{user_cache_dirs}/vim/{,**} rw, - owner @{user_config_dirs}/vim/{,**} r, - owner @{user_state_dirs}/nvim/{,**} rw, - owner @{user_config_dirs}/nvim/{,**} rw, + owner @{user_cache_dirs}/@{editor_names}/{,**} rw, + owner @{user_config_dirs}/@{editor_names}/{,**} rw, + owner @{user_state_dirs}/@{editor_names}/{,**} rw, - owner @{run}/user/@{uid}/nvim.* rw, + owner @{run}/user/@{uid}/@{editor_names}.* rw, include if exists diff --git a/apparmor.d/abstractions/app/firefox b/apparmor.d/abstractions/app/firefox index 602651587c..6a0b0b40ac 100644 --- a/apparmor.d/abstractions/app/firefox +++ b/apparmor.d/abstractions/app/firefox @@ -2,43 +2,63 @@ # Copyright (C) 2022-2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only # LOGPROF-SUGGEST: no +# NEEDS-VARIABLE: name +# NEEDS-VARIABLE: lib_dirs +# NEEDS-VARIABLE: config_dirs +# NEEDS-VARIABLE: cache_dirs # Full set of rules for all firefox based browsers. It works as a *function* # and requires some variables to be provided as *arguments* and set in the # header of the calling profile. Example: # -# @{name} = firefox{,.sh,-esr,-bin} -# @{lib_dirs} = @{lib}/@{name} /opt/@{name} -# @{config_dirs} = @{HOME}/.mozilla/ -# @{cache_dirs} = @{user_cache_dirs}/mozilla/ +# !!! quote "" +# +# ``` +# @{name} = firefox{,.sh,-esr,-bin} +# @{lib_dirs} = @{lib}/@{name} /opt/@{name} +# @{config_dirs} = @{HOME}/.mozilla/ +# @{cache_dirs} = @{user_cache_dirs}/mozilla/ +# ``` # abi , include - include - include - include - include - include + include + include + include + include + include + include include include include + include include include - include + include include + include + include include + include + include + include + include + include include + include include include userns, - capability sys_admin, # If kernel.unprivileged_userns_clone = 1 - capability sys_chroot, # If kernel.unprivileged_userns_clone = 1 capability sys_ptrace, + # Needed with sysctl_kernel_unprivileged_userns_clone = 1 + capability sys_admin, + capability sys_chroot, + network inet dgram, network inet stream, network inet6 dgram, @@ -49,8 +69,6 @@ signal (send) set=(term, kill) peer=@{profile_name}-*, - #aa:dbus talk bus=session name=org.gtk.vfs label="gvfsd{,-*}" - @{sh_path} rix, @{bin}/basename rix, @{bin}/dirname rix, @@ -64,7 +82,7 @@ @{lib_dirs}/plugin-container rPx, # Desktop integration - @{bin}/lsb_release rPx -> lsb_release, + @{bin}/lsb_release rPx, /usr/share/@{name}/{,**} r, /usr/share/doc/{,**} r, @@ -72,12 +90,10 @@ /usr/share/webext/{,**} r, /usr/share/xul-ext/kwallet5/* r, - /etc/{,opensc/}opensc.conf r, /etc/@{name}/{,**} r, /etc/fstab r, /etc/lsb-release r, /etc/mailcap r, - /etc/mime.types r, /etc/sysconfig/proxy r, /etc/xdg/* r, /etc/xul-ext/kwallet5.js r, @@ -96,8 +112,14 @@ /var/tmp/ r, owner @{tmp}/@{name}/ rw, owner @{tmp}/@{name}/* rwk, + owner @{tmp}/@{rand6}.tmp rw, owner @{tmp}/firefox/ rw, owner @{tmp}/firefox/* rwk, + owner @{tmp}/mozilla* rw, + owner @{tmp}/mozilla*/ rw, + owner @{tmp}/mozilla*/* rwk, + owner @{tmp}/remote-settings-startup-bundle- rw, + owner @{tmp}/remote-settings-startup-bundle-.tmp rw, owner @{tmp}/Temp-@{uuid}/ rw, owner @{tmp}/Temp-@{uuid}/* rwk, owner @{tmp}/tmp-*.xpi rw, @@ -113,6 +135,8 @@ @{run}/udev/data/+input:input@{int} r, # for mouse, keyboard, touchpad @{run}/udev/data/c13:@{int} r, # for /dev/input/* + @{sys}/devices/virtual/dmi/id/product_sku r, + @{sys}/bus/ r, @{sys}/cgroup/cpu,cpuacct/user.slice/cpu.cfs_quota_us r, @{sys}/class/ r, @@ -125,40 +149,71 @@ @{sys}/devices/power/events/energy-* r, @{sys}/devices/power/type r, @{sys}/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/cpu.max r, @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/session-@{word}.scope/cpu.max r, owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/**/cpu.max r, - @{PROC}/@{pid}/net/arp r, - @{PROC}/@{pid}/net/if_inet6 r, - @{PROC}/@{pid}/net/route r, + # Network interface information + @{PROC}/@{pid}/net/arp r, + @{PROC}/@{pid}/net/if_inet6 r, + @{PROC}/@{pid}/net/route r, + + # Pressure Stall Information interface + @{PROC}/pressure/cpu r, + @{PROC}/pressure/io r, + @{PROC}/pressure/memory r, + + # Allow reading cgroup membership information for process introspection owner @{PROC}/@{pid}/cgroup r, + + # Allow reading command line arguments for process identification owner @{PROC}/@{pid}/cmdline r, + owner @{PROC}/@{pid}/comm r, + + # Allow reading our own environment variables owner @{PROC}/@{pid}/environ r, + + # Allow listing file descriptors owner @{PROC}/@{pid}/fd/ r, - owner @{PROC}/@{pid}/gid_map w, # If kernel.unprivileged_userns_clone = 1 - owner @{PROC}/@{pid}/mountinfo r, + + # Needed with sysctl_kernel_unprivileged_userns_clone = 1 + owner @{PROC}/@{pid}/gid_map w, + owner @{PROC}/@{pid}/setgroups w, + owner @{PROC}/@{pid}/uid_map w, + + # This is an information leak but disallowing it leads to developer confusion + # when using the chromium content api file chooser due to a (harmless) glib + # warning and the noisy AppArmor denial. owner @{PROC}/@{pid}/mounts r, + owner @{PROC}/@{pid}/mountinfo r, + + # Reads of oom_adj and oom_score_adj are safe + owner @{PROC}/@{pid}/oom_adj r, + owner @{PROC}/@{pid}/oom_score_adj r, + + # This allows raising the OOM score of other processes owned by the user. owner @{PROC}/@{pid}/oom_score_adj w, - owner @{PROC}/@{pid}/setgroups w, # If kernel.unprivileged_userns_clone = 1 + + # Per man(5) proc, the kernel enforces that a thread may only modify its comm + # value or those in its thread group. + owner @{PROC}/@{pid}/task/@{tid}/comm rw, + + # Provide statistical information about our own processes/threads owner @{PROC}/@{pid}/smaps r, owner @{PROC}/@{pid}/stat r, owner @{PROC}/@{pid}/statm r, owner @{PROC}/@{pid}/task/ r, - owner @{PROC}/@{pid}/task/@{tid}/comm rw, owner @{PROC}/@{pid}/task/@{tid}/stat r, - owner @{PROC}/@{pid}/uid_map w, # If kernel.unprivileged_userns_clone = 1 + owner @{PROC}/@{pid}/task/@{tid}/status r, - /dev/ r, - /dev/hidraw@{int} rw, /dev/tty rw, - /dev/video@{int} rw, - owner /dev/tty@{int} rw, # File Inherit + owner /dev/tty@{u8} rw, # File Inherit # Silencer - deny dbus send bus=system path=/org/freedesktop/hostname1, + deny dbus bus=system path=/org/freedesktop/hostname1, + deny dbus bus=system path=/org/freedesktop/login1, deny /tmp/MozillaUpdateLock-* w, deny owner @{HOME}/.* r, - deny owner @{user_share_dirs}/gvfs-metadata/{,*} r, deny @{run}/user/@{uid}/gnome-shell-disable-extensions w, include if exists diff --git a/apparmor.d/abstractions/app/flatpak b/apparmor.d/abstractions/app/flatpak new file mode 100644 index 0000000000..3bf06198db --- /dev/null +++ b/apparmor.d/abstractions/app/flatpak @@ -0,0 +1,101 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no +# NEEDS-VARIABLE: appid +# NEEDS-VARIABLE: att +# NEEDS-VARIABLE: profile_dbus + +# Default rules for all flatpak applications. Ideally, they should be +# generated with settings from the flatpak metadata. +# +# Security objectives: +# +# 1. Split the sandbox handler (bwrap) from the app profile (fapp) +# 2. Provide defence in depth, as flatpak already provides a sandbox +# 3. The main purpose of this profile is to ensure all processes are confined +# +# Notable security improvements over no profile at all: +# +# - No capabilities (except `dac_override` & `dac_read_search`) +# - Restrict unix socket to profiles defined in apparmor.d +# - Limit dbus system communication to profiles defined in apparmor.d +# - Ensure flatpak-spawn and host-spawn are confined too +# - Filter `/proc/`, `/sys/` access +# +# Keep in mind that the profile is still common for all apps and is therefore +# way more permissive than a per-app profile would be. +# +# Abstractions in `abstractions/flatpak/` closelly follow the sandbox defined by +# flatpak, and are therefore different to they host equivalents, as flatpak apps +# do not have access to the full host filesystem. + + abi , + + include + + # The app base platform, similar to our desktop abstraction, but with flatpak paths + include + + # Base app specific rules, they are all included as it is for a generic profile + include + include + include + + # Flatpak devices '--device=' + include + include + + # Flatpack share (IPC, network) with the host '--share=' + include + include + + # Flatpack sockets '--socket=' + include + include + include + include + include + include + include + include + include + include + include + + # Flatpak features '--feature=' + include + include + include + include + include + + # Flatpak filesystem access '--filesystem=' + # As a generic profile cannot filter filesystem for each app, this gives + # full access to the user's home, and read only acccess to host system files. + # In the limmit of what is allowed by flatpak. + include + + # Programming language specific resources + include + + signal (send receive) peer=fapp, + signal (send receive) peer=fapp//&fbwrap, + signal (send receive) peer=fbwrap, + + ptrace (read trace) peer=fapp, + ptrace (read trace) peer=fapp//&fbwrap, + ptrace (read trace) peer=fbwrap, + + unix (bind listen) type=seqpacket addr=@*, + unix type=dgram peer=(label=fbwrap), + unix type=seqpacket peer=(label=fbwrap), + unix type=stream peer=(label=fbwrap), + unix type=stream peer=(label=unconfined), + + # apply_extra + /app/extra/** w, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/app/fusermount b/apparmor.d/abstractions/app/fusermount index 659eee99d4..c9dab01daf 100644 --- a/apparmor.d/abstractions/app/fusermount +++ b/apparmor.d/abstractions/app/fusermount @@ -17,8 +17,16 @@ @{bin}/fusermount{,3} mr, + @{bin}/mount rix, + @{bin}/umount rix, + @{etc_ro}/fuse{,3}.conf r, + /etc/machine-id r, + + @{run}/mount/utab r, + @{run}/mount/utab.* rwk, + @{PROC}/@{pid}/mountinfo r, @{PROC}/@{pid}/mounts r, /dev/fuse rw, diff --git a/apparmor.d/abstractions/app/git b/apparmor.d/abstractions/app/git new file mode 100644 index 0000000000..b96c1c0e78 --- /dev/null +++ b/apparmor.d/abstractions/app/git @@ -0,0 +1,80 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + +# Minimal set of rules for git subprofiles. Path to projects should +# be defined in the calling profile. + + abi , + + include + include + include + + network inet dgram, + network inet6 dgram, + network inet stream, + network inet6 stream, + network netlink raw, + + @{bin}/git mrix, + @{bin}/git-* mrix, + @{lib}/git-core/git mrix, + @{lib}/git-core/git-* mrix, + @{lib}/git-core/mergetools/* mrix, + @{lib}/git/git mrix, + @{lib}/git/git-* mrix, + @{lib}/git/mergetools/* mrix, + + # These are needed for "git submodule update" + @{sh_path} rix, + @{bin}/{,e}grep rix, + @{bin}/alts rix, + @{bin}/basename rix, + @{bin}/cat rix, + @{bin}/date rix, + @{bin}/dirname rix, + @{bin}/envsubst rix, + @{bin}/gettext rix, + @{bin}/gettext.sh rix, + @{bin}/hostname rix, + @{bin}/mkdir rix, + @{bin}/mv rix, + @{bin}/rm rix, + @{bin}/sed rix, + @{bin}/tar rix, + @{bin}/true rix, + @{bin}/uname rix, + @{bin}/wc rix, + @{bin}/whoami rix, + + /usr/share/git{,-core}/{,**} r, + + /etc/gitconfig r, + + owner @{HOME}/.gitconfig* r, + + owner @{user_config_dirs}/git/{,*} r, + + owner @{tmp}/.git_vtag_tmp@{rand6} rw, # For git log --show-signature + owner @{tmp}/git-commit-msg-.txt rw, # For android studio + owner @{tmp}/git-difftool.*/{,**} rw, # For diffs + owner @{tmp}/git-index-private@{int} rw, + + # When you mistype a command, git checks the $PATH variable and search its exec dirs to give you + # the most similar commands, which it thinks can be used instead. Git binaries are all under + # /usr/bin/ , so allow only this location. + @{bin}/ r, + deny @{bin}/*/ r, + deny /usr/games/ r, + deny /usr/local/{s,}bin/ r, + deny /usr/local/games/ r, + deny /var/lib/flatpak/exports/bin/ r, + deny owner @{HOME}/.go/bin/ r, + deny owner @{HOME}/bin/ r, + deny owner @{user_bin_dirs}/ r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/app/kmod b/apparmor.d/abstractions/app/kmod index 25a0c0c38b..ab3b39234e 100644 --- a/apparmor.d/abstractions/app/kmod +++ b/apparmor.d/abstractions/app/kmod @@ -7,13 +7,7 @@ include - @{bin}/depmod mr, - @{bin}/insmod mr, - @{bin}/kmod mr, - @{bin}/lsmod mr, - @{bin}/modinfo mr, - @{bin}/modprobe mr, - @{bin}/rmmod mr, + @{bin}/kmod mr, @{lib}/modprobe.d/ r, @{lib}/modprobe.d/*.conf r, @@ -23,6 +17,9 @@ /etc/modprobe.d/ r, /etc/modprobe.d/*.conf r, + @{run}/modprobe.d/ r, + @{run}/modprobe.d/*.conf r, + @{PROC}/cmdline r, @{PROC}/modules r, diff --git a/apparmor.d/abstractions/app/open b/apparmor.d/abstractions/app/open index 2b865457c2..0dc3a3a53f 100644 --- a/apparmor.d/abstractions/app/open +++ b/apparmor.d/abstractions/app/open @@ -3,11 +3,17 @@ # SPDX-License-Identifier: GPL-2.0-only # LOGPROF-SUGGEST: no -# Full set of rules for desktop generic open-* used in child-open-* profiles. +# Full set of rules for desktop generic `open-*` used in `child-open-*` profiles. abi , include + include + + dbus send bus=session path=/org/gnome/Nautilus + interface=org.freedesktop.Application + member=Open + peer=(name=org.gnome.Nautilus, label=nautilus), # We cannot use `@{open_path} mrix,` here because it includes: # @{lib}/@{multiarch}/glib-@{version}/gio-launch-desktop @@ -21,6 +27,9 @@ @{bin}/gio-launch-desktop mrix, @{lib}/gio-launch-desktop mrix, + #aa:only apparmor>=4.1 + priority=1 @{lib}/@{multiarch}/glib-@{version}/gio-launch-desktop mrix, + @{bin}/env rix, @{sh_path} r, @@ -29,13 +38,19 @@ # if @{DE} == kde include - include - include - include include + include + + /etc/xdg/menus/*.menu r, - owner @{run}/user//@{uid}/#@{int} rw, + owner @{user_config_dirs}/kioclientrc r, + owner @{user_config_dirs}/menus/*.menu r, + + owner @{run}/user/@{uid}/#@{int} rw, owner @{run}/user/@{uid}/kioclient@{rand6}.@{int}.kioworker.socket rwl -> @{run}/user/@{uid}/#@{int}, + owner @{run}/user/@{uid}/kde-open@{rand6}.@{int}.kioworker.socket rwl -> @{run}/user/@{uid}/#@{int}, + + @{PROC}/sys/kernel/random/boot_id r, # fi diff --git a/apparmor.d/abstractions/app/pager b/apparmor.d/abstractions/app/pager new file mode 100644 index 0000000000..12cddd5389 --- /dev/null +++ b/apparmor.d/abstractions/app/pager @@ -0,0 +1,39 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + +# Minimal set of rules for pagers. + + abi , + + include + + capability dac_override, + capability dac_read_search, + + signal receive set=(stop, cont, term, kill), + + @{bin}/ r, + @{pager_path} mrix, + + @{system_share_dirs}/terminfo/{,**} r, + /usr/share/file/misc/** r, + /usr/share/nvim/{,**} r, + + @{etc_ro}/lesskey.bin r, + + @{HOME}/.lesshst r, + + owner @{HOME}/ r, + owner @{HOME}/.lesshs* rw, + owner @{HOME}/.terminfo/@{int}/* r, + owner @{user_cache_dirs}/lesshs* rw, + owner @{user_state_dirs}/ r, + owner @{user_state_dirs}/lesshs* rw, + + /dev/tty@{u8} rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/app/pgrep b/apparmor.d/abstractions/app/pgrep index d6b7ba8a7e..cf4d3271a9 100644 --- a/apparmor.d/abstractions/app/pgrep +++ b/apparmor.d/abstractions/app/pgrep @@ -9,6 +9,7 @@ include + capability dac_override, capability sys_ptrace, ptrace read, @@ -19,11 +20,14 @@ @{sys}/devices/system/node/node@{int}/meminfo r, @{PROC}/ r, + @{PROC}/@{pids}/ r, @{PROC}/@{pids}/cgroup r, @{PROC}/@{pids}/cmdline r, @{PROC}/@{pids}/environ r, @{PROC}/@{pids}/stat r, + @{PROC}/@{pids}/status r, @{PROC}/sys/kernel/osrelease r, + @{PROC}/tty/drivers r, @{PROC}/uptime r, include if exists diff --git a/apparmor.d/abstractions/app/pkexec b/apparmor.d/abstractions/app/pkexec index 87b3ea8425..b04a9b53d9 100644 --- a/apparmor.d/abstractions/app/pkexec +++ b/apparmor.d/abstractions/app/pkexec @@ -30,11 +30,12 @@ /etc/shells r, + @{PROC}/@{pid}/cgroup r, @{PROC}/@{pid}/fdinfo/@{int} r, @{PROC}/@{pid}/stat r, owner @{PROC}/@{pid}/loginuid r, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, deny @{user_share_dirs}/gvfs-metadata/* r, diff --git a/apparmor.d/abstractions/app/sudo b/apparmor.d/abstractions/app/sudo index 333cbddbd3..0b6638890a 100644 --- a/apparmor.d/abstractions/app/sudo +++ b/apparmor.d/abstractions/app/sudo @@ -3,7 +3,7 @@ # SPDX-License-Identifier: GPL-2.0-only # LOGPROF-SUGGEST: no -# Minimal set of rules for sudo. Interactive sudo need more rules. +# Minimal set of rules for sudo. abi , @@ -24,8 +24,10 @@ network netlink raw, # PAM - #aa:dbus talk bus=system name=org.freedesktop.home1 label=systemd-homed - #aa:dbus talk bus=system name=org.freedesktop.login1 label=systemd-logind + unix type=stream addr=@@{udbus}/bus/sudo/system, + + #aa:dbus talk bus=system name=org.freedesktop.home1 label="@{p_systemd_homed}" + #aa:dbus talk bus=system name=org.freedesktop.login1 label="@{p_systemd_logind}" dbus (send receive) bus=session path=/org/freedesktop/systemd1 interface=org.freedesktop.systemd.Manager @@ -66,7 +68,7 @@ /dev/ r, /dev/ptmx rwk, /dev/tty rwk, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, deny @{user_share_dirs}/gvfs-metadata/* r, diff --git a/apparmor.d/abstractions/app/sudo-rs b/apparmor.d/abstractions/app/sudo-rs new file mode 100644 index 0000000000..c20a9c358c --- /dev/null +++ b/apparmor.d/abstractions/app/sudo-rs @@ -0,0 +1,55 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + +# Minimal set of rules for sudo-rs. + + abi , + + include + include + include + include + + capability audit_write, + capability dac_override, + capability dac_read_search, + capability net_admin, + capability setgid, + capability setuid, + + network (create receive send) netlink raw, + + unix type=stream addr=@@{udbus}/bus/sudo/system, + + dbus send bus=system path=/org/freedesktop/home1 + interface=org.freedesktop.home1.Manager + member=GetUserRecordByName + peer=(name=org.freedesktop.home1, label="@{p_systemd_homed}"), + + @{bin}/sudo mr, + @{bin}/sudo-rs mr, + + @{etc_ro}/sudo.conf r, + @{etc_ro}/sudoers r, + @{etc_ro}/sudoers.d/{,*} r, + + /etc/machine-id r, + + @{run}/systemd/io.systemd.Login rw, + + owner @{run}/sudo-rs/ w, + owner @{run}/sudo-rs/ts/ w, + owner @{run}/sudo-rs/ts/@{uid} rwk, + + @{PROC}/@{pid}/loginuid r, + @{PROC}/@{pid}/stat r, + @{PROC}/sys/kernel/random/boot_id r, + + /dev/ptmx rwk, + /dev/tty rwk, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/app/systemctl b/apparmor.d/abstractions/app/systemctl index b707add4d0..4a7fb4aafe 100644 --- a/apparmor.d/abstractions/app/systemctl +++ b/apparmor.d/abstractions/app/systemctl @@ -15,7 +15,7 @@ @{bin}/systemctl mr, - @{att}/@{run}/systemd/private rw, + @{att}@{run}/systemd/private rw, owner @{run}/systemd/private rw, diff --git a/apparmor.d/abstractions/app/udevadm b/apparmor.d/abstractions/app/udevadm index e8414d0266..d659143d6c 100644 --- a/apparmor.d/abstractions/app/udevadm +++ b/apparmor.d/abstractions/app/udevadm @@ -11,7 +11,8 @@ /etc/udev/udev.conf r, - @{run}/udev/data/* r, + @{run}/udev/data/+*:* r, # Identifies all subsystems + @{run}/udev/data/c@{int}:@{int} r, # Identifies all character devices @{sys}/** r, diff --git a/apparmor.d/abstractions/app/umu b/apparmor.d/abstractions/app/umu new file mode 100644 index 0000000000..cf04564b55 --- /dev/null +++ b/apparmor.d/abstractions/app/umu @@ -0,0 +1,53 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no +# NEEDS-VARIABLE: att +# NEEDS-VARIABLE: steam_share_dirs +# NEEDS-VARIABLE: runtime_dirs + + abi , + + include + include + + signal (send receive) peer=umu-bwrap, + signal (send receive) peer=umu-bwrap//&umu-game, + signal (send receive) peer=umu-game, + signal (send receive) peer=umu-run, + + unix type=seqpacket peer=(label=umu-bwrap), + unix type=stream peer=(label=umu-bwrap), + unix type=stream peer=(label=umu-game), + + ptrace (read trace) peer=umu-bwrap, + ptrace (read trace) peer=umu-bwrap//&umu-game, + ptrace (read trace) peer=umu-game, + + @{runtime_dirs}/umu-shim rix, + + @{wineprefix_dirs}/ r, + @{wineprefix_dirs}/** mrix, + @{user_config_dirs}/heroic/tools/proton/ r, + @{user_config_dirs}/heroic/tools/proton/*/ r, + @{user_config_dirs}/heroic/tools/proton/*/** mrix, + + # file_inherit + @{user_share_dirs}/umu/steamrt@{int}/VERSIONS.txt r, + @{user_share_dirs}/umu/steamrt@{int}/var/tmp-@{rand6}/usr/.ref rw, + @{att}@{user_share_dirs}/umu/steamrt@{int}/var/tmp-@{rand6}/usr/.ref rw, + + owner @{user_cache_dirs}/umu-protonfixes/protonfixes_test.log w, + + owner @{att}@{wineprefix_dirs}/ rw, + owner @{att}@{wineprefix_dirs}/** rwk, + owner @{wineprefix_dirs}/ rw, + owner @{wineprefix_dirs}/** rwk, + + owner @{tmp}/umu_crashreports/{,**} rw, + + owner @{PROC}/@{pid}/uid_map r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/common/apt b/apparmor.d/abstractions/apt similarity index 67% rename from apparmor.d/abstractions/common/apt rename to apparmor.d/abstractions/apt index 5dd8b26bc0..7d19e2aa0c 100644 --- a/apparmor.d/abstractions/common/apt +++ b/apparmor.d/abstractions/apt @@ -6,7 +6,9 @@ abi , /usr/share/dpkg/cputable r, + /usr/share/dpkg/ostable r, /usr/share/dpkg/tupletable r, + /usr/share/dpkg/varianttable r, /etc/apt/apt.conf r, /etc/apt/apt.conf.d/{,*} r, @@ -18,6 +20,9 @@ /etc/apt/sources.list.d/ r, /etc/apt/sources.list.d/*.{sources,list} r, + /etc/apt/trusted.gpg r, + /etc/apt/trusted.gpg.d/{,*} r, + /var/lib/apt/lists/{,**} r, /var/lib/apt/extended_states r, @@ -25,11 +30,17 @@ /var/cache/apt/srcpkgcache.bin r, /var/lib/dpkg/status r, - /var/lib/ubuntu-advantage/apt-esm/{,**} r, + /var/lib/ubuntu-advantage/apt-esm/{,**} r, #aa:only ubuntu owner @{tmp}/#@{int} rw, owner @{tmp}/clearsigned.message.* rw, - include if exists + #aa:only test + /tmp/@{rand10}/ rw, + /tmp/@{rand10}/** rwlkmix, + /tmp/tmp.@{word10}/ rw, + /tmp/tmp.@{word10}/** rwlkmix, + + include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/attached/base b/apparmor.d/abstractions/attached/base index 6a7486cf82..3412612468 100644 --- a/apparmor.d/abstractions/attached/base +++ b/apparmor.d/abstractions/attached/base @@ -3,18 +3,27 @@ # SPDX-License-Identifier: GPL-2.0-only # LOGPROF-SUGGEST: no - # Do not use it manually, it is automatically included in profiles when it is required. +# Add common attached path to the base abstraction. +# +# !!! warning +# +# Do not use it manually, It automatically replaces the base abstraction in a +# profile with the attach_disconnected flag set and the re-attached path enabled. +# abi , include - @{att}/@{run}/systemd/journal/dev-log w, - @{att}/@{run}/systemd/journal/socket w, - @{att}/@{run}/systemd/journal/stdout rw, + @{att}@{run}/systemd/journal/dev-log w, + @{att}@{run}/systemd/journal/socket w, + @{att}@{run}/systemd/journal/stdout rw, + @{att}@{run}/systemd/notify w, - deny /apparmor/.null rw, - deny @{att}/apparmor/.null rw, + @{att}/dev/null rw, + + /apparmor/.null rw, + @{att}/apparmor/.null rw, include if exists diff --git a/apparmor.d/abstractions/attached/consoles b/apparmor.d/abstractions/attached/consoles index dd2275a038..c97d2f4060 100644 --- a/apparmor.d/abstractions/attached/consoles +++ b/apparmor.d/abstractions/attached/consoles @@ -3,7 +3,13 @@ # SPDX-License-Identifier: GPL-2.0-only # LOGPROF-SUGGEST: no - # Do not use it manually, it is automatically included in profiles when it is required. +# Add common attached path to the consoles abstraction. +# +# !!! warning +# +# Do not use it manually, It automatically replaces the consoles abstraction in a +# profile with the attach_disconnected flag set and the re-attached path enabled. +# abi , diff --git a/apparmor.d/abstractions/attached/nameservice-strict b/apparmor.d/abstractions/attached/nameservice-strict new file mode 100644 index 0000000000..86a0e968b9 --- /dev/null +++ b/apparmor.d/abstractions/attached/nameservice-strict @@ -0,0 +1,27 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + +# Add common attached path to the nameservice-strict abstraction. +# +# !!! warning +# +# Do not use it manually, It automatically replaces the nameservice-strict abstraction in a +# profile with the attach_disconnected flag set and the re-attached path enabled. +# + + abi , + + include + + # nss-systemd + @{att}@{run}/systemd/io.systemd.NamespaceResource rw, + @{att}@{run}/systemd/userdb/io.systemd.DynamicUser rw, + @{att}@{run}/systemd/userdb/io.systemd.Home rw, + @{att}@{run}/systemd/userdb/io.systemd.Multiplexer rw, + @{att}@{run}/systemd/userdb/org.gnome.DisplayManager rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/audio-client b/apparmor.d/abstractions/audio-client index 166229a09f..2627532a54 100644 --- a/apparmor.d/abstractions/audio-client +++ b/apparmor.d/abstractions/audio-client @@ -4,9 +4,16 @@ # Most programs do not need access to audio devices, audio-client only includes # configuration files to be used by client applications. +# +# !!! warning "TODO" +# +# Will have to be split into `pipewire-client` and `pulse-client` abstractions +# abi , + include + /usr/share/alsa/{,**} r, /usr/share/openal/hrtf/{,**} r, /usr/share/pipewire/client-rt.conf r, @@ -21,6 +28,7 @@ /etc/openal/alsoft.conf r, /etc/pipewire/client{,-rt}.conf r, /etc/pipewire/client{,-rt}.conf.d/{,**} r, + /etc/pipewire/jack.conf.d/{,**} r, /etc/pulse/client.conf r, /etc/pulse/client.conf.d/{,**} r, /etc/wildmidi/wildmidi.cfg r, @@ -30,6 +38,7 @@ owner @{desktop_config_dirs}/pulse/client.conf r, owner @{desktop_config_dirs}/pulse/client.conf.d/{,*.conf} r, owner @{desktop_config_dirs}/pulse/cookie rwk, + owner @{desktop_config_dirs}/seat@{int}/config/pulse/cookie rk, owner @{HOME}/.alsoftrc r, owner @{HOME}/.asoundrc r, @@ -56,12 +65,19 @@ owner @{run}/user/@{uid}/pulse/ rw, owner @{run}/user/@{uid}/pulse/native rw, + @{run}/udev/data/c116:@{int} r, # For ALSA + @{run}/udev/data/+sound:card@{int} r, # For sound card + + @{sys}/class/ r, @{sys}/class/sound/ r, + @{sys}/devices/*/sound/*/uevent r, /dev/shm/ r, owner /dev/shm/pulse-shm-@{int} rw, /dev/snd/controlC@{int} r, + /dev/snd/pcmC@{int}D@{int}[cp] r, + /dev/snd/timer r, include if exists diff --git a/apparmor.d/abstractions/audio-server b/apparmor.d/abstractions/audio-server index 10bcef426e..a7f89b91bc 100644 --- a/apparmor.d/abstractions/audio-server +++ b/apparmor.d/abstractions/audio-server @@ -9,11 +9,6 @@ include - @{run}/udev/data/+sound:card@{int} r, # for sound card - - @{sys}/class/ r, - @{sys}/class/sound/ r, - @{PROC}/asound/** rw, /dev/admmidi* rw, diff --git a/apparmor.d/abstractions/authentication.d/complete b/apparmor.d/abstractions/authentication.d/complete index 450fa84d47..1ee3a40bf3 100644 --- a/apparmor.d/abstractions/authentication.d/complete +++ b/apparmor.d/abstractions/authentication.d/complete @@ -5,12 +5,20 @@ @{bin}/pam-tmpdir-helper rPx, @{lib}/pam-tmpdir/pam-tmpdir-helper rPx, - #aa:only abi3 - @{bin}/unix_chkpwd rPx, + #aa:only abi==3 + @{sbin}/unix_chkpwd rPx, #aa:only whonix @{lib}/security-misc/pam-abort-on-locked-password rPx, @{lib}/security-misc/pam-info rPx, @{lib}/security-misc/pam_faillock_not_if_x rPx, + # pam_limit + @{etc_ro}/security/limits.conf r, + + # pam_env + @{etc_ro}/security/pam_env.conf r, + @{etc_ro}/security/pam_env.conf.d/ r, + @{etc_ro}/security/pam_env.conf.d/{,*.conf} r, + # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/avahi-observe b/apparmor.d/abstractions/avahi-observe new file mode 100644 index 0000000000..aac14fa7dc --- /dev/null +++ b/apparmor.d/abstractions/avahi-observe @@ -0,0 +1,25 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2016 Canonical Ltd +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allows domain, record, service, and service type browsing as well as address, +# host and service resolving + + abi , + + include + + include + include + include + include + include + include + include + + @{run}/avahi-daemon/socket rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/backlight b/apparmor.d/abstractions/backlight new file mode 100644 index 0000000000..b351bbfef4 --- /dev/null +++ b/apparmor.d/abstractions/backlight @@ -0,0 +1,42 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow adjusting brightness of backlight and LEDs + + abi , + + @{run}/udev/data/+backlight:* r, # For display backlights on laptops, monitors, and other screens. + @{run}/udev/data/+leds:* r, # Identifies all LEDs (keyboard, mouse, etc.) + + @{sys}/class/ r, + @{sys}/class/backlight/ r, + @{sys}/class/leds/ r, + + @{sys}/devices/**/backlight/**/actual_brightness rw, + @{sys}/devices/**/backlight/**/brightness rw, + @{sys}/devices/**/backlight/**/brightness_hw_changed r, + @{sys}/devices/**/backlight/**/enabled r, + @{sys}/devices/**/backlight/**/max_brightness rw, + @{sys}/devices/**/backlight/**/type r, + @{sys}/devices/**/backlight/**/uevent r, + + @{sys}/devices/@{pci}/drm/card@{int}/**/actual_brightness rw, + @{sys}/devices/@{pci}/drm/card@{int}/**/brightness rw, + @{sys}/devices/@{pci}/drm/card@{int}/**/brightness_hw_changed r, + @{sys}/devices/@{pci}/drm/card@{int}/**/enabled r, + @{sys}/devices/@{pci}/drm/card@{int}/**/max_brightness rw, + @{sys}/devices/@{pci}/drm/card@{int}/**/type r, + @{sys}/devices/@{pci}/drm/card@{int}/**/uevent r, + + @{sys}/devices/**/leds/**/actual_brightness rw, + @{sys}/devices/**/leds/**/brightness rw, + @{sys}/devices/**/leds/**/brightness_hw_changed r, + @{sys}/devices/**/leds/**/enabled r, + @{sys}/devices/**/leds/**/max_brightness rw, + @{sys}/devices/**/leds/**/type r, + @{sys}/devices/**/leds/**/uevent r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/base-strict b/apparmor.d/abstractions/base-strict new file mode 100644 index 0000000000..b6c2859650 --- /dev/null +++ b/apparmor.d/abstractions/base-strict @@ -0,0 +1,150 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2002-2009 Novell/SUSE +# Copyright (C) 2009-2011 Canonical Ltd. +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + +# It is mostly a restructuring of the base abstraction with awareness +# of the apparmor.d architecture. +# +# Changes from the base abstraction: +# +# - Removed access to `@{run}/uuidd/request` +# - owner only access to some files in `@{PROC}/@{pid}/` +# - denied lttng +# +# !!! warning +# +# Do not use it manually, It automatically replaces the base abstraction in +# profiles when the base-strict prebuild feature is enabled (default). +# + + abi , + + include + include + include + include + include + include #aa:only test + + # Allow us to signal ourselves + signal peer=@{profile_name}, + + # Checking for PID existence is quite common so add it by default for now + signal (receive, send) set=exists, + + #aa:exclude RBAC + # Allow unconfined processes to send us signals by default + signal receive peer=unconfined, + + # Systemd: allow to receive any signal from the systemd profiles + signal receive peer=@{p_systemd}, + signal receive peer=@{p_systemd_user}, + + # Htop like programs can send any signals to any processes + signal receive peer=btop, + signal receive peer=htop, + signal receive peer=pkill, + signal receive peer=resources//kill, + signal receive peer=top, + signal receive set=(cont,term,kill,stop) peer=gnome-system-monitor, + + # Allow to receive termination signal from manager such as sudo, login, shutdown or systemd + signal receive peer=su, + signal receive set=(winch hup term) peer=sudo, + signal receive set=(winch hup term) peer=sudo-rs, + signal receive set=(cont,term,kill,stop) peer=gnome-shell, + signal receive set=(cont,term,kill,stop) peer=login, + signal receive set=(cont,term,kill,stop) peer=systemd-shutdown, + signal receive set=(cont,term,kill,stop) peer=xinit, + + # Allow other processes to read our /proc entries, futexes, perf tracing and + # kcmp for now (they will need 'read' in the first place). Administrators can + # override with: + # deny ptrace readby ... + ptrace readby, + + # Allow other processes to trace us by default (they will need 'trace' in + # the first place). Administrators can override with: + # deny ptrace tracedby ... + ptrace tracedby, + + # Allow us to ptrace read ourselves + ptrace read peer=@{profile_name}, + + # Allow us to create and use abstract and anonymous sockets + unix peer=(label=@{profile_name}), + + #aa:only pacman + # Allow pacman to communicate with us via unix sockets. It ensures pacman can communicate with its hooks. + unix (send receive) type=stream peer=(label=pacman), + signal receive set=kill peer=pacman-hook-*//pgrep, + + #aa:exclude RBAC + # Allow unconfined processes to communicate with us via unix sockets + unix receive peer=(label=unconfined), + + # Allow communication to children and stacked profiles + signal peer=@{profile_name}//*, + signal peer=@{profile_name}//&*, + unix type=stream peer=(label=@{profile_name}//*), + + # Allow us to create abstract and anonymous sockets + unix create, + + # Allow us to getattr, getopt, setop and shutdown on unix sockets + unix (getattr, getopt, setopt, shutdown), + + # Allow all programs to use common libraries + @{lib}/** r, + @{lib}/**.so* m, + @{lib}/@{multiarch}/**.so* m, + @{lib}/@{multiarch}/** r, + + # Some applications will display license information + /usr/share/common-licenses/** r, + + # Systemd's notification write only socket + @{run}/systemd/notify w, + + # Systemd's equivalent of /dev/log + @{run}/systemd/journal/dev-log w, + + # Systemd native journal API (see sd_journal_print(4)) + @{run}/systemd/journal/socket w, + + # Nested containers and anything using systemd-cat need this. 'r' shouldn't + # be required but applications fail without it. journald doesn't leak + # anything when reading so this is ok. + @{run}/systemd/journal/stdout rw, + + # Transparent hugepage support + @{sys}/kernel/mm/transparent_hugepage/enabled r, + @{sys}/kernel/mm/transparent_hugepage/hpage_pmd_size r, + + # Allow determining the highest valid capability of the running kernel + @{PROC}/sys/kernel/cap_last_cap r, + + # Controls how core dump files are named + @{PROC}/sys/kernel/core_pattern r, + + # Sometimes used to determine kernel/user interfaces to use + @{PROC}/sys/kernel/version r, + + # Harmless and frequently used + /dev/null rw, + /dev/random r, + /dev/urandom r, + /dev/zero rw, + + # The __canary_death_handler function writes a time-stamped log + # message to /dev/log for logging by syslogd. So, /dev/log, timezones, + # and localisations of date should be available EVERYWHERE, so + # StackGuard, FormatGuard, etc., alerts can be properly logged. + /dev/log w, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/base.d/complete b/apparmor.d/abstractions/base.d/complete index 230e0c9d5e..bff6036e91 100644 --- a/apparmor.d/abstractions/base.d/complete +++ b/apparmor.d/abstractions/base.d/complete @@ -3,28 +3,44 @@ # Copyright (C) 2021-2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only - # Allow to receive some signals from new well-known profiles - signal (receive) peer=btop, - signal (receive) peer=htop, - signal (receive) peer=sudo, - signal (receive) peer=top, - signal (receive) set=(cont,term,kill,stop) peer=systemd-shutdown, - signal (receive) set=(cont,term) peer=@{p_systemd_user}, - signal (receive) set=(cont,term) peer=@{p_systemd}, - signal (receive) set=(hup term) peer=login, - signal (receive) set=(hup) peer=xinit, - signal (receive) set=(term,kill) peer=gnome-shell, - signal (receive) set=(term,kill) peer=gnome-system-monitor, - signal (receive) set=(term,kill) peer=openbox, - signal (receive) set=(term,kill) peer=su, - - ptrace (readby) peer=systemd-coredump, - - @{etc_rw}/localtime r, - /etc/locale.conf r, - - @{sys}/devices/system/cpu/possible r, + # Profiles in apparmor.d now use base-strict. Therefore, these additions to + # the base abstraction are only needed for other profiles in order to integrate + # them with apparmor.d + include + include + include #aa:only test + + # Systemd: allow to receive any signal from the systemd profiles + signal receive peer=@{p_systemd}, + signal receive peer=@{p_systemd_user}, + + # Htop like programs can send any signals to any processes + signal receive peer=btop, + signal receive peer=htop, + signal receive peer=pkill, + signal receive peer=resources//kill, + signal receive peer=top, + signal receive set=(cont,term,kill,stop) peer=gnome-system-monitor, + + # Allow to receive termination signal from manager such as sudo, login, shutdown or systemd + signal receive peer=su, + signal receive peer=sudo, + signal receive peer=sudo-rs, + signal receive set=(cont,term,kill,stop) peer=gnome-shell, + signal receive set=(cont,term,kill,stop) peer=login, + signal receive set=(cont,term,kill,stop) peer=systemd-shutdown, + signal receive set=(cont,term,kill,stop) peer=xinit, + + # When apparmor re-attaches disconnected path using /, + /systemd/journal/dev-log w, + /systemd/journal/socket w, + /systemd/journal/stdout rw, + /systemd/notify w, + + # Controls how core dump files are named @{PROC}/sys/kernel/core_pattern r, + /apparmor/.null rw, + # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bash-strict b/apparmor.d/abstractions/bash-strict index 9ea35f8c28..cd4a7c8a7a 100644 --- a/apparmor.d/abstractions/bash-strict +++ b/apparmor.d/abstractions/bash-strict @@ -2,7 +2,7 @@ # Copyright (C) 2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only -# This abstraction is only required when an interactive shell is started. +# This abstraction is only required when .bashrc is loaded (e.g. interactive shell). # Classic shell scripts do not need it. abi , diff --git a/apparmor.d/abstractions/bluetooth-control b/apparmor.d/abstractions/bluetooth-control new file mode 100644 index 0000000000..3b8cf3cbd8 --- /dev/null +++ b/apparmor.d/abstractions/bluetooth-control @@ -0,0 +1,29 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allows control over Bluetooth devices such as pairing, connecting, +# and managing profiles. + + abi , + + include + + include + include + include + include + + dbus send bus=system path=/org/bluez/hci@{int} + interface=org.freedesktop.DBus.Properties + member=Set + peer=(name="{@{busname},org.bluez}", label="@{p_bluetoothd}"), + + dbus send bus=system path=/org/bluez/hci@{int}/dev_@{hex2}_@{hex2}_@{hex2}_@{hex2}_@{hex2}_@{hex2}{,/**} + interface=org.freedesktop.DBus.Properties + member=Set + peer=(name="{@{busname},org.bluez}", label="@{p_bluetoothd}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bluetooth-observe b/apparmor.d/abstractions/bluetooth-observe new file mode 100644 index 0000000000..6c7fab15ab --- /dev/null +++ b/apparmor.d/abstractions/bluetooth-observe @@ -0,0 +1,24 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allows listing Bluetooth devices and their properties. + + abi , + + include + + include + include + include + + # Allow quering GATT (Bluetooth Generic Attribute) services + + dbus send bus=system path=/org/bluez/hci@{int}/dev_@{hex2}_@{hex2}_@{hex2}_@{hex2}_@{hex2}_@{hex2}{,/**} + interface=org.bluez.GattCharacteristic1 + member=ReadValue + peer=(name=@{busname}, label="@{p_bluetoothd}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus-accessibility b/apparmor.d/abstractions/bus-accessibility index 70850b2ba1..739e9bb326 100644 --- a/apparmor.d/abstractions/bus-accessibility +++ b/apparmor.d/abstractions/bus-accessibility @@ -4,7 +4,7 @@ abi , - dbus send bus=accessibility path=/org/freedesktop/DBus + dbus send bus=accessibility path=/{,org/freedesktop/DBus} interface=org.freedesktop.DBus member={Hello,AddMatch,RemoveMatch,GetNameOwner,NameHasOwner,StartServiceByName} peer=(name=org.freedesktop.DBus, label="@{p_dbus_accessibility}"), diff --git a/apparmor.d/abstractions/bus-session b/apparmor.d/abstractions/bus-session index 38d39a4891..410dcb7238 100644 --- a/apparmor.d/abstractions/bus-session +++ b/apparmor.d/abstractions/bus-session @@ -4,9 +4,10 @@ abi , - unix bind type=stream addr=@@{udbus}/bus/@{profile_name}/session, + unix bind type=stream addr=@@{udbus}/bus/@{profile_name}/session, # dbus-daemon + unix bind type=stream addr=@@{udbus}/bus/@{profile_name}/user, # dbus-broker - dbus send bus=session path=/org/freedesktop/DBus + dbus send bus=session path=/{,org/freedesktop/{dbus,DBus}} interface=org.freedesktop.DBus member={Hello,AddMatch,RemoveMatch,GetNameOwner,NameHasOwner,StartServiceByName} peer=(name=org.freedesktop.DBus, label="@{p_dbus_session}"), diff --git a/apparmor.d/abstractions/bus-system b/apparmor.d/abstractions/bus-system index d05c018c72..ba71cf7a27 100644 --- a/apparmor.d/abstractions/bus-system +++ b/apparmor.d/abstractions/bus-system @@ -6,13 +6,13 @@ unix bind type=stream addr=@@{udbus}/bus/@{profile_name}/system, - dbus send bus=system path=/org/freedesktop/DBus + dbus send bus=system path=/{,org/freedesktop/DBus} interface=org.freedesktop.DBus member={Hello,AddMatch,RemoveMatch,GetNameOwner,NameHasOwner,StartServiceByName} peer=(name=org.freedesktop.DBus, label="@{p_dbus_system}"), - @{run}/dbus/system_bus_socket rw, - @{att}/@{run}/dbus/system_bus_socket rw, + @{run}/dbus/system_bus_socket rw, + @{att}@{run}/dbus/system_bus_socket rw, include if exists diff --git a/apparmor.d/abstractions/bus/accessibility/org.a11y b/apparmor.d/abstractions/bus/accessibility/org.a11y new file mode 100644 index 0000000000..0145fc494b --- /dev/null +++ b/apparmor.d/abstractions/bus/accessibility/org.a11y @@ -0,0 +1,65 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2017 Canonical Ltd +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + # Allow the accessibility services in the user session to send us any events + + dbus receive bus=accessibility + peer=(label="@{p_at_spi2_registryd}"), + + # Allow querying for capabilities and registering + + dbus send bus=accessibility path=/org/a11y/atspi/accessible/root + interface=org.a11y.atspi.Socket + member=Embed + peer=(name=org.a11y.atspi.Registry, label="@{p_at_spi2_registryd}"), + + dbus send bus=accessibility path=/org/a11y/atspi/registry + interface=org.a11y.atspi.Registry + member=GetRegisteredEvents + peer=(name=org.a11y.atspi.Registry, label="@{p_at_spi2_registryd}"), + + dbus send bus=accessibility path=/org/a11y/atspi/registry/deviceeventcontroller + interface=org.a11y.atspi.DeviceEventController + member={GetKeystrokeListeners,GetDeviceEventListeners} + peer=(name=org.a11y.atspi.Registry, label="@{p_at_spi2_registryd}"), + + dbus send bus=accessibility path=/org/a11y/atspi/registry/deviceeventcontroller + interface=org.a11y.atspi.DeviceEventController + member=NotifyListenersSync + peer=(name=org.a11y.atspi.Registry, label="@{p_at_spi2_registryd}"), + + # org.a11y.atspi is not designed for application isolation and these rules + # can be used to send change events for other processes. + + dbus send bus=accessibility path=/org/a11y/atspi/accessible/root + interface=org.a11y.atspi.Event.Object + member=ChildrenChanged + peer=(name=org.freedesktop.DBus, label="@{p_at_spi2_registryd}"), + + dbus send bus=accessibility path=/org/a11y/atspi/accessible/root + interface=org.a11y.atspi.Accessible + member=Get* + peer=(label="@{p_at_spi2_registryd}"), + + dbus send bus=accessibility path=/org/a11y/atspi/accessible/@{int} + interface=org.a11y.atspi.Event.Object + member={ChildrenChanged,PropertyChange,StateChanged,TextCaretMoved} + peer=(name=org.freedesktop.DBus, label="@{p_at_spi2_registryd}"), + + dbus send bus=accessibility path=/org/a11y/atspi/accessible/@{int} + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(label="@{p_at_spi2_registryd}"), + + dbus send bus=accessibility path=/org/a11y/atspi/cache + interface=org.a11y.atspi.Cache + member={AddAccessible,RemoveAccessible} + peer=(name=org.freedesktop.DBus, label="@{p_at_spi2_registryd}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/own-accessibility b/apparmor.d/abstractions/bus/accessibility/own similarity index 58% rename from apparmor.d/abstractions/bus/own-accessibility rename to apparmor.d/abstractions/bus/accessibility/own index 94968258c8..bef63d73e2 100644 --- a/apparmor.d/abstractions/bus/own-accessibility +++ b/apparmor.d/abstractions/bus/accessibility/own @@ -3,22 +3,26 @@ # SPDX-License-Identifier: GPL-2.0-only # LOGPROF-SUGGEST: no -# Do not use it manually, it is automatically included in a profile when it is required. - # Allow owning a name on DBus public bus +# +# !!! warning +# +# Do not use it manually, It is automatically included in a profile by the +# `aa:dbus own` directive. +# abi , - dbus send bus=accessibility path=/org/freedesktop/DBus + dbus send bus=accessibility path=/{,org/freedesktop/DBus,org/freedesktop/DBus/Bus} interface=org.freedesktop.DBus - member={RequestName,ReleaseName} + member={ListNames,RequestName,ReleaseName} peer=(name=org.freedesktop.DBus, label="@{p_dbus_accessibility}"), - dbus send bus=accessibility path=/org/freedesktop/DBus + dbus send bus=accessibility path=/{,org/freedesktop/DBus,org/freedesktop/DBus/Bus} interface=org.freedesktop.DBus member={GetConnectionUnixProcessID,GetConnectionUnixUser,GetConnectionCredentials} peer=(name=org.freedesktop.DBus, label="@{p_dbus_accessibility}"), - include if exists + include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/com.canonical.dbusmenu b/apparmor.d/abstractions/bus/com.canonical.dbusmenu deleted file mode 100644 index 61ce811114..0000000000 --- a/apparmor.d/abstractions/bus/com.canonical.dbusmenu +++ /dev/null @@ -1,14 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - dbus send bus=session path=/com/canonical/unity/launcherentry/** - interface=com.canonical.dbusmenu - member={GetGroupProperties,GetLayout} - peer=(name=@{busname}, label=nautilus), - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/fi.w1.wpa_supplicant1 b/apparmor.d/abstractions/bus/fi.w1.wpa_supplicant1 deleted file mode 100644 index 7989ea4c59..0000000000 --- a/apparmor.d/abstractions/bus/fi.w1.wpa_supplicant1 +++ /dev/null @@ -1,41 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - #aa:dbus common bus=system name=fi.w1.wpa_supplicant1 label=wpa-supplicant - - dbus send bus=system path=/fi/w1/wpa_supplicant1/Interfaces/@{int} - interface=org.freedesktop.DBus.Properties - member=Set - peer=(name="@{busname}", label=wpa-supplicant), - - dbus send bus=system path=/fi/w1/wpa_supplicant1 - interface=fi.w1.wpa_supplicant1.Interface - member=CreateInterface - peer=(name="@{busname}", label=wpa-supplicant), - - dbus send bus=system path=/fi/w1/wpa_supplicant1/Interfaces/@{int} - interface=fi.w1.wpa_supplicant1.Interface - member={AddNetwork,Disconnect,RemoveNetwork,Scan,SelectNetwork} - peer=(name="@{busname}", label=wpa-supplicant), - - dbus send bus=system path=/fi/w1/wpa_supplicant1/Interfaces/@{int} - interface=fi.w1.wpa_supplicant1.Interface.P2PDevice - member=Cancel - peer=(name="@{busname}", label=wpa-supplicant), - - dbus receive bus=system path=/org/freedesktop - interface=org.freedesktop.DBus.ObjectManager - member=InterfacesRemoved - peer=(name="@{busname}", label=wpa-supplicant), - - dbus receive bus=system path=/fi/w1/wpa_supplicant1/Interfaces/@{int} - interface=fi.w1.wpa_supplicant1.Interface - member={BSSAdded,BSSRemoved,NetworkAdded,NetworkRemoved,NetworkSelected,ScanDone,PropertiesChanged} - peer=(name="@{busname}", label=wpa-supplicant), - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.a11y b/apparmor.d/abstractions/bus/org.a11y deleted file mode 100644 index 018109a628..0000000000 --- a/apparmor.d/abstractions/bus/org.a11y +++ /dev/null @@ -1,48 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - # Accessibility bus - - dbus receive bus=accessibility path=/org/a11y/atspi/registry - interface=org.a11y.atspi.Registry - member=EventListenerDeregistered - peer=(name="@{busname}", label=at-spi2-registryd), - - dbus send bus=accessibility path=/org/a11y/atspi/registry - interface=org.a11y.atspi.Registry - member=GetRegisteredEvents - peer=(name=org.a11y.atspi.Registry, label=at-spi2-registryd), - - dbus send bus=accessibility path=/org/a11y/atspi/registry/deviceeventcontroller - interface=org.a11y.atspi.DeviceEventController - member={GetKeystrokeListeners,GetDeviceEventListeners} - peer=(name=org.a11y.atspi.Registry, label=at-spi2-registryd), - - dbus receive bus=accessibility path=/org/a11y/atspi/accessible/root - interface=org.freedesktop.DBus.Properties - member=Set - peer=(name="@{busname}", label=at-spi2-registryd), - - dbus send bus=accessibility path=/org/a11y/atspi/accessible/root - interface=org.a11y.atspi.Socket - member=Embed - peer=(name=org.a11y.atspi.Registry, label=at-spi2-registryd), - - # Session bus - - dbus send bus=session path=/org/a11y/bus - interface=org.a11y.Bus - member=Get - peer=(name=org.a11y.Bus, label="@{p_dbus_accessibility}"), - - dbus send bus=session path=/org/a11y/bus - interface=org.a11y.Bus - member=GetAddress - peer=(name=org.a11y.Bus), - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.bluez b/apparmor.d/abstractions/bus/org.bluez deleted file mode 100644 index 2969656914..0000000000 --- a/apparmor.d/abstractions/bus/org.bluez +++ /dev/null @@ -1,41 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - #aa:dbus common bus=system name=org.bluez label=bluetoothd - - dbus receive bus=system path=/ - interface=org.freedesktop.DBus.ObjectManager - member=InterfacesRemoved - peer=(name="{@{busname},org.bluez}", label=bluetoothd), - - dbus send bus=system path=/ - interface=org.freedesktop.DBus.ObjectManager - member=GetManagedObjects - peer=(name="{@{busname},org.bluez}", label=bluetoothd), - - dbus send bus=system path=/org/bluez - interface=org.bluez.AgentManager@{int} - member={RegisterAgent,RequestDefaultAgent,UnregisterAgent} - peer=(name=org.bluez, label=bluetoothd), - - dbus send bus=system path=/org/bluez - interface=org.bluez.ProfileManager@{int} - member=RegisterProfile - peer=(name=org.bluez, label=bluetoothd), - - dbus send bus=system path=/org/bluez/hci@{int} - interface=org.bluez.BatteryProviderManager@{int} - member=RegisterProfile - peer=(name=org.bluez, label=bluetoothd), - - dbus send bus=system path=/org/bluez/hci@{int} - interface=org.bluez.Media@{int} - member=RegisterApplication - peer=(name=org.bluez, label=bluetoothd), - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.freedesktop.Accounts b/apparmor.d/abstractions/bus/org.freedesktop.Accounts deleted file mode 100644 index 2ad151c456..0000000000 --- a/apparmor.d/abstractions/bus/org.freedesktop.Accounts +++ /dev/null @@ -1,31 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - #aa:dbus common bus=system name=org.freedesktop.Accounts label=accounts-daemon - - dbus send bus=system path=/org/freedesktop/Accounts - interface=org.freedesktop.Accounts - member={FindUserByName,ListCachedUsers} - peer=(name="@{busname}", label=accounts-daemon), - - dbus receive bus=system path=/org/freedesktop/Accounts/User@{uid} - interface=org.freedesktop.Accounts.User - member=*Changed - peer=(name="@{busname}", label=accounts-daemon), - - dbus receive bus=system path=/org/freedesktop/Accounts - interface=org.freedesktop.Accounts - member=UserAdded - peer=(name="@{busname}", label=accounts-daemon), - - dbus receive bus=system path=/org/freedesktop/Accounts/User@{uid} - interface=org.freedesktop.DBus.Properties - member=*Changed - peer=(name="@{busname}", label=accounts-daemon), - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.freedesktop.Avahi b/apparmor.d/abstractions/bus/org.freedesktop.Avahi deleted file mode 100644 index e3128f9845..0000000000 --- a/apparmor.d/abstractions/bus/org.freedesktop.Avahi +++ /dev/null @@ -1,31 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - #aa:dbus common bus=system name=org.freedesktop.Avahi label=avahi-daemon - - dbus send bus=system path=/ - interface=org.freedesktop.DBus.Peer - member=Ping - peer=(name=org.freedesktop.Avahi, label=avahi-daemon), - - dbus send bus=system path=/ - interface=org.freedesktop.Avahi.Server - member={GetAPIVersion,GetState,Service*New} - peer=(name=org.freedesktop.Avahi, label=avahi-daemon), - - dbus send bus=system path=/Client@{int}/ServiceBrowser@{int} - interface=org.freedesktop.Avahi.ServiceBrowser - member=Free - peer=(name=org.freedesktop.Avahi, label=avahi-daemon), - - dbus receive bus=system path=/Client@{int}/ServiceBrowser@{int} - interface=org.freedesktop.Avahi.ServiceBrowser - member={ItemNew,AllForNow,CacheExhausted} - peer=(name="@{busname}", label=avahi-daemon), - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.freedesktop.ColorManager b/apparmor.d/abstractions/bus/org.freedesktop.ColorManager deleted file mode 100644 index 27776b7767..0000000000 --- a/apparmor.d/abstractions/bus/org.freedesktop.ColorManager +++ /dev/null @@ -1,26 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - #aa:dbus common bus=system name=org.freedesktop.ColorManager label=colord - - dbus send bus=system path=/org/freedesktop/ColorManager - interface=org.freedesktop.ColorManager - member=GetDevices - peer=(name="@{busname}", label=colord), - - dbus send bus=system path=/org/freedesktop/ColorManager - interface=org.freedesktop.ColorManager - member=CreateDevice - peer=(name="@{busname}", label=colord), - - dbus receive bus=system path=/org/freedesktop/ColorManager - interface=org.freedesktop.ColorManager - member={DeviceAdded,DeviceRemoved} - peer=(name="@{busname}", label=colord), - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.freedesktop.FileManager1 b/apparmor.d/abstractions/bus/org.freedesktop.FileManager1 deleted file mode 100644 index 76095edaf4..0000000000 --- a/apparmor.d/abstractions/bus/org.freedesktop.FileManager1 +++ /dev/null @@ -1,11 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - #aa:dbus common bus=session name=org.freedesktop.FileManager1 label=nautilus - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.freedesktop.GeoClue2 b/apparmor.d/abstractions/bus/org.freedesktop.GeoClue2 deleted file mode 100644 index d15d5c5ba9..0000000000 --- a/apparmor.d/abstractions/bus/org.freedesktop.GeoClue2 +++ /dev/null @@ -1,26 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - #aa:dbus common bus=system name=org.freedesktop.GeoClue2 label=geoclue - - dbus receive bus=system path=/org/freedesktop/GeoClue2/Agent - interface=org.freedesktop.DBus.Properties - member=GetAll - peer=(name="@{busname}", label=geoclue), - - dbus send bus=system path=/org/freedesktop/GeoClue2/Manager - interface=org.freedesktop.DBus.Properties - member=GetAll - peer=(name="@{busname}", label=geoclue), - - dbus send bus=system path=/org/freedesktop/GeoClue2/Manager - interface=org.freedesktop.GeoClue2.Manager - member=AddAgent - peer=(name="@{busname}", label=geoclue), - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.freedesktop.ModemManager1 b/apparmor.d/abstractions/bus/org.freedesktop.ModemManager1 deleted file mode 100644 index 41e03f3255..0000000000 --- a/apparmor.d/abstractions/bus/org.freedesktop.ModemManager1 +++ /dev/null @@ -1,21 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - #aa:dbus common bus=system name=org.freedesktop.ModemManager1 label=ModemManager - - dbus send bus=system path=/org/freedesktop/ModemManager1 - interface=org.freedesktop.DBus.ObjectManager - member=GetManagedObjects - peer=(name=org.freedesktop.ModemManager1, label=ModemManager), - - dbus send bus=system path=/org/freedesktop/ModemManager1 - interface=org.freedesktop.DBus.ObjectManager - member=GetManagedObjects - peer=(name="@{busname}", label=ModemManager), - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.freedesktop.NetworkManager b/apparmor.d/abstractions/bus/org.freedesktop.NetworkManager deleted file mode 100644 index 0f188e05a1..0000000000 --- a/apparmor.d/abstractions/bus/org.freedesktop.NetworkManager +++ /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 - - abi , - - #aa:dbus common bus=system name=org.freedesktop.NetworkManager label=NetworkManager - - dbus send bus=system path=/org/freedesktop - interface=org.freedesktop.DBus.ObjectManager - member=GetManagedObjects - peer=(name="{@{busname},org.freedesktop.NetworkManager}", label=NetworkManager), - - dbus send bus=system path=/org/freedesktop/NetworkManager - interface=org.freedesktop.NetworkManager - member={GetDevices,GetPermissions} - peer=(name="{@{busname},org.freedesktop.NetworkManager}", label=NetworkManager), - - dbus send bus=system path=/org/freedesktop/NetworkManager/Settings - interface=org.freedesktop.NetworkManager.Settings - member=ListConnections - peer=(name="{@{busname},org.freedesktop.NetworkManager}", label=NetworkManager), - - dbus send bus=system path=/org/freedesktop/NetworkManager/Settings/@{int} - interface=org.freedesktop.NetworkManager.Settings.Connection - member=GetSettings - peer=(name="{@{busname},org.freedesktop.NetworkManager}", label=NetworkManager), - - dbus receive bus=system path=/org/freedesktop - interface=org.freedesktop.DBus.ObjectManager - member=InterfacesAdded - peer=(name="{@{busname},org.freedesktop.NetworkManager}", label=NetworkManager), - - dbus receive bus=system path=/org/freedesktop/NetworkManager - interface=org.freedesktop.DBus.Properties - member=CheckPermissions - peer=(name="{@{busname},org.freedesktop.NetworkManager}", label=NetworkManager), - - dbus receive bus=system path=/org/freedesktop/NetworkManager - interface=org.freedesktop.NetworkManager - member=CheckPermissions - peer=(name="{@{busname},org.freedesktop.NetworkManager}", label=NetworkManager), - - dbus receive bus=system path=/org/freedesktop/NetworkManager - interface=org.freedesktop.NetworkManager - member={CheckPermissions,DeviceAdded,DeviceRemoved,StateChanged} - peer=(name="{@{busname},org.freedesktop.NetworkManager}", label=NetworkManager), - - dbus receive bus=system path=/org/freedesktop/NetworkManager/Settings/@{int} - interface=org.freedesktop.NetworkManager.Settings.Connection - member=Updated - peer=(name="{@{busname},org.freedesktop.NetworkManager}", label=NetworkManager), - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.freedesktop.Notifications b/apparmor.d/abstractions/bus/org.freedesktop.Notifications deleted file mode 100644 index 6962bf7ecf..0000000000 --- a/apparmor.d/abstractions/bus/org.freedesktop.Notifications +++ /dev/null @@ -1,26 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - #aa:dbus common bus=session name=org.freedesktop.Notifications label=gjs-console - - dbus send bus=session path=/org/freedesktop/Notifications - interface=org.freedesktop.DBus.Properties - member={GetCapabilities,GetServerInformation,Notify} - peer=(name="@{busname}", label=gjs-console), - - dbus receive bus=session path=/org/freedesktop/Notifications - interface=org.freedesktop.DBus.Properties - member={NotificationClosed,CloseNotification} - peer=(name="@{busname}", label=gjs-console), - - dbus receive bus=session path=/org/freedesktop/Notifications - interface=org.freedesktop.DBus.Properties - member=Notify - peer=(name=org.freedesktop.DBus, label=gjs-console), - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.freedesktop.PackageKit b/apparmor.d/abstractions/bus/org.freedesktop.PackageKit deleted file mode 100644 index f6cde20301..0000000000 --- a/apparmor.d/abstractions/bus/org.freedesktop.PackageKit +++ /dev/null @@ -1,21 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - #aa:dbus common bus=system name=org.freedesktop.PackageKit label=packagekitd - - dbus send bus=system path=/org/freedesktop/PackageKit - interface=org.freedesktop.DBus.Introspectable - member=Introspect - peer=(name=org.freedesktop.PackageKit), - - dbus send bus=system path=/org/freedesktop/PackageKit - interface=org.freedesktop.PackageKit - member=StateHasChanged - peer=(name=org.freedesktop.PackageKit), - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.freedesktop.PolicyKit1 b/apparmor.d/abstractions/bus/org.freedesktop.PolicyKit1 deleted file mode 100644 index b770cdbb1d..0000000000 --- a/apparmor.d/abstractions/bus/org.freedesktop.PolicyKit1 +++ /dev/null @@ -1,30 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - #aa:dbus common bus=system name=org.freedesktop.PolicyKit1 label=polkitd - - dbus receive bus=system path=/org/freedesktop/PolicyKit1/Authority - interface=org.freedesktop.PolicyKit1.Authority - member=Changed - peer=(name="@{busname}", label=polkitd), - - dbus send bus=system path=/org/freedesktop/PolicyKit1/Authority - interface=org.freedesktop.PolicyKit1.Authority - member=CheckAuthorization - peer=(name=org.freedesktop.PolicyKit1, label=polkitd), - - dbus send bus=system path=/org/freedesktop/PolicyKit1/Authority - interface=org.freedesktop.PolicyKit1.Authority - member=CheckAuthorization - peer=(name="@{busname}", label=polkitd), - dbus send bus=system path=/org/freedesktop/PolicyKit1/Authority - interface=org.freedesktop.PolicyKit1.Authority - member=CheckAuthorization - peer=(name=org.freedesktop.PolicyKit1), - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.freedesktop.RealtimeKit1 b/apparmor.d/abstractions/bus/org.freedesktop.RealtimeKit1 deleted file mode 100644 index 34b15010cd..0000000000 --- a/apparmor.d/abstractions/bus/org.freedesktop.RealtimeKit1 +++ /dev/null @@ -1,26 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - -# Allow setting realtime priorities. Clients require RLIMIT_RTTIME in the first -# place and client authorization is done via PolicyKit. Note that setrlimit() -# is allowed by default seccomp policy but requires 'capability sys_resource', -# which we deny be default. -# http://git.0pointer.net/rtkit.git/tree/README - - abi , - - #-aa-dbus common bus=system name=org.freedesktop.RealtimeKit1 label=rtkit-daemon - dbus send bus=system path=/org/freedesktop/RealtimeKit1 - interface=org.freedesktop.DBus.Properties - member=Get - peer=(name=org.freedesktop.RealtimeKit1), - - dbus send bus=system path=/org/freedesktop/RealtimeKit1 - interface=org.freedesktop.RealtimeKit1 - member={MakeThreadHighPriority,MakeThreadRealtime,MakeThreadRealtimeWithPID} - peer=(name=org.freedesktop.RealtimeKit1, label=rtkit-daemon), - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.freedesktop.ScreenSaver b/apparmor.d/abstractions/bus/org.freedesktop.ScreenSaver deleted file mode 100644 index 43ed93af66..0000000000 --- a/apparmor.d/abstractions/bus/org.freedesktop.ScreenSaver +++ /dev/null @@ -1,14 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - dbus send bus=session path=/ScreenSaver - interface=org.freedesktop.ScreenSaver - member={Inhibit,UnInhibit} - peer=(name=org.freedesktop.ScreenSaver), - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.freedesktop.UDisks2 b/apparmor.d/abstractions/bus/org.freedesktop.UDisks2 deleted file mode 100644 index c97e83d714..0000000000 --- a/apparmor.d/abstractions/bus/org.freedesktop.UDisks2 +++ /dev/null @@ -1,41 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - #aa:dbus common bus=system name=org.freedesktop.UDisks2 label=udisksd - - dbus send bus=system path=/org/freedesktop/UDisks2 - interface=org.freedesktop.DBus.ObjectManager - member=GetManagedObjects - peer=(name="{@{busname},org.freedesktop.UDisks2}", label=udisksd), - - dbus send bus=system path=/ - interface=org.freedesktop.DBus.Introspectable - member=Introspect - peer=(name="{@{busname},org.freedesktop.UDisks2}", label=udisksd), - - dbus send bus=system path=/ - interface=org.freedesktop.DBus.Properties - member=Get - peer=(name="{@{busname},org.freedesktop.UDisks2}", label=udisksd), - - dbus send bus=system path=/org/freedesktop/UDisks2/drives{,/*} - interface=org.freedesktop.DBus.Introspectable - member=Introspect - peer=(name="{@{busname},org.freedesktop.UDisks2}", label=udisksd), - - dbus receive bus=system path=/org/freedesktop/UDisks2 - interface=org.freedesktop.DBus.ObjectManager - member=InterfacesAdded - peer=(name="{@{busname},org.freedesktop.UDisks2}", label=udisksd), - - dbus receive bus=system path=/org/freedesktop/UDisks2/jobs/@{int} - interface=org.freedesktop.UDisks2.Job - member=Completed - peer=(name="{@{busname},org.freedesktop.UDisks2}", label=udisksd), - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.freedesktop.UPower b/apparmor.d/abstractions/bus/org.freedesktop.UPower deleted file mode 100644 index ec0a2b15bd..0000000000 --- a/apparmor.d/abstractions/bus/org.freedesktop.UPower +++ /dev/null @@ -1,26 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - #aa:dbus common bus=system name=org.freedesktop.UPower label=upowerd - - dbus send bus=system path=/org/freedesktop/UPower - interface=org.freedesktop.UPower - member=EnumerateDevices - peer=(name="{@{busname},org.freedesktop.UPower}", label=upowerd), - - dbus send bus=system path=/org/freedesktop/UPower - interface=org.freedesktop.DBus.Properties - member=GetDisplayDevice - peer=(name=org.freedesktop.UPower, label=upowerd), - - dbus receive bus=system path=/org/freedesktop/UPower - interface=org.freedesktop.UPower - member=DeviceAdded - peer=(name="{@{busname},org.freedesktop.UPower}", label=upowerd), - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.freedesktop.impl.portal.PermissionStore b/apparmor.d/abstractions/bus/org.freedesktop.impl.portal.PermissionStore deleted file mode 100644 index 8461bb0478..0000000000 --- a/apparmor.d/abstractions/bus/org.freedesktop.impl.portal.PermissionStore +++ /dev/null @@ -1,16 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - #aa:dbus common bus=session name=org.freedesktop.impl.portal.PermissionStore label=xdg-permission-store - - dbus send bus=session path=/org/freedesktop/impl/portal/PermissionStore - interface=org.freedesktop.impl.portal.PermissionStore - member=Lookup - peer=(name="@{busname}", label=xdg-permission-store), - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.freedesktop.login1 b/apparmor.d/abstractions/bus/org.freedesktop.login1 deleted file mode 100644 index 7f9fc5fb77..0000000000 --- a/apparmor.d/abstractions/bus/org.freedesktop.login1 +++ /dev/null @@ -1,26 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - #aa:dbus common bus=system name=org.freedesktop.login1 label=systemd-logind - - dbus send bus=system path=/org/freedesktop/login1 - interface=org.freedesktop.login1.Manager - member={Inhibit,CanHibernate,CanHybridSleep,CanPowerOff,CanReboot,CanSuspend,CreateSession,GetSessionByPID} - peer=(name="{@{busname},org.freedesktop.login1}", label=systemd-logind), - - dbus receive bus=system path=/org/freedesktop/login1 - interface=org.freedesktop.login1.Manager - member={SessionNew,SessionRemoved,UserNew,UserRemoved,SeatNew,PrepareFor*} - peer=(name="{@{busname},org.freedesktop.login1}", label=systemd-logind), - - dbus send bus=system path=/org/freedesktop/login1/session/* - interface=org.freedesktop.login1.Session - member=PauseDeviceComplete - peer=(name=org.freedesktop.login1, label=systemd-logind), - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.freedesktop.login1.Session b/apparmor.d/abstractions/bus/org.freedesktop.login1.Session deleted file mode 100644 index 23ec52c8ed..0000000000 --- a/apparmor.d/abstractions/bus/org.freedesktop.login1.Session +++ /dev/null @@ -1,26 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - #aa:dbus common bus=system name=org.freedesktop.login1 label=systemd-logind - - dbus send bus=system path=/org/freedesktop/login1 - interface=org.freedesktop.login1.Manager - member=GetSession - peer=(name="@{busname}", label=systemd-logind), - - dbus send bus=system path=/org/freedesktop/login1/session/* - interface=org.freedesktop.login1.Session - member={ReleaseDevice,TakeControl,TakeDevice,SetBrightness,SetLockedHint,SetIdleHint} - peer=(name="{@{busname},org.freedesktop.login1}", label=systemd-logind), - - dbus receive bus=system path=/org/freedesktop/login1/session/* - interface=org.freedesktop.login1.Session - member={PauseDevice,Unlock} - peer=(name="{@{busname},org.freedesktop.login1}", label=systemd-logind), - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.freedesktop.portal.Desktop b/apparmor.d/abstractions/bus/org.freedesktop.portal.Desktop deleted file mode 100644 index 7b19a675a0..0000000000 --- a/apparmor.d/abstractions/bus/org.freedesktop.portal.Desktop +++ /dev/null @@ -1,40 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - #aa:dbus common bus=session name=org.freedesktop.portal.Desktop label=xdg-desktop-portal - dbus send bus=session path=/org/freedesktop/portal/desktop - interface=org.freedesktop.DBus.Properties - member=GetAll - peer=(name=@{busname}, label=xdg-desktop-portal), - - dbus send bus=session path=/org/freedesktop/portal/desktop - interface=org.freedesktop.DBus.Properties - member=Read - peer=(name="{@{busname},org.freedesktop.portal.Desktop}", label=xdg-desktop-portal), - - dbus send bus=session path=/org/freedesktop/portal/desktop - interface=org.freedesktop.portal.Settings - member={Read,ReadAll} - peer=(name="@{busname}", label=xdg-desktop-portal), - - dbus receive bus=session path=/org/freedesktop/portal/desktop - interface=org.freedesktop.portal.Settings - member=SettingChanged - peer=(name="@{busname}", label=xdg-desktop-portal), - - dbus receive bus=session path=/org/freedesktop/portal/desktop - interface=org.freedesktop.DBus.Properties - member={Get,GetAll} - peer=(name="@{busname}", label=xdg-desktop-portal), - - dbus receive bus=session path=/org/freedesktop/portal/desktop - interface=org.freedesktop.impl.portal.Settings - member={Read,ReadAll} - peer=(name="@{busname}", label=xdg-desktop-portal), - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.freedesktop.resolve1 b/apparmor.d/abstractions/bus/org.freedesktop.resolve1 deleted file mode 100644 index 8c7670382e..0000000000 --- a/apparmor.d/abstractions/bus/org.freedesktop.resolve1 +++ /dev/null @@ -1,16 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - #aa:dbus common bus=system name=org.freedesktop.resolve1 label=systemd-resolved - - dbus send bus=system path=/org/freedesktop/resolve1 - interface=org.freedesktop.resolve1.Manager - member={SetLink*,ResolveHostname} - peer=(name="{@{busname},org.freedesktop.resolve1}", label=systemd-resolved), - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.freedesktop.secrets b/apparmor.d/abstractions/bus/org.freedesktop.secrets deleted file mode 100644 index a2389a68a2..0000000000 --- a/apparmor.d/abstractions/bus/org.freedesktop.secrets +++ /dev/null @@ -1,26 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - #aa:dbus common bus=session name=org.freedesktop.secrets label=gnome-keyring-daemon - - dbus send bus=session path=/org/freedesktop/secrets - interface=org.freedesktop.Secret.Service - member={OpenSession,GetSecrets,SearchItems,ReadAlias} - peer=(name="@{busname}", label=gnome-keyring-daemon), - - dbus send bus=session path=/org/freedesktop/secrets/aliases/default - interface=org.freedesktop.Secret.Collection - member=CreateItem - peer=(name=org.freedesktop.secrets, label=gnome-keyring-daemon), - - dbus receive bus=session path=/org/freedesktop/secrets/collection/login - interface=org.freedesktop.Secret.Collection - member=ItemCreated - peer=(name="@{busname}", label=gnome-keyring-daemon), - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.freedesktop.systemd1 b/apparmor.d/abstractions/bus/org.freedesktop.systemd1 deleted file mode 100644 index 46297b4844..0000000000 --- a/apparmor.d/abstractions/bus/org.freedesktop.systemd1 +++ /dev/null @@ -1,21 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - #aa:dbus common bus=system name=org.freedesktop.systemd1 label="@{p_systemd}" - - dbus send bus=session path=/org/freedesktop/systemd1 - interface=org.freedesktop.systemd1.Manager - member={GetUnit,StartUnit,StartTransientUnit} - peer=(name=org.freedesktop.systemd1, label="@{p_systemd}"), - - dbus send bus=session path=/org/freedesktop/systemd1 - interface=org.freedesktop.systemd1.Manager - member={GetUnit,StartUnit,StartTransientUnit} - peer=(name=org.freedesktop.systemd1), - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.freedesktop.systemd1-session b/apparmor.d/abstractions/bus/org.freedesktop.systemd1-session deleted file mode 100644 index 577cc3ed92..0000000000 --- a/apparmor.d/abstractions/bus/org.freedesktop.systemd1-session +++ /dev/null @@ -1,16 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - #aa:dbus common bus=session name=org.freedesktop.systemd1 label="@{p_systemd_user}" - - dbus send bus=session path=/org/freedesktop/systemd1 - interface=org.freedesktop.systemd1.Manager - member=GetUnit - peer=(name="{@{busname},org.freedesktop.systemd1}", label="@{p_systemd_user}"), - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.freedesktop.timedate1 b/apparmor.d/abstractions/bus/org.freedesktop.timedate1 deleted file mode 100644 index 83f85c6786..0000000000 --- a/apparmor.d/abstractions/bus/org.freedesktop.timedate1 +++ /dev/null @@ -1,11 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - #aa:dbus common bus=system name=org.freedesktop.timedate1 label=systemd-timedated - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.gnome.Nautilus.FileOperations2 b/apparmor.d/abstractions/bus/org.gnome.Nautilus.FileOperations2 deleted file mode 100644 index 178139a8d8..0000000000 --- a/apparmor.d/abstractions/bus/org.gnome.Nautilus.FileOperations2 +++ /dev/null @@ -1,11 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - #aa:dbus common bus=session name=org.gnome.Nautilus.FileOperations2 label=nautilus - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.gnome.SessionManager b/apparmor.d/abstractions/bus/org.gnome.SessionManager deleted file mode 100644 index 0683a98fb2..0000000000 --- a/apparmor.d/abstractions/bus/org.gnome.SessionManager +++ /dev/null @@ -1,43 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - -# FIXME: Too large, restrict it. - - abi , - - #aa:dbus common bus=session name=org.gnome.SessionManager label=gnome-session-binary - - dbus send bus=session path=/org/gnome/SessionManager - interface=org.gnome.SessionManager - member={RegisterClient,IsSessionRunning} - peer=(name="@{busname}", label=gnome-session-binary), - - dbus send bus=session path=/org/gnome/SessionManager - interface=org.gnome.SessionManager - member={Setenv,IsSessionRunning} - peer=(name=org.gnome.SessionManager, label=gnome-session-binary), - - dbus receive bus=session path=/org/gnome/SessionManager - interface=org.gnome.SessionManager - member={ClientAdded,ClientRemoved,SessionRunning,InhibitorRemoved,InhibitorAdded} - peer=(name="@{busname}", label=gnome-session-binary), - - dbus send bus=session path=/org/gnome/SessionManager/Client@{int} - interface=org.gnome.SessionManager.ClientPrivate - member=EndSessionResponse - peer=(name="@{busname}", label=gnome-session-binary), - - dbus receive bus=session path=/org/gnome/SessionManager/Client@{int} - interface=org.gnome.SessionManager.ClientPrivate - member={CancelEndSession,QueryEndSession,EndSession,Stop} - peer=(name="@{busname}", label=gnome-session-binary), - - dbus receive bus=session path=/org/gnome/SessionManager/Presence - interface=org.gnome.SessionManager.Presence - member=StatusChanged - peer=(name="@{busname}", label=gnome-session-binary), - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.gnome.Shell.Introspect b/apparmor.d/abstractions/bus/org.gnome.Shell.Introspect deleted file mode 100644 index b53acf6101..0000000000 --- a/apparmor.d/abstractions/bus/org.gnome.Shell.Introspect +++ /dev/null @@ -1,21 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - #aa:dbus common bus=session name=org.gnome.Shell.Introspect label=gnome-shell - - dbus send bus=session path=/org/gnome/Shell/Introspect - interface=org.gnome.Shell.Introspect - member=GetRunningApplications - peer=(name="@{busname}", label=gnome-shell), - - dbus receive bus=session path=/org/gnome/Shell/Introspect - interface=org.gnome.Shell.Introspect - member={RunningApplicationsChanged,WindowsChanged} - peer=(name="@{busname}", label=gnome-shell), - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.gtk.vfs.Daemon b/apparmor.d/abstractions/bus/org.gtk.vfs.Daemon deleted file mode 100644 index 66910007bb..0000000000 --- a/apparmor.d/abstractions/bus/org.gtk.vfs.Daemon +++ /dev/null @@ -1,19 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - dbus send bus=session path=/org/gtk/vfs/Daemon - interface=org.gtk.vfs.Daemon - member={GetConnection,ListMonitorImplementations,ListMountableInfo} - peer=(name="@{busname}", label=gvfsd), - - dbus receive bus=session path=/org/gtk/vfs/Daemon - interface=org.gtk.vfs.Daemon - member=GetConnection - peer=(name=@{busname}), - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.kde.StatusNotifierItem b/apparmor.d/abstractions/bus/org.kde.StatusNotifierItem deleted file mode 100644 index 43947d52a7..0000000000 --- a/apparmor.d/abstractions/bus/org.kde.StatusNotifierItem +++ /dev/null @@ -1,9 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.kde.StatusNotifierWatcher b/apparmor.d/abstractions/bus/org.kde.StatusNotifierWatcher deleted file mode 100644 index d9ca82881c..0000000000 --- a/apparmor.d/abstractions/bus/org.kde.StatusNotifierWatcher +++ /dev/null @@ -1,16 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - - abi , - - #aa:dbus common bus=session name=org.kde.StatusNotifierWatcher label=gnome-shell - - dbus send bus=session path=/StatusNotifierWatcher - interface=org.kde.StatusNotifierWatcher - member=RegisterStatusNotifierItem - peer=(name="{:*,org.kde.StatusNotifierWatcher}", label=gnome-shell), - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/ca.desrt.dconf.Writer b/apparmor.d/abstractions/bus/session/ca.desrt.dconf.Writer similarity index 63% rename from apparmor.d/abstractions/bus/ca.desrt.dconf.Writer rename to apparmor.d/abstractions/bus/session/ca.desrt.dconf.Writer index 9bad3655d4..06f9c934e3 100644 --- a/apparmor.d/abstractions/bus/ca.desrt.dconf.Writer +++ b/apparmor.d/abstractions/bus/session/ca.desrt.dconf.Writer @@ -7,13 +7,18 @@ dbus send bus=session path=/ca/desrt/dconf/Writer/user interface=ca.desrt.dconf.Writer member=Change - peer=(name=ca.desrt.dconf), # no peer's labels + peer=(name=ca.desrt.dconf), + + dbus send bus=session path=/ca/desrt/dconf/Writer/user + interface=ca.desrt.dconf.Writer + member=Change + peer=(name=ca.desrt.dconf, label=dconf-service), dbus receive bus=session path=/ca/desrt/dconf/Writer/user interface=ca.desrt.dconf.Writer member=Notify peer=(name=@{busname}, label=dconf-service), - include if exists + include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/com.canonical.AppMenu.Registrar b/apparmor.d/abstractions/bus/session/com.canonical.AppMenu.Registrar new file mode 100644 index 0000000000..7a95e0f2bf --- /dev/null +++ b/apparmor.d/abstractions/bus/session/com.canonical.AppMenu.Registrar @@ -0,0 +1,32 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2016-2017 Canonical Ltd +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow access for connecting to/communication with the appmenu + + abi , + + dbus send bus=session path=/org/freedesktop/DBus + interface=org.freedesktop.DBus + member=ListNames + peer=(name=org.freedesktop.DBus, label="@{p_dbus_session}"), + + dbus send bus=session path=/com/canonical/AppMenu/Registrar + interface=com.canonical.AppMenu.Registrar + member={RegisterWindow,UnregisterWindow} + peer=(name=@{busname}, label="@{pp_dbusmenu}"), + + dbus send bus=session path=/com/canonical/AppMenu/Registrar + interface=com.canonical.dbusmenu + member=UnregisterWindow + peer=(name=@{busname}, label="@{pp_dbusmenu}"), + + dbus receive bus=session path=/com/canonical/menu/@{int} + interface={org.freedesktop.DBus.Properties,com.canonical.dbusmenu} + member={GetAll,GetLayout} + peer=(name=@{busname}, label="@{pp_dbusmenu}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/com.canonical.Unity.LauncherEntry b/apparmor.d/abstractions/bus/session/com.canonical.Unity.LauncherEntry similarity index 58% rename from apparmor.d/abstractions/bus/com.canonical.Unity.LauncherEntry rename to apparmor.d/abstractions/bus/session/com.canonical.Unity.LauncherEntry index 9363bb7578..a612868d12 100644 --- a/apparmor.d/abstractions/bus/com.canonical.Unity.LauncherEntry +++ b/apparmor.d/abstractions/bus/session/com.canonical.Unity.LauncherEntry @@ -1,4 +1,5 @@ # apparmor.d - Full set of apparmor profiles +# Copyright (C) 2017 Canonical Ltd # Copyright (C) 2023-2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only @@ -6,6 +7,20 @@ abi , + # Allow to send updates to the desktop session about ongoing jobs + # (for progress display in the task list) + dbus send bus=session + interface=com.canonical.Unity.LauncherEntry + member=Update + peer=(label=gnome-shell), + + # Allow to receive updates from applications to the desktop session about ongoing jobs + # (for progress display in the task list) + dbus send bus=session + interface=com.canonical.Unity.LauncherEntry + member=Update + peer=(label=gnome-shell), + dbus send bus=session path=/com/canonical/unity/launcherentry/@{int} interface=com.canonical.Unity.LauncherEntry member=Update @@ -21,6 +36,6 @@ member=GetAll peer=(name="@{busname}", label=gnome-shell), - include if exists + include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/com.canonical.dbusmenu b/apparmor.d/abstractions/bus/session/com.canonical.dbusmenu new file mode 100644 index 0000000000..25e65270b8 --- /dev/null +++ b/apparmor.d/abstractions/bus/session/com.canonical.dbusmenu @@ -0,0 +1,32 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2017 Canonical Ltd +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Dbus menu + + abi , + + dbus send bus=session path=/{MenuBar{,/@{hex}},com/canonical/{menu/@{hex},dbusmenu}} + interface=com.canonical.dbusmenu + member={LayoutUpdated,ItemsPropertiesUpdated} + peer=(label="@{pp_dbusmenu}"), + + dbus receive bus=session path=/{MenuBar{,/@{hex}},com/canonical/{menu/@{hex},dbusmenu}} + interface=com.canonical.dbusmenu + member={GetGroupProperties,GetLayout} + peer=(label="@{pp_dbusmenu}"), + + dbus receive bus=session path=/{MenuBar{,/@{hex}},com/canonical/{menu/@{hex},dbusmenu}} + interface=com.canonical.dbusmenu + member={AboutToShow,Event*} + peer=(label="@{pp_dbusmenu}"), + + dbus receive bus=session path=/{MenuBar{,/@{hex}},com/canonical/{menu/@{hex},dbusmenu}} + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(label="@{pp_dbusmenu}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/io.snapcraft.Launcher b/apparmor.d/abstractions/bus/session/io.snapcraft.Launcher new file mode 100644 index 0000000000..ca2bf92c81 --- /dev/null +++ b/apparmor.d/abstractions/bus/session/io.snapcraft.Launcher @@ -0,0 +1,21 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow use of snapd's internal xdg-open + + abi , + + dbus send bus=session path=/ + interface=com.canonical.SafeLauncher + member=OpenURL + peer=(name=@{busname}, label=snap), + + dbus send bus=session path=/io/snapcraft/Launcher + interface=io.snapcraft.Launcher + member={OpenURL,OpenFile} + peer=(name=@{busname}, label=snap), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/io.snapcraft.PrivilegedDesktopLauncher b/apparmor.d/abstractions/bus/session/io.snapcraft.PrivilegedDesktopLauncher new file mode 100644 index 0000000000..704d9010d1 --- /dev/null +++ b/apparmor.d/abstractions/bus/session/io.snapcraft.PrivilegedDesktopLauncher @@ -0,0 +1,16 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Can identify and launch other snaps. + + abi , + + dbus send bus=session path=/io/snapcraft/PrivilegedDesktopLauncher + interface=io.snapcraft.PrivilegedDesktopLauncher + member=OpenDesktopEntry + peer=(name=io.snapcraft.Launcher, label=snap), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/io.snapcraft.Settings b/apparmor.d/abstractions/bus/session/io.snapcraft.Settings new file mode 100644 index 0000000000..c50753cd6e --- /dev/null +++ b/apparmor.d/abstractions/bus/session/io.snapcraft.Settings @@ -0,0 +1,16 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow use of snapd's internal 'xdg-settings' + + abi , + + dbus send bus=session path=/io/snapcraft/Settings + interface=io.snapcraft.Settings + member={Check,CheckSub,Get,GetSub,Set,SetSub} + peer=(name=io.snapcraft.Settings, label=snap), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.a11y b/apparmor.d/abstractions/bus/session/org.a11y new file mode 100644 index 0000000000..8f517fe993 --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.a11y @@ -0,0 +1,29 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + dbus send bus=session path=/org/a11y/bus + interface=org.freedesktop.DBus.Properties + member=GetAll + peer=(name=@{busname}, label="@{p_dbus_accessibility}"), + + dbus send bus=session path=/org/a11y/bus + interface=org.freedesktop.DBus.Properties + member=Get + peer=(name=org.a11y.Bus, label="@{p_dbus_accessibility}"), + + dbus send bus=session path=/org/a11y/bus + interface=org.a11y.Bus + member=Get + peer=(name=org.a11y.Bus, label="@{p_dbus_accessibility}"), + + dbus send bus=session path=/org/a11y/bus + interface=org.a11y.Bus + member=GetAddress + peer=(name=org.a11y.Bus), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.ayatana.NotificationItem b/apparmor.d/abstractions/bus/session/org.ayatana.NotificationItem new file mode 100644 index 0000000000..6ef05910d2 --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.ayatana.NotificationItem @@ -0,0 +1,29 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + dbus receive bus=session path=/org/ayatana/NotificationItem/* + interface=org.freedesktop.DBus.Properties + member=Get + peer=(name=@{busname}, label="@{pp_app_indicator}"), + + dbus send bus=session path=/org/ayatana/NotificationItem/* + interface=org.kde.StatusNotifierItem + member={NewAttentionIcon,NewIcon,NewIconThemePath,NewOverlayIcon,NewStatus,NewTitle,NewToolTip} + peer=(name=@{busname}, label="@{pp_app_indicator}"), + + dbus send bus=session path=/org/ayatana/NotificationItem/*/Menu + interface=com.canonical.dbusmenu + member=LayoutUpdated + peer=(name=org.freedesktop.DBus, label="@{pp_app_indicator}"), + + dbus receive bus=session path=/org/ayatana/NotificationItem/*/Menu + interface=com.canonical.dbusmenu + member={AboutToShow,Event,GetGroupProperties,GetLayout} + peer=(name=@{busname}, label="@{pp_app_indicator}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.freedesktop.Application b/apparmor.d/abstractions/bus/session/org.freedesktop.Application new file mode 100644 index 0000000000..a16e9a34c0 --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.freedesktop.Application @@ -0,0 +1,24 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + dbus receive bus=session + interface=org.freedesktop.Application + member={Activate,ActivateAction} + peer=(name=@{busname}, label=gnome-shell), + + dbus receive bus=session + interface=org.freedesktop.Application + member=Open + peer=(name=@{busname}, label=gnome-shell), + + dbus receive bus=session + interface=org.freedesktop.Application + member=Open + peer=(name=@{busname}, label=nautilus), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.freedesktop.FileManager1 b/apparmor.d/abstractions/bus/session/org.freedesktop.FileManager1 new file mode 100644 index 0000000000..006ce1acfa --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.freedesktop.FileManager1 @@ -0,0 +1,16 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + #aa:dbus see bus=session name=org.freedesktop.FileManager1 label=nautilus + + dbus send bus=session path=/org/freedesktop/FileManager1 + interface=org.freedesktop.FileManager1 + member=ShowItems + peer=(name=org.freedesktop.FileManager1, label=nautilus), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.freedesktop.IBus.Portal b/apparmor.d/abstractions/bus/session/org.freedesktop.IBus.Portal new file mode 100644 index 0000000000..e7c0f9ceff --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.freedesktop.IBus.Portal @@ -0,0 +1,24 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow access to the IBus portal + + abi , + + dbus send bus=session path=/org/freedesktop/IBus + interface=org.freedesktop.IBus.Portal + member=CreateInputContext + peer=(name=org.freedesktop.portal.IBus), + + dbus send bus=session path=/org/freedesktop/IBus/InputContext_@{int} + interface=org.freedesktop.IBus.InputContext + peer=(label=ibus-daemon), + + dbus receive bus=session path=/org/freedesktop/IBus/InputContext_@{int} + interface=org.freedesktop.IBus.InputContext + peer=(label=ibus-daemon), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.freedesktop.Notifications b/apparmor.d/abstractions/bus/session/org.freedesktop.Notifications new file mode 100644 index 0000000000..c5b520f224 --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.freedesktop.Notifications @@ -0,0 +1,28 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + # DBus.Introspectable: allow clients to introspect the service + + dbus send bus=session path=/org/freedesktop/Notifications + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=@{busname}, label="@{pp_notification}"), + + # org.freedesktop.Notifications + + dbus send bus=session path=/org/freedesktop/Notifications + interface=org.freedesktop.Notifications + member={GetCapabilities,GetServerInformation,Notify,CloseNotification} + peer=(label="@{pp_notification}"), + + dbus receive bus=session path=/org/freedesktop/Notifications + interface=org.freedesktop.Notifications + member={ActivationToken,ActionInvoked,NotificationClosed,NotificationReplied} + peer=(label="@{pp_notification}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.freedesktop.ScreenSaver b/apparmor.d/abstractions/bus/session/org.freedesktop.ScreenSaver new file mode 100644 index 0000000000..dc1fe68f9e --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.freedesktop.ScreenSaver @@ -0,0 +1,31 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow checking status, activating and locking the screensaver + + abi , + + dbus send bus=session path=/ScreenSaver + interface=org.freedesktop.ScreenSaver + member={Inhibit,UnInhibit} + peer=(name=org.freedesktop.ScreenSaver), + + dbus send bus=session path=/ScreenSaver + interface=org.freedesktop.ScreenSaver + member={Inhibit,UnInhibit} + peer=(label=gsd-screensaver-proxy), + + dbus send bus=session path=/org/freedesktop/ScreenSaver + interface=org.freedesktop.ScreenSaver + member={GetActive,GetActiveTime,Lock,SetActive} + peer=(name="{@{busname},org.freedesktop.ScreenSaver}", label="{gsd-screensaver-proxy,ksmserver,kwin_wayland}"), + + dbus receive bus=session path=/org/freedesktop/ScreenSaver + interface=org.freedesktop.ScreenSaver + member={ActiveChanged,WakeUpScreen} + peer=(name=@{busname}, label="{gsd-screensaver-proxy,ksmserver,kwin_wayland}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.freedesktop.Secret b/apparmor.d/abstractions/bus/session/org.freedesktop.Secret new file mode 100644 index 0000000000..0694ca9479 --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.freedesktop.Secret @@ -0,0 +1,68 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2017 Canonical Ltd +# Copyright (C) 2021-2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Provide full access to the secret-service API: +# +# - https://standards.freedesktop.org/secret-service/) +# +# The secret-service allows managing (add/delete/lock/etc) collections and +# (add/delete/etc) items within collections. The API also has the concept of +# aliases for collections which is typically used to access the default +# collection. While it would be possible for an application developer to use a +# snap-specific collection and mediate by object path, application developers +# are meant to instead to treat collections (typically the default collection) +# as a database of key/value attributes each with an associated secret that +# applications may query. Because AppArmor does not mediate member data, +# typical and recommended usage of the API does not allow for application +# isolation. For details, see: +# +# - https://standards.freedesktop.org/secret-service/ch03.html +# + + abi , + + # DBus.Properties: read properties from the interface + + dbus send bus=session path=/org/freedesktop/secrets{,/**} + interface=org.freedesktop.DBus.Properties + member=Get + peer=(name=org.freedesktop.secrets, label=gnome-keyring-daemon), + + dbus send bus=session path=/org/freedesktop/secrets + interface=org.freedesktop.DBus.Properties + member=GetAll + peer=(name=@{busname}, label=gnome-keyring-daemon), + + # DBus.Properties: receive property changed events + + # DBus.ObjectManager: allow clients to enumerate sources + + # org.freedesktop.Secret + + dbus send bus=session path=/org/freedesktop/secrets/collection/** + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name=@{busname}, label=gnome-keyring-daemon), + + dbus send bus=session path=/org/freedesktop/secrets{,/**} + interface=org.freedesktop.Secret.{Collection,Item,Prompt,Service,Session} + peer=(name="{@{busname},org.freedesktop.secrets}", label=gnome-keyring-daemon), + + dbus receive bus=session path=/org/freedesktop/secrets{,/**} + interface=org.freedesktop.Secret.{Collection,Item,Prompt,Service,Session} + peer=(name="{@{busname},org.freedesktop.secrets}", label=gnome-keyring-daemon), + + dbus send bus=session path=/org/freedesktop/secrets + interface=org.freedesktop.Secret.Service + member=ReadAlias + peer=(name=org.freedesktop.secrets, label=gnome-keyring-daemon), + dbus send bus=session path=/org/freedesktop/secrets + interface=org.freedesktop.Secret.Service + member=SearchItems + peer=(name=@{busname}, label=gnome-keyring-daemon), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.freedesktop.Tracker3.Miner.Files b/apparmor.d/abstractions/bus/session/org.freedesktop.Tracker3.Miner.Files similarity index 62% rename from apparmor.d/abstractions/bus/org.freedesktop.Tracker3.Miner.Files rename to apparmor.d/abstractions/bus/session/org.freedesktop.Tracker3.Miner.Files index 48fa7e394d..c0b32ac658 100644 --- a/apparmor.d/abstractions/bus/org.freedesktop.Tracker3.Miner.Files +++ b/apparmor.d/abstractions/bus/session/org.freedesktop.Tracker3.Miner.Files @@ -7,13 +7,13 @@ dbus send bus=session path=/org/freedesktop/Tracker3/Endpoint interface=org.freedesktop.DBus.Peer member=Ping - peer=(name=org.freedesktop.Tracker3.Miner.Files, label=tracker-miner), + peer=(name=org.freedesktop.Tracker3.Miner.Files, label="{localsearch,tracker-miner}"), dbus send bus=session path=/org/freedesktop/Tracker3/Endpoint interface=org.freedesktop.Tracker3.Endpoint member=Query - peer=(name=org.freedesktop.Tracker3.Miner.Files, label=tracker-miner), + peer=(name=org.freedesktop.Tracker3.Miner.Files, label="{localsearch,tracker-miner}"), - include if exists + include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.freedesktop.background.Monitor b/apparmor.d/abstractions/bus/session/org.freedesktop.background.Monitor similarity index 52% rename from apparmor.d/abstractions/bus/org.freedesktop.background.Monitor rename to apparmor.d/abstractions/bus/session/org.freedesktop.background.Monitor index 0f371f79ba..2a44f09b2a 100644 --- a/apparmor.d/abstractions/bus/org.freedesktop.background.Monitor +++ b/apparmor.d/abstractions/bus/session/org.freedesktop.background.Monitor @@ -4,8 +4,8 @@ abi , - #aa:dbus common bus=session name=org.freedesktop.background.Monitor label=xdg-desktop-portal + #aa:dbus see bus=session name=org.freedesktop.background.Monitor label=xdg-desktop-portal - include if exists + include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.freedesktop.impl.portal.PermissionStore b/apparmor.d/abstractions/bus/session/org.freedesktop.impl.portal.PermissionStore new file mode 100644 index 0000000000..18cef81b37 --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.freedesktop.impl.portal.PermissionStore @@ -0,0 +1,31 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + #aa:dbus see bus=session name=org.freedesktop.impl.portal.PermissionStore label=xdg-permission-store + + dbus send bus=session path=/org/freedesktop/impl/portal/PermissionStore + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name=@{busname}, label=xdg-permission-store), + + dbus send bus=session path=/org/freedesktop/impl/portal/PermissionStore + interface=org.freedesktop.impl.portal.PermissionStore + member=Lookup + peer=(name="{@{busname},org.freedesktop.impl.portal.PermissionStore}", label=xdg-permission-store), + + dbus send bus=session path=/org/freedesktop/impl/portal/PermissionStore + interface=org.freedesktop.impl.portal.PermissionStore + member=Lookup + peer=(name=org.freedesktop.impl.portal.PermissionStore, label=xdg-permission-store), + + dbus receive bus=session path=/org/freedesktop/impl/portal/PermissionStore + interface=org.freedesktop.impl.portal.PermissionStore + member=Changed + peer=(name=@{busname}, label=xdg-permission-store), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.freedesktop.portal b/apparmor.d/abstractions/bus/session/org.freedesktop.portal new file mode 100644 index 0000000000..2470a9c910 --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.freedesktop.portal @@ -0,0 +1,20 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow access to xdg-desktop-portal and xdg-document-portal +# +# !!! warning "TODO" +# +# This should be restricted by a lot, however, the risk of breaking things is +# is also really important. Thus, for now we globally allow full talk access +# over the org.freedesktop.portal.* name to xdg-desktop-portal +# + + abi , + + #aa:dbus talk bus=session name=org.freedesktop.portal.* label=xdg-desktop-portal + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.freedesktop.portal.Desktop b/apparmor.d/abstractions/bus/session/org.freedesktop.portal.Desktop new file mode 100644 index 0000000000..ffd912e5f8 --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.freedesktop.portal.Desktop @@ -0,0 +1,100 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + # DBus.Properties: read properties from the interface + + dbus send bus=session path=/org/freedesktop/portal/desktop + interface=org.freedesktop.DBus.Properties + member=Get + peer=(name=org.freedesktop.portal.Desktop, label=xdg-desktop-portal), + + dbus send bus=session path=/org/freedesktop/portal/desktop + interface=org.freedesktop.DBus.Properties + member=GetAll + peer=(name=@{busname}, label=xdg-desktop-portal), + + dbus send bus=session path=/org/freedesktop/portal/desktop + interface=org.freedesktop.DBus.Properties + member=Read + peer=(label=xdg-desktop-portal), + + # DBus.Properties: receive property changed events + + dbus receive bus=session path=/org/freedesktop/portal/desktop{,/**} + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name=@{busname}, label=xdg-desktop-portal), + + # portal.Settings + + dbus send bus=session path=/org/freedesktop/portal/desktop + interface=org.freedesktop.portal.Settings + member={Read,ReadAll} + peer=(name=@{busname}, label=xdg-desktop-portal), + + dbus receive bus=session path=/org/freedesktop/portal/desktop + interface=org.freedesktop.portal.Settings + member=SettingChanged + peer=(name=@{busname}, label=xdg-desktop-portal), + + dbus receive bus=session path=/org/freedesktop/portal/desktop + interface=org.freedesktop.impl.portal.Settings + member={Read,ReadAll} + peer=(name=@{busname}, label=xdg-desktop-portal), + + # portal.Registry + + dbus send bus=session path=/org/freedesktop/portal/desktop + interface=org.freedesktop.host.portal.Registry + member=Register + peer=(name=org.freedesktop.portal.Desktop, label=xdg-desktop-portal), + + # portal.Inhibit + + dbus receive bus=session path=/org/freedesktop/portal/desktop + interface=org.freedesktop.portal.Inhibit + member={StateChanged,CreateMonitor} + peer=(name=@{busname}, label=xdg-desktop-portal), + + dbus send bus=session path=/org/freedesktop/portal/desktop + interface=org.freedesktop.portal.Inhibit + member=CreateMonitor + peer=(name=@{busname}, label=xdg-desktop-portal), + + # portal.Session + + dbus send bus=session path=/org/freedesktop/portal/desktop/session/** + interface=org.freedesktop.portal.Session + member=Close + peer=(name=org.freedesktop.portal.Desktop, label=xdg-desktop-portal), + + dbus receive bus=session path=/org/freedesktop/portal/desktop/session/** + interface=org.freedesktop.impl.portal.Session + member=Close + peer=(name=@{busname}, label=xdg-desktop-portal), + + # portal.Request + + dbus send bus=session path=/org/freedesktop/portal/desktop/request/** + interface=org.freedesktop.portal.Request + member=Close + peer=(name=org.freedesktop.portal.Desktop, label=xdg-desktop-portal), + + dbus receive bus=session path=/org/freedesktop/portal/desktop/** + interface=org.freedesktop.portal.Request + member=Response + peer=(name=@{busname}, label=xdg-desktop-portal), + + # portal.FileChooser + + dbus send bus=session path=/org/freedesktop/portal/desktop + interface=org.freedesktop.portal.FileChooser + member=OpenFile + peer=(name=org.freedesktop.portal.Desktop, label=xdg-desktop-portal), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.freedesktop.portal.Inhibit b/apparmor.d/abstractions/bus/session/org.freedesktop.portal.Inhibit new file mode 100644 index 0000000000..8a2ce06264 --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.freedesktop.portal.Inhibit @@ -0,0 +1,19 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + dbus send bus=session path=/org/freedesktop/portal/desktop + interface=org.freedesktop.portal.Inhibit + member=Inhibit + peer=(name=@{busname}, label=xdg-desktop-portal), + + dbus send bus=session path=/org/freedesktop/portal/desktop + interface=org.freedesktop.portal.Inhibit + member=QueryEndResponse + peer=(name=@{busname}, label=xdg-desktop-portal), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.freedesktop.portal.NetworkMonitor b/apparmor.d/abstractions/bus/session/org.freedesktop.portal.NetworkMonitor new file mode 100644 index 0000000000..79e0add83b --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.freedesktop.portal.NetworkMonitor @@ -0,0 +1,16 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow access to xdg-desktop-portal NetworkMonitor methods and signals + + abi , + + dbus send bus=session path=/org/freedesktop/portal/desktop + interface=org.freedesktop.portal.NetworkMonitor + member=GetStatus + peer=(name=@{busname}, label=xdg-desktop-portal), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.freedesktop.portal.Settings b/apparmor.d/abstractions/bus/session/org.freedesktop.portal.Settings new file mode 100644 index 0000000000..f14872a7fa --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.freedesktop.portal.Settings @@ -0,0 +1,24 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + dbus send bus=session path=/org/freedesktop/portal/desktop + interface=org.freedesktop.portal.Settings + member=Read + peer=(name=org.freedesktop.portal.Desktop, label=xdg-desktop-portal), + + dbus send bus=session path=/org/freedesktop/portal/desktop + interface=org.freedesktop.portal.Settings + member=ReadAll + peer=(name=@{busname}, label=xdg-desktop-portal), + + dbus receive bus=session path=/org/freedesktop/portal/desktop + interface=org.freedesktop.portal.Settings + member=SettingChanged + peer=(name=@{busname}, label=xdg-desktop-portal), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.freedesktop.systemd1 b/apparmor.d/abstractions/bus/session/org.freedesktop.systemd1 new file mode 100644 index 0000000000..5c847cfe3c --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.freedesktop.systemd1 @@ -0,0 +1,70 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow managing systemd user units services. This allow full control over all services. +# When possible use the systemctl directive instead. + + abi , + + # DBus.Properties: read properties from the interface + + dbus send bus=session path=/org/freedesktop/systemd1 + interface=org.freedesktop.DBus.Properties + member=Get + peer=(name=org.freedesktop.systemd1, label="@{p_systemd_user}"), + + dbus send bus=session path=/org/freedesktop/systemd1 + interface=org.freedesktop.DBus.Properties + member=GetAll + peer=(name=@{busname}, label="@{p_systemd_user}"), + + dbus send bus=session path=/org/freedesktop/systemd1/unit/* + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(label="@{p_systemd_user}"), + + # DBus.Properties: receive property changed events + + dbus receive bus=session path=/org/freedesktop/systemd1/unit/* + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(label="@{p_systemd_user}"), + + dbus send bus=session path=/org/freedesktop/systemd1 + interface=org.freedesktop.systemd1.Manager + member={SetEnvironment,UnsetAndSetEnvironment,ResetFailed} + peer=(name=org.freedesktop.systemd1, label="@{p_systemd_user}"), + + # List units + dbus send bus=session path=/org/freedesktop/systemd1 + interface=org.freedesktop.systemd1.Manager + member={GetUnit,GetUnitByPIDFD,ListUnitsByPatterns} + peer=(label="@{p_systemd_user}"), + + dbus receive bus=session path=/org/freedesktop/systemd1 + interface=org.freedesktop.systemd1.Manager + member={UnitNew,UnitRemoved} + peer=(label="@{p_systemd_user}"), + + # Start units + dbus send bus=session path=/org/freedesktop/systemd1 + interface=org.freedesktop.systemd1.Manager + member={StartUnit,StartTransientUnit,LoadUnit} + peer=(label="@{p_systemd_user}"), + + # Stop units + dbus send bus=session path=/org/freedesktop/systemd1 + interface=org.freedesktop.systemd1.Manager + member={StopUnit,KillUnit,ResetFailedUnit,Reload,JobRemoved} + peer=(label="@{p_systemd_user}"), + + # Enabled/Disable units + dbus send bus=session path=/org/freedesktop/systemd1 + interface=org.freedesktop.systemd1.Manager + member={DisableUnitFiles,EnableUnitFiles} + peer=(label="@{p_systemd_user}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.gnome.ArchiveManager1 b/apparmor.d/abstractions/bus/session/org.gnome.ArchiveManager1 similarity index 60% rename from apparmor.d/abstractions/bus/org.gnome.ArchiveManager1 rename to apparmor.d/abstractions/bus/session/org.gnome.ArchiveManager1 index ce572e9cd5..64d1a3f519 100644 --- a/apparmor.d/abstractions/bus/org.gnome.ArchiveManager1 +++ b/apparmor.d/abstractions/bus/session/org.gnome.ArchiveManager1 @@ -4,13 +4,13 @@ abi , - #aa:dbus common bus=session name=org.gnome.ArchiveManager1 label=file-roller + #aa:dbus see bus=session name=org.gnome.ArchiveManager1 label="@{p_file_roller}" dbus send bus=session path=/org/gnome/ArchiveManager1 interface=org.gnome.ArchiveManager1 member=GetSupportedTypes - peer=(name="@{busname}", label=file-roller), + peer=(name=@{busname}, label="@{p_file_roller}"), - include if exists + include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.gnome.Mutter.DisplayConfig b/apparmor.d/abstractions/bus/session/org.gnome.Mutter.DisplayConfig similarity index 83% rename from apparmor.d/abstractions/bus/org.gnome.Mutter.DisplayConfig rename to apparmor.d/abstractions/bus/session/org.gnome.Mutter.DisplayConfig index f275850cd1..5fa8580c7e 100644 --- a/apparmor.d/abstractions/bus/org.gnome.Mutter.DisplayConfig +++ b/apparmor.d/abstractions/bus/session/org.gnome.Mutter.DisplayConfig @@ -4,7 +4,7 @@ abi , - #aa:dbus common bus=session name=org.gnome.Mutter.DisplayConfig label=gnome-shell + #aa:dbus see bus=session name=org.gnome.Mutter.DisplayConfig label=gnome-shell dbus send bus=session path=/org/gnome/Mutter/DisplayConfig interface=org.gnome.Mutter.DisplayConfig @@ -21,6 +21,6 @@ member=MonitorsChanged peer=(name="@{busname}", label=gnome-shell), - include if exists + include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.gnome.Mutter.IdleMonitor b/apparmor.d/abstractions/bus/session/org.gnome.Mutter.IdleMonitor similarity index 56% rename from apparmor.d/abstractions/bus/org.gnome.Mutter.IdleMonitor rename to apparmor.d/abstractions/bus/session/org.gnome.Mutter.IdleMonitor index 3eb301f188..e8022e5d57 100644 --- a/apparmor.d/abstractions/bus/org.gnome.Mutter.IdleMonitor +++ b/apparmor.d/abstractions/bus/session/org.gnome.Mutter.IdleMonitor @@ -2,25 +2,27 @@ # Copyright (C) 2023-2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only +# Allow to get the current idle time + abi , - #aa:dbus common bus=session name=org.gnome.Mutter.IdleMonitor label=gnome-shell + #aa:dbus see bus=session name=org.gnome.Mutter.IdleMonitor label=gnome-shell dbus send bus=session path=/org/gnome/Mutter/IdleMonitor interface=org.freedesktop.DBus.ObjectManager member=GetManagedObjects - peer=(name="@{busname}", label=gnome-shell), + peer=(name=@{busname}, label=gnome-shell), dbus send bus=session path=/org/gnome/Mutter/IdleMonitor/Core interface=org.gnome.Mutter.IdleMonitor - member={AddIdleWatch,AddUserActiveWatch,RemoveWatch} - peer=(name="@{busname}", label=gnome-shell), + member={AddIdleWatch,AddUserActiveWatch,RemoveWatch,GetIdletime} + peer=(name="{@{busname},org.gnome.Mutter.IdleMonitor}", label=gnome-shell), dbus receive bus=session path=/org/gnome/Mutter/IdleMonitor/Core interface=org.gnome.Mutter.IdleMonitor member=WatchFired - peer=(name="@{busname}", label=gnome-shell), + peer=(name=@{busname}, label=gnome-shell), - include if exists + include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.freedesktop.hostname1 b/apparmor.d/abstractions/bus/session/org.gnome.Nautilus.FileOperations2 similarity index 71% rename from apparmor.d/abstractions/bus/org.freedesktop.hostname1 rename to apparmor.d/abstractions/bus/session/org.gnome.Nautilus.FileOperations2 index d2a0b1d83f..73eea6b866 100644 --- a/apparmor.d/abstractions/bus/org.freedesktop.hostname1 +++ b/apparmor.d/abstractions/bus/session/org.gnome.Nautilus.FileOperations2 @@ -4,8 +4,8 @@ abi , - #aa:dbus common bus=system name=org.freedesktop.hostname1 label=systemd-hostnamed + #aa:dbus see bus=session name=org.gnome.Nautilus.FileOperations2 label=nautilus - include if exists + include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.gnome.ScreenSaver b/apparmor.d/abstractions/bus/session/org.gnome.ScreenSaver similarity index 50% rename from apparmor.d/abstractions/bus/org.gnome.ScreenSaver rename to apparmor.d/abstractions/bus/session/org.gnome.ScreenSaver index 46d1a1006c..0a65e8562b 100644 --- a/apparmor.d/abstractions/bus/org.gnome.ScreenSaver +++ b/apparmor.d/abstractions/bus/session/org.gnome.ScreenSaver @@ -2,20 +2,25 @@ # Copyright (C) 2023-2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only +# Allow checking status, activating and locking the screensaver (GNOME version) + abi , - #aa:dbus common bus=session name=org.gnome.ScreenSaver label=gjs-console + dbus send bus=session path=/{,org/gnome/}ScreenSaver + interface=org.gnome.ScreenSaver + member={GetActive,GetActiveTime,Lock,SetActive} + peer=(name=@{busname}, label=gjs), dbus send bus=session path=/org/gnome/ScreenSaver interface=org.gnome.ScreenSaver member=GetActive - peer=(name="@{busname}", label=gjs-console), + peer=(name=org.gnome.ScreenSaver, label=gjs), dbus receive bus=session path=/org/gnome/ScreenSaver interface=org.gnome.ScreenSaver member={ActiveChanged,WakeUpScreen} - peer=(name="@{busname}", label=gjs-console), + peer=(name=@{busname}, label=gjs), - include if exists + include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.gnome.SessionManager b/apparmor.d/abstractions/bus/session/org.gnome.SessionManager new file mode 100644 index 0000000000..8110c4c861 --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.gnome.SessionManager @@ -0,0 +1,89 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow registering a client with the session manager. This is needed for +# applications that want to be notified of session events, such as shutdown +# or logout, and to be able to inhibit those actions. + + abi , + + # DBus.Properties: read properties from the interface + + dbus send bus=session path=/org/gnome/SessionManager + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name="{@{busname},org.gnome.SessionManager}", label="@{p_gnome_session}"), + + dbus send bus=session path=/org/gnome/SessionManager/Client@{int} + interface=org.freedesktop.DBus.Properties + member=GetAll + peer=(name="{@{busname},org.gnome.SessionManager}", label="@{p_gnome_session}"), + + # DBus.Properties: receive property changed events + + dbus receive bus=session path=/org/gnome/SessionManager + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name="{@{busname},org.gnome.SessionManager}", label="@{p_gnome_session}"), + + # DBus.Introspectable: allow clients to introspect the service + + dbus send bus=session path=/org/gnome/SessionManager + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name="{@{busname},org.gnome.SessionManager}", label="@{p_gnome_session}"), + + # SessionManager + + dbus send bus=session path=/org/gnome/SessionManager + interface=org.gnome.SessionManager + member={RegisterClient,IsSessionRunning} + peer=(name="{@{busname},org.gnome.SessionManager}", label="@{p_gnome_session}"), + + dbus receive bus=session path=/org/gnome/SessionManager + interface=org.gnome.SessionManager + member={ClientAdded,ClientRemoved} + peer=(name="{@{busname},org.gnome.SessionManager}", label="@{p_gnome_session}"), + + dbus receive bus=session path=/org/gnome/SessionManager + interface=org.gnome.SessionManager + member={SessionRunning,SessionOver} + peer=(name="{@{busname},org.gnome.SessionManager}", label="@{p_gnome_session}"), + + dbus receive bus=session path=/org/gnome/SessionManager + interface=org.gnome.SessionManager + member={InhibitorAdded,InhibitorRemoved} + peer=(name="{@{busname},org.gnome.SessionManager}", label="@{p_gnome_session}"), + + dbus receive bus=session path=/org/gnome/SessionManager/Presence + interface=org.gnome.SessionManager.Presence + member=StatusChanged + peer=(name="{@{busname},org.gnome.SessionManager}", label="@{p_gnome_session}"), + + dbus send bus=session path=/org/gnome/SessionManager/Client@{int} + interface=org.gnome.SessionManager.ClientPrivate + member=EndSessionResponse + peer=(name="{@{busname},org.gnome.SessionManager}", label="@{p_gnome_session}"), + + dbus receive bus=session path=/org/gnome/SessionManager/Client@{int} + interface=org.gnome.SessionManager.ClientPrivate + member={CancelEndSession,QueryEndSession,EndSession,Stop} + peer=(name="{@{busname},org.gnome.SessionManager}", label="@{p_gnome_session}"), + +# ==================== +# +# This one is not in this abs +# dbus send bus=session path=/org/gnome/SessionManager +# interface=org.gnome.SessionManager +# member={Inhibit,Uninhibit} +# peer=(name="@{busname}", label="@{p_gnome_session}"), +# +# dbus send bus=session path=/org/gnome/SessionManager +# interface=org.gnome.SessionManager +# member=Setenv +# peer=(name=org.gnome.SessionManager, label="@{p_gnome_session}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.gnome.SettingsDaemon.MediaKeys b/apparmor.d/abstractions/bus/session/org.gnome.SettingsDaemon.MediaKeys new file mode 100644 index 0000000000..93d8308281 --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.gnome.SettingsDaemon.MediaKeys @@ -0,0 +1,23 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow requesting interest in receiving media key events. This tells Gnome +# settings that our application should be notified when key events we are +# interested in are pressed, and allows us to receive those events. + + abi , + + # DBus.Properties: read all properties from the interface + dbus send bus=session path=/org/gnome/SettingsDaemon/MediaKeys + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name="{@{busname},org.gnome.SettingsDaemon.MediaKeys}", label=gsd-media-keys), + + dbus (receive, send) bus=session path=/org/gnome/SettingsDaemon/MediaKeys + interface=org.gnome.SettingsDaemon.MediaKeys + peer=(name="{@{busname},org.gnome.SettingsDaemon.MediaKeys}", label=gsd-media-keys), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.gnome.Shell.Introspect b/apparmor.d/abstractions/bus/session/org.gnome.Shell.Introspect new file mode 100644 index 0000000000..7473303fe0 --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.gnome.Shell.Introspect @@ -0,0 +1,35 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + # DBus.Properties: read properties from the interface + + dbus send bus=session path=/org/gnome/Shell/Introspect + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name="{@{busname},org.gnome.Shell.Introspect}", label=gnome-shell), + + # DBus.Properties: receive property changed events + + dbus receive bus=session path=/org/gnome/Shell/Introspect + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name="{@{busname},org.gnome.Shell.Introspect}", label=gnome-shell), + + # Shell.Introspect + + dbus send bus=session path=/org/gnome/Shell/Introspect + interface=org.gnome.Shell.Introspect + member=GetRunningApplications + peer=(name="{@{busname},org.gnome.Shell.Introspect}", label=gnome-shell), + + dbus receive bus=session path=/org/gnome/Shell/Introspect + interface=org.gnome.Shell.Introspect + member={RunningApplicationsChanged,WindowsChanged} + peer=(name="{@{busname},org.gnome.Shell.Introspect}", label=gnome-shell), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.gnome.Shell.SearchProvider2 b/apparmor.d/abstractions/bus/session/org.gnome.Shell.SearchProvider2 new file mode 100644 index 0000000000..0746686171 --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.gnome.Shell.SearchProvider2 @@ -0,0 +1,27 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + #aa:dbus see bus=session name=org.gnome.Shell.SearchProvider2 label=gnome-shell + + dbus receive bus=session path=/org/gnome/Characters/SearchProvider + interface=org.gnome.Shell.SearchProvider2 + member={GetInitialResultSet,GetSubsearchResultSet,GetResultMetas} + peer=(name=@{busname}, label=gnome-shell), + + dbus receive bus=session path=/org/gnome/Characters/SearchProvider + interface=org.gnome.Shell.SearchProvider2 + member=*Cancel + peer=(name=@{busname}, label=gnome-shell), + + dbus receive bus=session path=/org/gnome/Characters/SearchProvider + interface=org.gnome.Shell.SearchProvider2 + member=ActivateResult + peer=(name=@{busname}, label=gnome-shell), + + include if exists + +# vim:syntax=apparmor + diff --git a/apparmor.d/abstractions/bus/session/org.gnome.keyring.internal.Prompter b/apparmor.d/abstractions/bus/session/org.gnome.keyring.internal.Prompter new file mode 100644 index 0000000000..c25fb66b76 --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.gnome.keyring.internal.Prompter @@ -0,0 +1,28 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow accessing the GNOME crypto services prompt APIs as used by +# applications using libgcr (such as pinentry-gnome3) for secure pin +# entry to unlock GPG keys etc. See: +# https://developer.gnome.org/gcr/unstable/GcrPrompt.html +# https://developer.gnome.org/gcr/unstable/GcrSecretExchange.html +# https://github.com/snapcore/snapd/pull/7673#issuecomment-592229711 + + abi , + + unix type=stream peer=(label=gnome-keyring-daemon), + + dbus send bus=session path=/org/gnome/keyring/Prompter + interface=org.gnome.keyring.internal.Prompter + member={BeginPrompting,PerformPrompt,StopPrompting} + peer=(name=@{busname}, label=pinentry-*), + + dbus receive bus=session path=/org/gnome/keyring/Prompt/p@{int} + interface=org.gnome.keyring.internal.Prompter.Callback + member={PromptReady,PromptDone} + peer=(name=@{busname}, label=pinentry-*), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.gtk.Actions b/apparmor.d/abstractions/bus/session/org.gtk.Actions new file mode 100644 index 0000000000..3f724f5ccf --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.gtk.Actions @@ -0,0 +1,67 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + # DBus.Properties: read properties from the interface + + dbus receive bus=session + interface=org.freedesktop.DBus.Properties + member=GetAll + peer=(name=@{busname}, label=gnome-shell), + + # org.gtk.Actions + + dbus send bus=session + interface=org.gtk.Actions + member=DescribeAll + peer=(label=@{profile_name}), + + dbus receive bus=session + interface=org.gtk.Actions + member=Changed + peer=(name=@{busname}), + + # org.gtk.Application + + dbus send bus=session + interface=org.gtk.Application + member={CommandLine,DescribeAll} + peer=(label=@{profile_name}), + + dbus receive bus=session + interface=org.gtk.Actions + member={Activate,DescribeAll,SetState}, + + dbus receive bus=session + interface=org.gtk.Actions + member=CommandLine + peer=(label=@{profile_name}), + + dbus send bus=session + interface=org.gtk.Actions + member=Changed, + + dbus receive bus=session + interface=org.gtk.Actions + member=Changed + peer=(label=@{profile_name}), + + dbus receive bus=session + interface=org.gtk.Application + member=Open + peer=(name=@{busname}, label=@{profile_name}), + + dbus send bus=session + interface=org.gtk.Application + member=Open + peer=(label=@{profile_name}), + + dbus send bus=session + interface=org.gtk.Actions + member=Activate, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.gtk.Menus b/apparmor.d/abstractions/bus/session/org.gtk.Menus new file mode 100644 index 0000000000..b21c080671 --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.gtk.Menus @@ -0,0 +1,18 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + dbus receive bus=session + interface=org.gtk.Menus + member={Start,End} + peer=(name=@{busname}), + + dbus send bus=session + interface=org.gtk.Menus + member=Changed, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.gtk.MountOperationHandler b/apparmor.d/abstractions/bus/session/org.gtk.MountOperationHandler new file mode 100644 index 0000000000..3fce0d7192 --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.gtk.MountOperationHandler @@ -0,0 +1,14 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + dbus send bus=session path=/org/gtk/MountOperationHandler + interface=org.freedesktop.DBus.Properties + member=GetAll + peer=(name=@{busname}, label=gnome-shell), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.gtk.Notifications b/apparmor.d/abstractions/bus/session/org.gtk.Notifications new file mode 100644 index 0000000000..59259545d7 --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.gtk.Notifications @@ -0,0 +1,19 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + dbus send bus=session path=/org/gtk/Notifications + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name=@{busname}, label=gnome-shell), + + dbus send bus=session path=/org/gtk/Notifications + interface=org.gtk.Notifications + member={AddNotification,RemoveNotification} + peer=(name=org.gtk.Notifications, label=gnome-shell), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.gtk.Private.RemoteVolumeMonitor b/apparmor.d/abstractions/bus/session/org.gtk.Private.RemoteVolumeMonitor similarity index 91% rename from apparmor.d/abstractions/bus/org.gtk.Private.RemoteVolumeMonitor rename to apparmor.d/abstractions/bus/session/org.gtk.Private.RemoteVolumeMonitor index 9060c8c15d..b8160dcb21 100644 --- a/apparmor.d/abstractions/bus/org.gtk.Private.RemoteVolumeMonitor +++ b/apparmor.d/abstractions/bus/session/org.gtk.Private.RemoteVolumeMonitor @@ -19,6 +19,6 @@ member={VolumeAdded,DriveDisconnected,DriveConnected,DriveChanged} peer=(name="@{busname}", label=gvfs-*-volume-monitor), - include if exists + include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.gtk.Settings b/apparmor.d/abstractions/bus/session/org.gtk.Settings new file mode 100644 index 0000000000..fd84f83c0d --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.gtk.Settings @@ -0,0 +1,19 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + dbus send bus=session path=/org/gtk/Settings + interface=org.freedesktop.DBus.Properties + member=GetAll + peer=(name=@{busname}, label=gsd-xsettings), + + dbus receive bus=session path=/org/gtk/Settings + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name=@{busname}, label=gsd-xsettings), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.gtk.vfs.Daemon b/apparmor.d/abstractions/bus/session/org.gtk.vfs.Daemon new file mode 100644 index 0000000000..6187b53ef4 --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.gtk.vfs.Daemon @@ -0,0 +1,26 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Each daemon (main and for mounts) implement this. + + abi , + + dbus send bus=session path=/org/gtk/vfs/Daemon + interface=org.gtk.vfs.Daemon + member=ListMonitorImplementations + peer=(name=@{busname}, label=gvfsd), + + dbus send bus=session path=/org/gtk/vfs/Daemon + interface=org.gtk.vfs.Daemon + member=GetConnection + peer=(name=@{busname}, label="gvfsd{,-*}"), + + dbus receive bus=session path=/org/gtk/vfs/Daemon + interface=org.gtk.vfs.Daemon + member=GetConnection + peer=(name=@{busname}), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.gtk.vfs.Metadata b/apparmor.d/abstractions/bus/session/org.gtk.vfs.Metadata similarity index 56% rename from apparmor.d/abstractions/bus/org.gtk.vfs.Metadata rename to apparmor.d/abstractions/bus/session/org.gtk.vfs.Metadata index ae1b928c23..3f37300326 100644 --- a/apparmor.d/abstractions/bus/org.gtk.vfs.Metadata +++ b/apparmor.d/abstractions/bus/session/org.gtk.vfs.Metadata @@ -4,18 +4,21 @@ abi , - #aa:dbus common bus=system name=org.gtk.vfs.Metadata path=/org/gtk/vfs/metadata label=gvfsd-metadata + dbus send bus=session path=/org/gtk/vfs/metadata + interface=org.freedesktop.DBus.Properties + member=GetAll + peer=(name=@{busname}, label=gvfsd-metadata), dbus send bus=session path=/org/gtk/vfs/metadata interface=org.gtk.vfs.Metadata member={Set,Move,GetTreeFromDevice,Remove} - peer=(name="@{busname}", label=gvfsd-metadata), + peer=(name=@{busname}, label=gvfsd-metadata), dbus receive bus=session path=/org/gtk/vfs/metadata interface=org.gtk.vfs.Metadata member=AttributeChanged - peer=(name="@{busname}", label=gvfsd-metadata), + peer=(name=@{busname}, label=gvfsd-metadata), - include if exists + include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.gtk.vfs.MountOperation b/apparmor.d/abstractions/bus/session/org.gtk.vfs.MountOperation new file mode 100644 index 0000000000..40b4105ec5 --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.gtk.vfs.MountOperation @@ -0,0 +1,14 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + dbus receive bus=session path=/org/gtk/gvfs/mountop/@{int} + interface=org.gtk.vfs.MountOperation + member={AskPassword,AskQuestion,ShowProcesses} + peer=(name=@{busname}, label=gvfsd-*), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.gtk.vfs.MountTracker b/apparmor.d/abstractions/bus/session/org.gtk.vfs.MountTracker similarity index 52% rename from apparmor.d/abstractions/bus/org.gtk.vfs.MountTracker rename to apparmor.d/abstractions/bus/session/org.gtk.vfs.MountTracker index d88afd0ee0..012f3cd6ab 100644 --- a/apparmor.d/abstractions/bus/org.gtk.vfs.MountTracker +++ b/apparmor.d/abstractions/bus/session/org.gtk.vfs.MountTracker @@ -2,28 +2,36 @@ # Copyright (C) 2023-2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only +# The mount tracking interface. Allows to lookup mounts by ID and list mountable +# info. Allow to receive mount/umount signals from the mount tracker (gvfsd). + abi , dbus send bus=session path=/org/gtk/vfs/mounttracker interface=org.gtk.vfs.MountTracker - member=ListMountableInfo - peer=(name="@{busname}", label=gvfsd), + member=LookupMount + peer=(name=@{busname}, label=gvfsd), dbus send bus=session path=/org/gtk/vfs/mounttracker interface=org.gtk.vfs.MountTracker - member=LookupMount - peer=(name="@{busname}", label=gvfsd), + member=ListMounts2 + peer=(name=@{busname}, label=gvfsd), dbus send bus=session path=/org/gtk/vfs/mounttracker interface=org.gtk.vfs.MountTracker - member=ListMounts2 - peer=(name="@{busname}", label=gvfsd), + member=ListMountableInfo + peer=(name=@{busname}, label=gvfsd), + + dbus send bus=session path=/org/gtk/vfs/mounttracker + interface=org.gtk.vfs.MountTracker + member=MountLocation + peer=(name=@{busname}, label=gvfsd), dbus receive bus=session path=/org/gtk/vfs/mounttracker interface=org.gtk.vfs.MountTracker - member=Mounted - peer=(name="@{busname}", label=gvfsd), + member={Mounted,Unmounted} + peer=(name=@{busname}, label=gvfsd), - include if exists + include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.gtk.vfs.Mountable b/apparmor.d/abstractions/bus/session/org.gtk.vfs.Mountable new file mode 100644 index 0000000000..603ef709b5 --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.gtk.vfs.Mountable @@ -0,0 +1,14 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + dbus receive bus=session path=/org/gtk/vfs/mountable + interface=org.gtk.vfs.Mountable + member=Mount + peer=(name=@{busname}, label=gvfsd), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.gtk.vfs.Spawner b/apparmor.d/abstractions/bus/session/org.gtk.vfs.Spawner new file mode 100644 index 0000000000..7090afe24f --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.gtk.vfs.Spawner @@ -0,0 +1,14 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + dbus send bus=session path=/org/gtk/gvfs/exec_spaw/@{int} + interface=org.gtk.vfs.Spawner + member=Spawned + peer=(name=@{busname}, label=gvfsd), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.kde.JobView b/apparmor.d/abstractions/bus/session/org.kde.JobView new file mode 100644 index 0000000000..b7c69656e6 --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.kde.JobView @@ -0,0 +1,36 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2017 Canonical Ltd +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + # Allow to send updates to the desktop session about ongoing jobs + # (for KDE Plasma specific details) + + dbus send bus=session path=/JobViewServer + interface=org.kde.JobViewServer{,V2} + member=requestView + peer=(label=plasmashell), + + dbus send bus=session path=/org/kde/notificationmanager/jobs/* + interface=org.kde.JobView{,V2,V3} + member={update,terminate} + peer=(label=plasmashell), + + # Allow to receive updates from applications to the desktop session about ongoing jobs + # (for KDE Plasma specific details) + + dbus receive bus=session path=/JobViewServer + interface=org.kde.JobViewServer{,V2} + member=requestView + peer=(label=plasmashell), + + dbus send bus=session path=/org/kde/notificationmanager/jobs/* + interface=org.kde.JobView{,V2,V3} + member={update,terminate} + peer=(label=plasmashell), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.kde.StatusNotifierItem b/apparmor.d/abstractions/bus/session/org.kde.StatusNotifierItem new file mode 100644 index 0000000000..5b98e25384 --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.kde.StatusNotifierItem @@ -0,0 +1,48 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Own a StatusNotifierItem name. It gives ownership on any StatusNotifierItem names + + abi , + + #aa:lint ignore=abstractions + # Required to own 'org.kde.StatusNotifierItem-@{int}' + include + + dbus bind bus=session name=org.kde.StatusNotifierItem-@{int}, + dbus bind bus=session name=org.kde.StatusNotifierItem-@{int}-@{int}, + + dbus receive bus=session path=/StatusNotifierItem + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name=@{busname}, label="@{pp_app_indicator}"), + + dbus send bus=session path=/StatusNotifierItem + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name=org.freedesktop.DBus, label="@{pp_app_indicator}"), + + dbus send bus=session path=/StatusNotifierWatcher + interface=org.kde.StatusNotifierWatcher + member=RegisterStatusNotifierItem + peer=(name=org.kde.StatusNotifierWatcher, label="@{pp_app_indicator}"), + + dbus send bus=session path=/StatusNotifierItem + interface=org.kde.StatusNotifierItem + member={NewAttentionIcon,NewIcon,NewIconThemePath,NewOverlayIcon,NewStatus,NewTitle,NewToolTip} + peer=(name=org.freedesktop.DBus, label="@{pp_app_indicator}"), + + dbus send bus=session path=/org/ayatana/NotificationItem/* + interface=org.kde.StatusNotifierItem + member={NewAttentionIcon,NewIcon,NewIconThemePath,NewOverlayIcon,NewStatus,NewTitle,NewToolTip} + peer=(name=org.freedesktop.DBus, label="@{pp_app_indicator}"), + + dbus receive bus=session path=/StatusNotifierItem + interface=org.kde.StatusNotifierItem + member={Activate,ContextMenu,Scroll,SecondaryActivate,ProvideXdgActivationToken,XAyatanaSecondaryActivate} + peer=(name=@{busname}, label="@{pp_app_indicator}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.kde.StatusNotifierWatcher b/apparmor.d/abstractions/bus/session/org.kde.StatusNotifierWatcher new file mode 100644 index 0000000000..69724bb410 --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.kde.StatusNotifierWatcher @@ -0,0 +1,47 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2017 Canonical Ltd +# Copyright (C) 2023-2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow to display Status Notifier Items in the KDE Plasma systray (including supporting context menu) + + abi , + + dbus send bus=session path=/StatusNotifierWatcher + interface=org.freedesktop.DBus.Properties + member=Get + peer=(name=org.kde.StatusNotifierWatcher, label="@{pp_app_indicator}"), + + dbus send bus=session path=/StatusNotifierItem + interface=org.freedesktop.DBus.Properties + member=GetAll + peer=(name=@{busname}, label="@{pp_app_indicator}"), + + dbus receive bus=session path=/StatusNotifierWatcher + interface=org.freedesktop.DBus.Properties + member=Get + peer=(name=@{busname}, label="@{pp_app_indicator}"), + + dbus send bus=session path=/StatusNotifierWatcher + interface=org.kde.StatusNotifierWatcher + member=RegisterStatusNotifierItem + peer=(name="{@{busname},org.kde.StatusNotifierWatcher}", label="@{pp_app_indicator}"), + + dbus receive bus=session path=/StatusNotifierWatcher + interface=org.kde.StatusNotifierWatcher + member=RegisterStatusNotifierItem + peer=(name=@{busname}, label="@{pp_app_indicator}"), + + dbus send bus=session path=/StatusNotifierItem + interface=org.kde.StatusNotifierItem + member={ProvideXdgActivationToken,Activate} + peer=(name=@{busname}, label="@{pp_app_indicator}"), + + dbus send bus=session path=/MenuBar + interface=com.canonical.dbusmenu + member={AboutToShow,GetLayout,Event} + peer=(name=@{busname}, label="@{pp_app_indicator}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.kde.kwalletd b/apparmor.d/abstractions/bus/session/org.kde.kwalletd similarity index 50% rename from apparmor.d/abstractions/bus/org.kde.kwalletd rename to apparmor.d/abstractions/bus/session/org.kde.kwalletd index 1ae5a1ace2..0afce1cdf5 100644 --- a/apparmor.d/abstractions/bus/org.kde.kwalletd +++ b/apparmor.d/abstractions/bus/session/org.kde.kwalletd @@ -1,9 +1,9 @@ # apparmor.d - Full set of apparmor profiles -# Copyright (C) 2024 Alexandre Pujol +# Copyright (C) 2025 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only abi , - include if exists + include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.mpris.MediaPlayer2.Player b/apparmor.d/abstractions/bus/session/org.mpris.MediaPlayer2.Player new file mode 100644 index 0000000000..d1e6ca0185 --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.mpris.MediaPlayer2.Player @@ -0,0 +1,47 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + # DBus.Properties: read properties from the interface + + dbus send bus=system path=/org/mpris/MediaPlayer2 + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name="{@{busname},org.freedesktop.DBus}"), + + # DBus.Properties: send properties to the mpris controlers + + dbus receive bus=session path=/org/mpris/MediaPlayer2 + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name=@{busname}, label="@{pp_mpris}"), + + # DBus.Properties: receive property changed events + + dbus receive bus=session path=/org/mpris/MediaPlayer2 + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name=@{busname}, label="@{pp_mpris}"), + + # DBus.Introspectable: allow clients to introspect the service + dbus send bus=system path=/org/mpris/MediaPlayer2 + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=@{busname}), + + dbus receive bus=session path=/org/mpris/MediaPlayer2 + interface=org.mpris.MediaPlayer2.Player + member={Seeked,Previous,Next,Play,PlayPause,Pause} + peer=(name=@{busname}), + + # https://specifications.freedesktop.org/mpris-spec/latest/Player_Interface.html#Signal:Seeked + dbus send bus=session path=/org/mpris/MediaPlayer2 + interface=org.mpris.MediaPlayer2.Player + member=Seeked + peer=(name=org.freedesktop.DBus), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/session/org.openprinting.PrintBackend b/apparmor.d/abstractions/bus/session/org.openprinting.PrintBackend new file mode 100644 index 0000000000..68583bbb36 --- /dev/null +++ b/apparmor.d/abstractions/bus/session/org.openprinting.PrintBackend @@ -0,0 +1,43 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + #aa:dbus see bus=session name=org.openprinting.PrintBackend path=/ label=print-backends-cups + + # openprinting.PrintBackend + + dbus send bus=session path=/ + interface=org.openprinting.PrintBackend + member={GetAllOptions,GetAllPrinters} + peer=(name=@{busname}, label=print-backends-cups), + + dbus send bus=session path=/ + interface=org.openprinting.PrintBackend + member={getChoiceTranslation,getDefaultPrinter,getPrinterState} + peer=(name=@{busname}, label=print-backends-cups), + + dbus send bus=session path=/ + interface=org.openprinting.PrintBackend + member={getGroupTranslation,getOptionTranslation} + peer=(name=@{busname}, label=print-backends-cups), + + dbus send bus=session path=/ + interface=org.openprinting.PrintBackend + member=isAcceptingJobs + peer=(name=@{busname}, label=print-backends-cups), + + dbus send bus=session path=/ + interface=org.openprinting.PrintBackend + member=printSocket + peer=(name=@{busname}, label=print-backends-cups), + + dbus send bus=session path=/ + interface=org.openprinting.PrintBackend + member=doListing + peer=(name=@{busname}, label=print-backends-cups), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/own-session b/apparmor.d/abstractions/bus/session/own similarity index 58% rename from apparmor.d/abstractions/bus/own-session rename to apparmor.d/abstractions/bus/session/own index 8186f34cb8..62c932bbb7 100644 --- a/apparmor.d/abstractions/bus/own-session +++ b/apparmor.d/abstractions/bus/session/own @@ -3,22 +3,26 @@ # SPDX-License-Identifier: GPL-2.0-only # LOGPROF-SUGGEST: no -# Do not use it manually, it is automatically included in a profile when it is required. - # Allow owning a name on DBus public bus +# +# !!! warning +# +# Do not use it manually, It is automatically included in a profile by the +# `aa:dbus own` directive. +# abi , - dbus send bus=session path=/org/freedesktop/DBus + dbus send bus=session path=/{,org/freedesktop/DBus,org/freedesktop/DBus/Bus} interface=org.freedesktop.DBus - member={RequestName,ReleaseName} + member={ListNames,RequestName,ReleaseName} peer=(name=org.freedesktop.DBus, label="@{p_dbus_session}"), - dbus send bus=session path=/org/freedesktop/DBus + dbus send bus=session path=/{,org/freedesktop/DBus,org/freedesktop/DBus/Bus} interface=org.freedesktop.DBus member={GetConnectionUnixProcessID,GetConnectionUnixUser,GetConnectionCredentials} peer=(name=org.freedesktop.DBus, label="@{p_dbus_session}"), - include if exists + include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/fi.w1.wpa_supplicant1 b/apparmor.d/abstractions/bus/system/fi.w1.wpa_supplicant1 new file mode 100644 index 0000000000..dac62128d1 --- /dev/null +++ b/apparmor.d/abstractions/bus/system/fi.w1.wpa_supplicant1 @@ -0,0 +1,67 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + # DBus.Properties: read properties from the interface + + dbus send bus=system path=/fi/w1/wpa_supplicant1 + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name=@{busname}, label=wpa-supplicant), + + dbus send bus=system path=/fi/w1/wpa_supplicant1/Interfaces/@{int} + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name=@{busname}, label=wpa-supplicant), + + # DBus.Properties: receive property changed events + + dbus receive bus=system path=/fi/w1/wpa_supplicant1 + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name=@{busname}, label=wpa-supplicant), + + dbus receive bus=system path=/fi/w1/wpa_supplicant1/Interfaces/@{int} + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name=@{busname}, label=wpa-supplicant), + + # wpa_supplicant1: allow clients to enumerate sources + + dbus receive bus=system path=/fi/w1/wpa_supplicant1 + interface=fi.w1.wpa_supplicant1 + member={InterfaceAdded,InterfaceRemoved} + peer=(name=@{busname}, label=wpa-supplicant), + + # wpa_supplicant1.interface + + dbus send bus=system path=/fi/w1/wpa_supplicant1 + interface=fi.w1.wpa_supplicant1.Interface + member=CreateInterface + peer=(name=@{busname}, label=wpa-supplicant), + + dbus send bus=system path=/fi/w1/wpa_supplicant1/Interfaces/@{int} + interface=fi.w1.wpa_supplicant1.Interface + member={AddNetwork,Disconnect,RemoveNetwork,Scan,SelectNetwork} + peer=(name=@{busname}, label=wpa-supplicant), + + dbus send bus=system path=/fi/w1/wpa_supplicant1/Interfaces/@{int} + interface=fi.w1.wpa_supplicant1.Interface.P2PDevice + member=Cancel + peer=(name=@{busname}, label=wpa-supplicant), + + dbus receive bus=system path=/fi/w1/wpa_supplicant1/Interfaces/@{int} + interface=fi.w1.wpa_supplicant1.Interface + member=PropertiesChanged + peer=(name=@{busname}, label=wpa-supplicant), + + dbus receive bus=system path=/fi/w1/wpa_supplicant1/Interfaces/@{int} + interface=fi.w1.wpa_supplicant1.Interface + member={BSSAdded,BSSRemoved,NetworkAdded,NetworkRemoved,NetworkSelected,ScanDone} + peer=(name=@{busname}, label=wpa-supplicant), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/net.hadess.PowerProfiles b/apparmor.d/abstractions/bus/system/net.hadess.PowerProfiles similarity index 53% rename from apparmor.d/abstractions/bus/net.hadess.PowerProfiles rename to apparmor.d/abstractions/bus/system/net.hadess.PowerProfiles index 63f224c420..83c5b9e77a 100644 --- a/apparmor.d/abstractions/bus/net.hadess.PowerProfiles +++ b/apparmor.d/abstractions/bus/system/net.hadess.PowerProfiles @@ -4,8 +4,8 @@ abi , - #aa:dbus common bus=system name=net.hadess.PowerProfiles label=power-profiles-daemon + #aa:dbus see bus=system name=net.hadess.PowerProfiles label="@{p_power_profiles_daemon}" - include if exists + include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/net.hadess.SensorProxy b/apparmor.d/abstractions/bus/system/net.hadess.SensorProxy new file mode 100644 index 0000000000..baf0635afa --- /dev/null +++ b/apparmor.d/abstractions/bus/system/net.hadess.SensorProxy @@ -0,0 +1,16 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + # DBus.Properties: read properties from the interface + + dbus send bus=system path=/net/hadess/SensorProxy + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name=@{busname}, label=iio-sensor-proxy), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/net.hadess.SwitcherooControl b/apparmor.d/abstractions/bus/system/net.hadess.SwitcherooControl similarity index 54% rename from apparmor.d/abstractions/bus/net.hadess.SwitcherooControl rename to apparmor.d/abstractions/bus/system/net.hadess.SwitcherooControl index df65417dad..5961b3467c 100644 --- a/apparmor.d/abstractions/bus/net.hadess.SwitcherooControl +++ b/apparmor.d/abstractions/bus/system/net.hadess.SwitcherooControl @@ -4,8 +4,8 @@ abi , - #aa:dbus common bus=system name=net.hadess.SwitcherooControl label=switcheroo-control + #aa:dbus see bus=system name=net.hadess.SwitcherooControl label=switcheroo-control - include if exists + include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/net.reactivated.Fprint b/apparmor.d/abstractions/bus/system/net.reactivated.Fprint similarity index 60% rename from apparmor.d/abstractions/bus/net.reactivated.Fprint rename to apparmor.d/abstractions/bus/system/net.reactivated.Fprint index 2f36600828..b755e04288 100644 --- a/apparmor.d/abstractions/bus/net.reactivated.Fprint +++ b/apparmor.d/abstractions/bus/system/net.reactivated.Fprint @@ -4,12 +4,17 @@ abi , - #aa:dbus common bus=system name=net.reactivated.Fprint label=fprintd + #aa:dbus see bus=system name=net.reactivated.Fprint label="@{p_fprintd}" + + dbus send bus=system path=/net/reactivated/Fprint/Manager + interface=net.reactivated.Fprint.Manager + member=GetDefaultDevice + peer=(name=net.reactivated.Fprint), dbus send bus=system path=/net/reactivated/Fprint/Manager interface=net.reactivated.Fprint.Manager member={GetDevices,GetDefaultDevice} - peer=(name="@{busname}", label=fprintd), + peer=(name="@{busname}", label="@{p_fprintd}"), dbus send bus=system path=/net/reactivated/Fprint/Manager interface=net.reactivated.Fprint.Manager @@ -19,8 +24,8 @@ dbus send bus=system path=/net/reactivated/Fprint/Manager interface=net.reactivated.Fprint.Manager member={GetDevices,GetDefaultDevice} - peer=(name=net.reactivated.Fprint, label=fprintd), + peer=(name=net.reactivated.Fprint, label="@{p_fprintd}"), - include if exists + include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.bluez b/apparmor.d/abstractions/bus/system/org.bluez new file mode 100644 index 0000000000..8db7744baf --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.bluez @@ -0,0 +1,50 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + # DBus.Properties: read properties from the interface + + dbus send bus=system path=/org/bluez + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name=@{busname}, label="@{p_bluetoothd}"), + + dbus send bus=system path=/org/bluez/hci@{int} + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name=@{busname}, label="@{p_bluetoothd}"), + + dbus send bus=system path=/org/bluez/hci@{int}/dev_@{hex2}_@{hex2}_@{hex2}_@{hex2}_@{hex2}_@{hex2}{,/**} + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name=@{busname}, label="@{p_bluetoothd}"), + + # DBus.Properties: receive property changed events + + dbus receive bus=system path=/org/bluez/hci@{int} + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name=@{busname}, label="@{p_bluetoothd}"), + + dbus receive bus=system path=/org/bluez/hci@{int}/dev_@{hex2}_@{hex2}_@{hex2}_@{hex2}_@{hex2}_@{hex2}{,/**} + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name=@{busname}, label="@{p_bluetoothd}"), + + # DBus.ObjectManager: allow clients to enumerate sources + + dbus send bus=system path=/ + interface=org.freedesktop.DBus.ObjectManager + member=GetManagedObjects + peer=(name="{@{busname},org.bluez}", label="@{p_bluetoothd}"), + + dbus receive bus=system path=/ + interface=org.freedesktop.DBus.ObjectManager + member={InterfacesAdded,InterfacesRemoved} + peer=(name=@{busname}, label="@{p_bluetoothd}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.bluez.AgentManager1 b/apparmor.d/abstractions/bus/system/org.bluez.AgentManager1 new file mode 100644 index 0000000000..e1e549cf2f --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.bluez.AgentManager1 @@ -0,0 +1,14 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + dbus send bus=system path=/org/bluez + interface=org.bluez.AgentManager1 + member={RegisterAgent,RequestDefaultAgent,UnregisterAgent} + peer=(name="{@{busname},org.bluez}", label="@{p_bluetoothd}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.bluez.BatteryProviderManager1 b/apparmor.d/abstractions/bus/system/org.bluez.BatteryProviderManager1 new file mode 100644 index 0000000000..5999c239a1 --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.bluez.BatteryProviderManager1 @@ -0,0 +1,14 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + dbus send bus=system path=/org/bluez/hci@{int} + interface=org.bluez.BatteryProviderManager1 + member={RegisterBatteryProvider,RegisterProfile} + peer=(name=org.bluez, label="@{p_bluetoothd}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.bluez.Bearer b/apparmor.d/abstractions/bus/system/org.bluez.Bearer new file mode 100644 index 0000000000..644b18387d --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.bluez.Bearer @@ -0,0 +1,14 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + dbus receive bus=system path=/org/bluez/hci@{int}/dev_@{hex2}_@{hex2}_@{hex2}_@{hex2}_@{hex2}_@{hex2} + interface=org.bluez.Bearer.* + member=Disconnected + peer=(name=@{busname}, label=bluetoothd), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.bluez.Device1 b/apparmor.d/abstractions/bus/system/org.bluez.Device1 new file mode 100644 index 0000000000..bb32856bbc --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.bluez.Device1 @@ -0,0 +1,14 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + dbus receive bus=system path=/org/bluez/hci@{int}/dev_@{hex2}_@{hex2}_@{hex2}_@{hex2}_@{hex2}_@{hex2} + interface=org.bluez.Device1 + member=Disconnected + peer=(name=@{busname}, label=bluetoothd), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.bluez.GattCharacteristic1 b/apparmor.d/abstractions/bus/system/org.bluez.GattCharacteristic1 new file mode 100644 index 0000000000..9dc193d9a8 --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.bluez.GattCharacteristic1 @@ -0,0 +1,19 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + dbus send bus=system path=/org/bluez/hci@{int}/dev_@{hex2}_@{hex2}_@{hex2}_@{hex2}_@{hex2}_@{hex2} + interface=org.bluez.GattCharacteristic1 + member=ReadValue + peer=(name=@{busname}, label=bluetoothd), + + dbus send bus=system path=/org/bluez/hci@{int}/dev_@{hex2}_@{hex2}_@{hex2}_@{hex2}_@{hex2}_@{hex2}/service@{hex4}/char@{hex4} + interface=org.bluez.GattCharacteristic1 + member=ReadValue + peer=(name=@{busname}, label=bluetoothd), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.bluez.GattManager1 b/apparmor.d/abstractions/bus/system/org.bluez.GattManager1 new file mode 100644 index 0000000000..b0e48a0bf2 --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.bluez.GattManager1 @@ -0,0 +1,19 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + dbus send bus=system path=/org/bluez/hci@{int} + interface=org.bluez.GattManager1 + member=RegisterApplication + peer=(name=@{busname}, label="@{p_bluetoothd}"), + + dbus receive bus=system path=/midi/profile + interface=org.bluez.GattProfile1 + member=Release + peer=(name=@{busname}, label="@{p_bluetoothd}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.bluez.Media1 b/apparmor.d/abstractions/bus/system/org.bluez.Media1 new file mode 100644 index 0000000000..c6a66ec2ab --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.bluez.Media1 @@ -0,0 +1,14 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + dbus send bus=system path=/org/bluez/hci@{int} + interface=org.bluez.Media1 + member={RegisterPlayer,UnregisterPlayer,RegisterApplication} + peer=(name=org.bluez, label="@{p_bluetoothd}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.bluez.MediaEndpoint1 b/apparmor.d/abstractions/bus/system/org.bluez.MediaEndpoint1 new file mode 100644 index 0000000000..b79514aab0 --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.bluez.MediaEndpoint1 @@ -0,0 +1,19 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + dbus receive bus=system path=/MediaEndpoint + interface=org.freedesktop.DBus.ObjectManager + member=GetManagedObjects + peer=(name=@{busname}, label="@{p_bluetoothd}"), + + dbus receive bus=system path=/MediaEndpoint/A2DP{Sink,Source}/* + interface=org.bluez.MediaEndpoint1 + member={SetConfiguration,ClearConfiguration,Release} + peer=(name=@{busname}, label="@{p_bluetoothd}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.bluez.MediaTransport1 b/apparmor.d/abstractions/bus/system/org.bluez.MediaTransport1 new file mode 100644 index 0000000000..a103afb4af --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.bluez.MediaTransport1 @@ -0,0 +1,14 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + dbus send bus=system path=/org/bluez/hci@{int}/dev_@{hex2}_@{hex2}_@{hex2}_@{hex2}_@{hex2}_@{hex2}{,/**} + interface=org.bluez.MediaTransport1 + member={Acquire,Set,Release} + peer=(name=org.bluez, label="@{p_bluetoothd}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.bluez.ProfileManager1 b/apparmor.d/abstractions/bus/system/org.bluez.ProfileManager1 new file mode 100644 index 0000000000..a6bf3d9318 --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.bluez.ProfileManager1 @@ -0,0 +1,19 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + dbus send bus=system path=/org/bluez + interface=org.bluez.ProfileManager1 + member={RegisterProfile,UnregisterProfile} + peer=(name=org.bluez, label="@{p_bluetoothd}"), + + dbus receive bus=system path=/Profile/* + interface=org.bluez.Profile1 + member={NewConnection,RequestDisconnection,Release} + peer=(name=@{busname}, label="@{p_bluetoothd}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.cups.cupsd.Notifier b/apparmor.d/abstractions/bus/system/org.cups.cupsd.Notifier new file mode 100644 index 0000000000..154a28a855 --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.cups.cupsd.Notifier @@ -0,0 +1,24 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + dbus receive bus=system path=/org/cups/cupsd/Notifier + interface=org.cups.cupsd.Notifier + member={ServerStarted,ServerStopped} + peer=(name=@{busname}, label=cups-notifier-dbus), + + dbus receive bus=system path=/org/cups/cupsd/Notifier + interface=org.cups.cupsd.Notifier + member={PrinterDeleted,PrinterStateChanged,PrinterStopped,PrinterAdded,PrinterModified} + peer=(name=@{busname}, label=cups-notifier-dbus), + + dbus receive bus=system path=/org/cups/cupsd/Notifier + interface=org.cups.cupsd.Notifier + member={JobCreated,JobCompleted,JobProgress,JobState} + peer=(name=@{busname}, label=cups-notifier-dbus), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.freedesktop.Avahi.AddressResolver b/apparmor.d/abstractions/bus/system/org.freedesktop.Avahi.AddressResolver new file mode 100644 index 0000000000..283e33dde3 --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.freedesktop.Avahi.AddressResolver @@ -0,0 +1,25 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Avahi Address resolving + + abi , + + dbus send bus=system path=/ + interface=org.freedesktop.Avahi.Server + member=AddressResolverNew + peer=(name=org.freedesktop.Avahi, label="@{p_avahi_daemon}"), + + dbus send bus=system path=/Client@{int}/AddressResolver@{int} + interface=org.freedesktop.Avahi.AddressResolver + member=Free + peer=(name=org.freedesktop.Avahi, label="@{p_avahi_daemon}"), + + dbus receive bus=system path=/Client@{int}/AddressResolver@{int} + interface=org.freedesktop.Avahi.AddressResolver + peer=(name=@{busname}, label="@{p_avahi_daemon}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.freedesktop.Avahi.DomainBrowser b/apparmor.d/abstractions/bus/system/org.freedesktop.Avahi.DomainBrowser new file mode 100644 index 0000000000..39f5e4496f --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.freedesktop.Avahi.DomainBrowser @@ -0,0 +1,25 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Domain browsing + + abi , + + dbus send bus=system path=/ + interface=org.freedesktop.Avahi.Server + member=DomainBrowserNew + peer=(name=org.freedesktop.Avahi, label="@{p_avahi_daemon}"), + + dbus send bus=system path=/Client@{int}/DomainBrowser@{int} + interface=org.freedesktop.Avahi.DomainBrowser + member=Free + peer=(name=org.freedesktop.Avahi, label="@{p_avahi_daemon}"), + + dbus receive bus=system path=/Client@{int}/DomainBrowser@{int} + interface=org.freedesktop.Avahi.DomainBrowser + peer=(name=@{busname}, label="@{p_avahi_daemon}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.freedesktop.Avahi.EntryGroup b/apparmor.d/abstractions/bus/system/org.freedesktop.Avahi.EntryGroup new file mode 100644 index 0000000000..ca7a223065 --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.freedesktop.Avahi.EntryGroup @@ -0,0 +1,35 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Domain browsing + + abi , + + dbus send bus=system path=/Client@{int}/EntryGroup@{int} + interface=org.freedesktop.DBus.Properties + member=GetAll + peer=(name=@{busname}, label="@{p_avahi_daemon}"), + + dbus send bus=system path=/ + interface=org.freedesktop.Avahi.Server2 + member=EntryGroupNew + peer=(name="{@{busname},org.freedesktop.Avahi}", label="@{p_avahi_daemon}"), + +# dbus send bus=system path=/Client@{int}/EntryGroup@{int} +# interface=org.freedesktop.Avahi.EntryGroup +# member=Free +# peer=(name=org.freedesktop.Avahi, label="@{p_avahi_daemon}"), + + dbus send bus=system path=/Client@{int}/EntryGroup@{int} + interface=org.freedesktop.Avahi.EntryGroup + member={AddService,AddServiceSubtype,Commit,Reset} + peer=(name=@{busname}, label="@{p_avahi_daemon}"), + + dbus receive bus=system path=/Client@{int}/EntryGroup@{int} + interface=org.freedesktop.Avahi.EntryGroup + peer=(name=@{busname}, label="@{p_avahi_daemon}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.freedesktop.Avahi.HostNameResolver b/apparmor.d/abstractions/bus/system/org.freedesktop.Avahi.HostNameResolver new file mode 100644 index 0000000000..403a4db0f7 --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.freedesktop.Avahi.HostNameResolver @@ -0,0 +1,25 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Hostname resolving + + abi , + + dbus send bus=system path=/ + interface=org.freedesktop.Avahi.Server + member=HostNameResolverNew + peer=(name=org.freedesktop.Avahi, label="@{p_avahi_daemon}"), + + dbus send bus=system path=/Client@{int}/HostNameResolver@{int} + interface=org.freedesktop.Avahi.HostNameResolver + member=Free + peer=(name=org.freedesktop.Avahi, label="@{p_avahi_daemon}"), + + dbus receive bus=system path=/Client@{int}/HostNameResolver@{int} + interface=org.freedesktop.Avahi.HostNameResolver + peer=(name=@{busname}, label="@{p_avahi_daemon}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.freedesktop.Avahi.RecordBrowser b/apparmor.d/abstractions/bus/system/org.freedesktop.Avahi.RecordBrowser new file mode 100644 index 0000000000..bff079b134 --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.freedesktop.Avahi.RecordBrowser @@ -0,0 +1,25 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Record browsing + + abi , + + dbus send bus=system path=/ + interface=org.freedesktop.Avahi.Server + member=RecordBrowserNew + peer=(name=org.freedesktop.Avahi, label="@{p_avahi_daemon}"), + + dbus send bus=system path=/Client@{int}/RecordBrowser@{int} + interface=org.freedesktop.Avahi.RecordBrowser + member=Free + peer=(name=org.freedesktop.Avahi, label="@{p_avahi_daemon}"), + + dbus receive bus=system path=/Client@{int}/RecordBrowser@{int} + interface=org.freedesktop.Avahi.RecordBrowser + peer=(name=@{busname}, label="@{p_avahi_daemon}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.freedesktop.Avahi.Server b/apparmor.d/abstractions/bus/system/org.freedesktop.Avahi.Server new file mode 100644 index 0000000000..0805128208 --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.freedesktop.Avahi.Server @@ -0,0 +1,31 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + dbus send bus=system path=/ + interface=org.freedesktop.DBus.Peer + member=Ping + peer=(name=org.freedesktop.Avahi), + + # Allow service introspection + dbus send bus=system path=/ + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=@{busname}, label="@{p_avahi_daemon}"), + + # Allow accessing DBus properties and resolving + dbus send bus=system path=/ + interface=org.freedesktop.Avahi.Server + member={Get*,Resolve*,IsNSSSupportAvailable} + peer=(name=org.freedesktop.Avahi, label="@{p_avahi_daemon}"), + + # Allow receiving anything from the Avahi server + dbus receive bus=system + interface=org.freedesktop.Avahi.Server + peer=(name=@{busname}, label="@{p_avahi_daemon}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.freedesktop.Avahi.ServiceBrowser b/apparmor.d/abstractions/bus/system/org.freedesktop.Avahi.ServiceBrowser new file mode 100644 index 0000000000..6a3b1510d5 --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.freedesktop.Avahi.ServiceBrowser @@ -0,0 +1,23 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + dbus send bus=system path=/ + interface=org.freedesktop.Avahi.Server + member=ServiceBrowserNew + peer=(name=org.freedesktop.Avahi, label="@{p_avahi_daemon}"), + + dbus send bus=system path=/Client@{int}/ServiceBrowser@{int} + interface=org.freedesktop.Avahi.ServiceBrowser + member=Free + peer=(name=org.freedesktop.Avahi, label="@{p_avahi_daemon}"), + + dbus receive bus=system path=/Client@{int}/ServiceBrowser@{int} + interface=org.freedesktop.Avahi.ServiceBrowser + peer=(name=@{busname}, label="@{p_avahi_daemon}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.freedesktop.Avahi.ServiceResolver b/apparmor.d/abstractions/bus/system/org.freedesktop.Avahi.ServiceResolver new file mode 100644 index 0000000000..d90e9ca147 --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.freedesktop.Avahi.ServiceResolver @@ -0,0 +1,25 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Service resolving + + abi , + + dbus send bus=system path=/ + interface=org.freedesktop.Avahi.Server + member=ServiceResolverNew + peer=(name=org.freedesktop.Avahi, label="@{p_avahi_daemon}"), + + dbus send bus=system path=/Client@{int}/ServiceResolver@{int} + interface=org.freedesktop.Avahi.ServiceResolver + member=Free + peer=(name=org.freedesktop.Avahi, label="@{p_avahi_daemon}"), + + dbus receive bus=system path=/Client@{int}/ServiceResolver@{int} + interface=org.freedesktop.Avahi.ServiceResolver + peer=(name=@{busname}, label="@{p_avahi_daemon}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.freedesktop.Avahi.ServiceTypeBrowser b/apparmor.d/abstractions/bus/system/org.freedesktop.Avahi.ServiceTypeBrowser new file mode 100644 index 0000000000..93affdc51e --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.freedesktop.Avahi.ServiceTypeBrowser @@ -0,0 +1,25 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Service type browsing + + abi , + + dbus send bus=system path=/ + interface=org.freedesktop.Avahi.Server + member=ServiceTypeBrowserNew + peer=(name=org.freedesktop.Avahi, label="@{p_avahi_daemon}"), + + dbus send bus=system path=/Client@{int}/ServiceTypeBrowser@{int} + interface=org.freedesktop.Avahi.ServiceTypeBrowser + member=Free + peer=(name=org.freedesktop.Avahi, label="@{p_avahi_daemon}"), + + dbus receive bus=system path=/Client@{int}/ServiceTypeBrowser@{int} + interface=org.freedesktop.Avahi.ServiceTypeBrowser + peer=(name=@{busname}, label="@{p_avahi_daemon}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.freedesktop.ColorManager b/apparmor.d/abstractions/bus/system/org.freedesktop.ColorManager new file mode 100644 index 0000000000..946399561a --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.freedesktop.ColorManager @@ -0,0 +1,44 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow for color managed applications to communicate with colord + + abi , + + + # ColorManager + + dbus send bus=system path=/org/freedesktop/ColorManager + interface=org.freedesktop.ColorManager + member=GetDevices + peer=(name="@{busname}", label="@{p_colord}"), + + dbus send bus=system path=/org/freedesktop/ColorManager + interface=org.freedesktop.ColorManager + member={CreateProfile,CreateDevice,DeleteDevice} + peer=(name="{@{busname},org.freedesktop.ColorManager}", label="@{p_colord}"), + + dbus send bus=system path=/org/freedesktop/ColorManager/devices/* + interface=org.freedesktop.ColorManager.Device + member=AddProfile + peer=(name="{@{busname},org.freedesktop.ColorManager}", label="@{p_colord}"), + + dbus receive bus=system path=/org/freedesktop/ColorManager + interface=org.freedesktop.ColorManager + member={DeviceAdded,DeviceRemoved} + peer=(name="{@{busname},org.freedesktop.ColorManager}", label="@{p_colord}"), + + dbus (receive, send) bus=system path=/org/freedesktop/ColorManager + interface=org.freedesktop.ColorManager + member={FindDeviceByProperty,FindDeviceById} + peer=(name="{@{busname},org.freedesktop.ColorManager}", label="@{p_colord}"), + + dbus send bus=system path=/org/freedesktop/ColorManager + interface=org.freedesktop.ColorManager + member={FindDeviceByProperty,FindDeviceById} + peer=(name=org.freedesktop.ColorManager), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.freedesktop.GeoClue2 b/apparmor.d/abstractions/bus/system/org.freedesktop.GeoClue2 new file mode 100644 index 0000000000..46778361c5 --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.freedesktop.GeoClue2 @@ -0,0 +1,67 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + # DBus.Properties: read properties from the interface + + dbus send bus=system path=/org/freedesktop/GeoClue2/Manager + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name=@{busname}, label="@{p_geoclue}"), + + dbus send bus=system path=/org/freedesktop/GeoClue2/Client/@{int} + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name=@{busname}, label="@{p_geoclue}"), + + # DBus.Properties: receive property changed events + + dbus receive bus=system path=/org/freedesktop/GeoClue2 + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name=@{busname}, label="@{p_geoclue}"), + + dbus receive bus=system path=/org/freedesktop/GeoClue2/Client/@{int} + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name=@{busname}, label="@{p_geoclue}"), + + dbus receive bus=system path=/org/freedesktop/GeoClue2/Manager + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name=@{busname}, label="@{p_geoclue}"), + + # DBus.Properties: allow clients to set properties + + dbus send bus=system path=/org/freedesktop/GeoClue2/Client/@{int} + interface=org.freedesktop.DBus.Properties + member=Set + peer=(name=@{busname}, label="@{p_geoclue}"), + + # GeoClue2 + + dbus send bus=system path=/org/freedesktop/GeoClue2/Manager + interface=org.freedesktop.GeoClue2.Manager + member=AddAgent + peer=(name="@{busname}", label="@{p_geoclue}"), + + dbus send bus=system path=/org/freedesktop/GeoClue2/Manager + interface=org.freedesktop.GeoClue2.Manager + member={GetClient,DeleteClient} + peer=(name=@{busname}, label="@{p_geoclue}"), + + dbus send bus=system path=/org/freedesktop/GeoClue2/Client/@{int} + interface=org.freedesktop.GeoClue2.Client + member=Start + peer=(name=@{busname}, label="@{p_geoclue}"), + + dbus receive bus=system path=/org/freedesktop/GeoClue2/Client/@{int} + interface=org.freedesktop.GeoClue2.Client + member=LocationUpdated + peer=(name=@{busname}, label="@{p_geoclue}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.freedesktop.ModemManager1 b/apparmor.d/abstractions/bus/system/org.freedesktop.ModemManager1 new file mode 100644 index 0000000000..0faaf1fdc9 --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.freedesktop.ModemManager1 @@ -0,0 +1,50 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + # DBus.Properties: read properties from the interface + + dbus send bus=system path=/org/freedesktop/ModemManager1 + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name=@{busname}, label="@{p_ModemManager}"), + + dbus send bus=system path=/org/freedesktop/ModemManager1/*/@{int} + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name=@{busname}, label="@{p_ModemManager}"), + + # DBus.Properties: receive property changed events + + dbus receive bus=system path=/org/freedesktop/ModemManager1 + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name=@{busname}, label="@{p_ModemManager}"), + + dbus receive bus=system path=/org/freedesktop/ModemManager1/* + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name=@{busname}, label="@{p_ModemManager}"), + + dbus receive bus=system path=/org/freedesktop/ModemManager1/*/@{int} + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name=@{busname}, label="@{p_ModemManager}"), + + # DBus.ObjectManager: allow clients to enumerate sources + + dbus send bus=system path=/org/freedesktop/ModemManager1 + interface=org.freedesktop.DBus.ObjectManager + member=GetManagedObjects + peer=(name=org.freedesktop.ModemManager1, label="@{p_ModemManager}"), + + dbus send bus=system path=/org/freedesktop/ModemManager1 + interface=org.freedesktop.DBus.ObjectManager + member=GetManagedObjects + peer=(name="@{busname}", label="@{p_ModemManager}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.freedesktop.NetworkManager b/apparmor.d/abstractions/bus/system/org.freedesktop.NetworkManager new file mode 100644 index 0000000000..754c02d09e --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.freedesktop.NetworkManager @@ -0,0 +1,111 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allows observing NetworkManager settings. It grants access to listing +# MAC addresses, previous networks, etc but not secrets. + + abi , + + # DBus.Properties: read properties from the interface + + dbus send bus=system path=/org/freedesktop/NetworkManager + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name=@{busname}, label=NetworkManager), + + dbus send bus=system path=/org/freedesktop/NetworkManager/*/@{int} + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name=@{busname}, label=NetworkManager), + + # DBus.Properties: receive property changed events + + dbus receive bus=system path=/org/freedesktop/NetworkManager + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name=@{busname}, label=NetworkManager), + + dbus receive bus=system path=/org/freedesktop/NetworkManager/* + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name=@{busname}, label=NetworkManager), + + dbus receive bus=system path=/org/freedesktop/NetworkManager/*/@{int} + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name=@{busname}, label=NetworkManager), + + # DBus.ObjectManager: allow clients to enumerate sources + + dbus send bus=system path=/org/freedesktop + interface=org.freedesktop.DBus.ObjectManager + member=GetManagedObjects + peer=(name=@{busname}, label=NetworkManager), + + dbus receive bus=system path=/org/freedesktop + interface=org.freedesktop.DBus.ObjectManager + member={InterfacesAdded,InterfacesRemoved} + peer=(name=@{busname}, label=NetworkManager), + + # DBus.Introspectable: allow clients to introspect the service + + dbus send bus=system path=/org/freedesktop/NetworkManager + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=@{busname}, label=NetworkManager), + + dbus send bus=system path=/org/freedesktop/NetworkManager/*/@{int} + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=@{busname}, label=NetworkManager), + + # NetworkManager + + dbus send bus=system path=/org/freedesktop/NetworkManager + interface=org.freedesktop.NetworkManager + member={GetDevices,GetAllDevices,GetDeviceByIpIface} + peer=(name=@{busname}, label=NetworkManager), + + dbus send bus=system path=/org/freedesktop/NetworkManager + interface=org.freedesktop.NetworkManager + member=GetPermissions + peer=(name=@{busname}, label=NetworkManager), + + dbus receive bus=system path=/org/freedesktop/NetworkManager + interface=org.freedesktop.NetworkManager + member={CheckPermissions,DeviceAdded,DeviceRemoved,StateChanged} + peer=(name=@{busname}, label=NetworkManager), + + dbus send bus=system path=/org/freedesktop/NetworkManager + interface=org.freedesktop.NetworkManager + member=state + peer=(name=@{busname}, label=NetworkManager), + + # NetworkManager.Connection + + dbus receive bus=system path=/org/freedesktop/NetworkManager/*/@{int} + interface=org.freedesktop.NetworkManager.Connection.Active + member=StateChanged + peer=(name=@{busname}, label=NetworkManager), + + # NetworkManager.Settings + + dbus send bus=system path=/org/freedesktop/NetworkManager/Settings + interface=org.freedesktop.NetworkManager.Settings + member=ListConnections + peer=(name=@{busname}, label=NetworkManager), + + dbus send bus=system path=/org/freedesktop/NetworkManager/Settings/@{int} + interface=org.freedesktop.NetworkManager.Settings.Connection + member=GetSettings + peer=(name=@{busname}, label=NetworkManager), + + dbus receive bus=system path=/org/freedesktop/NetworkManager/Settings/@{int} + interface=org.freedesktop.NetworkManager.Settings.Connection + member=Updated + peer=(name=@{busname}, label=NetworkManager), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.freedesktop.PackageKit b/apparmor.d/abstractions/bus/system/org.freedesktop.PackageKit new file mode 100644 index 0000000000..ebc238aa07 --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.freedesktop.PackageKit @@ -0,0 +1,32 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow communication with PackageKit transactions. Transactions are exported +# with random object paths that currently take the form /@{int}_@{hex8}. + + abi , + + #aa:dbus see bus=system name=org.freedesktop.PackageKit label=packagekitd + + dbus send bus=system path=/org/freedesktop/PackageKit + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=org.freedesktop.PackageKit), + + dbus send bus=system path=/org/freedesktop/PackageKit + interface=org.freedesktop.PackageKit + member=StateHasChanged + peer=(name=org.freedesktop.PackageKit), + + dbus send bus=system path=/@{int}_@{hex8} + interface=org.freedesktop.PackageKit.Transaction + peer=(label=packagekitd), + + dbus receive bus=system path=/@{int}_@{hex8} + interface=org.freedesktop.PackageKit.Transaction + peer=(label=packagekitd), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.freedesktop.PolicyKit1 b/apparmor.d/abstractions/bus/system/org.freedesktop.PolicyKit1 new file mode 100644 index 0000000000..e9401e2b8a --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.freedesktop.PolicyKit1 @@ -0,0 +1,47 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Can talk to polkitd's CheckAuthorization API + + abi , + + # DBus.Properties: read properties from the interface + + dbus send bus=system path=/org/freedesktop/PolicyKit1/Authority + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name=@{busname}, label=polkitd), + + # DBus.Introspectable: allow clients to introspect the service + + dbus send bus=system path=/org/freedesktop/PolicyKit1/Authority + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=@{busname}, label=polkitd), + + # PolicyKit1.Authority + + dbus receive bus=system path=/org/freedesktop/PolicyKit1/Authority + interface=org.freedesktop.PolicyKit1.Authority + member=Changed + peer=(name="@{busname}", label="@{p_polkitd}"), + + dbus send bus=system path=/org/freedesktop/PolicyKit1/Authority + interface=org.freedesktop.PolicyKit1.Authority + member=CheckAuthorization + peer=(name=org.freedesktop.PolicyKit1), + + dbus send bus=system path=/org/freedesktop/PolicyKit1/Authority + interface=org.freedesktop.PolicyKit1.Authority + member={CheckAuthorization,CancelCheckAuthorization} + peer=(name="{@{busname},org.freedesktop.PolicyKit1}", label="@{p_polkitd}"), + + dbus send bus=system path=/org/freedesktop/PolicyKit1/Authority + interface=org.freedesktop.PolicyKit1.Authority + member=RegisterAuthenticationAgentWithOptions + peer=(name="{@{busname},org.freedesktop.PolicyKit1}", label="@{p_polkitd}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.freedesktop.RealtimeKit1 b/apparmor.d/abstractions/bus/system/org.freedesktop.RealtimeKit1 new file mode 100644 index 0000000000..9f31cd7d98 --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.freedesktop.RealtimeKit1 @@ -0,0 +1,35 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow setting realtime priorities. + + abi , + + # DBus.Properties: read properties from the interface + + dbus send bus=system path=/org/freedesktop/RealtimeKit1 + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name=@{busname}, label=rtkit-daemon), + + dbus send bus=system path=/org/freedesktop/RealtimeKit1 + interface=org.freedesktop.DBus.Properties + member=Get + peer=(name=org.freedesktop.RealtimeKit1), + + # RealtimeKit1 + + dbus send bus=system path=/org/freedesktop/RealtimeKit1 + interface=org.freedesktop.RealtimeKit1 + member={MakeThreadHighPriority,MakeThreadRealtime} + peer=(name="{@{busname},org.freedesktop.RealtimeKit1}", label="@{p_rtkit_daemon}"), + + dbus send bus=system path=/org/freedesktop/RealtimeKit1 + interface=org.freedesktop.RealtimeKit1 + member={MakeThreadHighPriorityWithPID,MakeThreadRealtimeWithPID} + peer=(name="{@{busname},org.freedesktop.RealtimeKit1}", label="@{p_rtkit_daemon}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.freedesktop.UDisks2 b/apparmor.d/abstractions/bus/system/org.freedesktop.UDisks2 new file mode 100644 index 0000000000..50fd9f606a --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.freedesktop.UDisks2 @@ -0,0 +1,71 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + # DBus.Properties: read properties from the interface + + dbus send bus=system path=/{,/org/freedesktop/UDisks2} + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(label=udisksd), + + dbus send bus=system path=/org/freedesktop/UDisks2{,/**} + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(label=udisksd), + + # DBus.Properties: receive property changed events + + dbus receive bus=system path=/org/freedesktop/UDisks2{,/**} + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(label=udisksd), + + # DBus.ObjectManager: allow clients to enumerate sources + + dbus send bus=system path=/org/freedesktop/UDisks2 + interface=org.freedesktop.DBus.ObjectManager + member=GetManagedObjects + peer=(label=udisksd), + + dbus receive bus=system path=/org/freedesktop/UDisks2 + interface=org.freedesktop.DBus.ObjectManager + member={InterfacesAdded,InterfacesRemoved} + peer=(label=udisksd), + + # DBus.Introspectable: allow clients to introspect the service + + dbus send bus=system path=/ + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(label=udisksd), + + dbus send bus=system path=/org/freedesktop/UDisks2{,/**} + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(label=udisksd), + + # UDisks2.Job + + dbus receive bus=system path=/org/freedesktop/UDisks2/jobs/@{int} + interface=org.freedesktop.UDisks2.Job + member=Completed + peer=(label=udisksd), + + # UDisks2.Manager + + dbus send bus=system path=/org/freedesktop/UDisks2/Manager + interface=org.freedesktop.UDisks2.Manager + member=Can* + peer=(label=udisksd), + + dbus send bus=system path=/org/freedesktop/UDisks2/Manager + interface=org.freedesktop.UDisks2.Manager + member=EnableModule + peer=(label=udisksd), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.freedesktop.UPower b/apparmor.d/abstractions/bus/system/org.freedesktop.UPower new file mode 100644 index 0000000000..876d8be708 --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.freedesktop.UPower @@ -0,0 +1,69 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Can query UPower for power devices, history and statistics. + + abi , + + # DBus.Properties: read properties from the interface + + dbus send bus=system path=/org/freedesktop/UPower + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name="{@{busname},org.freedesktop.UPower}", label="@{p_upowerd}"), + + dbus send bus=system path=/org/freedesktop/UPower/devices/** + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name="{@{busname},org.freedesktop.UPower}", label="@{p_upowerd}"), + + # DBus.Properties: receive property changed events + + dbus receive bus=system path=/org/freedesktop/UPower + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name="{@{busname},org.freedesktop.UPower}", label="@{p_upowerd}"), + + dbus receive bus=system path=/org/freedesktop/UPower/devices/** + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name="{@{busname},org.freedesktop.UPower}", label="@{p_upowerd}"), + + # DBus.Introspectable: allow clients to introspect the service + + dbus send bus=system path=/org/freedesktop/UPower + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name="{@{busname},org.freedesktop.UPower}", label="@{p_upowerd}"), + + # Find all devices monitored by UPower + dbus send bus=system path=/org/freedesktop/UPower + interface=org.freedesktop.UPower + member=EnumerateDevices + peer=(name="{@{busname},org.freedesktop.UPower}", label="@{p_upowerd}"), + + # Allow clients to enumerate devices + dbus receive bus=system path=/org/freedesktop/UPower + interface=org.freedesktop.UPower + member={DeviceAdded,DeviceRemoved} + peer=(name="{@{busname},org.freedesktop.UPower}", label="@{p_upowerd}"), + + dbus send bus=system path=/org/freedesktop/UPower + interface=org.freedesktop.UPower + member={GetDisplayDevice,GetCriticalAction} + peer=(name=org.freedesktop.UPower, label="@{p_upowerd}"), + + dbus send bus=system path=/org/freedesktop/UPower/devices/** + interface=org.freedesktop.UPower.Device + member={GetHistory,Refresh} + peer=(name=org.freedesktop.UPower, label="@{p_upowerd}"), + + dbus send bus=system path=/org/freedesktop/UPower/KbdBacklight + interface=org.freedesktop.UPower.KbdBacklight + member={GetBrightness,GetMaxBrightness} + peer=(name=org.freedesktop.UPower, label="@{p_upowerd}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.freedesktop.UPower.PowerProfiles b/apparmor.d/abstractions/bus/system/org.freedesktop.UPower.PowerProfiles new file mode 100644 index 0000000000..3fe054efde --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.freedesktop.UPower.PowerProfiles @@ -0,0 +1,30 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + # DBus.Properties: read properties from the interface + + dbus send bus=system path=/org/freedesktop/UPower/PowerProfiles + interface=org.freedesktop.DBus.Properties + member=GetAll + peer=(name=@{busname}, label=power-profiles-daemon), + + # DBus.Properties: receive property changed events + + dbus receive bus=system path=/org/freedesktop/UPower/PowerProfiles + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name=@{busname}, label=power-profiles-daemon), + + # UPower.PowerProfiles + + dbus send bus=system path=/org/freedesktop/UPower/PowerProfiles + interface=org.freedesktop.UPower.PowerProfiles + member=HoldProfile + peer=(name=@{busname}, label=power-profiles-daemon), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.freedesktop.hostname1 b/apparmor.d/abstractions/bus/system/org.freedesktop.hostname1 new file mode 100644 index 0000000000..06078bd52c --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.freedesktop.hostname1 @@ -0,0 +1,35 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + # DBus.Properties: read properties from the interface + + dbus send bus=system path=/org/freedesktop/hostname1 + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name=org.freedesktop.hostname1), + + dbus send bus=system path=/org/freedesktop/hostname1 + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(label=systemd-hostnamed), + + # DBus.Properties: receive property changed events + + dbus receive bus=system path=/org/freedesktop/hostname1 + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name=@{busname}, label=systemd-hostnamed), + + # DBus.Introspectable: allow clients to introspect the service + + dbus send bus=system path=/org/freedesktop/hostname1 + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=@{busname}, label=systemd-hostnamed), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.freedesktop.locale1 b/apparmor.d/abstractions/bus/system/org.freedesktop.locale1 similarity index 59% rename from apparmor.d/abstractions/bus/org.freedesktop.locale1 rename to apparmor.d/abstractions/bus/system/org.freedesktop.locale1 index 511a44dd66..ea972d2de2 100644 --- a/apparmor.d/abstractions/bus/org.freedesktop.locale1 +++ b/apparmor.d/abstractions/bus/system/org.freedesktop.locale1 @@ -4,12 +4,16 @@ abi , - #aa:dbus common bus=system name=org.freedesktop.locale1 label=systemd-localed dbus send bus=system path=/org/freedesktop/locale1 interface=org.freedesktop.DBus.Properties member=GetAll peer=(name=org.freedesktop.locale1), - include if exists + dbus send bus=system path=/org/freedesktop/locale1 + interface=org.freedesktop.DBus.Properties + member=GetAll + peer=(name=@{busname}, label=systemd-localed), + + include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.freedesktop.login1 b/apparmor.d/abstractions/bus/system/org.freedesktop.login1 new file mode 100644 index 0000000000..8a1222d16d --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.freedesktop.login1 @@ -0,0 +1,101 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow seting up login session & seat. It grants privileged access to user sessions. + + abi , + + # DBus.Properties: read properties from the interface + + dbus send bus=system path=/org/freedesktop/login1{,/session/**} + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name="{@{busname},org.freedesktop.login1}", label="@{p_systemd_logind}"), + + # DBus.Properties: receive property changed events + + dbus receive bus=system path=/org/freedesktop/login1 + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name=@{busname}, label="@{p_systemd_logind}"), + + dbus receive bus=system path=/org/freedesktop/login1{,/session/**} + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name=@{busname}, label="@{p_systemd_logind}"), + + # DBus.Introspectable: allow clients to introspect the service + + dbus send bus=system path=/org/freedesktop/login1 + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=@{busname}, label="@{p_systemd_logind}"), + + # Inhibit system actions + + dbus send bus=system path=/org/freedesktop/login1 + interface=org.freedesktop.login1.Manager + member=Inhibit + peer=(name="{@{busname},org.freedesktop.login1}", label="@{p_systemd_logind}"), + + # Check login session observe & login session control + + dbus receive bus=system path=/org/freedesktop/login1 + interface=org.freedesktop.login1.Manager + member={SessionNew,UserNew,SeatNew} + peer=(name="{@{busname},org.freedesktop.login1}", label="@{p_systemd_logind}"), + + dbus receive bus=system path=/org/freedesktop/login1 + interface=org.freedesktop.login1.Manager + member={SessionRemoved,UserRemoved,SeatRemoved} + peer=(name="{@{busname},org.freedesktop.login1}", label="@{p_systemd_logind}"), + + dbus receive bus=system path=/org/freedesktop/login1 + interface=org.freedesktop.login1.Manager + member={PrepareForShutdow,PrepareForSleep} + peer=(name="{@{busname},org.freedesktop.login1}", label="@{p_systemd_logind}"), + + dbus send bus=system path=/org/freedesktop/login1 + interface=org.freedesktop.login1.Manager + member={ListSeats,ListSessions,ListUsers} + peer=(name="{@{busname},org.freedesktop.login1}", label="@{p_systemd_logind}"), + + dbus send bus=system path=/org/freedesktop/login1 + interface=org.freedesktop.login1.Manager + member={GetSeat,GetSessions,GetSessionByPID,GetUsers} + peer=(name="{@{busname},org.freedesktop.login1}", label="@{p_systemd_logind}"), + + # Receive shutdown & sleep notifications + + dbus receive bus=system path=/org/freedesktop/login1 + interface=org.freedesktop.login1.Manager + member={PrepareForShutdown,PrepareForShutdownWithMetadata} + peer=(name="{@{busname},org.freedesktop.login1}", label="@{p_systemd_logind}"), + + dbus send bus=system path=/org/freedesktop/login1 + interface=org.freedesktop.login1.Manager + member={CanHibernate,CanHybridSleep,CanPowerOff,CanReboot,CanSuspend,CanSuspendThenHibernate,CreateSession} + peer=(name="{@{busname},org.freedesktop.login1}", label="@{p_systemd_logind}"), + + # Sessions + + dbus send bus=system path=/org/freedesktop/login1/session/** + interface=org.freedesktop.login1.Session + peer=(name="{@{busname},org.freedesktop.login1}", label="@{p_systemd_logind}"), + dbus receive bus=system path=/org/freedesktop/login1/session/** + interface=org.freedesktop.login1.Session + peer=(name="{@{busname},org.freedesktop.login1}", label="@{p_systemd_logind}"), + + # Seats + + dbus send bus=system path=/org/freedesktop/login1/seat/** + interface=org.freedesktop.login1.Session + peer=(name="{@{busname},org.freedesktop.login1}", label="@{p_systemd_logind}"), + dbus receive bus=system path=/org/freedesktop/login1/seat/** + interface=org.freedesktop.login1.Session + peer=(name="{@{busname},org.freedesktop.login1}", label="@{p_systemd_logind}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.freedesktop.network1 b/apparmor.d/abstractions/bus/system/org.freedesktop.network1 similarity index 54% rename from apparmor.d/abstractions/bus/org.freedesktop.network1 rename to apparmor.d/abstractions/bus/system/org.freedesktop.network1 index be11a7ceba..a61627c9d7 100644 --- a/apparmor.d/abstractions/bus/org.freedesktop.network1 +++ b/apparmor.d/abstractions/bus/system/org.freedesktop.network1 @@ -4,8 +4,8 @@ abi , - #aa:dbus common bus=system name=org.freedesktop.network1 label=systemd-networkd + #aa:dbus see bus=system name=org.freedesktop.network1 label="@{p_systemd_networkd}" - include if exists + include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.freedesktop.systemd1 b/apparmor.d/abstractions/bus/system/org.freedesktop.systemd1 new file mode 100644 index 0000000000..6ff695a121 --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.freedesktop.systemd1 @@ -0,0 +1,80 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow managing systemd units services. This allow full control over all services. +# When possible use the systemctl directive instead. + + abi , + + # DBus.Properties: read properties from the interface + + dbus send bus=system path=/org/freedesktop/systemd1 + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name=org.freedesktop.systemd1), + + dbus send bus=system path=/org/freedesktop/systemd1 + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(label="@{p_systemd}"), + + dbus send bus=system path=/org/freedesktop/systemd1/unit/* + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(label="@{p_systemd}"), + + dbus send bus=system path=/org/freedesktop/systemd1/unit/* + interface=org.freedesktop.DBus.Properties + member=Get + peer=(name=org.freedesktop.systemd1, label="@{p_systemd}"), + + # DBus.Properties: receive property changed events + + dbus receive bus=system path=/org/freedesktop/systemd1/unit/* + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(label="@{p_systemd}"), + + dbus send bus=system path=/org/freedesktop/systemd1 + interface=org.freedesktop.systemd1.Manager + member={SetEnvironment,UnsetAndSetEnvironment,ResetFailed} + peer=(name=org.freedesktop.systemd1, label="@{p_systemd}"), + + # List units + dbus send bus=system path=/org/freedesktop/systemd1 + interface=org.freedesktop.systemd1.Manager + member={GetUnit,GetUnitByPIDFD,ListUnitsByPatterns} + peer=(label="@{p_systemd}"), + + dbus receive bus=system path=/org/freedesktop/systemd1 + interface=org.freedesktop.systemd1.Manager + member={UnitNew,UnitRemoved} + peer=(label="@{p_systemd}"), + + # Start units + dbus send bus=system path=/org/freedesktop/systemd1 + interface=org.freedesktop.systemd1.Manager + member={StartUnit,StartTransientUnit,LoadUnit} + peer=(label="@{p_systemd}"), + + # Stop units + dbus send bus=system path=/org/freedesktop/systemd1 + interface=org.freedesktop.systemd1.Manager + member={StopUnit,KillUnit,ResetFailedUnit,Reload,JobRemoved} + peer=(label="@{p_systemd}"), + + dbus receive bus=system path=/org/freedesktop/systemd1 + interface=org.freedesktop.systemd1.Manager + member={JobNew,JobRemoved} + peer=(label="@{p_systemd}"), + + # Enabled/Disable units + dbus send bus=system path=/org/freedesktop/systemd1 + interface=org.freedesktop.systemd1.Manager + member={DisableUnitFiles,EnableUnitFiles} + peer=(label="@{p_systemd}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.freedesktop.systemd1.Manager b/apparmor.d/abstractions/bus/system/org.freedesktop.systemd1.Manager new file mode 100644 index 0000000000..2b06c45a7d --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.freedesktop.systemd1.Manager @@ -0,0 +1,19 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# libnss-systemd (D-Bus portion from nameservice abstraction) +# +# Also allow lookups for systemd-exec's DynamicUsers via D-Bus +# https://www.freedesktop.org/software/systemd/man/systemd.exec.html + + abi , + + dbus send bus=system path=/org/freedesktop/systemd1 + interface=org.freedesktop.systemd1.Manager + member={GetDynamicUsers,LookupDynamicUserByName,LookupDynamicUserByUID} + peer=(name=org.freedesktop.systemd1, label="@{p_systemd}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/system/org.freedesktop.timedate1 b/apparmor.d/abstractions/bus/system/org.freedesktop.timedate1 new file mode 100644 index 0000000000..6d4f336d59 --- /dev/null +++ b/apparmor.d/abstractions/bus/system/org.freedesktop.timedate1 @@ -0,0 +1,30 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + # DBus.Properties: read properties from the interface + + dbus send bus=system path=/org/freedesktop/timedate1 + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name=@{busname}, label=systemd-timedated), + + # DBus.Introspectable: allow clients to introspect the service + + dbus send bus=system path=/org/freedesktop/timedate1 + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=@{busname}, label=systemd-timedated), + + # org.freedesktop.timedate1 + + dbus send bus=system path=/org/freedesktop/timedate1 + interface=org.freedesktop.timedate1 + member=SetTimezone + peer=(name=org.freedesktop.timedate1, label=systemd-timedated), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/org.gnome.DisplayManager b/apparmor.d/abstractions/bus/system/org.gnome.DisplayManager similarity index 60% rename from apparmor.d/abstractions/bus/org.gnome.DisplayManager rename to apparmor.d/abstractions/bus/system/org.gnome.DisplayManager index 741631f4b6..38ec52c7f9 100644 --- a/apparmor.d/abstractions/bus/org.gnome.DisplayManager +++ b/apparmor.d/abstractions/bus/system/org.gnome.DisplayManager @@ -1,16 +1,16 @@ # apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol +# Copyright (C) 2023-2025 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only abi , - #aa:dbus common bus=system name=org.gnome.DisplayManager label=gdm + #aa:dbus see bus=system name=org.gnome.DisplayManager label=gdm dbus send bus=system path=/org/gnome/DisplayManager/Manager interface=org.gnome.DisplayManager.Manager member=RegisterDisplay peer=(name="@{busname}", label=gdm), - include if exists + include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bus/own-system b/apparmor.d/abstractions/bus/system/own similarity index 58% rename from apparmor.d/abstractions/bus/own-system rename to apparmor.d/abstractions/bus/system/own index f2ee3219c1..00c31033cc 100644 --- a/apparmor.d/abstractions/bus/own-system +++ b/apparmor.d/abstractions/bus/system/own @@ -3,22 +3,26 @@ # SPDX-License-Identifier: GPL-2.0-only # LOGPROF-SUGGEST: no -# Do not use it manually, it is automatically included in a profile when it is required. - # Allow owning a name on DBus public bus +# +# !!! warning +# +# Do not use it manually, It is automatically included in a profile by the +# `aa:dbus own` directive. +# abi , - dbus send bus=system path=/org/freedesktop/DBus + dbus send bus=system path=/{,org/freedesktop/DBus,org/freedesktop/DBus/Bus} interface=org.freedesktop.DBus - member={RequestName,ReleaseName} + member={ListNames,RequestName,ReleaseName} peer=(name=org.freedesktop.DBus, label="@{p_dbus_system}"), - dbus send bus=system path=/org/freedesktop/DBus + dbus send bus=system path=/{,org/freedesktop/DBus,org/freedesktop/DBus/Bus} interface=org.freedesktop.DBus member={GetConnectionUnixProcessID,GetConnectionUnixUser,GetConnectionCredentials} peer=(name=org.freedesktop.DBus, label="@{p_dbus_system}"), - include if exists + include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/bwrap b/apparmor.d/abstractions/bwrap new file mode 100644 index 0000000000..6caf2c12a9 --- /dev/null +++ b/apparmor.d/abstractions/bwrap @@ -0,0 +1,77 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# NEEDS-VARIABLE: att + +# Bubblewrap creates isolated environments for applications. It requires the +# `sys_admin` capability to enter a new PID namespace. Until this capability is +# dropped, the process can potentially escape confinement. For this reason, we +# typically transition to another application profile, even if it requires +# managing a stacked set of profiles since bwrap sets the `no_new_privs` (nnp) +# flag. The resulting profile should take the form: `//&` +# +# A profile using this abstraction still needs to set: +# +# - the flag: `attach_disconnected` +# - bwrap execution: `@{bin}/bwrap ix,` is needed. + + abi , + + userns, + + capability net_admin, + capability setpcap, + capability sys_admin, + capability sys_ptrace, + + network netlink raw, + + mount options=(rw rbind) -> /newroot/{,**}, + mount options=(rw rbind) /tmp/newroot/ -> /tmp/newroot/, + mount fstype=devpts options=(rw nosuid noexec) devpts -> /newroot/dev/pts/, + mount fstype=proc options=(rw nosuid nodev noexec) proc -> /newroot/@{PROC}/, + mount fstype=tmpfs options=(rw nosuid nodev) tmpfs -> /newroot/{,**}, + mount fstype=tmpfs options=(rw nosuid nodev) tmpfs -> /tmp/, + + mount options=(rw silent make-rslave) /, + mount options=(rw silent make-rprivate) /oldroot/, + + remount /newroot/{,**}, + + umount /, + umount /oldroot/, + + #aa:only debian whonix + mount -> /newroot/{,**}, # Debian does not support the remount rule. + + pivot_root oldroot=/newroot/ /newroot/, + pivot_root oldroot=/tmp/oldroot/ /tmp/, + + @{bin}/bwrap mr, + + owner /newroot/{,**} w, + + owner /tmp/newroot/ w, + owner /tmp/oldroot/ w, + + owner / r, + @{att}/ r, + @{att}@{run}/.userns r, + + @{PROC}/sys/kernel/overflowgid r, + @{PROC}/sys/kernel/overflowuid r, + @{PROC}/sys/user/max_user_namespaces r, + @{PROC}/sys/kernel/seccomp/actions_avail r, + owner @{PROC}/@{pid}/fd/ r, + + @{att}@{PROC}/sys/user/max_user_namespaces rw, + owner @{att}@{PROC}/@{pid}/cgroup r, + owner @{att}@{PROC}/@{pid}/fd/ r, + owner @{att}@{PROC}/@{pid}/gid_map rw, + owner @{att}@{PROC}/@{pid}/mountinfo r, + owner @{att}@{PROC}/@{pid}/setgroups rw, + owner @{att}@{PROC}/@{pid}/uid_map rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/camera b/apparmor.d/abstractions/camera new file mode 100644 index 0000000000..a358283048 --- /dev/null +++ b/apparmor.d/abstractions/camera @@ -0,0 +1,27 @@ +# 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 , + + include + + @{run}/udev/data/c81:@{int} r, # For video4linux + + @{sys}/class/video4linux/ r, + @{sys}/devices/**/video4linux/video@{int}/ r, + @{sys}/devices/**/video4linux/video@{int}/uevent r, + + /dev/ r, + + # 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/cgroup-limits b/apparmor.d/abstractions/cgroup-limits new file mode 100644 index 0000000000..5b1906c15a --- /dev/null +++ b/apparmor.d/abstractions/cgroup-limits @@ -0,0 +1,32 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow reading CPU and memory limits from cgroup hierarchy + + abi , + + @{sys}/fs/cgroup/cgroup.controllers r, + + @{sys}/fs/cgroup/user.slice/memory.high r, + @{sys}/fs/cgroup/user.slice/memory.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/memory.high r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/memory.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/memory.high r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/memory.max r, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/**/memory.high r, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/**/memory.max r, + + @{sys}/fs/cgroup/cpu.max r, + @{sys}/fs/cgroup/user.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/session-@{int}.scope/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/cpu.max r, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/**/cpu.max r, + + # Allow reading cgroup membership information + owner @{PROC}/@{pid}/cgroup r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/common/app b/apparmor.d/abstractions/common/app index f2201bd647..4c2575414a 100644 --- a/apparmor.d/abstractions/common/app +++ b/apparmor.d/abstractions/common/app @@ -2,53 +2,48 @@ # Copyright (C) 2023-2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only # LOGPROF-SUGGEST: no +# NEEDS-VARIABLE: att -# Common rules for applications sandboxed using bwrap. - -# This abstraction is wide on purpose. It is meant to be used by sandbox -# applications (bwrap) that have no way to restrict access depending on the -# application being confined. +# Common rules for a generic UI application. +# +# This abstraction is wide on purpose. It is meant to be used by a generic +# user UI aplications wich no asumption made on the access they need. abi , + include include - include - include - include - include + include + include + include + include + include include include include + include include include include include include include + include include + include + include include + include + include + include + include + include + include include - include - - dbus bus=accessibility, - dbus bus=session, - dbus bus=system, - - /usr/cache/** r, - /usr/local/{,**} r, - /usr/share/** rk, - - /etc/{,**} r, + include + include - / r, - /.* r, - /*/ r, - @{bin}/ r, - @{lib}/ r, - /usr/local/bin/ r, - owner /_@{int}_/ w, - owner /@{uuid}/ w, - owner /var/cache/ldconfig/{,**} rw, + /usr/** r, # Full access to user's data / r, @@ -57,92 +52,113 @@ @{MOUNTS}/ r, @{MOUNTS}/** rwl, owner @{HOME}/ r, - owner @{HOME}/.var/app/** rmix, - owner @{HOME}/** rwlk -> @{HOME}/**, + owner @{HOME}/** mrwlkix -> @{HOME}/**, owner @{run}/user/@{uid}/ r, - owner @{run}/user/@{uid}/** rwlk -> @{run}/user/@{uid}/**, - owner @{user_games_dirs}/** rmix, + owner @{run}/user/@{uid}/** mrwlkix -> @{run}/user/@{uid}/**, #aa:lint ignore=too-wide + owner @{user_games_dirs}/** mrwlkix, - owner /var/cache/tmp/** rwlk -> /var/cache/tmp/**, - owner @{tmp}/** rmwk, - owner /dev/shm/** rwlk -> /dev/shm/**, + #aa:lint ignore=too-wide + owner @{tmp}/** mrwlkix, + owner /dev/shm/** mrwlkix -> /dev/shm/**, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, - @{run}/havahi-daemon/socket rw, # Allow access to avahi-daemon socket. - @{run}/host/{,**} r, - @{run}/pcscd/pcscd.comm rw, # Allow access to pcscd socket. @{run}/utmp rk, - @{run}/udev/data/c13:@{int} r, # for /dev/input/* - @{sys}/ r, @{sys}/block/ r, @{sys}/bus/ r, @{sys}/bus/*/devices/ r, @{sys}/bus/pci/slots/ r, + @{sys}/bus/pci/slots/@{int}-@{int}/address r, @{sys}/bus/pci/slots/@{int}/address r, @{sys}/class/*/ r, @{sys}/devices/** r, + @{sys}/devices/virtual/dmi/id/bios_version k, @{sys}/fs/cgroup/user.slice/* r, @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/* r, @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/* r, owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/* r, + # Show the list of active tty + @{sys}/devices/virtual/tty/tty@{int}/active r, + + # This is an information leak but disallowing it leads to developer confusion + # when using the chromium content api file chooser due to a (harmless) glib + # warning and the noisy AppArmor denial. + owner @{PROC}/@{pid}/mounts r, + owner @{PROC}/@{pid}/mountinfo r, + + # Reads of oom_adj and oom_score_adj are safe + owner @{PROC}/@{pid}/oom_adj r, + owner @{PROC}/@{pid}/oom_score_adj r, + + # Per man(5) proc, the kernel enforces that a thread may only modify its comm + # value or those in its thread group. + owner @{PROC}/@{pid}/task/@{tid}/comm rw, + @{PROC}/ r, - @{PROC}/@{pid}/cgroup r, - @{PROC}/@{pid}/cmdline r, - @{PROC}/@{pid}/comm rk, + @{PROC}/@{pid}/cpuset r, @{PROC}/@{pid}/fd/ r, - @{PROC}/@{pid}/mountinfo r, - @{PROC}/@{pid}/net/** r, + @{PROC}/@{pid}/io r, + @{PROC}/@{pid}/maps r, @{PROC}/@{pid}/smaps r, @{PROC}/@{pid}/stat r, @{PROC}/@{pid}/statm r, - @{PROC}/@{pid}/task/@{tid}/stat r, + @{PROC}/@{pid}/status r, @{PROC}/@{pid}/task/@{tid}/status r, - @{PROC}/bus/pci/devices r, - @{PROC}/cmdline r, - @{PROC}/driver/** r, - @{PROC}/locks r, - @{PROC}/pressure/cpu r, - @{PROC}/pressure/io r, - @{PROC}/pressure/memory r, + @{PROC}/loadavg r, + @{PROC}/sys/fs/file-max r, + @{PROC}/sys/fs/file-nr r, + @{PROC}/sys/fs/inotify/max_queued_events r, + @{PROC}/sys/fs/inotify/max_user_instances r, @{PROC}/sys/fs/inotify/max_user_watches r, + @{PROC}/sys/fs/nr_open r, + @{PROC}/sys/fs/pipe-max-size r, + @{PROC}/sys/kernel/hostname r, @{PROC}/sys/kernel/osrelease r, + @{PROC}/sys/kernel/ostype r, @{PROC}/sys/kernel/pid_max r, - @{PROC}/sys/kernel/sched_autogroup_enabled r, + @{PROC}/sys/kernel/random/boot_id r, + @{PROC}/sys/kernel/random/entropy_avail r, + @{PROC}/sys/kernel/random/uuid r, + @{PROC}/sys/kernel/shmmax r, @{PROC}/sys/kernel/yama/ptrace_scope r, - @{PROC}/sys/net/core/bpf_jit_enable r, @{PROC}/uptime r, @{PROC}/version r, - @{PROC}/zoneinfo r, - owner @{PROC}/@{pid}/autogroup rw, + @{PROC}/version_signature r, + owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/clear_refs w, - owner @{PROC}/@{pid}/comm rw, + owner @{PROC}/@{pid}/cmdline rk, + owner @{PROC}/@{pid}/comm rk, owner @{PROC}/@{pid}/environ r, - owner @{PROC}/@{pid}/fd/@{int} rw, + owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/fdinfo/@{int} r, - owner @{PROC}/@{pid}/io r, + owner @{PROC}/@{pid}/limits r, owner @{PROC}/@{pid}/loginuid r, - owner @{PROC}/@{pid}/mem r, - owner @{PROC}/@{pid}/mounts r, - owner @{PROC}/@{pid}/net/if_inet6 r, - owner @{PROC}/@{pid}/oom_score_adj rw, - owner @{PROC}/@{pid}/pagemap r, - owner @{PROC}/@{pid}/statm r, + owner @{PROC}/@{pid}/sessionid r, + owner @{PROC}/@{pid}/smaps_rollup r, owner @{PROC}/@{pid}/task/ r, - owner @{PROC}/@{pid}/task/@{tid}/comm rw, + owner @{PROC}/@{pid}/task/@{tid}/smaps r, + owner @{PROC}/@{pid}/task/@{tid}/stat r, + owner @{PROC}/@{pid}/task/@{tid}/statm r, + + @{att}/dev/dri/card@{int} rw, + @{att}/dev/dri/renderD128 rw, + @{att}/dev/dri/renderD129 rw, + owner @{att}/dev/shm/@{uuid} r, - /dev/hidraw@{int} rw, - /dev/input/ r, - /dev/input/event@{int} rw, /dev/ptmx rw, /dev/pts/ptmx rw, /dev/tty rw, /dev/udmabuf rw, + deny @{user_share_dirs}/gvfs-metadata/* r, + + # This allows raising the OOM score of other processes owned by the user. + deny owner @{PROC}/@{pid}/oom_score_adj w, + include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/common/bwrap b/apparmor.d/abstractions/common/bwrap deleted file mode 100644 index f4630475d9..0000000000 --- a/apparmor.d/abstractions/common/bwrap +++ /dev/null @@ -1,63 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - -# A minimal set of rules for sandboxed programs using bwrap. -# A profile using this abstraction still needs to set: -# - the flag: attach_disconnected -# - bwrap execution: '@{bin}/bwrap rix,' - - abi , - - userns, - - capability net_admin, - capability setpcap, - capability sys_admin, - capability sys_ptrace, - - network netlink raw, - - mount options=(rw rbind) -> /newroot/{,**}, - mount options=(rw rbind) /tmp/newroot/ -> /tmp/newroot/, - mount options=(rw silent rprivate) -> /oldroot/, - mount options=(rw silent rslave) -> /, - mount fstype=devpts options=(rw nosuid noexec) devpts -> /newroot/dev/pts/, - mount fstype=proc options=(rw nosuid nodev noexec) proc -> /newroot/@{PROC}/, - mount fstype=tmpfs options=(rw nosuid nodev) tmpfs -> /newroot/{,**}, - mount fstype=tmpfs options=(rw nosuid nodev) tmpfs -> /tmp/, - - remount /newroot/{,**}, - - umount /, - umount /oldroot/, - - #aa:only debian whonix - mount -> /newroot/{,**}, # Debian does not support the remount rule. - - pivot_root oldroot=/newroot/ /newroot/, - pivot_root oldroot=/tmp/oldroot/ /tmp/, - - owner / r, - owner /newroot/{,**} w, - - owner /tmp/newroot/ w, - owner /tmp/oldroot/ w, - - @{PROC}/sys/kernel/overflowgid r, - @{PROC}/sys/kernel/overflowuid r, - @{PROC}/sys/user/max_user_namespaces r, - @{PROC}/sys/kernel/seccomp/actions_avail r, - owner @{PROC}/@{pid}/fd/ r, - - @{att}/@{PROC}/sys/user/max_user_namespaces rw, - owner @{att}/@{PROC}/@{pid}/cgroup r, - owner @{att}/@{PROC}/@{pid}/fd/ r, - owner @{att}/@{PROC}/@{pid}/gid_map rw, - owner @{att}/@{PROC}/@{pid}/mountinfo r, - owner @{att}/@{PROC}/@{pid}/setgroups rw, - owner @{att}/@{PROC}/@{pid}/uid_map rw, - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/common/chromium b/apparmor.d/abstractions/common/chromium index 9fba7b8bb6..b925baef19 100644 --- a/apparmor.d/abstractions/common/chromium +++ b/apparmor.d/abstractions/common/chromium @@ -2,41 +2,68 @@ # Copyright (C) 2022 Mikhail Morfikov # Copyright (C) 2022-2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only +# NEEDS-VARIABLE: domain # This abstraction is for chromium based application. Chromium based browsers -# need to use abstractions/chromium instead. +# need to use abstractions/app/chromium instead. +# +# It works as a *function* and requires a variable to be provided as *arguments* +# and set in the header of the calling profile. Example: +# +# !!! quote "" +# +# ``` +# @{domain} = org.chromium.Chromium +# ``` +# abi , + include + userns, - capability setgid, # If kernel.unprivileged_userns_clone = 1 - capability setuid, # If kernel.unprivileged_userns_clone = 1 + # Required for dropping into PID namespace. Keep in mind that until the + # process drops this capability it can escape confinement, but once it + # drops CAP_SYS_ADMIN we are ok. capability sys_admin, + capability sys_chroot, capability sys_ptrace, - owner @{HOME}/.pki/ rw, - owner @{HOME}/.pki/nssdb/ rw, - owner @{HOME}/.pki/nssdb/pkcs11.txt rw, - owner @{HOME}/.pki/nssdb/{cert9,key4}.db rwk, - owner @{HOME}/.pki/nssdb/{cert9,key4}.db-journal rw, + # Needed with sysctl_kernel_unprivileged_userns_clone = 1 + audit capability setgid, + audit capability setuid, - owner @{user_share_dirs}/.org.chromium.Chromium.@{rand6} rw, + owner @{user_share_dirs}/.@{domain}.@{rand6} rw, - /tmp/ r, - /var/tmp/ r, - owner @{tmp}/.org.chromium.Chromium.@{rand6} rw, - owner @{tmp}/.org.chromium.Chromium.@{rand6}/{,**} rw, + @{tmp}/ r, + owner @{tmp}/{,.}@{domain}.@{rand6} rw, + owner @{tmp}/{,.}@{domain}.@{rand6}/ rw, + owner @{tmp}/{,.}@{domain}.@{rand6}/*.@{image_ext} rw, + owner @{tmp}/{,.}@{domain}.@{rand6}/SingletonCookie rw, + owner @{tmp}/{,.}@{domain}.@{rand6}/SingletonSocket rw, + owner @{tmp}/{,.}@{domain}.scoped_dir.@{rand6}/ rw, + owner @{tmp}/{,.}@{domain}.scoped_dir.@{rand6}/SingletonCookie rw, + owner @{tmp}/{,.}@{domain}.scoped_dir.@{rand6}/SingletonSocket rw, owner @{tmp}/scoped_dir@{rand6}/ rw, - owner @{tmp}/scoped_dir@{rand6}/SingletonCookie w, - owner @{tmp}/scoped_dir@{rand6}/SingletonSocket w, - owner @{tmp}/scoped_dir@{rand6}/SS w, + owner @{tmp}/scoped_dir@{rand6}/SingletonCookie rw, + owner @{tmp}/scoped_dir@{rand6}/SingletonSocket rw, + owner @{tmp}/scoped_dir@{rand6}/SS rw, /dev/shm/ r, - owner /dev/shm/.org.chromium.Chromium.@{rand6} rw, + owner /dev/shm/.@{domain}.@{rand6} rw, + + @{sys}/devices/system/cpu/kernel_max r, + + # Show the list of active tty + @{sys}/devices/virtual/tty/tty@{int}/active r, + + # Allow getting the manufacturer and model of the computer where chromium is currently running. + @{sys}/devices/virtual/dmi/id/product_name r, + @{sys}/devices/virtual/dmi/id/sys_vendor r, - # If kernel.unprivileged_userns_clone = 1 + # Needed with sysctl_kernel_unprivileged_userns_clone = 1 owner @{PROC}/@{pid}/setgroups w, owner @{PROC}/@{pid}/gid_map w, owner @{PROC}/@{pid}/uid_map w, diff --git a/apparmor.d/abstractions/common/debconf b/apparmor.d/abstractions/common/debconf new file mode 100644 index 0000000000..1d9a6d145b --- /dev/null +++ b/apparmor.d/abstractions/common/debconf @@ -0,0 +1,28 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + + abi , + + include + include + include + + @{sh_path} rix, + @{bin}/locale ix, + @{bin}/whiptail Px, + + /usr/share/debconf/frontend rix, + /usr/share/debconf/confmodule r, + + /etc/debconf.conf r, + + /var/ r, + /var/cache/ r, + /var/cache/debconf/ r, + owner /var/cache/debconf/{config,passwords,templates}.dat{,-new,-old} rwk, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/common/electron b/apparmor.d/abstractions/common/electron index 8134f86811..b671a199f0 100644 --- a/apparmor.d/abstractions/common/electron +++ b/apparmor.d/abstractions/common/electron @@ -1,36 +1,46 @@ # apparmor.d - Full set of apparmor profiles # Copyright (C) 2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only +# NEEDS-VARIABLE: name +# NEEDS-VARIABLE: domain +# NEEDS-VARIABLE: lib_dirs +# NEEDS-VARIABLE: config_dirs +# NEEDS-VARIABLE: cache_dirs # Minimal set of rules for all electron based UI application. It works as a # *function* and requires some variables to be provided as *arguments* and set # in the header of the calling profile. Example: # -# @{name} = spotify -# @{lib_dirs} = /opt/@{name} -# @{config_dirs} = @{user_config_dirs}/@{name} -# @{cache_dirs} = @{user_cache_dirs}/@{name} +# !!! quote "" +# +# ``` +# @{name} = spotify +# @{domain} = org.chromium.chromium +# @{lib_dirs} = /opt/@{name}/ /usr/share/@{name}/ +# @{config_dirs} = @{user_config_dirs}/@{name} +# @{cache_dirs} = @{user_cache_dirs}/@{name} +# ``` # abi , + include + include include include + include include include include - userns, - - capability setgid, # If kernel.unprivileged_userns_clone = 1 - capability setuid, # If kernel.unprivileged_userns_clone = 1 - capability sys_admin, - capability sys_chroot, - capability sys_ptrace, + @{bin}/xdg-mime rix, + @{bin}/xdg-settings rix, @{bin}/electron rix, @{bin}/electron@{int} rix, @{lib}/electron@{int}/{,**} r, + @{lib}/electron@{int}/chrome_crashpad_handler Cx -> crashpad_handler, + @{lib}/electron@{int}/chrome-sandbox ix, @{lib}/electron@{int}/electron rix, @{lib_dirs}/{,**} r, @@ -38,60 +48,109 @@ @{lib_dirs}/{,resources/}app.asar.unpacked/node_modules/**.node mr, @{lib_dirs}/{,resources/}app.asar.unpacked/node_modules/**.so mr, @{lib_dirs}/{,resources/}app.asar.unpacked/node_modules/**.so.@{int} mr, + @{lib_dirs}/chrome_crashpad_handler Cx -> crashpad_handler, /etc/@{name}/{,**} r, owner @{config_dirs}/ rw, - owner @{config_dirs}/** rwlk -> @{config_dirs}/**, + owner @{config_dirs}/** rwlk, owner @{cache_dirs}/ rw, - owner @{cache_dirs}/** rwlk -> @{cache_dirs}/**, + owner @{cache_dirs}/** rwlk, - owner @{HOME}/.pki/ rw, - owner @{HOME}/.pki/nssdb/ rw, - owner @{HOME}/.pki/nssdb/pkcs11.txt rw, - owner @{HOME}/.pki/nssdb/{cert9,key4}.db rwk, - owner @{HOME}/.pki/nssdb/{cert9,key4}.db-journal rw, + # For direct integration with xdg-mime and xdg-settings + owner @{user_config_dirs}/mimeapps.list{,.new} rw, + owner @{user_config_dirs}/xfce4/helpers.rc{,.@{rand6}} rw, + owner @{user_share_dirs}/applications/{,**} rw, owner @{user_config_dirs}/electron-flags.conf r, - owner @{user_share_dirs}/.org.chromium.Chromium.@{rand6} rw, + owner @{user_config_dirs}/electron@{u8}-flags.conf r, - owner @{tmp}/.org.chromium.Chromium.@{rand6} rw, - owner @{tmp}/.org.chromium.Chromium.@{rand6}/ rw, - owner @{tmp}/.org.chromium.Chromium.@{rand6}/SingletonCookie w, - owner @{tmp}/.org.chromium.Chromium.@{rand6}/SingletonSocket w, - owner @{tmp}/scoped_dir@{rand6}/ rw, - owner @{tmp}/scoped_dir@{rand6}/SingletonCookie w, - owner @{tmp}/scoped_dir@{rand6}/SingletonSocket w, - owner @{tmp}/scoped_dir@{rand6}/SS w, + owner @{tmp}/{,.}@{domain}.*/{,**} rw, - /dev/shm/ r, - owner /dev/shm/.org.chromium.Chromium.@{rand6} rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, - @{sys}/devices/system/cpu/kernel_max r, - @{sys}/devices/virtual/dmi/id/product_name r, - @{sys}/devices/virtual/dmi/id/sys_vendor r, - @{sys}/devices/virtual/tty/tty@{int}/active r, + @{sys}/fs/cgroup/user.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/session-@{word}.scope/memory.high r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/session-@{word}.scope/memory.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/cpu.max r, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/*-@{int}.scope/memory.high r, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/*-@{int}.scope/memory.max r, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/cpu.max r, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/session.slice/cpu.max r, - @{PROC}/ r, + # This is an information leak + owner @{PROC}/@{pid}/mountinfo r, + + # Provide statistical information about our own and other processes/threads @{PROC}/@{pid}/stat r, + @{PROC}/@{pid}/task/@{tid}/status r, + owner @{PROC}/@{pid}/statm r, + owner @{PROC}/@{pid}/task/ r, + owner @{PROC}/@{pid}/task/@{tid}/stat r, + + # Allow listing file descriptors for resource monitoring + owner @{PROC}/@{pid}/fd/ r, + + # Allow reading of smaps_rollup, which is a summary of the memory use of a process + owner @{PROC}/@{pid}/smaps_rollup r, + + # Reads of oom_adj and oom_score_adj are safe + owner @{PROC}/@{pid}/oom_adj r, + owner @{PROC}/@{pid}/oom_score_adj r, + + # This allows raising the OOM score of other processes owned by the user. + owner @{PROC}/@{pid}/oom_score_adj w, + + # Per man(5) proc, the kernel enforces that a thread may only modify its comm + # value or those in its thread group. + owner @{PROC}/@{pid}/task/@{tid}/comm rw, + + @{PROC}/ r, @{PROC}/sys/fs/inotify/max_user_watches r, @{PROC}/sys/kernel/yama/ptrace_scope r, + @{PROC}/version r, + @{PROC}/version_signature r, owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/cmdline r, - owner @{PROC}/@{pid}/fd/ r, - owner @{PROC}/@{pid}/gid_map w, # If kernel.unprivileged_userns_clone = 1 - owner @{PROC}/@{pid}/mountinfo r, - owner @{PROC}/@{pid}/oom_score_adj rw, - owner @{PROC}/@{pid}/setgroups w, # If kernel.unprivileged_userns_clone = 1 - owner @{PROC}/@{pid}/stat r, - owner @{PROC}/@{pid}/statm r, - owner @{PROC}/@{pid}/task/ r, - owner @{PROC}/@{pid}/task/@{tid}/stat r, - owner @{PROC}/@{pid}/task/@{tid}/status r, - owner @{PROC}/@{pid}/uid_map w, # If kernel.unprivileged_userns_clone = 1 - deny @{user_share_dirs}/gvfs-metadata/* r, + profile crashpad_handler flags=(attach_disconnected) { + include + include + + signal send peer=@{name}, + + ptrace read peer=@{name}, + ptrace trace peer=@{name}, + + unix (send receive) type=seqpacket peer=(label=@{name}), + unix (send receive) type=seqpacket, # peer=(label=---), + + @{lib}/electron@{int}/chrome_crashpad_handler mr, + @{lib_dirs}/chrome_crashpad_handler mr, + + owner @{config_dirs}/Crashpad/{,**} rwk, + + @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_cur_freq r, + @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_max_freq r, + + @{PROC}/@{pid}/maps r, + @{PROC}/@{pid}/status r, + @{PROC}/sys/kernel/yama/ptrace_scope r, + owner @{PROC}/@{pid}/fd/ r, + owner @{PROC}/@{pid}/mem r, + owner @{PROC}/@{pid}/stat r, + owner @{PROC}/@{pid}/task/ r, + owner @{PROC}/@{pid}/task/@{tid}/comm r, + + deny network inet dgram, + deny network inet stream, + deny network inet6 dgram, + deny network inet6 stream, + + include if exists + } include if exists diff --git a/apparmor.d/abstractions/common/game b/apparmor.d/abstractions/common/game index 3b4a982f1e..29890148f1 100644 --- a/apparmor.d/abstractions/common/game +++ b/apparmor.d/abstractions/common/game @@ -1,46 +1,33 @@ # apparmor.d - Full set of apparmor profiles # Copyright (C) 2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only +# NEEDS-VARIABLE: user_games_dirs +# NEEDS-VARIABLE: system_games_dirs +# NEEDS-VARIABLE: XDG_GAMESSTUDIO_DIR -# Core set of resources for any games on Linux. Runtimes such as sandboxing, -# wine, proton, game launchers should use this abstraction. - +# Common set of locations for any games on Linux. Runtimes independants. +# # This abstraction uses the following tunables: -# - @{XDG_GAMESSTUDIO_DIR} for game studio and game engines specific directories -# (Default: @{XDG_GAMESSTUDIO_DIR}="unity3d") -# - @{user_games_dirs} for user specific game directories (eg: steam storage dir) +# +# - `@{XDG_GAMESSTUDIO_DIR}/` for game studio and game engines specific directories +# (Default: `@{XDG_GAMESSTUDIO_DIR}="unity3d"`) +# - `@{user_games_dirs}/` for user specific game directories (eg: steam storage dir) abi , - include - include - include - include - include - include - include - - @{bin}/uname rix, - @{bin}/xdg-settings rPx, - @{browsers_path} rPx, - - @{bin}/env r, - - @{lib}/ r, - / r, - /home/ r, - /usr/ r, - /usr/local/ r, - /usr/local/lib/ r, - - /etc/machine-id r, - /var/lib/dbus/machine-id r, - - owner @{HOME}/ r, + /var/ r, + /var/lib/ r, + @{system_games_dirs}/ r, + @{system_games_dirs}/*/ r, + @{system_games_dirs}/*/** mrix, + @{system_games_dirs}/*/**cache* w, owner @{user_games_dirs}/ r, owner @{user_games_dirs}/*/ r, - owner @{user_games_dirs}/*/** rwlk, + owner @{user_games_dirs}/*/** mrix, + owner @{user_games_dirs}/*/**cache* w, + + owner @{user_config_dirs}/MangoHud/MangoHud.conf r, owner @{user_config_dirs}/@{XDG_GAMESSTUDIO_DIR}/ rw, owner @{user_config_dirs}/@{XDG_GAMESSTUDIO_DIR}/** rwlk, @@ -48,71 +35,7 @@ owner @{user_share_dirs}/@{XDG_GAMESSTUDIO_DIR}/ rw, owner @{user_share_dirs}/@{XDG_GAMESSTUDIO_DIR}/** rwlk, - @{tmp}/ r, - owner @{tmp}/@{XDG_GAMESSTUDIO_DIR}/ rw, - owner @{tmp}/@{XDG_GAMESSTUDIO_DIR}/** rwlk, - owner @{tmp}/#@{int} rw, - owner @{tmp}/AsyncGPUReadbackPlugin_*.log w, owner @{tmp}/CASESENSITIVETEST@{hex32} rw, - owner @{tmp}/crashes/ rw, - owner @{tmp}/crashes/** rwk, - owner @{tmp}/miles_image_@{rand6} mrw, - owner @{tmp}/runtime-info.txt.@{rand6} rw, - owner @{tmp}/tmp@{rand6}.tmp rw, - owner @{tmp}/tmp@{rand6}@{h}.tmp rw, - owner @{tmp}/tmp@{rand8}.tmp rw, - owner @{tmp}/vdpau-drivers-@{rand6}/{,**} rw, - - owner /dev/shm/mono.@{int} rw, - owner /dev/shm/softbuffer-x11-@{rand6}@{c} rw, - - @{run}/udev/data/+input:input@{int} r, # for mouse, keyboard, touchpad - @{run}/udev/data/c13:@{int} r, # for /dev/input/* - - @{sys}/ r, - @{sys}/bus/ r, - @{sys}/class/ r, - @{sys}/class/hidraw/ r, - @{sys}/class/input/ r, - @{sys}/devices/ r, - @{sys}/devices/@{pci}/boot_vga r, - @{sys}/devices/@{pci}/net/*/carrier r, - @{sys}/devices/**/input@{int}/ r, - @{sys}/devices/**/input@{int}/**/{vendor,product} r, - @{sys}/devices/**/input@{int}/capabilities/* r, - @{sys}/devices/**/input/input@{int}/ r, - @{sys}/devices/**/uevent r, - @{sys}/devices/system/ r, - @{sys}/devices/system/clocksource/clocksource@{int}/current_clocksource r, - @{sys}/devices/system/cpu/cpu@{int}/ r, - @{sys}/devices/virtual/dmi/id/* r, - @{sys}/devices/virtual/net/*/carrier r, - @{sys}/kernel/ r, - - @{sys}/fs/cgroup/user.slice/cpu.max r, - @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/cpu.max r, - @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/cpu.max r, - owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/cpu.max r, - - @{PROC}/uptime r, - @{PROC}/version r, - owner @{PROC}/@{pid}/cgroup r, - owner @{PROC}/@{pid}/cmdline r, - owner @{PROC}/@{pid}/fd/ r, - owner @{PROC}/@{pid}/mounts r, - owner @{PROC}/@{pid}/pagemap r, - owner @{PROC}/@{pid}/stat r, - owner @{PROC}/@{pid}/task/ r, - owner @{PROC}/@{pid}/task/@{tid}/comm rw, - owner @{PROC}/@{pid}/task/@{tid}/stat r, - - /dev/ r, - /dev/hidraw@{int} rw, - /dev/input/ r, - /dev/input/event@{int} rw, - /dev/input/js@{int} rw, - /dev/tty rw, - /dev/uinput rw, include if exists diff --git a/apparmor.d/abstractions/common/gnome b/apparmor.d/abstractions/common/gnome index ccb5de8b3b..e27a307981 100644 --- a/apparmor.d/abstractions/common/gnome +++ b/apparmor.d/abstractions/common/gnome @@ -4,34 +4,39 @@ # Minimal set of rules for all gnome based UI application. +# !!! warning +# +# In the future, this abstraction could be generalized and renamed to `gui` +# + abi , - include - include - include include include include /usr/share/@{profile_name}/{,**} r, - / r, - owner @{user_cache_dirs}/@{profile_name}/ rw, - owner @{user_cache_dirs}/@{profile_name}/** rwlk -> @{user_cache_dirs}/@{profile_name}/**, + owner @{user_cache_dirs}/@{profile_name}/** rwlk, owner @{user_config_dirs}/@{profile_name}/ rw, - owner @{user_config_dirs}/@{profile_name}/** rwlk -> @{user_config_dirs}/@{profile_name}/**, + owner @{user_config_dirs}/@{profile_name}/** rwlk, owner @{user_share_dirs}/@{profile_name}/ rw, - owner @{user_share_dirs}/@{profile_name}/** rwlk -> @{user_share_dirs}/@{profile_name}/**, + owner @{user_share_dirs}/@{profile_name}/** rwlk, - @{sys}/fs/cgroup/user.slice/cpu.max r, - @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/cpu.max r, - @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/cpu.max r, - owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/cpu.max r, + owner @{user_state_dirs}/@{profile_name}/ rw, + owner @{user_state_dirs}/@{profile_name}/** rwlk, owner @{PROC}/@{pid}/cmdline r, + owner @{PROC}/@{pid}/cgroup r, + + # Provide statistical information about our own process + owner @{PROC}/@{pid}/stat r, + + # Per man(5) proc, the kernel enforces that a thread may only modify its comm + # value or those in its thread group. owner @{PROC}/@{pid}/task/@{tid}/comm rw, include if exists diff --git a/apparmor.d/abstractions/common/pressure-vessel b/apparmor.d/abstractions/common/pressure-vessel new file mode 100644 index 0000000000..8b8d39472b --- /dev/null +++ b/apparmor.d/abstractions/common/pressure-vessel @@ -0,0 +1,181 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no +# NEEDS-VARIABLE: att +# NEEDS-VARIABLE: steam_share_dirs +# NEEDS-VARIABLE: runtime_dirs + +# Pressure vessel abstraction, for games that are sandboxed in a similar way to +# Flatpak. It is used by steam and umu. +# +# It is assumed that profile including this abstraction wants to confine a game +# running sandboxed with bwrap. +# +# As Pressure vessel is architecturally very close to Flatpak, it is possible to +# use flatpak only abstractions (`abstractions/flatpak/...`) here. + + abi , + + # Base abstractions + include + include + include + include + include + include + + # The app base platform, similar to our desktop abstraction, but with flatpak paths + include + + # Base app specific rules + include + + # Flatpak devices + include + include + include + + # Flatpack share (IPC, network) + include + include + + # Flatpack sockets + include + include + + # Dbus: all dbus interfaces a pressure vessel app can access + # While close to flatpak, pressure-vessel does not use dbux-proxy. + include + include + include + include + + # Common to all @{lib}/pressure-vessel/from-host/libexec/steam-runtime-tools-@{int}/pv-adverb + @{sh_path} rix, + @{coreutils_path} ix, + @{bin}/getopt ix, + @{bin}/gzip ix, + @{bin}/localedef ix, + @{bin}/steam-runtime-launcher-interface-@{int} ix, + @{bin}/steam-runtime-system-info ix, + @{bin}/steam-runtime-urlopen ix, + @{bin}/xrandr ix, + @{bin}/zenity ix, + @{python_path} rix, + @{run}/host/@{bin}/localedef ix, + @{run}/host/@{sbin}/ldconfig ix, + @{sbin}/ldconfig ix, + + @{lib}/pressure-vessel/from-host/libexec/steam-runtime-tools-@{d}/** ix, + + @{att}@{steam_share_dirs}/compatibilitytools.d/ r, + @{att}@{steam_share_dirs}/compatibilitytools.d/*/ r, + @{att}@{steam_share_dirs}/compatibilitytools.d/*/** mrix, + @{steam_share_dirs}/compatibilitytools.d/ r, + @{steam_share_dirs}/compatibilitytools.d/*/ r, + @{steam_share_dirs}/compatibilitytools.d/*/** mrix, + @{steam_share_dirs}/compatibilitytools.d/*/**.msi k, + + @{runtime_dirs}/pressure-vessel/@{bin}/** ix, + @{runtime_dirs}/pressure-vessel/@{lib}/** mr, + + @{run}/host/@{lib}/**.dll m, + @{run}/host/@{lib}/**.so* m, + + /usr/share/zenity/{,**} r, + + @{run}/media/ r, + /mnt/ r, + owner / r, + owner @{lib}/ r, + owner /usr/local/lib/ r, + owner /usr/local/lib/**/ r, + owner @{HOME}/ r, + owner @{HOME}/.local/ r, + owner @{user_share_dirs}/ r, + + owner /var/cache/fontconfig/ rw, + owner /var/cache/fontconfig/** rwl, + owner /var/cache/ldconfig/aux-cache* rw, + owner /var/pressure-vessel/ldso/* rw, + + owner @{HOME}/.steam/steam.pid r, + owner @{HOME}/steam-@{int}.log rw, + + owner @{steam_share_dirs}/ r, + owner @{steam_share_dirs}/compatibilitytools.d/{,**/}__pycache__/ w, + owner @{steam_share_dirs}/compatibilitytools.d/{,**/}__pycache__/**.pyc.@{u64} w, + + owner @{runtime_dirs}/pressure-vessel/lib/@{multiarch}/steam-runtime-tools-0/libcap.so.2 mr, + owner @{runtime_dirs}/var/tmp-@{rand6}/.ref rw, + owner @{att}@{runtime_dirs}/var/tmp-@{rand6}/.ref rw, + + /tmp/ r, + owner /tmp/pressure-vessel-libs-@{rand6}/ rw, + owner /tmp/pressure-vessel-libs-@{rand6}/** rwlk, + owner /tmp/pressure-vessel-locales-@{rand6}/ rw, + owner /tmp/pressure-vessel-locales-@{rand6}/** rwlk, + + owner @{att}@{run}/user/@{uid}/bus rw, + owner @{att}@{run}/user/@{uid}/pulse/native rw, + + @{run}/host/usr/{,**} r, + owner @{run}/pressure-vessel/{,**} r, + + # The active clock source used by the kernel for timekeeping (e.g., tsc, hpet, acpi_pm) + @{sys}/devices/system/clocksource/clocksource@{int}/current_clocksource r, + + # The active CPU frequency scaling governor (e.g., performance, powersave, schedutil, ondemand) + @{sys}/devices/system/cpu/cpufreq/ r, + @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_governor r, + + # Allow to check check if BPF JIT is enabled + @{PROC}/sys/net/core/bpf_jit_enable r, + + # Allow to read system uptime + @{PROC}/uptime r, + + # Allow to read the maximum number of file handles that can be allocated system-wide. + @{PROC}/sys/fs/file-max r, + @{PROC}/sys/fs/file-nr r, + @{PROC}/sys/fs/nr_open r, + + # Allow reading cgroup membership information for process introspection + owner @{PROC}/@{pid}/cgroup r, + + # Allow reading command line arguments for process identification + owner @{PROC}/@{pid}/cmdline rk, + owner @{PROC}/@{pid}/comm rk, + + # Allow listing file descriptors + owner @{PROC}/@{pid}/fd/ r, + + # Allow reading file descriptor info + owner @{PROC}/@{pid}/fdinfo/ r, + owner @{PROC}/@{pid}/fdinfo/@{int} r, + + # Allow reading mount points for filesystem awareness. This is an information leak + owner @{PROC}/@{pid}/mountinfo r, + owner @{PROC}/@{pid}/mounts r, + + # Allow reading page mapping information for memory profiling + owner @{PROC}/@{pid}/pagemap r, + + # Per man(5) proc, the kernel enforces that a thread may only modify its comm + # value or those in its thread group. + owner @{PROC}/@{pid}/task/@{tid}/comm rw, + + # Provide statistical information about our own processes/threads + owner @{PROC}/@{pid}/stat r, + owner @{PROC}/@{pid}/task/ r, + owner @{PROC}/@{pid}/task/@{tid}/stat r, + + # Remain from `abstractions/flatpak/platform/org.freedesktop` not used outside flatpak. + deny /var/lib/flatpak/app/*/@{arch}/stable/@{hex64}/export/share/icons/{,**} r, + deny /var/lib/flatpak/exports/share/icons/{,**} r, + deny @{att}@{run}/user/@{uid}/.flatpak-helper/pkcs11-flatpak-@{int} rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/common/steam-game b/apparmor.d/abstractions/common/steam-game index b60e74a104..6ee0c21c94 100644 --- a/apparmor.d/abstractions/common/steam-game +++ b/apparmor.d/abstractions/common/steam-game @@ -1,10 +1,13 @@ # apparmor.d - Full set of apparmor profiles # Copyright (C) 2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only +# NEEDS-VARIABLE: app_dirs +# NEEDS-VARIABLE: lib_dirs +# NEEDS-VARIABLE: share_dirs abi , - include + include @{lib_dirs}/ r, diff --git a/apparmor.d/abstractions/common/systemd b/apparmor.d/abstractions/common/systemd index f4a10076ef..5a28be170e 100644 --- a/apparmor.d/abstractions/common/systemd +++ b/apparmor.d/abstractions/common/systemd @@ -3,11 +3,15 @@ # Copyright (C) 2021-2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only +# !!! warning +# +# This abstraction should only be used by profiles in the systemd software suite. +# + abi , - ptrace read peer=@{p_systemd}, + / r, - @{sys}/firmware/efi/efivars/SecureBoot-@{uuid} r, @{sys}/fs/cgroup/system.slice/@{profile_name}.service/ r, @{sys}/fs/cgroup/system.slice/@{profile_name}.service/memory.pressure rw, diff --git a/apparmor.d/abstractions/common/xdg b/apparmor.d/abstractions/common/xdg new file mode 100644 index 0000000000..e58836862f --- /dev/null +++ b/apparmor.d/abstractions/common/xdg @@ -0,0 +1,64 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + +# Minimal set of rules for XDG utilities like xdg-mime, xdg-settings, etc. + + abi , + + include + include + include + + #aa:only apparmor>=4.1 + priority=-1 @{sh_path} mrix, + + @{bin}/{,e}grep rix, + @{bin}/{m,g,}awk rix, + @{bin}/basename rix, + @{bin}/cat rix, + @{bin}/chmod rix, + @{bin}/cp rix, + @{bin}/cut rix, + @{bin}/dirname rix, + @{bin}/env rix, + @{bin}/file rix, + @{bin}/head rix, + @{bin}/ln rix, + @{bin}/mkdir rix, + @{bin}/mktemp rix, + @{bin}/mv rix, + @{bin}/readlink rix, + @{bin}/realpath rix, + @{bin}/rm rix, + @{bin}/sed rix, + @{bin}/sleep rix, + @{bin}/sort rix, + @{bin}/touch rix, + @{bin}/tr rix, + @{bin}/umask rix, + @{bin}/uname rix, + @{bin}/wc rix, + @{bin}/whoami rix, + + # To set/get DE information + @{bin}/gconftool{,-2} ix, + @{bin}/gio ix, + @{bin}/gnomevfs-info ix, + @{bin}/gvfs-info ix, + @{bin}/kde{,4}-config ix, + @{bin}/kfile ix, + @{bin}/kmimetypefinder{,5} ix, + @{bin}/ktraderclient{,5} ix, + @{bin}/kwriteconfig{,5,6} ix, + @{bin}/qtpaths ix, + @{bin}/qtxdg-mat ix, + + / r, + + @{PROC}/version r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/consoles.d/complete b/apparmor.d/abstractions/consoles.d/complete new file mode 100644 index 0000000000..b8b7ad90fe --- /dev/null +++ b/apparmor.d/abstractions/consoles.d/complete @@ -0,0 +1,8 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + # There are the common ways to refer to consoles + /dev/tty@{u8} rw, + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/contacts-service b/apparmor.d/abstractions/contacts-service new file mode 100644 index 0000000000..671df1688a --- /dev/null +++ b/apparmor.d/abstractions/contacts-service @@ -0,0 +1,123 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2018 Canonical Ltd +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow access to Evolution Data Service for contacts + + abi , + + # DBus.Properties: read properties from the interface + + dbus send bus=session path=/org/gnome/evolution/dataserver/SourceManager{,/**} + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(label=evolution-source-registry), + + dbus send bus=session path=/org/gnome/evolution/dataserver/AddressBook{,/**} + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(label=evolution-addressbook-factory), + + dbus send bus=session path=/org/gnome/evolution/dataserver/AddressBookFactory + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(label=evolution-addressbook-factory), + + dbus send bus=session path=/org/gnome/evolution/dataserver/AddressBookCursor{,/**} + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(label=evolution-addressbook-factory), + + dbus send bus=session path=/org/gnome/evolution/dataserver/AddressBookView{,/**} + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(label=evolution-addressbook-factory), + + dbus send bus=session path=/org/gnome/evolution/dataserver/Subprocess{,/**} + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(label=evolution-addressbook-factory), + + # DBus.Properties: receive property changed events + + # DBus.ObjectManager: allow clients to enumerate sources + + dbus send bus=session path=/org/gnome/evolution/dataserver{,/**} + interface=org.freedesktop.DBus.ObjectManager + member=GetManagedObjects + peer=(label=evolution-source-registry), + dbus receive bus=session path=/org/gnome/evolution/dataserver{,/**} + interface=org.freedesktop.DBus.ObjectManager + member={InterfacesAdded,InterfacesRemoved} + peer=(label=evolution-source-registry), + + dbus send bus=session path=/org/gnome/evolution/dataserver{,/**} + interface=org.freedesktop.DBus.ObjectManager + member=GetManagedObjects + peer=(label=evolution-addressbook-factory), + dbus receive bus=session path=/org/gnome/evolution/dataserver{,/**} + interface=org.freedesktop.DBus.ObjectManager + member={InterfacesAdded,InterfacesRemoved} + peer=(label=evolution-addressbook-factory), + + # DBus.Introspectable: allow clients to introspect the service + + dbus send bus=session path=/org/gnome/evolution/dataserver/SourceManager{,/**} + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(label=evolution-source-registry), + + dbus send bus=session path=/org/gnome/evolution/dataserver/AddressBook{,/**} + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(label=evolution-addressbook-factory), + + dbus send bus=session path=/org/gnome/evolution/dataserver/AddressBookFactory + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(label=evolution-addressbook-factory), + + dbus send bus=session path=/org/gnome/evolution/dataserver/AddressBookCursor{,/**} + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(label=evolution-addressbook-factory), + + dbus send bus=session path=/org/gnome/evolution/dataserver/AddressBookView{,/**} + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(label=evolution-addressbook-factory), + + # Allow access to methods + + dbus (send receive) bus=session path=/org/gnome/evolution/dataserver/SourceManager + interface=org.gnome.evolution.dataserver.SourceManager + peer=(label=evolution-source-registry), + + dbus (send receive) bus=session path=/org/gnome/evolution/dataserver/SourceManager{,/**} + interface=org.gnome.evolution.dataserver.Source + peer=(label=evolution-source-registry), + + dbus (send receive) bus=session path=/org/gnome/evolution/dataserver/SourceManager{,/**} + interface=org.gnome.evolution.dataserver.Source.Removable + peer=(label=evolution-source-registry), + + dbus (send receive) bus=session path=/org/gnome/evolution/dataserver/{Subprocess,AddressBook}{,/**} + interface=org.gnome.evolution.dataserver.AddressBook + peer=(label=evolution-addressbook-factory), + + dbus (send receive) bus=session path=/org/gnome/evolution/dataserver/AddressBookFactory + interface=org.gnome.evolution.dataserver.AddressBookFactory + peer=(label=evolution-addressbook-factory), + + dbus (send receive) bus=session path=/org/gnome/evolution/dataserver/AddressBookCursor{,/**} + interface=org.gnome.evolution.dataserver.AddressBookCursor + peer=(label=evolution-addressbook-factory), + + dbus (send receive) bus=session path=/org/gnome/evolution/dataserver/AddressBookView{,/**} + interface=org.gnome.evolution.dataserver.AddressBookView + peer=(label=evolution-addressbook-factory), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/crypto.d/complete b/apparmor.d/abstractions/crypto.d/complete index a163af66d8..8fb84d2611 100644 --- a/apparmor.d/abstractions/crypto.d/complete +++ b/apparmor.d/abstractions/crypto.d/complete @@ -4,7 +4,15 @@ include + # FIPS-140-2 versions of some crypto libraries need to access their + # associated integrity verification file, or they will abort. + @{lib}/.lib*.so*.hmac r, + @{lib}/@{multiarch}/.lib*.so*.hmac r, + @{etc_ro}/gnutls/config r, @{etc_ro}/gnutls/pkcs11.conf r, + # Used to determine if Linux is running in FIPS mode + @{PROC}/sys/crypto/fips_enabled r, + # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/dconf-write b/apparmor.d/abstractions/dconf-write index 3f25c66af6..ded7fd7496 100644 --- a/apparmor.d/abstractions/dconf-write +++ b/apparmor.d/abstractions/dconf-write @@ -8,9 +8,12 @@ abi , include - include + include - owner @{user_config_dirs}/glib-2.0/settings/keyfile w, + owner @{user_cache_dirs}/dconf/ w, + owner @{user_cache_dirs}/dconf/user w, + + owner @{user_config_dirs}/glib-2.0/settings/keyfile w, # When GSETTINGS_BACKEND=keyfile owner @{run}/user/@{uid}/dconf/ w, owner @{run}/user/@{uid}/dconf/user w, diff --git a/apparmor.d/abstractions/dconf.d/complete b/apparmor.d/abstractions/dconf.d/complete index b207e45391..b5aca50b74 100644 --- a/apparmor.d/abstractions/dconf.d/complete +++ b/apparmor.d/abstractions/dconf.d/complete @@ -3,8 +3,18 @@ # SPDX-License-Identifier: GPL-2.0-only /usr/share/dconf/profile/gdm r, + /usr/share/dconf/profile/gnome-initial-setup r, + /usr/share/gdm/greeter-dconf-defaults r, + /usr/share/gnome-initial-setup/initial-setup-dconf-defaults r, - owner @{user_config_dirs}/glib-2.0/settings/keyfile r, + @{DESKTOP_HOME}/greeter-dconf-defaults r, + + owner @{desktop_config_dirs}/dconf/user r, + + owner @{user_cache_dirs}/dconf/ r, + owner @{user_cache_dirs}/dconf/user r, + + owner @{user_config_dirs}/glib-2.0/settings/keyfile r, # When GSETTINGS_BACKEND=keyfile owner @{run}/user/@{uid}/dconf/ r, diff --git a/apparmor.d/abstractions/deny-sensitive-home b/apparmor.d/abstractions/deny-sensitive-home index 68c013a51d..d39c35e681 100644 --- a/apparmor.d/abstractions/deny-sensitive-home +++ b/apparmor.d/abstractions/deny-sensitive-home @@ -2,13 +2,14 @@ # Copyright (C) 2022-2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only -# DO NOT USE IT WITHOUT EXPLICIT AUTHORISATION FROM THE PROJECT MAINTAINER - # Per the first rule of this project: -# As these are mandatory access control policies only what it explicitly required -# should be authorized. Meaning, you should not allow everything (or a large area) -# and blacklist some sub area. - +# +# !!! quote +# +# As these are mandatory access control policies only what it explicitly required +# should be authorized. Meaning, you should not allow everything (or a large area) +# and blacklist some sub area. +# # The only legitimate use in this project is for file browser and search engine. abi , diff --git a/apparmor.d/abstractions/desktop b/apparmor.d/abstractions/desktop index 78a98a3cf8..1d7494b610 100644 --- a/apparmor.d/abstractions/desktop +++ b/apparmor.d/abstractions/desktop @@ -3,80 +3,51 @@ # SPDX-License-Identifier: GPL-2.0-only # Unified minimal abstraction for all UI application regardless of the desktop environment. - -# When supported in apparmor, condition will be used in this abstraction to filter -# resources specific for supported DE. +# +# !!! note +# +# When supported in apparmor, condition will be used in this abstraction to filter +# resources specific for supported DE. +# abi , - include - include - include + include + include + include + include + include #aa:only ubuntu + include + include + include + include + include + include + include + include + include + include + include + include include - include + include + include + include + include include include + # include - # if @{DE} == gnome - - dbus receive bus=session - interface=org.freedesktop.DBus.Introspectable - member=Introspect - peer=(name=@{busname}, label=gnome-shell), - - /usr/{local/,}share/ r, - /usr/{local/,}share/glib-@{version}/schemas/** r, - /usr/{local/,}share/gvfs/remote-volume-monitors/{,*} r, - - /etc/gnome/* r, - /etc/xdg/{,*-}mimeapps.list r, - - /var/cache/gio-@{version}/gnome-mimeapps.list r, - - / r, # deny? - - owner @{user_share_dirs}/gnome-shell/session.gvdb rw, - - # else if @{DE} == kde - - @{lib}/kde{,3,4}/*.so mr, - @{lib}/kde{,3,4}/plugins/*/ r, - @{lib}/kde{,3,4}/plugins/*/*.so mr, - - /usr/share/knotifications{5,6}/*.notifyrc r, - - /etc/xdg/baloofilerc r, - /etc/xdg/kcminputrc r, - /etc/xdg/kdeglobals r, - /etc/xdg/kwinrc r, - - owner @{user_cache_dirs}/#@{int} rw, - owner @{user_cache_dirs}/icon-cache.kcache rw, - owner @{user_cache_dirs}/ksycoca{5,6}_??{_,-}*.@{rand6} rwlk, - - owner @{user_config_dirs}/baloofilerc r, - owner @{user_config_dirs}/dolphinrc r, - owner @{user_config_dirs}/kcminputrc r, - owner @{user_config_dirs}/kdedefaults/ r, - owner @{user_config_dirs}/kdedefaults/kcminputrc r, - owner @{user_config_dirs}/kdedefaults/kdeglobals r, - owner @{user_config_dirs}/kdedefaults/kwinrc r, - owner @{user_config_dirs}/kdeglobals r, - owner @{user_config_dirs}/kwinrc r, - owner @{user_config_dirs}/trashrc r, - - # else if @{DE} == xfce - - /usr/share/xfce{,4}/ r, + # if "gnome" in @{DE} { + include if exists - owner @{user_config_dirs}/xfce4/help{,ers}.rc rw, - owner @{user_config_dirs}/xfce4/help{,ers}.rc.@{int}.tmp rw, + # } else if "kde" in @{DE} { + include if exists - # end + # } else if "xfce" in @{DE} { + include if exists - /usr/share/desktop-base/{,**} r, - /usr/share/hwdata/*.ids r, - /usr/share/icu/@{int}.@{int}/*.dat r, + # } include if exists diff --git a/apparmor.d/abstractions/desktop-base b/apparmor.d/abstractions/desktop-base new file mode 100644 index 0000000000..cdb362c2f3 --- /dev/null +++ b/apparmor.d/abstractions/desktop-base @@ -0,0 +1,19 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Base files required by any GUI on any desktop environment. +# +# It should only contain basic files required everywhere. It is intended to be +# included in desktop environment specific abstractions, and not directly in profiles. + + abi , + + /usr/share/desktop-base/{,**} r, + /usr/share/hwdata/*.ids r, + /usr/share/icu/@{int}.@{int}/*.dat r, + /usr/share/poppler/{,**} r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/desktop-files b/apparmor.d/abstractions/desktop-files new file mode 100644 index 0000000000..b56abdbe72 --- /dev/null +++ b/apparmor.d/abstractions/desktop-files @@ -0,0 +1,27 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2009 Canonical Ltd. +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + @{system_share_dirs}/applications/{,**} r, + @{system_share_dirs}/*ubuntu/applications/{,**} r, + @{system_share_dirs}/gnome/applications/{,**} r, + @{system_share_dirs}/xfce4/applications/{,**} r, + + @{etc_ro}/gnome/defaults.list r, + @{etc_ro}/xdg/menus/ r, + @{etc_ro}/xdg/menus/applications-merged/{,**} r, + @{etc_ro}/xfce4/defaults.list r, + + /var/lib/snapd/desktop/applications/{,**} r, + + owner @{user_share_dirs}/applications/{,**} r, + + owner @{user_config_dirs}/menus/ r, + owner @{user_config_dirs}/menus/applications-merged/{,**} r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/development b/apparmor.d/abstractions/development new file mode 100644 index 0000000000..a9ec261a94 --- /dev/null +++ b/apparmor.d/abstractions/development @@ -0,0 +1,111 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# NEEDS-VARIABLE: devtools + +# Allows access to various development tools such as compilers and, build tools etc. + + abi , + + include + include + include + include + include + include + include + include + + @{bin}/** rix, + @{sbin}/** rix, + @{HOME}/** ix, + @{lib}/** rix, + /opt/*/** ix, + /usr/local/bin/** ix, + /usr/local/lib/** ix, + /usr/share/** ix, + @{user_bin_dirs}/** ix, + + @{bin}/lsb_release Px, + @{bin}/nproc Px, + @{bin}/uptime Px, + @{bin}/w Px, + @{pager_path} Px -> child-pager, + + / r, + /usr/{,**} r, + /opt/{,**} r, + @{user_bin_dirs}/{,**} r, + + /etc/ r, + /etc/debuginfod/{,**} r, + /etc/gitconfig r, + /etc/inputrc r, + /etc/magic r, + /etc/shells r, + + owner @{HOME}/.gitconfig* r, + + owner @{HOME}/.local/ r, + owner @{user_lib_dirs}/ r, + + owner /dev/shm/sem.* rwl, + + owner @{tmp}/@{word8} rw, + owner @{tmp}/*tests*/ rw, + owner @{tmp}/*tests*/** mix, + owner @{tmp}/*tests*/** rwlk, + owner @{tmp}/cc@{rand6}* rw, + owner @{tmp}/GMfifo@{int} rw, + owner @{tmp}/tmp.@{rand10} rw, + owner @{tmp}/tmp@{word8}/ rw, + owner @{tmp}/tmp@{word8}/** rwlk, + owner /var/tmp/@{word8} rw, + + # Git + owner @{tmp}/.git_vtag_tmp@{rand6} rw, # For git log --show-signature + owner @{tmp}/git-commit-msg-.txt rw, # For android studio + owner @{tmp}/git-difftool.*/{,**} rw, # For diffs + owner @{tmp}/git-index-private@{int} rw, + + @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_cur_freq r, + @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_max_freq r, + + # Memory usage in pages (total, resident, shared, text, data) + @{PROC}/@{pid}/statm r, + + # Get kernel version string + @{PROC}/sys/kernel/osrelease r, + + # Kernel version + @{PROC}/version r, + @{PROC}/version_signature r, + + # Allow reading command line arguments for process identification + owner @{PROC}/@{pid}/cmdline r, + owner @{PROC}/@{pid}/comm r, + + # Allow reading our own environment variables + owner @{PROC}/@{pid}/environ r, + + # Allow listing file descriptors for resource monitoring + owner @{PROC}/@{pid}/fd/ r, + owner @{PROC}/@{pid}/fd/@{int} rw, + + # Allow reading mount points for filesystem awareness. This is an information leak + owner @{PROC}/@{pid}/mountinfo r, + owner @{PROC}/@{pid}/mounts r, + + # Per man(5) proc, the kernel enforces that a thread may only modify its comm + # value or those in its thread group. + owner @{PROC}/@{pid}/task/@{tid}/comm rw, + + # Provide statistical information about our own processes/threads + owner @{PROC}/@{pid}/stat r, + owner @{PROC}/@{pid}/task/ r, + owner @{PROC}/@{pid}/task/@{tid}/stat r, + owner @{PROC}/@{pid}/task/@{tid}/statm r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/devices-u2f b/apparmor.d/abstractions/devices-u2f new file mode 100644 index 0000000000..8ae8dccdc9 --- /dev/null +++ b/apparmor.d/abstractions/devices-u2f @@ -0,0 +1,28 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2019 Canonical Ltd +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allows access to Universal 2nd Factor (U2F) devices + + abi , + + @{run}/udev/data/+power_supply:* r, # For power supply devices (batteries, AC adapters, USB chargers) + + # Needed for dynamic assignment of U2F devices + @{run}/udev/data/c@{dynamic}:@{int} r, # For dynamic assignment range 234 to 254, 384 to 511 + + @{sys}/ r, + @{sys}/bus/ r, + @{sys}/class/ r, + @{sys}/class/hidraw/ r, + @{sys}/class/hidraw/hidraw@{int} r, + @{sys}/devices/**/i2c*/**/report_descriptor r, + @{sys}/devices/**/usb@{int}/**/report_descriptor r, + + # Allow raw access HDI (Human Interface Devices) wich is how U2F devices are exposed + /dev/hidraw@{int} rwk, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/devices-usb b/apparmor.d/abstractions/devices-usb index 85f8f6b92e..3361f10ec2 100644 --- a/apparmor.d/abstractions/devices-usb +++ b/apparmor.d/abstractions/devices-usb @@ -3,13 +3,22 @@ # Copyright (C) 2021-2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only +# Allow raw access to all connected USB devices + abi , include - /dev/bus/usb/@{int}/@{int} wk, + @{PROC}/tty/drivers r, + + /dev/bus/usb/@{d}@{d}@{d}/@{d}@{d}@{d} wk, + + # Allow access to all ttyUSB devices too + /dev/ttyACM@{int} wk, + /dev/ttyUSB@{int} wk, - @{sys}/devices/**/usb@{int}/{,**} w, + # Allow raw access to USB printers (i.e. for receipt printers in POS systems). + /dev/usb/lp@{int} wk, include if exists diff --git a/apparmor.d/abstractions/devices-usb-read b/apparmor.d/abstractions/devices-usb-read index 6bd0c80150..48ac000d7a 100644 --- a/apparmor.d/abstractions/devices-usb-read +++ b/apparmor.d/abstractions/devices-usb-read @@ -3,26 +3,44 @@ # Copyright (C) 2021-2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only - abi , +# Allow detection of usb devices. Leaks plugged in USB device info - /dev/ r, - /dev/bus/usb/ r, - /dev/bus/usb/@{int}/ r, - /dev/bus/usb/@{int}/@{int} r, + abi , @{sys}/class/ r, @{sys}/class/usbmisc/ r, @{sys}/bus/ r, @{sys}/bus/usb/ r, - @{sys}/bus/usb/devices/{,**} r, - - @{sys}/devices/**/usb@{int}/{,**} r, + @{sys}/bus/usb/devices/ r, + @{sys}/devices/**/uevent r, + @{sys}/devices/**/usb@{int}/ r, + + @{sys}/devices/**/usb@{int}/{,**/}bcdDevice r, + @{sys}/devices/**/usb@{int}/{,**/}bConfigurationValue r, + @{sys}/devices/**/usb@{int}/{,**/}bInterfaceNumber r, + @{sys}/devices/**/usb@{int}/{,**/}busnum r, + @{sys}/devices/**/usb@{int}/{,**/}descriptors r, + @{sys}/devices/**/usb@{int}/{,**/}devnum r, + @{sys}/devices/**/usb@{int}/{,**/}idProduct r, + @{sys}/devices/**/usb@{int}/{,**/}idVendor r, + @{sys}/devices/**/usb@{int}/{,**/}manufacturer r, + @{sys}/devices/**/usb@{int}/{,**/}modalias r, + @{sys}/devices/**/usb@{int}/{,**/}product r, + @{sys}/devices/**/usb@{int}/{,**/}removable r, + @{sys}/devices/**/usb@{int}/{,**/}serial r, + @{sys}/devices/**/usb@{int}/{,**/}speed r, # Udev data about usb devices (~equal to content of lsusb -v) - @{run}/udev/data/+usb:* r, - @{run}/udev/data/c16[6,7]:@{int} r, # USB modems - @{run}/udev/data/c18[0,8,9]:@{int} r, # USB devices & USB serial converters + @{run}/udev/data/+usb:* r, # Identifies all USB devices + @{run}/udev/data/b180:@{int} r, # USB block devices + @{run}/udev/data/c16{6,7}:@{d} r, # ACM USB modems + @{run}/udev/data/c18{0,8,9}:@{int} r, # USB character devices + + /dev/ r, + /dev/bus/usb/ r, + /dev/bus/usb/@{int}/ r, + /dev/bus/usb/@{d}@{d}@{d}/@{d}@{d}@{d} r, include if exists diff --git a/apparmor.d/abstractions/devrun b/apparmor.d/abstractions/devrun new file mode 100644 index 0000000000..e408efb001 --- /dev/null +++ b/apparmor.d/abstractions/devrun @@ -0,0 +1,34 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# NEEDS-VARIABLE: devtools + +# Well known programs used in various development shells. Only programs that are +# safe to allow running from a shell dev environment are allowed here. Profile +# must exist, and may have more permissions than the shell it is coming from. + + abi , + + @{bin}/aa-log Px, + @{bin}/claude Px, + @{bin}/docker Px, + @{bin}/dpkg-query Px, + @{bin}/git Px, + @{bin}/htop Px, + @{bin}/ip Px, + @{bin}/journalctl Px, + @{bin}/lscpu Px, + @{bin}/man Px, + @{bin}/podman Px, + @{bin}/ps Px, + @{bin}/ssh Px, + @{bin}/top Px, + + # Well known shells tools + @{bin}/starship PUx, + priority=1 @{user_cache_dirs}/gitstatus/gitstatusd{,-*} Px, + priority=1 /usr/share/zsh-theme-powerlevel{9,10}k/gitstatus/usrbin/gitstatusd{,-*} Px, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/devtools b/apparmor.d/abstractions/devtools new file mode 100644 index 0000000000..b052b31966 --- /dev/null +++ b/apparmor.d/abstractions/devtools @@ -0,0 +1,59 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# NEEDS-VARIABLE: devtools + +# Allows common file for various development tools. This abstraction is meant +# to be included in profiles of development tools only. +# +# It does not aims at allowing execution of development tools, only file access. +# The tools are defined in the `@{devtools}` variable. +# + + abi , + + /usr/share/*@{devtools}*/ r, + /usr/share/*@{devtools}*/** r, + + /etc/*@{devtools}*/ r, + /etc/*@{devtools}*/** r, + + owner @{HOME}/.*@{devtools}* rw, + owner @{HOME}/.*@{devtools}*/ rw, + owner @{HOME}/.*@{devtools}*/** rwlk, + owner @{HOME}/.*@{devtools}*/** mix, + + owner @{HOME}/*@{devtools}*/ rw, + owner @{HOME}/*@{devtools}*/** rwlk, + owner @{HOME}/.*@{devtools}*/** mix, + + owner @{user_lib_dirs}/ r, + owner @{user_lib_dirs}/*@{devtools}*/ rw, + owner @{user_lib_dirs}/*@{devtools}*/** rwlk, + + owner @{user_cache_dirs}/ r, + owner @{user_cache_dirs}/*@{devtools}*/ rw, + owner @{user_cache_dirs}/*@{devtools}*/** rwlk, + + owner @{user_config_dirs}/ r, + owner @{user_config_dirs}/*@{devtools}*/ rw, + owner @{user_config_dirs}/*@{devtools}*/** rwlk, + + owner @{user_share_dirs}/ r, + owner @{user_share_dirs}/*@{devtools}*/ rw, + owner @{user_share_dirs}/*@{devtools}*/** rwlk, + + owner @{user_state_dirs}/ r, + owner @{user_state_dirs}/*@{devtools}*/ rw, + owner @{user_state_dirs}/*@{devtools}*/** rwlk, + + /tmp/ r, + owner @{tmp}/ r, + owner @{tmp}/*@{devtools}* rw, + owner @{tmp}/*@{devtools}*/ rw, + owner @{tmp}/*@{devtools}*/** rwlk, + owner @{tmp}/*@{devtools}*/** mix, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/disks-read b/apparmor.d/abstractions/disks-read index 62e24b70df..1e4f35a51b 100644 --- a/apparmor.d/abstractions/disks-read +++ b/apparmor.d/abstractions/disks-read @@ -3,7 +3,7 @@ # Copyright (C) 2022-2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only - # The /sys/ entries probably should be tightened + # The `/sys/` entries probably should be tightened abi , @@ -17,7 +17,6 @@ @{sys}/devices/@{pci}/ata@{int}/** r, @{sys}/devices/@{pci}/block/{s,v}d[a-z]/ r, @{sys}/devices/@{pci}/block/{s,v}d[a-z]/** r, - @{sys}/devices/@{pci}/host@{int}/** r, @{sys}/devices/@{pci}/usb@{int}/** r, @{sys}/devices/@{pci}/virtio@{int}/** r, @{sys}/devices/**/host@{int}/** r, @@ -44,6 +43,12 @@ @{sys}/devices/virtual/block/loop@{int}/ r, @{sys}/devices/virtual/block/loop@{int}/** r, + # Xen PVH devices + @{sys}/devices/vbd-@{int}/block/** r, + + # Channel subsystem for IBM Z + @{sys}/devices/css@{int}/** r, + # LUKS/LVM (device-mapper) devices /dev/dm-@{int} rk, /dev/mapper/{,*} r, @@ -75,27 +80,34 @@ # CD-ROM /dev/sr@{int} rk, + # MD RAID devices + /dev/md@{int} rk, + @{sys}/devices/virtual/block/md@{int}/ r, + @{sys}/devices/virtual/block/md@{int}/** r, + # Lookup block device by major:minor numbers # See: https://apparmor.pujol.io/development/internal/#udev-rules @{sys}/block/ r, @{sys}/class/block/ r, + @{sys}/class/iscsi_session/ r, @{sys}/dev/block/ r, @{run}/udev/data/b2:@{int} r, # for /dev/fd* @{run}/udev/data/b7:@{int} r, # for /dev/loop* @{run}/udev/data/b8:@{int} r, # for /dev/sd* + @{run}/udev/data/b9:@{int} r, # for /dev/md* @{run}/udev/data/b11:@{int} r, # for /dev/sr* @{run}/udev/data/b43:@{int} r, # for /dev/nbd* @{run}/udev/data/b179:@{int} r, # for /dev/mmcblk* @{run}/udev/data/b230:@{int} r, # for /dev/zvol* - @{run}/udev/data/b24[0-9]:@{int} r, # for dynamic assignment range 240 to 254 - @{run}/udev/data/b25[0-4]:@{int} r, + @{run}/udev/data/b24[0-9]:@{int} r, # for dynamic assignment range 240 + @{run}/udev/data/b25[0-4]:@{int} r, # to 254 @{run}/udev/data/b259:@{int} r, # Block Extended Major @{run}/udev/data/c189:@{int} r, # for /dev/bus/usb/** - @{run}/udev/data/+usb:* r, # for disk over usb hub + @{run}/udev/data/+usb:* r, # Identifies all USB devices include if exists diff --git a/apparmor.d/abstractions/disks-write b/apparmor.d/abstractions/disks-write index ce0a05dd53..a525180422 100644 --- a/apparmor.d/abstractions/disks-write +++ b/apparmor.d/abstractions/disks-write @@ -41,6 +41,9 @@ # CD-ROM /dev/sr@{int} w, + # MD RAID devices + /dev/md@{int} w, + include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/dri b/apparmor.d/abstractions/dri index dd8f7b55ac..1da420da5a 100644 --- a/apparmor.d/abstractions/dri +++ b/apparmor.d/abstractions/dri @@ -17,6 +17,9 @@ /etc/drirc r, + @{run}/udev/data/c226:@{int} r, # For DRI card /dev/dri/card@{int} + + @{sys}/devices/@{pci}/boot_vga r, @{sys}/devices/@{pci}/class r, @{sys}/devices/@{pci}/config r, @{sys}/devices/@{pci}/device r, @@ -28,8 +31,14 @@ @{sys}/devices/@{pci}/uevent r, @{sys}/devices/@{pci}/vendor r, + @{sys}/devices/@{pci}/drm/card@{int}/*/status r, + @{sys}/devices/@{pci}/gpu_metrics r, + + # Allow access to all cards /dev/dri/ r, /dev/dri/card@{int} rw, + + # Video Acceleration API /dev/dri/renderD128 rw, /dev/dri/renderD129 rw, diff --git a/apparmor.d/abstractions/fish b/apparmor.d/abstractions/fish index 2ae6ab93d3..390a4c894e 100644 --- a/apparmor.d/abstractions/fish +++ b/apparmor.d/abstractions/fish @@ -2,16 +2,18 @@ # Copyright (C) 2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only -# This abstraction is only required when an interactive shell is started. +# This abstraction is only required when zshrc is loaded (e.g. interactive shell). # Classic shell scripts do not need it. abi , /usr/share/fish/{,**} r, + /usr/share/*-fish-config//{,**} r, /etc/fish/{,**} r, - owner @{user_config_dirs}/fish/{,**} r, + owner @{user_config_dirs}/fish/ rk, + owner @{user_config_dirs}/fish/** r, include if exists diff --git a/apparmor.d/abstractions/flatpak/base b/apparmor.d/abstractions/flatpak/base new file mode 100644 index 0000000000..6d3e443821 --- /dev/null +++ b/apparmor.d/abstractions/flatpak/base @@ -0,0 +1,255 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no +# NEEDS-VARIABLE: appid +# NEEDS-VARIABLE: att +# NEEDS-VARIABLE: profile_dbus + +# attach_disconnected: tweak the build system to replace attached abstractions + + abi , + + include + include + + capability dac_override, + capability dac_read_search, + + signal receive set=(int term) peer=flatpak-portal, + signal receive set=(int term) peer=flatpak//bwrap, + + unix (send receive) type=seqpacket peer=(label=@{profile_dbus}), + unix (send receive) type=seqpacket peer=(label=dbus-session), + unix (send receive) type=seqpacket peer=(label=flatpak-portal), + unix (send receive) type=seqpacket peer=(label=flatpak), + unix (send receive) type=seqpacket peer=(label=flatpak//bwrap), + unix (send receive) type=stream peer=(label=@{profile_dbus}), + unix (send receive) type=stream peer=(label=dbus-session), + unix (send receive) type=stream peer=(label=flatpak-portal), + unix (send receive) type=stream peer=(label=flatpak), + unix (send receive) type=stream peer=(label=flatpak//bwrap), + + # Run in the flatpak sandbox, the app + /app/ rk, + /app/** mrkix, + + # Run in the flatpak sandbox, the app runtime + @{bin}/ r, + @{bin}/** rix, + @{lib}/ r, + @{lib}/** rix, + @{sbin}/ r, + @{sbin}/** rix, + + # Core directory of the flatpak platform runtime + / r, + /usr/ r, + + /etc/timezone r, + /etc/machine-id r, + /var/lib/dbus/machine-id r, + + owner /.flatpak-info r, + + # In the sandbox, they are the same than ~/.var/app/@{appid}/{cache,config,data,cache/tmp} + #aa:lint ignore=too-wide + owner /var/ r, + owner /var/cache/ r, + owner /var/cache/** rwlk, + owner /var/config/ r, + owner /var/config/** rwlk, + owner /var/data/ r, + owner /var/data/** rwlk, + owner /var/tmp/ r, + owner /var/tmp/** rwlk, + + owner /home/ r, + + owner @{att}@{HOME}/ r, + owner @{att}@{HOME}/.var/app/@{appid}/ r, + owner @{att}@{HOME}/.var/app/@{appid}/** mrwlk, + + owner @{HOME}/.var/ w, + owner @{HOME}/.var/app/ w, + owner @{HOME}/.var/app/@{appid}/ rw, + owner @{HOME}/.var/app/@{appid}/** mrwlk -> @{HOME}/.var/app/@{appid}/**, + owner @{HOME}/.var/app/@{appid}/** ix, + + @{run}/parent/** mrix, + + owner @{run}/flatpak/app/@{appid}/ r, + owner @{run}/flatpak/app/@{appid}/** mrwlk -> @{run}/flatpak/app/@{appid}/**, + owner @{att}@{run}/flatpak/app/@{appid}/ r, + owner @{att}@{run}/flatpak/app/@{appid}/** mrwlk, + + owner @{run}/flatpak/doc/ r, + owner @{run}/flatpak/doc/** mrw, + owner @{run}/flatpak/ld.so.conf.d/ r, + owner @{run}/flatpak/ld.so.conf.d/*.conf r, + + owner @{run}/user/@{uid}/app/@{appid}/ r, + owner @{run}/user/@{uid}/app/@{appid}/** rwlk -> @{run}/user/@{uid}/app/@{appid}/**, + + owner @{att}@{run}/user/@{uid}/.dbus-proxy/a11y-bus-proxy-@{rand6} rw, + owner @{att}@{run}/user/@{uid}/.dbus-proxy/session-bus-proxy-@{rand6} rw, + owner @{att}@{run}/user/@{uid}/.dbus-proxy/system-bus-proxy-@{rand6} rw, + + @{run}/host/os-release r, + owner @{run}/host/ r, + owner @{run}/host/container-manager r, + + #aa:lint ignore=too-wide + # Flatpak creates an app-specific private restricted /tmp. As such, we can + # simply allow full access to /tmp. + /tmp/ r, + owner /tmp/** mrwlkix, + @{att}/tmp/ r, + owner @{att}/tmp/** mrwlkix, + + @{sys}/devices/system/cpu/kernel_max r, + + # Show the list of active tty + @{sys}/devices/virtual/tty/tty@{int}/active r, + + # List processes in /proc + @{PROC}/ r, + + # Which CPUs/memory nodes the process is assigned to + @{PROC}/@{pid}/cpuset r, + + # I/O statistics (bytes read/written) + @{PROC}/@{pid}/io r, + + # Memory mappings (addresses, permissions, mapped files) + @{PROC}/@{pid}/maps r, + + # Process status in one line (pid, state, ppid, CPU time, threads, etc.) + @{PROC}/@{pid}/stat r, + + # Memory usage in pages (total, resident, shared, text, data) + @{PROC}/@{pid}/statm r, + + # Human-readable process status (name, state, UIDs, memory, capabilities) + @{PROC}/@{pid}/status r, + + # Human-readable thread status + @{PROC}/@{pid}/task/@{tid}/status r, + + # Uptime + @{PROC}/uptime r, + @{PROC}/loadavg r, + + # Allow to read the maximum number of file handles that can be allocated system-wide. + @{PROC}/sys/fs/file-max r, + @{PROC}/sys/fs/file-nr r, + @{PROC}/sys/fs/nr_open r, + + # Limits for how many inotify instances, watches, and pending events a user can have. + @{PROC}/sys/fs/inotify/max_queued_events r, + @{PROC}/sys/fs/inotify/max_user_instances r, + @{PROC}/sys/fs/inotify/max_user_watches r, + + # Maximum size that an unprivileged process can set for a pipe buffer + @{PROC}/sys/fs/pipe-max-size r, + + # Get the system hostname + @{PROC}/sys/kernel/hostname r, + + # Get kernel version string + @{PROC}/sys/kernel/osrelease r, + + # Get OS type (always Linux) + @{PROC}/sys/kernel/ostype r, + + # Maximum PID value the kernel will assign + @{PROC}/sys/kernel/pid_max r, + + # Unique UUID generated each boot, used to identify the current boot session + @{PROC}/sys/kernel/random/boot_id r, + + # Get the amount of available entropy in the kernel's random pool + @{PROC}/sys/kernel/random/entropy_avail r, + + # Generates a fresh random UUID each time it's read + @{PROC}/sys/kernel/random/uuid r, + + # Maximum size of a single shared memory segment + @{PROC}/sys/kernel/shmmax r, + + # Get the ptrace restrictions level + @{PROC}/sys/kernel/yama/ptrace_scope r, + + # Allow to check check if BPF JIT is enabled + @{PROC}/sys/net/core/bpf_jit_enable r, + + # Kernel version + @{PROC}/version r, + @{PROC}/version_signature r, + + # Information about memory zones (DMA, Normal, HighMem) including free pages, + # watermarks, and per-CPU page counts. + @{PROC}/zoneinfo r, + + # Allow reading cgroup membership information for process introspection + owner @{PROC}/@{pid}/cgroup r, + + # Clearing the referenced bits in a process's page table entries provides a method to + # measure approximately how much memory a process is using. + owner @{PROC}/@{pid}/clear_refs w, + + # Allow reading command line arguments for process identification + owner @{PROC}/@{pid}/cmdline rk, + owner @{PROC}/@{pid}/comm rk, + + # Allow reading our own environment variables + owner @{PROC}/@{pid}/environ r, + + # Allow listing file descriptors + @{PROC}/@{pid}/fd/ r, + owner @{PROC}/@{pid}/fd/ r, + + # Allow reading file descriptor info + owner @{PROC}/@{pid}/fdinfo/ r, + owner @{PROC}/@{pid}/fdinfo/@{int} r, + + # Shows the process's current resource limits (soft/hard), the ulimit value. + owner @{PROC}/@{pid}/limits r, + + # Show the loginuid and sessionid of the process, which can be used for auditing and debugging. + owner @{PROC}/@{pid}/loginuid r, + owner @{PROC}/@{pid}/sessionid r, + + # Allow reading mount points for filesystem awareness. This is an information leak + owner @{PROC}/@{pid}/mountinfo r, + owner @{PROC}/@{pid}/mounts r, + + # Reads of oom_adj and oom_score_adj are safe + owner @{PROC}/@{pid}/oom_adj r, + owner @{PROC}/@{pid}/oom_score_adj r, + + # This allows raising the OOM score of other processes owned by the user. + owner @{PROC}/@{pid}/oom_score_adj w, + + # Allow reading of smaps_rollup, which is a summary of the memory use of a process + @{PROC}/@{pid}/smaps r, + owner @{PROC}/@{pid}/smaps_rollup r, + + # Per man(5) proc, the kernel enforces that a thread may only modify its comm + # value or those in its thread group. + owner @{PROC}/@{pid}/task/@{tid}/comm rw, + + # Provide statistical information about our own processes/threads + owner @{PROC}/@{pid}/task/ r, + owner @{PROC}/@{pid}/task/@{tid}/smaps r, + owner @{PROC}/@{pid}/task/@{tid}/stat r, + owner @{PROC}/@{pid}/task/@{tid}/statm r, + owner @{PROC}/@{pid}/task/@{tid}/status r, + + # Allow setting up pseudoterminal via /dev/pts system. This is safe because + # flatpak uses a per-app devpts. + /dev/ptmx rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/baseapp/com.valvesoftware.Steam b/apparmor.d/abstractions/flatpak/baseapp/com.valvesoftware.Steam new file mode 100644 index 0000000000..bf9ad29d67 --- /dev/null +++ b/apparmor.d/abstractions/flatpak/baseapp/com.valvesoftware.Steam @@ -0,0 +1,43 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + + abi , + + include + include + + @{lib}/os-release rk, + + owner @{run}/user/@{uid}/ r, + owner @{run}/user/@{uid}/discord-ipc-@{int} w, + + owner /dev/shm/#@{int} rw, + owner /dev/shm/fossilize-*-@{int}-@{int} rw, + owner /dev/shm/u@{uid}-Shm_@{hex6} rw, + owner /dev/shm/u@{uid}-Shm_@{hex6}@{h} rw, + owner /dev/shm/u@{uid}-Shm_@{hex8} rw, + owner /dev/shm/u@{uid}-ValveIPCSharedObj-Steam rwk, + + owner @{att}/dev/shm/ValveIPCSHM_@{uid} rw, + owner /dev/shm/ValveIPCSHM_@{uid} rw, + + @{sys}/devices/system/clocksource/clocksource@{int}/current_clocksource r, + @{sys}/devices/virtual/dmi/id/board_name r, + + # Pressure Stall Information interface + @{PROC}/pressure/cpu r, + @{PROC}/pressure/io r, + @{PROC}/pressure/memory r, + + # Allow reading command line arguments for process identification + @{PROC}/@{pids}/comm rk, + + @{PROC}/locks r, + @{PROC}/sys/kernel/sched_autogroup_enabled r, + owner @{PROC}/@{pid}/autogroup rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/baseapp/org.chromium.Chromium b/apparmor.d/abstractions/flatpak/baseapp/org.chromium.Chromium new file mode 100644 index 0000000000..a7c392b741 --- /dev/null +++ b/apparmor.d/abstractions/flatpak/baseapp/org.chromium.Chromium @@ -0,0 +1,37 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no +# NEEDS-VARIABLE: appid + + abi , + + include + + /dev/shm/ r, + owner /dev/shm/.@{appid}.@{rand6} rw, + owner /dev/shm/.org.chromium.Chromium.@{rand6} rw, + + @{sys}/devices/**/usb@{int}/{,*/}bConfigurationValue r, + @{sys}/devices/**/usb@{int}/{,*/}descriptors r, + @{sys}/devices/**/usb@{int}/{,*/}manufacturer r, + @{sys}/devices/**/usb@{int}/{,*/}product r, + @{sys}/devices/**/usb@{int}/{,*/}serial r, + @{sys}/devices/**/usb@{int}/{,*/}vendor r, + @{sys}/devices/system/cpu/kernel_max r, + + # Allow getting the manufacturer and model of the computer where chromium is currently running. + @{sys}/devices/virtual/dmi/id/product_name r, + @{sys}/devices/virtual/dmi/id/sys_vendor r, + + # Pressure Stall Information interface + @{PROC}/pressure/cpu r, + @{PROC}/pressure/io r, + @{PROC}/pressure/memory r, + + # Chromium content api unfortunately needs these for normal operation + owner @{PROC}/@{pid}/fd/@{int} w, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/baseapp/org.mozilla.firefox b/apparmor.d/abstractions/flatpak/baseapp/org.mozilla.firefox new file mode 100644 index 0000000000..f6e29fb1ee --- /dev/null +++ b/apparmor.d/abstractions/flatpak/baseapp/org.mozilla.firefox @@ -0,0 +1,24 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + + abi , + + /dev/shm/ r, + owner /dev/shm/org.chromium.@{rand6} rw, + owner /dev/shm/org.mozilla.ipc.@{pid}.@{int} rw, + owner /dev/shm/wayland.mozilla.ipc.@{int} rw, + + # Allow getting the manufacturer and model of the computer where firefox is currently running. + @{sys}/devices/virtual/dmi/id/product_name r, + @{sys}/devices/virtual/dmi/id/sys_vendor r, + + # Pressure Stall Information interface + @{PROC}/pressure/cpu r, + @{PROC}/pressure/io r, + @{PROC}/pressure/memory r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/baseapp/org.winehq.Wine b/apparmor.d/abstractions/flatpak/baseapp/org.winehq.Wine new file mode 100644 index 0000000000..5fa05619f6 --- /dev/null +++ b/apparmor.d/abstractions/flatpak/baseapp/org.winehq.Wine @@ -0,0 +1,37 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + + abi , + + include + + owner /tmp/.wine-@{uid}/ rw, + owner /tmp/.wine-@{uid}/server-*/ rw, + owner /tmp/.wine-@{uid}/server-*/lock rwk, + owner /tmp/.wine-@{uid}/server-*/socket rw, + owner /tmp/.wine-@{uid}/server-*/tmpmap-@{hex8} mrw, + owner @{att}/tmp/.wine-@{uid}/server-*/socket rw, + + owner /tmp/@{word8} rw, + owner /tmp/protonfixes_test.log w, + owner /tmp/protonfixes-gtk-@{word8}/{,**} rw, + + owner @{run}/user/@{uid}/pressure-vessel/ r, + owner @{run}/user/@{uid}/pressure-vessel/{,**} rw, + owner @{run}/user/@{uid}/srt-fifo.@{rand6}/{,*} rw, + + owner /dev/shm/wine-@{hex6}-fsync rw, + owner /dev/shm/wine-@{hex6}@{h}-fsync rw, + + owner /dev/shm/mono.@{int} rw, + owner /dev/shm/softbuffer-x11-@{rand6}@{c} rw, + + # NT synchronization driver (performance improvement for games) + # https://www.phoronix.com/news/Linux-6.14-NTSYNC-Driver-Ready + /dev/ntsync r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/devices/all b/apparmor.d/abstractions/flatpak/devices/all new file mode 100644 index 0000000000..5d7a561151 --- /dev/null +++ b/apparmor.d/abstractions/flatpak/devices/all @@ -0,0 +1,48 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + +# Flatpack `all` devices gives full access to the system. +# To limit this, we explicitly list the devices allowed, using the abstractions +# for common devices. +# +# As it may lead to issues, a future implementation will leverage apparmor prompts +# to request access to devices on demand. + + abi , + + include + include + include + include + + include + include + include + include + + include + + @{sys}/class/*/ r, + @{sys}/bus/*/devices/ r, + + @{sys}/devices/ r, + @{sys}/devices/@{pci_bus}/ r, + @{sys}/devices/@{pci}/ r, + @{sys}/devices/** k, + + @{sys}/devices/system/cpu/cpufreq/ r, + @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_governor rw, + + owner @{PROC}/@{pid}/uid_map r, + + # Allow reading info about the physical mapping of virtual pages + owner @{PROC}/@{pid}/mem r, + owner @{PROC}/@{pids}/pagemap r, + + /dev/udmabuf rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/devices/dri b/apparmor.d/abstractions/flatpak/devices/dri new file mode 100644 index 0000000000..3b200e0b45 --- /dev/null +++ b/apparmor.d/abstractions/flatpak/devices/dri @@ -0,0 +1,39 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + + abi , + + include + include + include + include + + unix (bind listen) type=seqpacket addr=@@{hex}@{hex}, + + # The orcexec.* file is JIT compiled code for various GStreamer elements. + # If one is blocked the next is used instead. + # The orcexec file is placed under /home/user/ also when the /tmp/ dir is mounted with the noexec flag. + owner @{run}/user/@{uid}/orcexec.@{rand6} mrw, + deny owner @{HOME}/orcexec.@{rand6} mrw, + deny owner @{tmp}/orcexec.@{rand6} mrw, + + @{sys}/bus/ r, + @{sys}/devices/@{pci_bus}/uevent r, + + @{PROC}/devices r, + @{PROC}/driver/nvidia/capabilities/mig/config r, + @{PROC}/sys/vm/nr_hugepages r, + + # Video Acceleration API + @{att}/dev/dri/renderD128 rw, + @{att}/dev/dri/renderD129 rw, + + /dev/ r, + /dev/nvidia-caps/ rw, + /dev/nvidia-caps/nvidia-cap@{int} rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/devices/input b/apparmor.d/abstractions/flatpak/devices/input new file mode 100644 index 0000000000..46da3b9392 --- /dev/null +++ b/apparmor.d/abstractions/flatpak/devices/input @@ -0,0 +1,13 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + + abi , + + include + include + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/devices/kvm b/apparmor.d/abstractions/flatpak/devices/kvm new file mode 100644 index 0000000000..6dce9ea516 --- /dev/null +++ b/apparmor.d/abstractions/flatpak/devices/kvm @@ -0,0 +1,10 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + + abi , + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/devices/shm b/apparmor.d/abstractions/flatpak/devices/shm new file mode 100644 index 0000000000..3d78984bd4 --- /dev/null +++ b/apparmor.d/abstractions/flatpak/devices/shm @@ -0,0 +1,15 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + + abi , + + #aa:lint ignore=too-wide + /dev/shm/ r, + owner /dev/shm/** mrwlkix, + owner @{att}/dev/shm/** mrwlkix, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/devices/usb b/apparmor.d/abstractions/flatpak/devices/usb new file mode 100644 index 0000000000..c4b92a8712 --- /dev/null +++ b/apparmor.d/abstractions/flatpak/devices/usb @@ -0,0 +1,13 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + + abi , + + include + include + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/features/bluetooth b/apparmor.d/abstractions/flatpak/features/bluetooth new file mode 100644 index 0000000000..403b4c1a3d --- /dev/null +++ b/apparmor.d/abstractions/flatpak/features/bluetooth @@ -0,0 +1,15 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + +# The bluetooth feature allows the application to use bluetooth (AF_BLUETOOTH) +# sockets. Note, for bluetooth to fully work you must also have network access. + + abi , + + network bluetooth, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/features/canbus b/apparmor.d/abstractions/flatpak/features/canbus new file mode 100644 index 0000000000..8bb50f14c3 --- /dev/null +++ b/apparmor.d/abstractions/flatpak/features/canbus @@ -0,0 +1,13 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + +# The canbus feature allows the application to use canbus (AF_CAN) sockets. +# Note, for this work you must also have network access. + + abi , + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/features/devel b/apparmor.d/abstractions/flatpak/features/devel new file mode 100644 index 0000000000..8da7594ef1 --- /dev/null +++ b/apparmor.d/abstractions/flatpak/features/devel @@ -0,0 +1,16 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + +# The devel feature allows the application to access certain syscalls such as +# ptrace(), and perf_event_open(). + + abi , + + ptrace read peer=flatpak//bwrap, + ptrace trace peer=@{profile_name}, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/features/multiarch b/apparmor.d/abstractions/flatpak/features/multiarch new file mode 100644 index 0000000000..fbcbaf0b3a --- /dev/null +++ b/apparmor.d/abstractions/flatpak/features/multiarch @@ -0,0 +1,14 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + +# The multiarch feature allows the application to execute programs compiled for +# an ABI other than the one supported natively by the system. For example, for +# the x86_64 architecture, 32-bit x86 binaries will be allowed as well. + + abi , + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/features/per-app-dev-shm b/apparmor.d/abstractions/flatpak/features/per-app-dev-shm new file mode 100644 index 0000000000..acbaf5e104 --- /dev/null +++ b/apparmor.d/abstractions/flatpak/features/per-app-dev-shm @@ -0,0 +1,19 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + +# The per-app-dev-shm feature shares a single instance of `/dev/shm` between the +# application, any unrestricted subsandboxes that it creates, and any other +# instances of the application that are launched while it is running. +# +# We should theoretically allow all access of `/dev/shm/` here. However, as it is +# a potential source of information leaks and confinement escapes, we only allow, +# we only allow some well-known paths that are used by the application. +# Baseapp can be used to allow access to more paths if needed. + + abi , + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/filesystem b/apparmor.d/abstractions/flatpak/filesystem new file mode 100644 index 0000000000..aad04f64f1 --- /dev/null +++ b/apparmor.d/abstractions/flatpak/filesystem @@ -0,0 +1,62 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + +#aa:lint ignore=too-wide + +# Used by the generic flatpak app profile (fapp) to cover the filesystem access +# as defined in the flatpak doc. Dynamically generated flatpak profiles do +# not use this abstraction. + +# As a generic profile cannot filter filesystem for each app, the flatpak/filesystem +# abstraction gives full access to the user's home, and read only acccess to +# host system files. In the limit of what is defined by flatpak. + +# https://docs.flatpak.org/en/latest/sandbox-permissions.html#filesystem-access + + abi , + + /att/ r, + /att/**/ r, + + # Access an arbitrary path except any reserved ones + owner /etc/{,**} rw, + owner @{sys}/ r, + owner /usr/{,**} r, + + # host-os + @{run}/host/bin/{,**} r, + @{run}/host/etc/alternatives r, + @{run}/host/etc/ld.so.cache r, + @{run}/host/lib{32,64}/{,**} r, + @{run}/host/sbin/{,**} r, + @{run}/host/usr/{,**} r, + + # host-etc + @{run}/host/etc/** r, + + # host + /opt/{,**} r, + /srv/{,**} r, + @{MOUNTS}/ r, + owner @{MOUNTS}/** rwlk -> @{MOUNTS}/**, + + # home + owner /home/ r, + owner @{HOME}/ r, + owner @{HOME}/** rwlk -> @{HOME}/**, + + # xdg-run + owner @{run}/ r, + owner @{run}/user/ r, + owner @{run}/user/@{uid}/ rw, + owner @{run}/user/@{uid}/** rwlk -> @{run}/user/@{uid}/**, + + /var/lib/** r, + owner /var/ r, + owner /var/tmp/ r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/platform/org.freedesktop b/apparmor.d/abstractions/flatpak/platform/org.freedesktop new file mode 100644 index 0000000000..6b4a415dc9 --- /dev/null +++ b/apparmor.d/abstractions/flatpak/platform/org.freedesktop @@ -0,0 +1,64 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no +# NEEDS-VARIABLE: appid + + abi , + + include + include + + # Base directories of the flatpak platform + /usr/share/ r, + /usr/share/** r, + + # Fonts + # We are purposely not using the fonts abstraction as it gives access to + # system-wide and user fonts out of the sandbox. + + /usr/cache/fontconfig/** r, + /usr/local/share/fonts/{,**} rk, + /usr/share/fonts/{,**} rk, + + /etc/fonts/{,**} r, + + owner /var/cache/fontconfig/@{hex32}-le{32,64}.cache-@{int} r, + owner /var/cache/fontconfig/@{hex32}-le{32,64}.cache-reindex@{int}-@{int} r, + + @{run}/host/fonts-cache/{,**} r, + @{run}/host/fonts/{,**} r, + owner @{run}/host/font-dirs.xml r, + owner @{run}/host/user-fonts-cache/@{hex32}-le{32,64}.cache-@{int} r, + owner @{run}/host/user-fonts/{,**} r, + + # Icons + # We are purposely not using the icons abstraction as it gives access to + # system-wide and user icon out of the sandbox. + + /var/lib/flatpak/app/@{appid}/@{arch}/stable/@{hex64}/export/share/icons/{,**} r, + /var/lib/flatpak/exports/share/icons/{,**} r, + + @{run}/host/local-fonts/{,**} r, + @{run}/host/share/icons/{,**} r, + @{run}/host/user-share/icons/{,**} r, + @{run}/host/usr/share/applications/{,**} r, + @{run}/host/usr/share/icons/{,**} r, + @{run}/host/usr/share/pixmaps/{,**} r, + + # Pkcs11 + # Flatpak only pkcs11 paths + + /etc/pki/ca-trust/extracted/** r, + /etc/pki/tls/certs/{,**} r, + /etc/pki/tls/openssl.cnf r, + + owner /etc/pkcs11/modules/ r, + owner /etc/pkcs11/modules/p11-kit-trust.module r, + owner /etc/pkcs11/pkcs11.conf r, + + owner @{att}@{run}/user/@{uid}/.flatpak-helper/pkcs11-flatpak-@{int} rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/shared/ipc b/apparmor.d/abstractions/flatpak/shared/ipc new file mode 100644 index 0000000000..ef235fc096 --- /dev/null +++ b/apparmor.d/abstractions/flatpak/shared/ipc @@ -0,0 +1,12 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + + abi , + + network netlink raw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/shared/network b/apparmor.d/abstractions/flatpak/shared/network new file mode 100644 index 0000000000..65f75307ac --- /dev/null +++ b/apparmor.d/abstractions/flatpak/shared/network @@ -0,0 +1,53 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + + abi , + + include + + network inet dgram, + network inet6 dgram, + network inet stream, + network inet6 stream, + + @{run}/systemd/resolve/io.systemd.Resolve rw, + @{att}@{run}/systemd/resolve/io.systemd.Resolve rw, + + owner @{run}/host/monitor/gai.conf r, + owner @{run}/host/monitor/host.conf r, + owner @{run}/host/monitor/hosts r, + owner @{run}/host/monitor/resolv.conf r, + + @{sys}/class/net/ r, + @{sys}/devices/**/net/*/ r, + @{sys}/devices/**/net/*/carrier r, + + # Leaks interface names and stats, but not in a way that is traceable + # to the user/device + @{PROC}/@{pid}/net/dev r, + @{PROC}/@{pid}/net/if_inet6 r, + @{PROC}/@{pid}/net/ipv6_route r, + @{PROC}/@{pid}/net/packet r, + @{PROC}/@{pid}/net/raw r, + @{PROC}/@{pid}/net/raw6 r, + @{PROC}/@{pid}/net/route r, + @{PROC}/@{pid}/net/snmp r, + @{PROC}/@{pid}/net/sockstat r, + @{PROC}/@{pid}/net/sockstat6 r, + @{PROC}/@{pid}/net/tcp r, + @{PROC}/@{pid}/net/tcp6 r, + @{PROC}/@{pid}/net/udp r, + @{PROC}/@{pid}/net/udp6 r, + @{PROC}/@{pid}/net/udplite r, + @{PROC}/@{pid}/net/unix r, + @{PROC}/@{pid}/net/wireless r, + @{PROC}/net/dev r, + + @{PROC}/sys/net/ipv4/conf/default/forwarding r, + @{PROC}/sys/net/ipv4/ip_default_ttl r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/sockets/cups b/apparmor.d/abstractions/flatpak/sockets/cups new file mode 100644 index 0000000000..2b4c6c7e0d --- /dev/null +++ b/apparmor.d/abstractions/flatpak/sockets/cups @@ -0,0 +1,10 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + + abi , + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/sockets/fallback-x11 b/apparmor.d/abstractions/flatpak/sockets/fallback-x11 new file mode 100644 index 0000000000..55ae024d68 --- /dev/null +++ b/apparmor.d/abstractions/flatpak/sockets/fallback-x11 @@ -0,0 +1,10 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + + abi , + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/sockets/gpg-agent b/apparmor.d/abstractions/flatpak/sockets/gpg-agent new file mode 100644 index 0000000000..6c6d519207 --- /dev/null +++ b/apparmor.d/abstractions/flatpak/sockets/gpg-agent @@ -0,0 +1,12 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + + abi , + + owner @{run}/user/@{uid}/gnupg/S.gpg-agent rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/sockets/inherit-wayland-socket b/apparmor.d/abstractions/flatpak/sockets/inherit-wayland-socket new file mode 100644 index 0000000000..68ee9c611b --- /dev/null +++ b/apparmor.d/abstractions/flatpak/sockets/inherit-wayland-socket @@ -0,0 +1,10 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + + abi , + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/sockets/pcsc b/apparmor.d/abstractions/flatpak/sockets/pcsc new file mode 100644 index 0000000000..a58ac52b05 --- /dev/null +++ b/apparmor.d/abstractions/flatpak/sockets/pcsc @@ -0,0 +1,12 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + + abi , + + @{run}/pcscd/pcscd.comm rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/sockets/pulseaudio b/apparmor.d/abstractions/flatpak/sockets/pulseaudio new file mode 100644 index 0000000000..735d3386fc --- /dev/null +++ b/apparmor.d/abstractions/flatpak/sockets/pulseaudio @@ -0,0 +1,23 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + + abi , + + owner @{att}@{run}/user/@{uid}/pulse/native rw, + + owner @{run}/flatpak/pulse/config r, + + @{sys}/class/ r, + @{sys}/class/sound/ r, + @{sys}/devices/virtual/sound/seq/uevent r, + @{sys}/devices/virtual/sound/timer/uevent r, + + /dev/snd/ r, + /dev/snd/* rw, + /dev/sound/* rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/sockets/session-bus b/apparmor.d/abstractions/flatpak/sockets/session-bus new file mode 100644 index 0000000000..f238af05fc --- /dev/null +++ b/apparmor.d/abstractions/flatpak/sockets/session-bus @@ -0,0 +1,10 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + + abi , + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/sockets/ssh-auth b/apparmor.d/abstractions/flatpak/sockets/ssh-auth new file mode 100644 index 0000000000..4eb81e4887 --- /dev/null +++ b/apparmor.d/abstractions/flatpak/sockets/ssh-auth @@ -0,0 +1,14 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + + abi , + + owner @{run}/flatpak/ssh-auth r, + + owner @{att}@{run}/user/@{uid}/gcr/ssh rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/sockets/system-bus b/apparmor.d/abstractions/flatpak/sockets/system-bus new file mode 100644 index 0000000000..eeeb913424 --- /dev/null +++ b/apparmor.d/abstractions/flatpak/sockets/system-bus @@ -0,0 +1,10 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + + abi , + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/sockets/wayland b/apparmor.d/abstractions/flatpak/sockets/wayland new file mode 100644 index 0000000000..c8fa3fb7c4 --- /dev/null +++ b/apparmor.d/abstractions/flatpak/sockets/wayland @@ -0,0 +1,19 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + + abi , + + owner @{run}/flatpak/wayland-@{int} r, + + # Allow access to the Wayland compositor server socket + owner @{run}/user/@{uid}/wayland-@{int} rw, + owner @{run}/user/@{uid}/wayland-proxy-@{int} rw, + owner @{att}@{run}/user/@{uid}/wayland-@{int} rw, + + owner @{att}/dev/shm/@{uuid} rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/flatpak/sockets/x11 b/apparmor.d/abstractions/flatpak/sockets/x11 new file mode 100644 index 0000000000..23f7983a15 --- /dev/null +++ b/apparmor.d/abstractions/flatpak/sockets/x11 @@ -0,0 +1,19 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + + abi , + + unix (send receive connect) type=stream peer=(label=gnome-shell, addr=@/tmp/.X11-unix/X@{int}), + unix (send receive connect) type=stream peer=(label=xkbcomp, addr=@/tmp/.X11-unix/X@{int}), + unix (send receive connect) type=stream peer=(label=xwayland, addr=@/tmp/.X11-unix/X@{int}), + + /usr/share/X11/{,**} r, + /usr/share/xkeyboard-config-2/{,**} r, + + owner @{run}/flatpak/Xauthority r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/fontconfig-cache b/apparmor.d/abstractions/fontconfig-cache new file mode 100644 index 0000000000..2bf6f9947b --- /dev/null +++ b/apparmor.d/abstractions/fontconfig-cache @@ -0,0 +1,79 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2018-2021 Mikhail Morfikov +# Copyright (C) 2021-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# The fontconfig cache can be generated via the following command: +# +# !!! quote "" +# +# ```sh +# fc-cache -f -v +# ``` +# +# There is no need to give apps the ability to create cache for their own. +# However, apps can generate the fontconfig cache if some cache files are missing. +# Therefore, if this behavior is desirable, you can use: +# +# !!! quote "" +# +# ``` +# +# ``` +# +# If not, you can block writing to the cache directories with +# +# !!! quote "" +# +# ``` +# +# ``` +# + + abi , + + /var/cache/fontconfig/ r, + /var/cache/fontconfig/CACHEDIR.TAG r, + /var/cache/fontconfig/@{hex32}-@{arch}.cache-@{d} r, + /var/cache/fontconfig/@{hex32}-le{32,64}{,d4}.cache-@{d} r, + /var/cache/fontconfig/@{hex32}-le{32,64}{,d4}.cache-@{d}.TMP-@{rand6} r, + + owner @{gdm_cache_dirs}/fontconfig/ r, + owner @{gdm_cache_dirs}/fontconfig/CACHEDIR.TAG r, + owner @{gdm_cache_dirs}/fontconfig/CACHEDIR.TAG.LCK r, + owner @{gdm_cache_dirs}/fontconfig/CACHEDIR.TAG.NEW r, + owner @{gdm_cache_dirs}/fontconfig/CACHEDIR.TAG.TMP-@{rand6} r, + owner @{gdm_cache_dirs}/fontconfig/@{hex32}-le{32,64}{,d4}.cache-@{d} r, + owner @{gdm_cache_dirs}/fontconfig/@{hex32}-le{32,64}{,d4}.cache-@{d}.NEW r, + owner @{gdm_cache_dirs}/fontconfig/@{hex32}-le{32,64}{,d4}.cache-@{d}.TMP-@{rand6} r, + + owner @{HOME}/.fontconfig/ r, + owner @{HOME}/.fontconfig/CACHEDIR.TAG r, + owner @{HOME}/.fontconfig/@{hex32}-le{32,64}{,d4}.cache-@{d} r, + owner @{HOME}/.fontconfig/@{hex32}-le{32,64}{,d4}.cache-@{d}.NEW r, + owner @{HOME}/.fontconfig/@{hex32}-le{32,64}{,d4}.cache-@{d}.TMP-@{rand6} r, + + owner @{user_config_dirs}/fontconfig/fonts.conf r, + owner @{user_config_dirs}/fontconfig/conf.d/{,**} r, + + owner @{user_cache_dirs}/fontconfig/ r, + owner @{user_cache_dirs}/fontconfig/CACHEDIR.TAG r, # {,.NEW,.LCK,.TMP-*} r, + owner @{user_cache_dirs}/fontconfig/@{hex32}-le{32,64}{,d4}.cache-@{d} r, # {,.NEW,.LCK,.TMP-*} r, + owner @{user_cache_dirs}/fontconfig/@{hex32}-le{32,64}{,d4}.cache-@{d}.NEW r, + owner @{user_cache_dirs}/fontconfig/@{hex32}-le{32,64}{,d4}.cache-@{d}.TMP-@{rand6} r, + owner @{user_cache_dirs}/fontconfig/@{hex32}-le{32,64}{,d4}.cache-reindex@{d}-@{int} rk, + owner @{user_cache_dirs}/fontconfig/@{hex32}-le{32,64}{,d4}.cache-@{int} r, + + # This is to create .uuid file containing an UUID at a font directory. The UUID will be used to + # identify the font directory and is used to determine the cache filename if available. + /usr/share/**/.uuid r, + owner /usr/local/share/fonts/ r, + owner /usr/local/share/fonts/.uuid r, + owner @{HOME}/.fonts/ r, + owner @{HOME}/.fonts/.uuid r, + owner @{user_share_dirs}/fonts/ r, + owner @{user_share_dirs}/fonts/**/.uuid r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/fontconfig-cache-read b/apparmor.d/abstractions/fontconfig-cache-read index 3067873780..26ba79f98e 100644 --- a/apparmor.d/abstractions/fontconfig-cache-read +++ b/apparmor.d/abstractions/fontconfig-cache-read @@ -3,14 +3,18 @@ # Copyright (C) 2021-2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only - # The fontconfig cache can be generated via the following command: - # $ fc-cache -f -v - # There's no need to give apps the ability to create cache for their own. Apps can generate the - # fontconfig cache if some cache files are missing, so if this behavior is desirable, you can use - # the "fontconfig-cache-write" abstraction. +# See for documentation. abi , + include + + owner @{gdm_cache_dirs}/fontconfig/ r, + owner @{gdm_cache_dirs}/fontconfig/@{hex32}.cache-?{,.NEW,.LCK,.TMP-*} r, + owner @{gdm_cache_dirs}/fontconfig/CACHEDIR.TAG{,.NEW,.LCK,.TMP-*} r, + deny @{gdm_cache_dirs}/fontconfig/ w, + deny @{gdm_cache_dirs}/fontconfig/** w, + owner @{user_cache_dirs}/fontconfig/ r, deny @{user_cache_dirs}/fontconfig/ w, deny @{user_cache_dirs}/fontconfig/** w, diff --git a/apparmor.d/abstractions/fontconfig-cache-write b/apparmor.d/abstractions/fontconfig-cache-write index 922a15a6a7..ff844f3284 100644 --- a/apparmor.d/abstractions/fontconfig-cache-write +++ b/apparmor.d/abstractions/fontconfig-cache-write @@ -3,42 +3,67 @@ # Copyright (C) 2022-2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only +# See for documentation. + abi , - owner @{user_cache_dirs}/fontconfig/ rw, - owner @{user_cache_dirs}/fontconfig/CACHEDIR.TAG{,.NEW,.LCK,.TMP-*} rw, - owner @{user_cache_dirs}/fontconfig/[a-f0-9]*.cache-?{,.NEW,.LCK,.TMP-*} rwk, - owner @{user_cache_dirs}/fontconfig/*-le64.cache-@{int} w, - owner @{user_cache_dirs}/fontconfig/*-le64.cache-@{int}{,TMP-@{rand6},NEW,LCK} w, - - owner @{HOME}/.fontconfig/ rw, - owner @{HOME}/.fontconfig/CACHEDIR.TAG{,.NEW,.LCK,.TMP-*} rw, - owner @{HOME}/.fontconfig/[a-f0-9]*.cache-?{,.NEW,.LCK,.TMP-*} rwk, - - owner @{HOME}/.fonts/ rw, - link @{HOME}/.fonts/.uuid.LCK -> @{HOME}/.fonts/.uuid.TMP-*, - owner @{HOME}/.fonts/.uuid{,.NEW,.LCK,.TMP-*} r, - owner @{HOME}/.fonts/.uuid{,.NEW,.LCK,.TMP-*} w, - - # This is to create .uuid file containing an UUID at a font directory. The UUID will be used to - # identify the font directory and is used to determine the cache filename if available. - owner /usr/local/share/fonts/ rw, - owner /usr/local/share/fonts/.uuid{,.NEW,.LCK,.TMP-*} rw, - link /usr/local/share/fonts/.uuid.LCK -> /usr/local/share/fonts/.uuid.TMP-*, - # Should writing to these dirs be blocked? - /usr/share/**/.uuid{,.NEW,.LCK,.TMP-*} r, - deny /usr/share/**/.uuid{,.NEW,.LCK,.TMP-*} w, - - /var/cache/fontconfig/ rw, - owner /var/cache/fontconfig/** rw, - owner /var/cache/fontconfig/*.cache-@{int} rwk, - owner /var/cache/fontconfig/*.cache-@{int}.LCK rwl, - owner /var/cache/fontconfig/CACHEDIR.TAG.LCK rwl, - - # For fonts downloaded via font-manager (###FIXME### when they fix resolving of vars) - owner @{user_share_dirs}/fonts/ rw, - owner @{user_share_dirs}/fonts/**/.uuid{,.NEW,.LCK,.TMP-*} rw, - link @{user_share_dirs}/fonts/**/.uuid.LCK -> @{user_share_dirs}/fonts/**/.uuid.TMP-*, + include + + /var/cache/fontconfig/ w, + owner /var/cache/fontconfig/CACHEDIR.TAG w, + owner /var/cache/fontconfig/CACHEDIR.TAG.LCK wl, + owner /var/cache/fontconfig/CACHEDIR.TAG.NEW w, + owner /var/cache/fontconfig/CACHEDIR.TAG.TMP-@{rand6} wl, + owner /var/cache/fontconfig/@{uuid}-le{32,64}{,d4}.cache-@{d} wl, + owner /var/cache/fontconfig/@{uuid}-le{32,64}{,d4}.cache-@{d}.LCK wl, + owner /var/cache/fontconfig/@{uuid}-le{32,64}{,d4}.cache-@{d}.NEW w, + owner /var/cache/fontconfig/@{uuid}-le{32,64}{,d4}.cache-@{d}.TMP-@{rand6} wl, + owner /var/cache/fontconfig/@{hex32}-le{32,64}{,d4}.cache-@{d} wl, + owner /var/cache/fontconfig/@{hex32}-le{32,64}{,d4}.cache-@{d}.LCK wl, + owner /var/cache/fontconfig/@{hex32}-le{32,64}{,d4}.cache-@{d}.NEW w, + owner /var/cache/fontconfig/@{hex32}-le{32,64}{,d4}.cache-@{d}.TMP-@{rand6} wl, + + owner @{desktop_cache_dirs}/fontconfig/ w, + owner @{desktop_cache_dirs}/fontconfig/@{hex32}-le{32,64}{,d4}.cache-@{d} wl, + owner @{desktop_cache_dirs}/fontconfig/@{hex32}-le{32,64}{,d4}.cache-@{d}.LCK wl, + owner @{desktop_cache_dirs}/fontconfig/@{hex32}-le{32,64}{,d4}.cache-@{d}.NEW w, + owner @{desktop_cache_dirs}/fontconfig/@{hex32}-le{32,64}{,d4}.cache-@{d}.TMP-@{rand6} wl, + owner @{desktop_cache_dirs}/fontconfig/@{uuid}-le{32,64}{,d4}.cache-@{d}.NEW w, + owner @{desktop_cache_dirs}/fontconfig/@{uuid}-le{32,64}{,d4}.cache-@{d}.TMP-@{rand6} wl, + owner @{desktop_cache_dirs}/fontconfig/@{uuid}-le{32,64}{,d4}.cache-@{d} wl, + owner @{desktop_cache_dirs}/fontconfig/@{uuid}-le{32,64}{,d4}.cache-@{d}.LCK wl, + owner @{desktop_cache_dirs}/fontconfig/CACHEDIR.TAG w, + owner @{desktop_cache_dirs}/fontconfig/CACHEDIR.TAG.LCK wl, + owner @{desktop_cache_dirs}/fontconfig/CACHEDIR.TAG.NEW w, + owner @{desktop_cache_dirs}/fontconfig/CACHEDIR.TAG.TMP-@{rand6} wl, + + owner @{HOME}/.fontconfig/ w, + owner @{HOME}/.fontconfig/fontconfig/@{hex32}-le{32,64}{,d4}.cache-@{d} wl, + owner @{HOME}/.fontconfig/@{hex32}-le{32,64}{,d4}.cache-@{d}.LCK wl, + owner @{HOME}/.fontconfig/@{hex32}-le{32,64}{,d4}.cache-@{d}.NEW w, + owner @{HOME}/.fontconfig/@{hex32}-le{32,64}{,d4}.cache-@{d}.TMP-@{rand6} w, + owner @{HOME}/.fontconfig/@{uuid}-le{32,64}{,d4}.cache-@{d}.NEW w, + owner @{HOME}/.fontconfig/@{uuid}-le{32,64}{,d4}.cache-@{d}.TMP-@{rand6} w, + owner @{HOME}/.fontconfig/@{uuid}-le{32,64}{,d4}.cache-@{d} wl, + owner @{HOME}/.fontconfig/@{uuid}-le{32,64}{,d4}.cache-@{d}.LCK wl, + owner @{HOME}/.fontconfig/CACHEDIR.TAG w, + owner @{HOME}/.fontconfig/CACHEDIR.TAG.LCK wl, + owner @{HOME}/.fontconfig/CACHEDIR.TAG.NEW w, + owner @{HOME}/.fontconfig/CACHEDIR.TAG.TMP-@{rand6} wl, + + owner @{user_cache_dirs}/fontconfig/ w, + owner @{user_cache_dirs}/fontconfig/@{hex32}-le{32,64}{,d4}.cache-@{d} wlk, + owner @{user_cache_dirs}/fontconfig/@{hex32}-le{32,64}{,d4}.cache-@{d}.LCK wl, + owner @{user_cache_dirs}/fontconfig/@{hex32}-le{32,64}{,d4}.cache-@{d}.NEW w, + owner @{user_cache_dirs}/fontconfig/@{hex32}-le{32,64}{,d4}.cache-@{d}.TMP-@{rand6} wl, + owner @{user_cache_dirs}/fontconfig/@{uuid}-le{32,64}{,d4}.cache-@{d}.NEW w, + owner @{user_cache_dirs}/fontconfig/@{uuid}-le{32,64}{,d4}.cache-@{d}.TMP-@{rand6} wl, + owner @{user_cache_dirs}/fontconfig/@{uuid}-le{32,64}{,d4}.cache-@{d} wl, + owner @{user_cache_dirs}/fontconfig/@{uuid}-le{32,64}{,d4}.cache-@{d}.LCK wl, + owner @{user_cache_dirs}/fontconfig/CACHEDIR.TAG w, + owner @{user_cache_dirs}/fontconfig/CACHEDIR.TAG.LCK wl, + owner @{user_cache_dirs}/fontconfig/CACHEDIR.TAG.NEW w, + owner @{user_cache_dirs}/fontconfig/CACHEDIR.TAG.TMP-@{rand6} wl, include if exists diff --git a/apparmor.d/abstractions/fonts-strict b/apparmor.d/abstractions/fonts-strict new file mode 100644 index 0000000000..3736ccd7ac --- /dev/null +++ b/apparmor.d/abstractions/fonts-strict @@ -0,0 +1,36 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2002-2009 Novell/SUSE +# Copyright (C) 2009 Canonical Ltd. +# Copyright (C) 2024-2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + include + + /usr/local/share/fonts/{,**} r, + /usr/share/*-fonts/conf.avail/{,**} r, + /usr/share/a2ps/fonts/{,**} r, + /usr/share/AbiSuite/fonts/** r, + /usr/share/fontconfig/conf.avail/{,**} r, + /usr/share/fonts-*/{,**} r, + /usr/share/fonts/{,**} r, + /usr/share/ghostscript/fonts/{,**} r, + /usr/share/javascript/*/fonts/{,**} r, + /usr/share/libthai/thbrk.tri r, + /usr/share/texlive/texmf-dist/fonts/{,**} r, + /usr/share/texmf/{,*/}fonts/{,**} r, + /usr/share/xfce{,4}/fonts/{,**} r, + + /etc/fonts/{,**} r, + + /var/cache/fonts/{,**} r, + + owner @{HOME}/.fonts.conf r, + owner @{HOME}/.fonts.conf.d/{,**} r, + owner @{HOME}/.fonts/{,**} r, + owner @{user_share_dirs}/fonts/{,**} r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/freedesktop.org.d/complete b/apparmor.d/abstractions/freedesktop.org.d/complete index 4724c694a3..df445cef56 100644 --- a/apparmor.d/abstractions/freedesktop.org.d/complete +++ b/apparmor.d/abstractions/freedesktop.org.d/complete @@ -16,11 +16,16 @@ /opt/*/**.{desktop,png} r, /etc/gnome/defaults.list r, - /etc/xfce4/defaults.list r, + /etc/xfce4/defaults.list r, /var/lib/snapd/desktop/applications/{,**} r, /var/lib/snapd/desktop/icons/{,**} r, owner @{HOME}/.icons/{,**} r, + owner @{user_share_dirs}/#@{int} rw, + owner @{user_share_dirs}/recently-used.xbel rw, + owner @{user_share_dirs}/recently-used.xbel.@{rand6} rwl, + owner @{user_share_dirs}/recently-used.xbel.lock rwk, + # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/glibc b/apparmor.d/abstractions/glibc new file mode 100644 index 0000000000..2beebf2704 --- /dev/null +++ b/apparmor.d/abstractions/glibc @@ -0,0 +1,53 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2002-2009 Novell/SUSE +# Copyright (C) 2009-2011 Canonical Ltd. +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# !!! note +# +# As this abstraction is included in the `base` / `base-strict` abstractions. +# It is not necessary to include it manually. +# + + abi , + + # Used by Glibc when binding to ephemeral ports + @{etc_ro}/bindresvport.blacklist r, + + # Depending on which Glibc routine uses this file, base may not be the + # best place -- but many profiles require it, and it is quite harmless. + @{PROC}/sys/kernel/ngroups_max r, + + # Glibc's sysconf(3) routine to determine free memory, etc + @{sys}/devices/system/cpu/ r, + @{sys}/devices/system/cpu/online r, + @{sys}/devices/system/cpu/possible r, + @{PROC}/cpuinfo r, + @{PROC}/meminfo r, + @{PROC}/stat r, + + # Glibc's *printf protections read the maps file + owner @{PROC}/@{pid}/auxv r, + owner @{PROC}/@{pid}/maps r, + owner @{PROC}/@{pid}/status r, + + # @{PROC}/@{pid}/map_files/ contains the same info than @{PROC}/@{pid}/maps, + # but in a format that is easier to manage, because it doesn't require to + # parse the text data inside a file, but just reading the contents of + # a directory. + owner @{PROC}/@{pid}/map_files/ r, + + # Glibc statvfs + @{PROC}/filesystems r, + + # Glibc malloc (man 5 proc) + @{PROC}/sys/vm/overcommit_memory r, + + # Recent glibc uses /dev/full in preference to /dev/null for programs + # that don't have open fds at exec() + /dev/full rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/gnome-base b/apparmor.d/abstractions/gnome-base new file mode 100644 index 0000000000..74b785f40b --- /dev/null +++ b/apparmor.d/abstractions/gnome-base @@ -0,0 +1,43 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2021-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Minimal gnome specific rules. + + abi , + + include + include + include + + dbus send bus=system path=/org/freedesktop/DBus + interface=org.freedesktop.DBus + member={ListNames,RequestName} + peer=(name=org.freedesktop.DBus, label="@{p_dbus_system}"), + + # DBus.Introspectable: allow introspection from gnome-shell + dbus receive bus=session + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(label=gnome-shell), + dbus receive bus=session + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=@{busname}, label=gnome-extension), + + @{system_share_dirs}/gvfs/remote-volume-monitors/{,*} r, + + / r, + + # Allow GNOME Shell session state database + owner @{user_share_dirs}/gnome-shell/session.gvdb rw, + + # Allow reading CPU limits from cgroup hierarchy for resource monitoring + @{sys}/fs/cgroup/user.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/cpu.max r, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/cpu.max r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/gnome-strict b/apparmor.d/abstractions/gnome-strict index fadaedcbf3..ba258b96ef 100644 --- a/apparmor.d/abstractions/gnome-strict +++ b/apparmor.d/abstractions/gnome-strict @@ -4,34 +4,34 @@ abi , - include - include - include - include + # Common abstractions for any desktop environment + include + include + include + include + include #aa:only ubuntu + include + include + include + include + include + include + include + include + include + include + include + include + include + include + include + include + include include include - dbus receive bus=session - interface=org.freedesktop.DBus.Introspectable - member=Introspect - peer=(name=@{busname}, label=gnome-shell), - - /usr/share/desktop-base/{,**} r, - /usr/share/hwdata/*.ids r, - /usr/share/icu/@{int}.@{int}/*.dat r, - - /usr/{local/,}share/ r, - /usr/{local/,}share/glib-@{int}.@{int}/schemas/** r, - /usr/{local/,}share/gvfs/remote-volume-monitors/{,*} r, - - /etc/gnome/* r, - /etc/xdg/{,*-}mimeapps.list r, - - /var/cache/gio-@{int}.@{int}/gnome-mimeapps.list r, - - / r, - - owner @{user_share_dirs}/gnome-shell/session.gvdb rw, + # Gnome specific rules + include include if exists diff --git a/apparmor.d/abstractions/gnome.d/complete b/apparmor.d/abstractions/gnome.d/complete index 71e76f9dad..3b08aba332 100644 --- a/apparmor.d/abstractions/gnome.d/complete +++ b/apparmor.d/abstractions/gnome.d/complete @@ -2,12 +2,17 @@ # Copyright (C) 2021-2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only - include + include dbus receive bus=session interface=org.freedesktop.DBus.Introspectable - member=Introspect - peer=(name=@{busname}, label=gnome-shell), + member=Introspect + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), + + dbus receive bus=session + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=@{busname}, label=gnome-extension), /var/cache/gio-@{int}.@{int}/gnome-mimeapps.list r, diff --git a/apparmor.d/abstractions/golang-strict b/apparmor.d/abstractions/golang-strict new file mode 100644 index 0000000000..ca6b05245e --- /dev/null +++ b/apparmor.d/abstractions/golang-strict @@ -0,0 +1,26 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Container-aware GOMAXPROCS + + abi , + + audit @{sys}/fs/cgroup/**/cpu.cfs_period_us r, + audit @{sys}/fs/cgroup/**/cpu.cfs_quota_us r, + + @{sys}/fs/cgroup/user.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/session-@{int}.scope/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/*.scope/*.scope/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/*.scope/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/cpu.max r, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/cpu.max r, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/*.service/cpu.max r, + + owner @{PROC}/@{pid}/mountinfo r, + owner @{PROC}/@{pid}/cgroup r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/graphics b/apparmor.d/abstractions/graphics index 37f6be70ed..06b4e4b892 100644 --- a/apparmor.d/abstractions/graphics +++ b/apparmor.d/abstractions/graphics @@ -13,13 +13,42 @@ /etc/libva.conf r, @{sys}/bus/pci/devices/ r, - @{sys}/devices/system/cpu/cpu@{int}/cache/index@{int}/* r, + + # GPU sysfs for PCI graphics cards: + @{sys}/devices/@{pci}/current_link_speed r, # Current PCIe link speed (e.g., 8.0 GT/s) + @{sys}/devices/@{pci}/current_link_width r, # Current PCIe lane width (e.g., x16) + @{sys}/devices/@{pci}/max_link_speed r, # Maximum supported PCIe speed + @{sys}/devices/@{pci}/max_link_width r, # Maximum supported PCIe lane width + + @{sys}/devices/system/ r, + @{sys}/devices/system/cpu/cpu@{int}/ r, + @{sys}/devices/system/cpu/cpu@{int}/cache/ r, + @{sys}/devices/system/cpu/cpu@{int}/cache/index@{int}/coherency_line_size r, + @{sys}/devices/system/cpu/cpu@{int}/cache/index@{int}/id r, + @{sys}/devices/system/cpu/cpu@{int}/cache/index@{int}/level r, + @{sys}/devices/system/cpu/cpu@{int}/cache/index@{int}/physical_line_partition r, + @{sys}/devices/system/cpu/cpu@{int}/cache/index@{int}/shared_cpu_list r, + @{sys}/devices/system/cpu/cpu@{int}/cache/index@{int}/shared_cpu_map r, + @{sys}/devices/system/cpu/cpu@{int}/cache/index@{int}/size r, + @{sys}/devices/system/cpu/cpu@{int}/cache/index@{int}/type r, + @{sys}/devices/system/cpu/cpu@{int}/cache/index@{int}/ways_of_associativity r, + @{sys}/devices/system/cpu/cpu@{int}/cpu_capacity r, @{sys}/devices/system/cpu/cpu@{int}/online r, - @{sys}/devices/system/cpu/cpu@{int}/topology/* r, - @{sys}/devices/system/cpu/cpufreq/policy@{int}/* r, + @{sys}/devices/system/cpu/cpu@{int}/topology/core_cpus r, + @{sys}/devices/system/cpu/cpu@{int}/topology/physical_package_id r, + @{sys}/devices/system/cpu/cpu@{int}/topology/thread_siblings r, + @{sys}/devices/system/cpu/cpu@{int}/topology/thread_siblings_list r, + @{sys}/devices/system/cpu/cpufreq/policy@{int}/cpuinfo_max_freq r, + @{sys}/devices/system/cpu/cpufreq/policy@{int}/cpuinfo_min_freq r, + @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_cur_freq r, + @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_max_freq r, @{sys}/devices/system/cpu/present r, + @{sys}/devices/system/node/ r, + @{sys}/devices/system/node/node@{int}/ r, + @{sys}/devices/system/node/node@{int}/cpumap r, @{sys}/devices/system/node/node@{int}/meminfo r, + @{sys}/devices/system/node/online r, include if exists diff --git a/apparmor.d/abstractions/graphics-full b/apparmor.d/abstractions/graphics-full index 1f2b0ffd2b..6e635c922d 100644 --- a/apparmor.d/abstractions/graphics-full +++ b/apparmor.d/abstractions/graphics-full @@ -4,11 +4,13 @@ abi , + include include + include + + include /dev/char/@{dynamic}:@{int} w, # For dynamic assignment range 234 to 254, 384 to 511 - /dev/nvidia-uvm rw, - /dev/nvidia-uvm-tools rw, include if exists diff --git a/apparmor.d/abstractions/gschemas b/apparmor.d/abstractions/gschemas new file mode 100644 index 0000000000..21a4d860c3 --- /dev/null +++ b/apparmor.d/abstractions/gschemas @@ -0,0 +1,14 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2009 Canonical Ltd. +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + @{system_share_dirs}/ r, + @{system_share_dirs}/glib-2.0/schemas/ r, + @{system_share_dirs}/glib-2.0/schemas/gschemas.compiled r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/gstreamer b/apparmor.d/abstractions/gstreamer index 10655740a6..91e332fa7d 100644 --- a/apparmor.d/abstractions/gstreamer +++ b/apparmor.d/abstractions/gstreamer @@ -5,66 +5,43 @@ abi , + include + include + + unix (bind listen) type=seqpacket addr=@@{hex}, + unix (bind listen) type=seqpacket addr=@@{hex}@{hex}, + + @{gstreamer_path} rix, + @{lib}/@{multiarch}/libproxy/*/modules/*.so mr, @{lib}/@{multiarch}/libvisual-@{version}/*/*.so mr, @{lib}/frei0r-@{int}/*.so mr, - @{lib}/@{multiarch}/gstreamer1.0/gstreamer-1.0/gst-plugin-scanner rix, - @{lib}/@{multiarch}/gstreamer-1.0/gst-plugin-scanner rix, - @{lib}/gstreamer-1.0/gst-plugin-scanner rix, + owner @{lib}/gstreamer-1.0/python/__pycache__/ w, + owner @{lib}/gstreamer-1.0/python/__pycache__/**.pyc.@{u64} w, /usr/share/gstreamer-1.0/presets/Gst*Enc.prs r, + /usr/share/ladspa/rdf/{,**} r, + /usr/share/xml/iso-codes/*.xml r, /etc/openni2/OpenNI.ini r, - /tmp/ r, /var/tmp/ r, - - owner @{HOME}/orcexec.@{rand6} rw, - - owner @{HOME}/.gstreamer-@{int}.@{int}/ rw, - owner @{HOME}/.gstreamer-@{int}.@{int}/registry.*.bin{,.tmp@{rand6}} rw, - - owner @{user_cache_dirs}/gstreamer-@{int}.@{int}/ rw, - owner @{user_cache_dirs}/gstreamer-@{int}.@{int}/registry.*.bin{,.tmp@{rand6}} rw, - - # The orcexec.* file is JIT compiled code for various GStreamer elements. - # If one is blocked the next is used instead. - # The orcexec file is placed under /home/user/ also when the /tmp/ dir is mounted with the noexec flag. - owner @{run}/user/@{uid}/orcexec.@{rand6} mrw, - #owner /tmp/orcexec.* mrw, - #owner @{HOME}/orcexec.* mrw, + /tmp/ r, @{run}/udev/data/+drm:card@{int}-* r, # For screen outputs - @{run}/udev/data/+usb:* r, # For /dev/bus/usb/** - @{run}/udev/data/c81:@{int} r, # For video4linux - @{run}/udev/data/c189:@{int} r, # For USB serial converters - @{run}/udev/data/c226:@{int} r, # For /dev/dri/card[0-9]* + @{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}/bus/usb/devices/ r, - @{sys}/class/ r, - @{sys}/class/drm/ r, - @{sys}/class/video4linux/ r, - @{sys}/devices/@{pci}/busnum r, - @{sys}/devices/@{pci}/config r, - @{sys}/devices/@{pci}/descriptors r, - @{sys}/devices/@{pci}/devnum r, - @{sys}/devices/@{pci}/numa_node r, - @{sys}/devices/@{pci}/speed r, - @{sys}/devices/@{pci}/uevent r, - @{sys}/devices/system/node/ r, - @{sys}/devices/system/node/node@{int}/cpumap r, - @{sys}/devices/system/node/node@{int}/meminfo r, - @{PROC}/devices r, + @{sys}/class/video4linux/ r, + @{sys}/devices/**/video4linux/video@{int}/ r, + @{sys}/devices/**/video4linux/video@{int}/uevent r, /dev/ r, - /dev/bus/usb/ r, - /dev/dri/ r, - /dev/nvidia-uvm rw, + /dev/char/@{dynamic}:@{int} w, # For dynamic assignment range 234 to 254, 384 to 511 include if exists diff --git a/apparmor.d/abstractions/gstreamer-registry b/apparmor.d/abstractions/gstreamer-registry new file mode 100644 index 0000000000..7d7a79b909 --- /dev/null +++ b/apparmor.d/abstractions/gstreamer-registry @@ -0,0 +1,34 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Plugin registry cache for the multimedia framework GStreamer. +# It stores metadata about all the GStreamer plugins available on the system, +# including their types, capabilities, and locations. +# +# It is usually needed by application calling GStreamer libraries. + + abi , + + owner @{desktop_cache_dirs}/gstreamer-1.0/ w, + owner @{desktop_cache_dirs}/gstreamer-1.0/registry.@{arch}.bin rw, + owner @{desktop_cache_dirs}/gstreamer-1.0/registry.@{arch}.bin.tmp@{rand6} rw, + + owner @{HOME}/.gstreamer-1.0/ rw, + owner @{HOME}/.gstreamer-1.0/registry.@{arch}.bin rw, + owner @{HOME}/.gstreamer-1.0/registry.@{arch}.bin.tmp@{rand6} rw, + + owner @{user_cache_dirs}/gstreamer-1.0/ rw, + owner @{user_cache_dirs}/gstreamer-1.0/registry.@{arch}.bin rw, + owner @{user_cache_dirs}/gstreamer-1.0/registry.@{arch}.bin.tmp@{rand6} rw, + + # The orcexec.* file is JIT compiled code for various GStreamer elements. + # If one is blocked the next is used instead. + # The orcexec file is placed under /home/user/ also when the /tmp/ dir is mounted with the noexec flag. + owner @{run}/user/@{uid}/orcexec.@{rand6} mrw, + deny owner @{HOME}/orcexec.@{rand6} mrw, + deny owner @{tmp}/orcexec.@{rand6} mrw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/gtk-strict b/apparmor.d/abstractions/gtk-strict new file mode 100644 index 0000000000..750bb75932 --- /dev/null +++ b/apparmor.d/abstractions/gtk-strict @@ -0,0 +1,104 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2021-2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + include + include + include + include + + #aa:only apparmor>=4.1 + #aa:only apparmor<5.0 ubuntu + unix type=stream peer=(label=glycin), + unix type=stream peer=(label=glycin//loaders), + signal send set=kill peer=glycin, + priority=-1 @{bin}/bwrap Px -> glycin, + + #aa:exclude ubuntu + #aa:only apparmor>=5.0 + # Need to be allowed for all peer because from the host namespace we do not + # see the glycin namespace. This is showned by 'peer=(label=---)' in the logs. + # + # As of today, we cannot specify the ns scope and view of the peer. + # See: https://gitlab.com/apparmor/apparmor/-/wikis/AppArmorPolicyView + unix (send receive) type=seqpacket, # peer=(label=---), # file_inherit + unix (send receive) type=stream, # peer=(label=---), # file_inherit + priority=-10 @{bin}/bwrap Px -> :glycin:bwrap, + + @{lib}/{,@{multiarch}/}gtk-2.0/{,**} mr, + @{lib}/{,@{multiarch}/}gtk-3.0/{,**} mr, + @{lib}/{,@{multiarch}/}gtk-4.0/{,**} mr, + + /usr/share/gtksourceview-2.0/{,**} r, + /usr/share/gtksourceview-3.0/{,**} r, + /usr/share/gtksourceview-4/{,**} r, + /usr/share/gtksourceview-5/{,**} r, + + /usr/share/glycin-loaders/{,**} r, + + /usr/share/gtk-2.0/ r, + /usr/share/gtk-2.0/gtkrc r, + + /usr/share/gtk-3.0/ r, + /usr/share/gtk-3.0/settings.ini r, + + /usr/share/gtk-4.0/ r, + /usr/share/gtk-4.0/settings.ini r, + + /etc/gtk/gtkrc r, + + /etc/gtk-2.0/ r, + /etc/gtk-2.0/gtkrc r, + + /etc/gtk-3.0/ r, + /etc/gtk-3.0/*.conf r, + /etc/gtk-3.0/settings.ini r, + + /etc/gtk-4.0/ r, + /etc/gtk-4.0/*.conf r, + /etc/gtk-4.0/settings.ini r, + + owner @{HOME}/.gtk r, + owner @{HOME}/.gtkrc r, + owner @{HOME}/.gtkrc-2.0 r, + owner @{HOME}/.gtk-bookmarks r, + + owner @{user_cache_dirs}/gtk-4.0/ rw, + owner @{user_cache_dirs}/gtk-4.0/vulkan-pipeline-cache/{,*} rw, + owner @{user_cache_dirs}/gtkrc r, + owner @{user_cache_dirs}/gtkrc-2.0 r, + + owner @{user_cache_dirs}/glycin/ w, + owner @{user_cache_dirs}/glycin/usr/ w, + owner @{user_cache_dirs}/glycin/usr/lib/ w, + owner @{user_cache_dirs}/glycin/usr/lib/glycin-loaders/ w, + owner @{user_cache_dirs}/glycin/usr/lib/glycin-loaders/@{d}+/ w, + owner @{user_cache_dirs}/glycin/usr/lib/glycin-loaders/@{d}+/glycin-svg/ w, + owner @{user_cache_dirs}/glycin/usr/lib/glycin-loaders/@{d}+/glycin-svg/fontconfig/ w, + + owner @{user_config_dirs}/gtk-2.0/ rw, + owner @{user_config_dirs}/gtk-2.0/gtkfilechooser.ini* rw, + + owner @{user_config_dirs}/gtk-3.0/ rw, + owner @{user_config_dirs}/gtk-3.0/bookmarks r, + owner @{user_config_dirs}/gtk-3.0/colors.css r, + owner @{user_config_dirs}/gtk-3.0/gtk.css r, + owner @{user_config_dirs}/gtk-3.0/servers r, + owner @{user_config_dirs}/gtk-3.0/settings.ini r, + owner @{user_config_dirs}/gtk-3.0/window_decorations.css r, + + owner @{user_config_dirs}/gtk-4.0/ rw, + owner @{user_config_dirs}/gtk-4.0/bookmarks r, + owner @{user_config_dirs}/gtk-4.0/colors.css r, + owner @{user_config_dirs}/gtk-4.0/gtk.css r, + owner @{user_config_dirs}/gtk-4.0/servers r, + owner @{user_config_dirs}/gtk-4.0/settings.ini r, + owner @{user_config_dirs}/gtk-4.0/window_decorations.css r, + + owner @{tmp}/gdk-pixbuf-glycin-tmp.@{rand6} rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/gtk.d/complete b/apparmor.d/abstractions/gtk.d/complete index 700e5e3057..d452d21fab 100644 --- a/apparmor.d/abstractions/gtk.d/complete +++ b/apparmor.d/abstractions/gtk.d/complete @@ -2,35 +2,33 @@ # Copyright (C) 2022-2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only - dbus send bus=session - interface=org.gtk.Actions - member=DescribeAll - peer=(name=@{busname}), - dbus send bus=session - interface=org.gtk.Actions - member=DescribeAll - peer=(label=gnome-shell), - - dbus receive bus=session - interface=org.gtk.Actions - member=Changed - peer=(name=@{busname}), - dbus receive bus=session - interface=org.gtk.Actions - member=Changed - peer=(label=gnome-shell), - - dbus send bus=session path=/org/gtk/Settings - interface=org.freedesktop.DBus.Properties - member=GetAll - peer=(name=@{busname}, label=gsd-xsettings), - dbus receive bus=session path=/org/gtk/Settings - interface=org.freedesktop.DBus.Properties - member=PropertiesChanged - peer=(name=@{busname}, label=gsd-xsettings), + include + include + include + include + + #aa:only apparmor>=4.1 + #aa:only apparmor<5.0 ubuntu + unix type=stream peer=(label=glycin), + unix type=stream peer=(label=glycin//loaders), + signal send set=kill peer=glycin, + priority=-1 @{bin}/bwrap Px -> glycin, + + #aa:exclude ubuntu + #aa:only apparmor>=5.0 + # Need to be allowed for all peer because from the host namespace we do not + # see the glycin namespace. This is showned by 'peer=(label=---)' in the logs. + # + # As of today, we cannot specify the ns scope and view of the peer. + # See: https://gitlab.com/apparmor/apparmor/-/wikis/AppArmorPolicyView + unix (send receive) type=seqpacket, # peer=(label=---), # file_inherit + unix (send receive) type=stream, # peer=(label=---), # file_inherit + priority=-10 @{bin}/bwrap Px -> :glycin:bwrap, @{lib}/{,@{multiarch}/}gtk*/** mr, + /usr/share/glycin-loaders/{,**} r, + /etc/gtk-{3,4}.0/settings.ini r, owner @{user_config_dirs}/gtk-{3,4}.0/ rw, @@ -41,4 +39,14 @@ owner @{user_config_dirs}/gtk-{3,4}.0/settings.ini r, owner @{user_config_dirs}/gtk-{3,4}.0/window_decorations.css r, + owner @{user_cache_dirs}/glycin/ w, + owner @{user_cache_dirs}/glycin/usr/ w, + owner @{user_cache_dirs}/glycin/usr/lib/ w, + owner @{user_cache_dirs}/glycin/usr/lib/glycin-loaders/ w, + owner @{user_cache_dirs}/glycin/usr/lib/glycin-loaders/@{d}+/ w, + owner @{user_cache_dirs}/glycin/usr/lib/glycin-loaders/@{d}+/glycin-svg/ w, + owner @{user_cache_dirs}/glycin/usr/lib/glycin-loaders/@{d}+/glycin-svg/fontconfig/ w, + + owner @{tmp}/gdk-pixbuf-glycin-tmp.@{rand6} rw, + # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/gvfs b/apparmor.d/abstractions/gvfs new file mode 100644 index 0000000000..92640a2da8 --- /dev/null +++ b/apparmor.d/abstractions/gvfs @@ -0,0 +1,15 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow access to GVFS files. + + abi , + + #aa:dbus talk bus=session name=org.gtk.vfs label="gvfsd{,-*}" + + owner @{run}/user/@{uid}/gvfsd/socket-@{rand8} rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/gvfs-backend b/apparmor.d/abstractions/gvfs-backend new file mode 100644 index 0000000000..1f8518b397 --- /dev/null +++ b/apparmor.d/abstractions/gvfs-backend @@ -0,0 +1,28 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow to act as a gvfs backend app + + abi , + + include + include + include + + #aa:dbus talk bus=session name=org.gtk.vfs.MountTracker path=/org/gtk/vfs/mounttracker label=gvfsd + + # Server's side of session/org.gtk.vfs.MountOperation + dbus send bus=session path=/org/gtk/gvfs/mountop/@{int} + interface=org.gtk.vfs.MountOperation + member={AskPassword,AskQuestion} + peer=(name=@{busname}), + + dbus receive bus=session + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/gvfs-metadata b/apparmor.d/abstractions/gvfs-metadata new file mode 100644 index 0000000000..873536f824 --- /dev/null +++ b/apparmor.d/abstractions/gvfs-metadata @@ -0,0 +1,20 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + include + + owner @{user_share_dirs}/gvfs-metadata/root r, + owner @{user_share_dirs}/gvfs-metadata/root-@{hex8}.log r, + + owner @{user_share_dirs}/gvfs-metadata/home r, + owner @{user_share_dirs}/gvfs-metadata/home-@{hex8}.log r, + + owner @{user_share_dirs}/gvfs-metadata/uuid-@{uuid} r, + owner @{user_share_dirs}/gvfs-metadata/uuid-@{uuid}-@{hex8}.log r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/hwmon b/apparmor.d/abstractions/hwmon new file mode 100644 index 0000000000..bfee9cf5ba --- /dev/null +++ b/apparmor.d/abstractions/hwmon @@ -0,0 +1,23 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# hwmon nodes are written in accordance with https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface + + abi , + + include + include + include + include + include + include + include + include + include + include + include + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/hwmon-write b/apparmor.d/abstractions/hwmon-write new file mode 100644 index 0000000000..92d2a53244 --- /dev/null +++ b/apparmor.d/abstractions/hwmon-write @@ -0,0 +1,25 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# hwmon-write abstraction includes all rules from hwmon with read permission +# and adds rules for write and write-only permission in hwmon structure + + abi , + + include + + include + include + include + include + include + include + include + include + include + include + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/ibus-strict b/apparmor.d/abstractions/ibus-strict new file mode 100644 index 0000000000..949171b0b9 --- /dev/null +++ b/apparmor.d/abstractions/ibus-strict @@ -0,0 +1,18 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow communicating with ibus-daemon (this allows sniffing key events) + + abi , + + owner @{user_cache_dirs}/ibus/dbus-@{rand8} rw, + + owner @{user_config_dirs}/ibus/ r, + owner @{user_config_dirs}/ibus/bus/ rw, + owner @{user_config_dirs}/ibus/bus/@{hex32}-unix-@{int} rw, + owner @{user_config_dirs}/ibus/bus/@{hex32}-unix-wayland-@{int} rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/ibus.d/complete b/apparmor.d/abstractions/ibus.d/complete index 5c53b9fa17..3ecd8c36d6 100644 --- a/apparmor.d/abstractions/ibus.d/complete +++ b/apparmor.d/abstractions/ibus.d/complete @@ -8,6 +8,7 @@ type=stream peer=(addr="@/tmp/ibus/dbus-????????"), + #aa:lint ignore=tunables # abstract path in ibus >= 1.5.22 uses $XDG_CACHE_HOME (ie, @{user_cache_dirs}) # This should use this, but due to LP: #1856738 we cannot #unix (connect, receive, send) @@ -16,7 +17,6 @@ unix (connect, receive, send) type=stream peer=(addr="@/home/*/.cache/ibus/dbus-????????"), - unix (connect, send, receive, accept, bind, listen) type=stream addr="@/home/*/.cache/ibus/dbus-????????", diff --git a/apparmor.d/abstractions/icons b/apparmor.d/abstractions/icons new file mode 100644 index 0000000000..6a721b8370 --- /dev/null +++ b/apparmor.d/abstractions/icons @@ -0,0 +1,23 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2009 Canonical Ltd. +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + @{system_share_dirs}/icons/{,**} r, + @{system_share_dirs}/pixmaps/{,**} r, + + /opt/**/share/icons/{,**} r, + /opt/*/**.desktop r, + /opt/*/**/*.png r, + + /var/lib/snapd/desktop/icons/{,**} r, + + owner @{HOME}/.icons/{,**} r, + + owner @{user_share_dirs}/icons/{,**} r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/input b/apparmor.d/abstractions/input new file mode 100644 index 0000000000..8270ed477d --- /dev/null +++ b/apparmor.d/abstractions/input @@ -0,0 +1,38 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2021 Canonical Ltd +# Copyright (C) 2022-2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow reading and writing to raw input devices + + abi , + + @{sys}/class/input/ r, + + # Allow reading for supported event reports for all input devices. See + # https://www.kernel.org/doc/Documentation/input/event-codes.txt + @{sys}/devices/**/input@{int}/capabilities/* r, + + @{sys}/devices/**/input@{int}/ r, + @{sys}/devices/**/input@{int}/{,**/}name r, + @{sys}/devices/**/input@{int}/{,**/}properties r, + @{sys}/devices/**/input@{int}/{,**/}uevent r, + @{sys}/devices/**/input@{int}/event@{int}/ r, + @{sys}/devices/**/input@{int}/event@{int}/uevent r, + @{sys}/devices/**/input@{int}/id/ r, + @{sys}/devices/**/input@{int}/id/product r, + @{sys}/devices/**/input@{int}/id/vendor r, + @{sys}/devices/**/input/ r, + + @{run}/udev/data/+input:input@{int} r, # for mouse, keyboard, touchpad + @{run}/udev/data/c13:@{int} r, # for /dev/input/* + + /dev/input/ r, + /dev/input/event@{int} rw, + /dev/input/js@{int} rw, + /dev/input/mice rw, + /dev/input/mouse@{int} rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/java b/apparmor.d/abstractions/java new file mode 100644 index 0000000000..0931fe8545 --- /dev/null +++ b/apparmor.d/abstractions/java @@ -0,0 +1,21 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + /usr/share/java/{,**} r, + + /etc/java/{,**} r, + /etc/java-*/{,**} r, + + @{sys}/devices/system/cpu/cpu@{int}/microcode/version r, + + @{PROC}/cgroups r, + + # Control which memory segments are written to the core dump file + owner @{PROC}/@{pid}/coredump_filter rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/kde-base b/apparmor.d/abstractions/kde-base new file mode 100644 index 0000000000..9247e8647c --- /dev/null +++ b/apparmor.d/abstractions/kde-base @@ -0,0 +1,43 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2021-2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Minimal kde specific rules. + + abi , + + @{lib}/kde{,3,4}/*.so mr, + @{lib}/kde{,3,4}/plugins/*/ r, + @{lib}/kde{,3,4}/plugins/*/*.so mr, + + /usr/share/knotifications{5,6}/*.notifyrc r, + /usr/share/kubuntu-default-settings/{,**} r, + + /etc/xdg/baloofilerc r, + /etc/xdg/kcminputrc r, + /etc/xdg/kdeglobals r, + /etc/xdg/kwinrc r, + + owner @{user_cache_dirs}/#@{int} rw, + owner @{user_cache_dirs}/icon-cache.kcache rw, + owner @{user_cache_dirs}/ksycoca{5,6}_??{_,-}* rwlk, + + owner @{user_config_dirs}/baloofilerc r, + owner @{user_config_dirs}/dolphinrc r, + owner @{user_config_dirs}/kcminputrc r, + owner @{user_config_dirs}/kdedefaults/ r, + owner @{user_config_dirs}/kdedefaults/kcminputrc r, + owner @{user_config_dirs}/kdedefaults/kdeglobals r, + owner @{user_config_dirs}/kdedefaults/kwinrc r, + owner @{user_config_dirs}/kdeglobals r, + owner @{user_config_dirs}/kwinrc r, + owner @{user_config_dirs}/session/ rw, + owner @{user_config_dirs}/session/* rwlk, + owner @{user_config_dirs}/session/#@{int} rw, + owner @{user_config_dirs}/trashrc r, + + owner @{user_share_dirs}/#@{int} rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/kde-strict b/apparmor.d/abstractions/kde-strict index 0f4410a123..a8f9cf33a6 100644 --- a/apparmor.d/abstractions/kde-strict +++ b/apparmor.d/abstractions/kde-strict @@ -4,42 +4,34 @@ abi , - include - include - include + # Common abstractions for any desktop environment + include + include + include + include + include #aa:only ubuntu + include + include + include + include + include + include + include + include + include + include + include + include include - include + include + include + include + include include include - @{lib}/kde{,3,4}/*.so mr, - @{lib}/kde{,3,4}/plugins/*/ r, - @{lib}/kde{,3,4}/plugins/*/*.so mr, - - /usr/share/desktop-base/{,**} r, - /usr/share/hwdata/*.ids r, - /usr/share/icu/@{int}.@{int}/*.dat r, - /usr/share/knotifications{5,6}/*.notifyrc r, - - /etc/xdg/baloofilerc r, - /etc/xdg/kcminputrc r, - /etc/xdg/kdeglobals r, - /etc/xdg/kwinrc r, - - owner @{user_cache_dirs}/#@{int} rw, - owner @{user_cache_dirs}/icon-cache.kcache rw, - owner @{user_cache_dirs}/ksycoca{5,6}_??{_,-}*.@{rand6} rwlk, - - owner @{user_config_dirs}/baloofilerc r, - owner @{user_config_dirs}/dolphinrc r, - owner @{user_config_dirs}/kcminputrc r, - owner @{user_config_dirs}/kdedefaults/ r, - owner @{user_config_dirs}/kdedefaults/kcminputrc r, - owner @{user_config_dirs}/kdedefaults/kdeglobals r, - owner @{user_config_dirs}/kdedefaults/kwinrc r, - owner @{user_config_dirs}/kdeglobals r, - owner @{user_config_dirs}/kwinrc r, - owner @{user_config_dirs}/trashrc r, + # Kde specific rules + include include if exists diff --git a/apparmor.d/abstractions/ld b/apparmor.d/abstractions/ld new file mode 100644 index 0000000000..c3bbcec8a1 --- /dev/null +++ b/apparmor.d/abstractions/ld @@ -0,0 +1,29 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2002-2009 Novell/SUSE +# Copyright (C) 2009-2011 Canonical Ltd. +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# ld.so.cache and ld are used to load shared libraries, therefore they are +# required by almost all applications. +# +# !!! note +# +# As this abstraction is included in the `base` / `base-strict` abstractions. +# It is not necessary to include it manually. +# + + abi , + + /opt/*-linux-uclibc/lib/ld-uClibc*so* mr, + + @{etc_ro}/ld.so.cache mr, + @{etc_ro}/ld.so.conf r, + @{etc_ro}/ld.so.conf.d/ r, + @{etc_ro}/ld.so.conf.d/*.conf r, + @{etc_ro}/ld.so.preload r, + @{etc_ro}/ld-musl-*.path r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/libvirt-qemu.d/complete b/apparmor.d/abstractions/libvirt-qemu.d/complete new file mode 100644 index 0000000000..7397cb32dd --- /dev/null +++ b/apparmor.d/abstractions/libvirt-qemu.d/complete @@ -0,0 +1,8 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + unix type=stream peer=(label=virtiofsd), + unix type=stream peer=(label=virt-manager), + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/locale b/apparmor.d/abstractions/locale new file mode 100644 index 0000000000..c275820790 --- /dev/null +++ b/apparmor.d/abstractions/locale @@ -0,0 +1,33 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2002-2009 Novell/SUSE +# Copyright (C) 2009-2011 Canonical Ltd. +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# !!! note +# +# As this abstraction is included in the `base` / `base-strict` abstractions. +# It is not necessary to include it manually. +# + + abi , + + @{etc_ro}/locale.alias r, + @{etc_ro}/locale.conf r, + @{etc_ro}/locale/** r, + @{etc_ro}/localtime r, + @{etc_rw}/localtime r, + + /usr/share/**/locale/** r, + /usr/share/coreutils/locales/** r, + /usr/share/locale-bundle/** r, + /usr/share/locale-langpack/** r, + /usr/share/locale/ r, + /usr/share/locale/** r, + /usr/share/X11/locale/** r, + /usr/share/zoneinfo{,-icu}/ r, + /usr/share/zoneinfo{,-icu}/** r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/localization b/apparmor.d/abstractions/localization new file mode 100644 index 0000000000..cdeb1ba1cf --- /dev/null +++ b/apparmor.d/abstractions/localization @@ -0,0 +1,11 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + include + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/localization-control b/apparmor.d/abstractions/localization-control new file mode 100644 index 0000000000..c6906be34f --- /dev/null +++ b/apparmor.d/abstractions/localization-control @@ -0,0 +1,23 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + include + + # GeoClue2 + + dbus send bus=system path=/org/freedesktop/GeoClue2/Client/@{int} + interface=org.freedesktop.DBus.Properties + member=Set + peer=(name=@{busname}, label="@{p_geoclue}"), + + dbus send bus=system path=/org/freedesktop/GeoClue2/Client/@{int} + interface=org.freedesktop.GeoClue2.Client + member={Start,Stop} + peer=(name=@{busname}, label="@{p_geoclue}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/login-observe b/apparmor.d/abstractions/login-observe new file mode 100644 index 0000000000..8f6286a8c2 --- /dev/null +++ b/apparmor.d/abstractions/login-observe @@ -0,0 +1,36 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Check login session observe & login session control + + abi , + + dbus receive bus=system path=/org/freedesktop/login1 + interface=org.freedesktop.login1.Manager + member={SessionNew,UserNew,SeatNew} + peer=(name="{@{busname},org.freedesktop.login1}", label="@{p_systemd_logind}"), + + dbus receive bus=system path=/org/freedesktop/login1 + interface=org.freedesktop.login1.Manager + member={SessionRemoved,UserRemoved,SeatRemoved} + peer=(name="{@{busname},org.freedesktop.login1}", label="@{p_systemd_logind}"), + + dbus receive bus=system path=/org/freedesktop/login1 + interface=org.freedesktop.login1.Manager + member={PrepareForShutdow,PrepareForSleep} + peer=(name="{@{busname},org.freedesktop.login1}", label="@{p_systemd_logind}"), + + dbus send bus=system path=/org/freedesktop/login1 + interface=org.freedesktop.login1.Manager + member={ListSeats,ListSessions,ListUsers} + peer=(name="{@{busname},org.freedesktop.login1}", label="@{p_systemd_logind}"), + + dbus send bus=system path=/org/freedesktop/login1 + interface=org.freedesktop.login1.Manager + member={GetSeat,GetSessions,GetSessionByPID,GetUsers} + peer=(name="{@{busname},org.freedesktop.login1}", label="@{p_systemd_logind}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/lttng b/apparmor.d/abstractions/lttng new file mode 100644 index 0000000000..eb266f0ddf --- /dev/null +++ b/apparmor.d/abstractions/lttng @@ -0,0 +1,27 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# LTTng is an open source tracing framework for Linux - https://lttng.org +# +# Lttng tracing is very noisy and should not be allowed by confined apps. +# +# !!! note +# +# As this abstraction is included in the `base` / `base-strict` abstractions. +# It is not necessary to include it manually. +# + + abi , + + deny @{run}/shm/lttng-ust-@{int} rwl, + deny owner @{run}/shm/lttng-ust-@{int}-@{uid} rwl, + deny owner @{run}/shm/lttng-ust-@{int}-@{int} rwl, + + deny /dev/shm/lttng-ust-wait-@{int} rwl, + deny owner /dev/shm/lttng-ust-wait-@{int}-@{int} rwl, + deny owner /dev/shm/lttng-ust-wait-@{int}-@{uid} rwl, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/lxqt b/apparmor.d/abstractions/lxqt index f20c24a323..3dd7848d81 100644 --- a/apparmor.d/abstractions/lxqt +++ b/apparmor.d/abstractions/lxqt @@ -4,12 +4,25 @@ abi , - include - include - include - include + include + include + include + include + include + include + include + include + include + include + include + include + include + include include - include + include + include + include + include include include diff --git a/apparmor.d/abstractions/mapping/login b/apparmor.d/abstractions/mapping/login index 54a8c1c7f1..40139796f0 100644 --- a/apparmor.d/abstractions/mapping/login +++ b/apparmor.d/abstractions/mapping/login @@ -25,12 +25,13 @@ dbus send bus=system path=/org/freedesktop/login1 interface=org.freedesktop.login1.Manager member=ReleaseSession - peer=(name=org.freedesktop.login1, label=systemd-logind), + peer=(name=org.freedesktop.login1, label="@{p_systemd_logind}"), @{etc_ro}/security/group.conf r, @{etc_ro}/security/limits.conf r, @{etc_ro}/security/limits.d/{,*} r, @{etc_ro}/security/pam_env.conf r, + @{etc_ro}/security/pam_env.conf.d/{,*} r, @{etc_ro}/login.defs r, @{etc_ro}/login.defs.d/{,*} r, diff --git a/apparmor.d/abstractions/mapping/sshd b/apparmor.d/abstractions/mapping/sshd index bb0064956c..b4a0be1df8 100644 --- a/apparmor.d/abstractions/mapping/sshd +++ b/apparmor.d/abstractions/mapping/sshd @@ -15,6 +15,8 @@ capability audit_write, capability chown, capability dac_read_search, + capability fowner, + capability fsetid, capability kill, capability setgid, capability setuid, @@ -25,18 +27,20 @@ # but will fall back to a non-privileged version if it fails. deny capability net_admin, + network inet stream, network inet6 stream, network netlink raw, - signal receive set=exists peer=systemd-journald, + signal receive set=exists peer=@{p_systemd_journald}, signal receive set=hup peer=@{p_systemd}, + unix bind type=stream addr=@@{udbus}/bus/sshd-session/system, unix bind type=stream addr=@@{udbus}/bus/sshd/system, dbus send bus=system path=/org/freedesktop/login1 interface=org.freedesktop.login1.Manager member={CreateSession,ReleaseSession,CreateSessionWithPIDFD} - peer=(name=org.freedesktop.login1, label=systemd-logind), + peer=(name=org.freedesktop.login1, label="@{p_systemd_logind}"), /etc/motd r, /etc/locale.conf r, @@ -47,7 +51,7 @@ @{PROC}/1/limits r, /dev/ptmx rw, - /dev/pts/@{int} k, + /dev/pts/@{u16} k, include if exists diff --git a/apparmor.d/abstractions/media-control b/apparmor.d/abstractions/media-control new file mode 100644 index 0000000000..20bc59fc4c --- /dev/null +++ b/apparmor.d/abstractions/media-control @@ -0,0 +1,23 @@ +# 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 , + + @{sys}/bus/media/devices/ r, + + # 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/mediakeys b/apparmor.d/abstractions/mediakeys new file mode 100644 index 0000000000..d9aafa7646 --- /dev/null +++ b/apparmor.d/abstractions/mediakeys @@ -0,0 +1,15 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow requesting interest in receiving media key events. This tells Gnome +# settings that our application should be notified when key events we are +# interested in are pressed, and allows us to receive those events. + + abi , + + include + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/mesa.d/complete b/apparmor.d/abstractions/mesa.d/complete index a191663674..a2de919808 100644 --- a/apparmor.d/abstractions/mesa.d/complete +++ b/apparmor.d/abstractions/mesa.d/complete @@ -2,6 +2,20 @@ # Copyright (C) 2021-2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only + # Fallback location when @{user_cache_dirs} is not available + /var/cache/mesa_shader_cache_db/ rw, + /var/cache/mesa_shader_cache_db/index rw, + /var/cache/mesa_shader_cache_db/marker rw, + /var/cache/mesa_shader_cache_db/part@{int}/ rw, + /var/cache/mesa_shader_cache_db/part@{int}/mesa_cache.db rwk, + /var/cache/mesa_shader_cache_db/part@{int}/mesa_cache.idx rwk, + /var/cache/mesa_shader_cache/ rw, + /var/cache/mesa_shader_cache/@{hex2}/ rw, + /var/cache/mesa_shader_cache/@{hex2}/@{hex} rw, + /var/cache/mesa_shader_cache/@{hex2}/@{hex}.tmp rwk, + /var/cache/mesa_shader_cache/index rw, + /var/cache/mesa_shader_cache/marker rw, + # Extra Mesa rules for desktop environments owner @{desktop_cache_dirs}/ w, owner @{desktop_cache_dirs}/mesa_shader_cache_db/ rw, @@ -12,8 +26,8 @@ owner @{desktop_cache_dirs}/mesa_shader_cache_db/part@{int}/mesa_cache.idx rwk, owner @{desktop_cache_dirs}/mesa_shader_cache/ rw, owner @{desktop_cache_dirs}/mesa_shader_cache/@{hex2}/ rw, - owner @{desktop_cache_dirs}/mesa_shader_cache/@{hex2}/@{hex38} rw, - owner @{desktop_cache_dirs}/mesa_shader_cache/@{hex2}/@{hex38}.tmp rwk, + owner @{desktop_cache_dirs}/mesa_shader_cache/@{hex2}/@{hex} rw, + owner @{desktop_cache_dirs}/mesa_shader_cache/@{hex2}/@{hex}.tmp rwk, owner @{desktop_cache_dirs}/mesa_shader_cache/index rw, owner @{desktop_cache_dirs}/mesa_shader_cache/marker rw, @@ -26,6 +40,15 @@ owner @{user_cache_dirs}/mesa_shader_cache_db/part@{int}/mesa_cache.db rwk, owner @{user_cache_dirs}/mesa_shader_cache_db/part@{int}/mesa_cache.idx rwk, + owner @{user_cache_dirs}/radv_builtin_shaders/ w, + owner @{user_cache_dirs}/radv_builtin_shaders/index rw, + owner @{user_cache_dirs}/radv_builtin_shaders/marker rw, + owner @{user_cache_dirs}/radv_builtin_shaders/part@{int}/ rw, + owner @{user_cache_dirs}/radv_builtin_shaders/part@{int}/mesa_cache.db rwk, + owner @{user_cache_dirs}/radv_builtin_shaders/part@{int}/mesa_cache.idx rwk, + @{PROC}/sys/dev/xe/observation_paranoid r, + /dev/udmabuf rw, # In upstream, but not released yet + # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/mime b/apparmor.d/abstractions/mime new file mode 100644 index 0000000000..e4e9463412 --- /dev/null +++ b/apparmor.d/abstractions/mime @@ -0,0 +1,30 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2009 Canonical Ltd. +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + @{system_share_dirs}/ r, + @{system_share_dirs}/mime/{,**} r, + + # if "gdm" in @{DM} { + /usr/share/gdm/greeter/applications/ r, + /usr/share/gdm/greeter/applications/mimeapps.list r, + # } + + /etc/httpd/conf/mime.types r, + /etc/mime.types r, + /etc/xdg/{,*-}mimeapps.list r, + + # if "gnome" in @{DE} { + /var/cache/gio-@{version}/{,*-}-mimeapps.list r, + # } + + owner @{user_config_dirs}/mimeapps.list r, + + owner @{user_share_dirs}/mime/{,**} r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/modem-manager-observe b/apparmor.d/abstractions/modem-manager-observe new file mode 100644 index 0000000000..3c64433caf --- /dev/null +++ b/apparmor.d/abstractions/modem-manager-observe @@ -0,0 +1,14 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allows observing ModemManager settings. It grants access to listing +# MAC addresses, previous networks, etc but not secrets. + + abi , + + include + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/mpris b/apparmor.d/abstractions/mpris new file mode 100644 index 0000000000..2f7feccb14 --- /dev/null +++ b/apparmor.d/abstractions/mpris @@ -0,0 +1,31 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow operating as an MPRIS player. + + abi , + + include + + # Allow binding to the well-known DBus mpris interface based on the app's name + # See: https://specifications.freedesktop.org/mpris-spec/latest/ + #aa:dbus own bus=session name=org.mpris.MediaPlayer2.@{profile_name} + + # DBus.Properties: receive properties from any mpris controller + + dbus receive bus=system path=/org/mpris/MediaPlayer2 + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name=@{busname}, label="@{pp_mpris}"), + + # DBus.Properties: send property changed events to any mpris controller + + dbus send bus=session path=/org/mpris/MediaPlayer2 + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name=org.freedesktop.DBus, label="@{pp_mpris}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/network-manager-observe b/apparmor.d/abstractions/network-manager-observe new file mode 100644 index 0000000000..64e6951e57 --- /dev/null +++ b/apparmor.d/abstractions/network-manager-observe @@ -0,0 +1,15 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2019 Canonical Ltd +# Copyright (C) 2023-2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allows observing NetworkManager settings. It grants access to listing +# MAC addresses, previous networks, etc but not secrets. + + abi , + + include + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/notifications b/apparmor.d/abstractions/notifications new file mode 100644 index 0000000000..29d227e2b7 --- /dev/null +++ b/apparmor.d/abstractions/notifications @@ -0,0 +1,13 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + include + include + include + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/nss b/apparmor.d/abstractions/nss new file mode 100644 index 0000000000..af7a85881e --- /dev/null +++ b/apparmor.d/abstractions/nss @@ -0,0 +1,20 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Network Security Services (NSS) +# +# It only allows access to the system-provided configuration files, not the ones +# that are applications specific. + + abi , + + owner @{HOME}/.pki/ rw, + owner @{HOME}/.pki/nssdb/ rw, + owner @{HOME}/.pki/nssdb/pkcs11.txt rw, + owner @{HOME}/.pki/nssdb/{cert9,key4}.db rwk, + owner @{HOME}/.pki/nssdb/{cert9,key4}.db-journal rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/nss-systemd.d/complete b/apparmor.d/abstractions/nss-systemd.d/complete new file mode 100644 index 0000000000..d277f8e637 --- /dev/null +++ b/apparmor.d/abstractions/nss-systemd.d/complete @@ -0,0 +1,8 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + @{run}/systemd/io.systemd.NamespaceResource rw, + @{run}/systemd/resolve/io.systemd.Resolve rw, + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/nvidia-drivers b/apparmor.d/abstractions/nvidia-drivers new file mode 100644 index 0000000000..0137e42221 --- /dev/null +++ b/apparmor.d/abstractions/nvidia-drivers @@ -0,0 +1,30 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023 Canonical Ltd +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow creating nvidia device files to be used by unprivileged user-space programs + + abi , + + capability mknod, + + # To read dynamically allocated MAJOR for nvidia-uvm + @{PROC}/devices r, + + # Nvidia proprietary modset driver + /dev/nvidia-modeset w, + + # Nvidia's Unified Memory driver + /dev/nvidia-uvm w, + /dev/nvidia-uvm-tools w, + + # Nvidia graphics devices + /dev/nvidia@{int} rw, + + # Global control device for driver-wide operations. + /dev/nvidiactl rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/nvidia-strict b/apparmor.d/abstractions/nvidia-strict index a3948e144b..9a1cf7e04a 100644 --- a/apparmor.d/abstractions/nvidia-strict +++ b/apparmor.d/abstractions/nvidia-strict @@ -4,35 +4,72 @@ abi , + dbus bind bus=system name=nvidia.nvfbc.pid_@{pid}, + @{bin}/nvidia-modprobe Px -> child-modprobe-nvidia, + /opt/cuda/targets/@{arch}-linux/lib/*.so mr, + /opt/cuda/targets/@{arch}-linux/lib/*.so.* mr, + /usr/share/nvidia/nvidia-application-profiles-* r, /etc/nvidia/nvidia-application-profiles-* r, + /etc/nvidia/nvidia-application-profiles-rc.d/{,*} r, /etc/vdpau_wrapper.cfg r, - owner @{HOME}/.cache/nvidia/ w, - owner @{HOME}/.cache/nvidia/GLCache/ rw, - owner @{HOME}/.cache/nvidia/GLCache/** rwk, + owner @{DESKTOP_HOME}/.nv/ w, + owner @{DESKTOP_HOME}/.nv/ComputeCache/ w, + owner @{DESKTOP_HOME}/.nv/ComputeCache/** rw, + owner @{DESKTOP_HOME}/.nv/ComputeCache/index rwk, + + owner @{HOME}/.nv/ w, owner @{HOME}/.nv/ComputeCache/ w, owner @{HOME}/.nv/ComputeCache/** rw, owner @{HOME}/.nv/ComputeCache/index rwk, owner @{HOME}/.nv/nvidia-application-profiles-* r, + @{user_cache_dirs}/nvidia/GLCache/@{hex32}/ rw, + owner @{user_cache_dirs}/nvidia/ w, + owner @{user_cache_dirs}/nvidia/GLCache/ rw, + owner @{user_cache_dirs}/nvidia/GLCache/** rwk, + + @{sys}/devices/@{pci}/numa_node r, @{sys}/devices/system/memory/block_size_bytes r, + @{sys}/module/nvidia_drm/version r, @{sys}/module/nvidia/version r, - @{PROC}/driver/nvidia/params r, - @{PROC}/modules r, - @{PROC}/sys/vm/max_map_count r, - @{PROC}/sys/vm/mmap_min_addr r, - owner @{PROC}/@{pid}/cmdline r, - owner @{PROC}/@{pid}/comm r, + @{PROC}/devices r, + @{PROC}/driver/nvidia/capabilities/mig/config r, + @{PROC}/driver/nvidia/capabilities/mig/monitor r, + @{PROC}/driver/nvidia/gpus/@{pci_id}/information r, + @{PROC}/driver/nvidia/params r, + @{PROC}/modules r, + @{PROC}/sys/vm/max_map_count r, + @{PROC}/sys/vm/mmap_min_addr r, + + @{PROC}/@{pid}/cmdline r, + @{PROC}/@{pid}/comm r, owner @{PROC}/@{pid}/task/@{tid}/comm r, - /dev/char/195:@{int} w, # Nvidia graphics devices + /dev/ r, + + # Nvidia graphics devices + /dev/char/195:@{u8} w, + + # Dynamic device files for nvidia-uvm and nvidia-uvm-tools + /dev/char/@{dynamic}:@{int} w, # For dynamic assignment range 234 to 254, 384 to 511 + + # Nvidia proprietary modset driver /dev/nvidia-modeset rw, + + # Nvidia graphics devices /dev/nvidia@{int} rw, + + # Nvidia's Unified Memory driver + /dev/nvidia-uvm rw, + /dev/nvidia-uvm-tools rw, + + # Nvidia's control device /dev/nvidiactl rw, deny owner @{HOME}/.nv/.local/share/gvfs-metadata/* r, diff --git a/apparmor.d/abstractions/nvidia.d/complete b/apparmor.d/abstractions/nvidia.d/complete index ef9d0c40d5..e00385efdf 100644 --- a/apparmor.d/abstractions/nvidia.d/complete +++ b/apparmor.d/abstractions/nvidia.d/complete @@ -8,6 +8,6 @@ /etc/nvidia/nvidia-application-profiles* r, - /dev/char/195:@{int} rw, # Nvidia graphics devices + /dev/char/195:@{u8} rw, # Nvidia graphics devices # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/oneapi b/apparmor.d/abstractions/oneapi new file mode 100644 index 0000000000..17225ef035 --- /dev/null +++ b/apparmor.d/abstractions/oneapi @@ -0,0 +1,14 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Intel oneAPI compiler libraries + + abi , + + /opt/intel/oneapi/{compiler,lib,mkl}/**/ r, + /opt/intel/oneapi/{compiler,lib,mkl}/**.so* mr, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/path b/apparmor.d/abstractions/path new file mode 100644 index 0000000000..9e636e280a --- /dev/null +++ b/apparmor.d/abstractions/path @@ -0,0 +1,27 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Common directories in $PATH, used by launchers and interactive shells. + + abi , + + @{bin}/ r, + @{bin}/*/ r, + @{sbin}/ r, + @{sbin}/*/ r, + + / r, + /usr/ r, + /usr/local/bin/ r, + /usr/local/sbin/ r, + + @{user_bin_dirs}/ r, + + /snap/bin/ r, + /opt/cuda/bin/ r, + /var/lib/flatpak/exports/bin/ r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/pcscd b/apparmor.d/abstractions/pcscd new file mode 100644 index 0000000000..33a981279e --- /dev/null +++ b/apparmor.d/abstractions/pcscd @@ -0,0 +1,19 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023 Canonical Ltd +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allows interacting with PC/SC Smart Card Daemon + + abi , + + # Configuration file for OPENSC + /etc/opensc.conf r, + /etc/opensc/opensc.conf r, + + # Socket for communication between PCSCD and PS/SC API library + @{run}/pcscd/pcscd.comm rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/power-profiles b/apparmor.d/abstractions/power-profiles new file mode 100644 index 0000000000..60da8a3164 --- /dev/null +++ b/apparmor.d/abstractions/power-profiles @@ -0,0 +1,14 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow to read power profiles configuration. + + abi , + + include + include + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/python.d/complete b/apparmor.d/abstractions/python.d/complete index e372c312c2..35a5d34523 100644 --- a/apparmor.d/abstractions/python.d/complete +++ b/apparmor.d/abstractions/python.d/complete @@ -4,12 +4,24 @@ # SPDX-License-Identifier: GPL-2.0-only @{bin}/ r, - @{python_path} rm, + @{python_path} mr, - owner @{user_lib_dirs}/@{python_name}/ r, - owner @{user_lib_dirs}/@{python_name}/**.{egg,py,pyi,pth} r, - owner @{user_lib_dirs}/@{python_name}/**.{pyc,so} mr, - owner @{user_lib_dirs}/@{python_name}/{site,dist}-packages/ r, + @{user_lib_dirs}/@{python_name}/ r, + @{user_lib_dirs}/@{python_name}/site-packages/ r, + owner @{user_lib_dirs}/@{python_name}/{site,dist}-packages/ r, owner @{user_lib_dirs}/@{python_name}/{site,dist}-packages/**/ r, + owner @{user_lib_dirs}/@{python_name}/**.{egg,py,pyi,pth} r, + owner @{user_lib_dirs}/@{python_name}/**.{pyc,so} mr, + owner @{user_lib_dirs}/@{python_name}/**/entry_points.txt r, + + #aa:only apparmor>=4.1 + # Normal python run do not need to update pycache files. It is done by pycompile. + audit @{lib}/@{python_name}/{,**/}__pycache__/ w, + audit @{lib}/@{python_name}/{,**/}__pycache__/**.pyc w, + audit @{lib}/@{python_name}/{,**/}__pycache__/**.pyc.@{u64} w, + + #aa:only test + owner /tmp/pytest-of-user/ rw, + owner /tmp/pytest-of-user/** rwlk, # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/recently-used b/apparmor.d/abstractions/recently-used new file mode 100644 index 0000000000..66a80867b2 --- /dev/null +++ b/apparmor.d/abstractions/recently-used @@ -0,0 +1,19 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2009 Canonical Ltd. +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + owner @{HOME}/.recently-used.xbel rw, + owner @{HOME}/.recently-used.xbel.@{rand6} rwl, + owner @{HOME}/.recently-used.xbel.lock rwk, + + owner @{user_share_dirs}/#@{int} rw, + owner @{user_share_dirs}/recently-used.xbel rw, + owner @{user_share_dirs}/recently-used.xbel.@{rand6} rwl, + owner @{user_share_dirs}/recently-used.xbel.lock rwk, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/ruby.d/complete b/apparmor.d/abstractions/ruby.d/complete new file mode 100644 index 0000000000..f987925b4f --- /dev/null +++ b/apparmor.d/abstractions/ruby.d/complete @@ -0,0 +1,8 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + #aa:only test + /usr/share/rubygems-integration/{,**} r, + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/screen-inhibit b/apparmor.d/abstractions/screen-inhibit new file mode 100644 index 0000000000..50320a4fba --- /dev/null +++ b/apparmor.d/abstractions/screen-inhibit @@ -0,0 +1,60 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2016 Canonical Ltd +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Can inhibit and uninhibit screen savers in desktop sessions. + + abi , + + # Allow listing bus names to check for screen saver presence and implementation + dbus send bus=session path=/org/freedesktop/DBus + interface=org.freedesktop.DBus + member=ListNames + peer=(name=org.freedesktop.DBus, label="@{p_dbus_session}"), + + # Gnome Session, not using bus/session/org.gnome.SessionManager as it allows + # full session management + dbus send bus=session path=/org/gnome/SessionManager + interface=org.gnome.SessionManager + member={Inhibit,Uninhibit} + peer=(name="{@{busname},org.gnome.SessionManager}", label="@{p_gnome_session}"), + + dbus send bus=session path=/ScreenSaver + interface=org.gnome.ScreenSaver + member=SimulateUserActivity + peer=(name="{@{busname},org.gnome.SessionManager}", label="@{p_gnome_session}"), + + # Generic freedesktop, not using bus/session/org.freedesktop.ScreenSaver as + # it allows too much + dbus send bus=session path=/ScreenSaver + interface=org.freedesktop.ScreenSaver + member={Inhibit,UnInhibit,SimulateUserActivity} + peer=(name=org.freedesktop.ScreenSaver), + + dbus send bus=session path=/org/gnome/ScreenSaver + interface=org.{freedesktop,gnome}.ScreenSaver + member={Inhibit,UnInhibit,SimulateUserActivity} + peer=(name=@{busname}, label=gjs), + + dbus send bus=system path=/org/freedesktop/login1 + interface=org.freedesktop.login1.Manager + member=Inhibit + peer=(name=org.freedesktop.login1, label=systemd-logind), + + # Login session manager + dbus send bus=system path=/org/freedesktop/login1 + interface=org.freedesktop.login1.Manager + member=Inhibit + peer=(name=org.freedesktop.login1, label="@{p_systemd_logind}"), + + # Receive shutdown & sleep notifications + + dbus receive bus=system path=/org/freedesktop/login1 + interface=org.freedesktop.login1.Manager + member={PrepareForShutdown,PrepareForShutdownWithMetadata} + peer=(name="{@{busname},org.freedesktop.login1}", label="@{p_systemd_logind}"), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/screensaver b/apparmor.d/abstractions/screensaver new file mode 100644 index 0000000000..1a93690918 --- /dev/null +++ b/apparmor.d/abstractions/screensaver @@ -0,0 +1,14 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow checking status, activating and locking the screensaver + + abi , + + include if exists + include if exists + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/secrets-service b/apparmor.d/abstractions/secrets-service new file mode 100644 index 0000000000..809b0d9b5f --- /dev/null +++ b/apparmor.d/abstractions/secrets-service @@ -0,0 +1,32 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2017 Canonical Ltd +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Provide full access to the secret-service API: https://standards.freedesktop.org/secret-service/ +# +# The secret-service allows managing (add/delete/lock/etc) collections and +# (add/delete/etc) items within collections. The API also has the concept of +# aliases for collections which is typically used to access the default +# collection. While it would be possible for an application developer to use a +# snap-specific collection and mediate by object path, application developers +# are meant to instead to treat collections (typically the default collection) +# as a database of key/value attributes each with an associated secret that +# applications may query. Because AppArmor does not mediate member data, +# typical and recommended usage of the API does not allow for application +# isolation. For details, see: https://standards.freedesktop.org/secret-service/ch03.html +# + + abi , + + include + include + + dbus send bus=session path=/org/gnome/keyring/daemon + interface=org.gnome.keyring.Daemon + member=GetEnvironment + peer=(name=org.gnome.keyring, label=gnome-keyring-daemon), + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/session-manager b/apparmor.d/abstractions/session-manager new file mode 100644 index 0000000000..2c7b631800 --- /dev/null +++ b/apparmor.d/abstractions/session-manager @@ -0,0 +1,15 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow registering a client with the session manager. This is needed for +# applications that want to be notified of session events, such as shutdown +# or logout, and to be able to inhibit those actions. + + abi , + + include + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/shells b/apparmor.d/abstractions/shells index 35d3a580a5..663513e72e 100644 --- a/apparmor.d/abstractions/shells +++ b/apparmor.d/abstractions/shells @@ -9,6 +9,7 @@ include include + include include include if exists diff --git a/apparmor.d/abstractions/sqlite b/apparmor.d/abstractions/sqlite new file mode 100644 index 0000000000..690417f877 --- /dev/null +++ b/apparmor.d/abstractions/sqlite @@ -0,0 +1,23 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# SQlite temporary files (hexadecimal from 12 to 16 characters) + + abi , + + owner /var/tmp/etilqs_@{hex12} rw, + owner /var/tmp/etilqs_@{hex12}@{h} rw, + owner /var/tmp/etilqs_@{hex12}@{hex2} rw, + owner /var/tmp/etilqs_@{hex15} rw, + owner /var/tmp/etilqs_@{hex16} rw, + + owner @{tmp}/etilqs_@{hex12} rw, + owner @{tmp}/etilqs_@{hex12}@{h} rw, + owner @{tmp}/etilqs_@{hex12}@{hex2} rw, + owner @{tmp}/etilqs_@{hex15} rw, + owner @{tmp}/etilqs_@{hex16} rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/sys/amdgpu b/apparmor.d/abstractions/sys/amdgpu new file mode 100644 index 0000000000..a477990d56 --- /dev/null +++ b/apparmor.d/abstractions/sys/amdgpu @@ -0,0 +1,26 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# AMD's amdgpu driver power management (PowerPlay) + + abi , + + # DPM performance level (auto/low/high/manual) + @{sys}/devices/@{pci}/power_dpm_force_performance_level r, + + # Memory clock frequency states and current selection + @{sys}/devices/@{pci}/pp_dpm_mclk r, + + # PCIe bandwidth states + @{sys}/devices/@{pci}/pp_dpm_pcie r, + + # Shader/core clock frequency states + @{sys}/devices/@{pci}/pp_dpm_sclk r, + + # Overclocking table (clock/voltage curves) + @{sys}/devices/@{pci}/pp_od_clk_voltage r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/sys/dmi b/apparmor.d/abstractions/sys/dmi new file mode 100644 index 0000000000..80d47cbce7 --- /dev/null +++ b/apparmor.d/abstractions/sys/dmi @@ -0,0 +1,24 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Desktop Management Interface (DMI) firmware tables and identity files +# +# DMI is a standard framework for managing and tracking hardware components in a +# computer. +# +# It is a light version of `` that leaks only the most +# basic identity information and no version strings. + + abi , + + @{sys}/devices/virtual/dmi/id/bios_vendor r, # BIOS manufacturer + @{sys}/devices/virtual/dmi/id/board_vendor r, # Motherboard manufacturer + @{sys}/devices/virtual/dmi/id/product_family r, # Product family name + @{sys}/devices/virtual/dmi/id/product_name r, # System product name + @{sys}/devices/virtual/dmi/id/product_version r, # Product version + @{sys}/devices/virtual/dmi/id/sys_vendor r, # System manufacturer + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/sys/dmi-full b/apparmor.d/abstractions/sys/dmi-full new file mode 100644 index 0000000000..d89aef39cf --- /dev/null +++ b/apparmor.d/abstractions/sys/dmi-full @@ -0,0 +1,33 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Desktop Management Interface (DMI) firmware tables and identity files +# +# DMI is a standard framework for managing and tracking hardware components in a +# computer. +# +# Games and game launchers (Steam, Proton, anti-cheat) read these for hardware +# fingerprinting, telemetry, and compatibility checks. This is the same data +# from dmidecode but readable without root via sysfs. + + abi , + + include + + @{sys}/devices/virtual/dmi/id/ r, + @{sys}/devices/virtual/dmi/id/bios_date r, # BIOS release date + @{sys}/devices/virtual/dmi/id/bios_version r, # BIOS version string + @{sys}/devices/virtual/dmi/id/board_asset_tag r, # Motherboard asset tag + @{sys}/devices/virtual/dmi/id/board_version r, # Motherboard revision + @{sys}/devices/virtual/dmi/id/chassis_asset_tag r, # Chassis asset tag + @{sys}/devices/virtual/dmi/id/chassis_type r, # Chassis form factor (numeric) + @{sys}/devices/virtual/dmi/id/chassis_vendor r, # Chassis manufacturer + @{sys}/devices/virtual/dmi/id/chassis_version r, # Chassis version + @{sys}/devices/virtual/dmi/id/product_serial r, # Product serial number + @{sys}/devices/virtual/dmi/id/product_sku r, # Product SKU identifier + @{sys}/devices/virtual/dmi/id/product_uuid r, # Product UUID + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/sys/gpumon b/apparmor.d/abstractions/sys/gpumon new file mode 100644 index 0000000000..77bc581caf --- /dev/null +++ b/apparmor.d/abstractions/sys/gpumon @@ -0,0 +1,28 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# GPU Power/Thermal Controls and Monitoring +# +# See: +# +# - https://www.kernel.org/doc/html/latest/gpu/amdgpu/thermal.html +# - https://www.kernel.org/doc/html/latest/gpu/amdgpu/driver-misc.html#gpu-memory-usage-information + + abi , + + @{sys}/devices/@{pci}/gpu_busy_percent r, + @{sys}/devices/@{pci}/mem_info_gtt_total r, + @{sys}/devices/@{pci}/mem_info_gtt_used r, + @{sys}/devices/@{pci}/mem_info_vis_vram_total r, + @{sys}/devices/@{pci}/mem_info_vis_vram_used r, + @{sys}/devices/@{pci}/mem_info_vram_total r, + @{sys}/devices/@{pci}/mem_info_vram_used r, + + # hwmon interfaces for GPU clocks: + @{sys}/devices/**/hwmon@{int}/freq@{int}_input r, + @{sys}/devices/**/hwmon@{int}/freq@{int}_label r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/sys/hwmon b/apparmor.d/abstractions/sys/hwmon new file mode 100644 index 0000000000..fc66a2bab3 --- /dev/null +++ b/apparmor.d/abstractions/sys/hwmon @@ -0,0 +1,22 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Global attributes +# +# See https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface + + abi , + + @{sys}/class/hwmon/ r, + @{sys}/class/hwmon/hwmon@{int}/ r, + + @{sys}/devices/**/hwmon/ r, + @{sys}/devices/**/hwmon@{int}/ r, + + @{sys}/devices/**/hwmon@{int}/name r, + @{sys}/devices/**/hwmon@{int}/update_interval r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/sys/hwmon-alarm b/apparmor.d/abstractions/sys/hwmon-alarm new file mode 100644 index 0000000000..430288563d --- /dev/null +++ b/apparmor.d/abstractions/sys/hwmon-alarm @@ -0,0 +1,52 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Alarms +# +# Alarms enumeration starts from 1 not 0 + + abi , + + include + + @{sys}/devices/**/hwmon@{int}/in@{int}_alarm r, + @{sys}/devices/**/hwmon@{int}/curr@{int}_alarm r, + @{sys}/devices/**/hwmon@{int}/power@{int}_alarm r, + @{sys}/devices/**/hwmon@{int}/fan@{int}_alarm r, + @{sys}/devices/**/hwmon@{int}/temp@{int}_alarm r, + + @{sys}/devices/**/hwmon@{int}/in@{int}_min_alarm r, + @{sys}/devices/**/hwmon@{int}/in@{int}_max_alarm r, + @{sys}/devices/**/hwmon@{int}/in@{int}_lcrit_alarm r, + @{sys}/devices/**/hwmon@{int}/in@{int}_crit_alarm r, + @{sys}/devices/**/hwmon@{int}/curr@{int}_min_alarm r, + @{sys}/devices/**/hwmon@{int}/curr@{int}_max_alarm r, + @{sys}/devices/**/hwmon@{int}/curr@{int}_lcrit_alarm r, + @{sys}/devices/**/hwmon@{int}/curr@{int}_crit_alarm r, + @{sys}/devices/**/hwmon@{int}/power@{int}_cap_alarm r, + @{sys}/devices/**/hwmon@{int}/power@{int}_max_alarm r, + @{sys}/devices/**/hwmon@{int}/power@{int}_crit_alarm r, + @{sys}/devices/**/hwmon@{int}/fan@{int}_min_alarm r, + @{sys}/devices/**/hwmon@{int}/fan@{int}_max_alarm r, + @{sys}/devices/**/hwmon@{int}/temp@{int}_min_alarm r, + @{sys}/devices/**/hwmon@{int}/temp@{int}_max_alarm r, + @{sys}/devices/**/hwmon@{int}/temp@{int}_lcrit_alarm r, + @{sys}/devices/**/hwmon@{int}/temp@{int}_crit_alarm r, + @{sys}/devices/**/hwmon@{int}/temp@{int}_emergency_alarm r, + + @{sys}/devices/**/hwmon@{int}/fan@{int}_fault r, + @{sys}/devices/**/hwmon@{int}/temp@{int}_fault r, + + @{sys}/devices/**/hwmon@{int}/beep_enable r, + @{sys}/devices/**/hwmon@{int}/in@{int}_beep r, + @{sys}/devices/**/hwmon@{int}/curr@{int}_beep r, + @{sys}/devices/**/hwmon@{int}/fan@{int}_beep r, + @{sys}/devices/**/hwmon@{int}/temp@{int}_beep r, + + @{sys}/devices/**/hwmon@{int}/alarms r, + @{sys}/devices/**/hwmon@{int}/beep_mask r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/sys/hwmon-alarm:w b/apparmor.d/abstractions/sys/hwmon-alarm:w new file mode 100644 index 0000000000..50ee26ff1b --- /dev/null +++ b/apparmor.d/abstractions/sys/hwmon-alarm:w @@ -0,0 +1,20 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Alarms +# +# Alarms enumeration starts from 1 not 0 + + abi , + + @{sys}/devices/**/hwmon@{int}/beep_enable rw, + @{sys}/devices/**/hwmon@{int}/beep_maks rw, + @{sys}/devices/**/hwmon@{int}/curr@{int}_beep rw, + @{sys}/devices/**/hwmon@{int}/fan@{int}_beep rw, + @{sys}/devices/**/hwmon@{int}/in@{int}_beep rw, + @{sys}/devices/**/hwmon@{int}/temp@{int}_beep rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/sys/hwmon-current b/apparmor.d/abstractions/sys/hwmon-current new file mode 100644 index 0000000000..9d9e1ff7ab --- /dev/null +++ b/apparmor.d/abstractions/sys/hwmon-current @@ -0,0 +1,28 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Currents +# +# Currents enumeration starts from 1 not 0 + + abi , + + include + + @{sys}/devices/**/hwmon@{int}/curr@{int}_average r, + @{sys}/devices/**/hwmon@{int}/curr@{int}_crit r, + @{sys}/devices/**/hwmon@{int}/curr@{int}_enable r, + @{sys}/devices/**/hwmon@{int}/curr@{int}_highest r, + @{sys}/devices/**/hwmon@{int}/curr@{int}_input r, + @{sys}/devices/**/hwmon@{int}/curr@{int}_lcrit r, + @{sys}/devices/**/hwmon@{int}/curr@{int}_lowest r, + @{sys}/devices/**/hwmon@{int}/curr@{int}_max r, + @{sys}/devices/**/hwmon@{int}/curr@{int}_min r, + + # The line below is not in kernel doc, but present in real system for CPU hwmon + @{sys}/devices/**/hwmon@{int}/curr@{int}_label r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/sys/hwmon-current:w b/apparmor.d/abstractions/sys/hwmon-current:w new file mode 100644 index 0000000000..a098631753 --- /dev/null +++ b/apparmor.d/abstractions/sys/hwmon-current:w @@ -0,0 +1,21 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Currents +# +# Currents enumeration starts from 1 not 0 + + abi , + + @{sys}/devices/**/hwmon@{int}/curr_reset_history w, + @{sys}/devices/**/hwmon@{int}/curr@{int}_crit rw, + @{sys}/devices/**/hwmon@{int}/curr@{int}_enable rw, + @{sys}/devices/**/hwmon@{int}/curr@{int}_lcrit rw, + @{sys}/devices/**/hwmon@{int}/curr@{int}_max rw, + @{sys}/devices/**/hwmon@{int}/curr@{int}_min rw, + @{sys}/devices/**/hwmon@{int}/curr@{int}_reset_history w, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/sys/hwmon-energy b/apparmor.d/abstractions/sys/hwmon-energy new file mode 100644 index 0000000000..cca45f79e5 --- /dev/null +++ b/apparmor.d/abstractions/sys/hwmon-energy @@ -0,0 +1,18 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Energy +# +# Energy enumeration starts from 1 not 0 + + abi , + + include + + @{sys}/devices/**/hwmon@{int}/energy@{int}_enable r, + @{sys}/devices/**/hwmon@{int}/energy@{int}_input r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/sys/hwmon-energy:w b/apparmor.d/abstractions/sys/hwmon-energy:w new file mode 100644 index 0000000000..b5e709b91c --- /dev/null +++ b/apparmor.d/abstractions/sys/hwmon-energy:w @@ -0,0 +1,15 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Energy +# +# Energy enumeration starts from 1 not 0 + + abi , + + @{sys}/devices/**/hwmon@{int}/energy@{int}_enable rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/sys/hwmon-fan b/apparmor.d/abstractions/sys/hwmon-fan new file mode 100644 index 0000000000..faf682dd1a --- /dev/null +++ b/apparmor.d/abstractions/sys/hwmon-fan @@ -0,0 +1,24 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Fans +# +# Fan enumeration starts from 1 not 0 + + abi , + + include + + @{sys}/devices/**/hwmon@{int}/fan@{int}_min r, + @{sys}/devices/**/hwmon@{int}/fan@{int}_max r, + @{sys}/devices/**/hwmon@{int}/fan@{int}_input r, + @{sys}/devices/**/hwmon@{int}/fan@{int}_div r, + @{sys}/devices/**/hwmon@{int}/fan@{int}_pulses r, + @{sys}/devices/**/hwmon@{int}/fan@{int}_target r, + @{sys}/devices/**/hwmon@{int}/fan@{int}_label r, + @{sys}/devices/**/hwmon@{int}/fan@{int}_enable r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/sys/hwmon-fan:w b/apparmor.d/abstractions/sys/hwmon-fan:w new file mode 100644 index 0000000000..4bcdcdb579 --- /dev/null +++ b/apparmor.d/abstractions/sys/hwmon-fan:w @@ -0,0 +1,20 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Fans +# +# Fan enumeration starts from 1 not 0 + + abi , + + @{sys}/devices/**/hwmon@{int}/fan@{int}_div rw, + @{sys}/devices/**/hwmon@{int}/fan@{int}_enable rw, + @{sys}/devices/**/hwmon@{int}/fan@{int}_max rw, + @{sys}/devices/**/hwmon@{int}/fan@{int}_min rw, + @{sys}/devices/**/hwmon@{int}/fan@{int}_pulses rw, + @{sys}/devices/**/hwmon@{int}/fan@{int}_target rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/sys/hwmon-humidity b/apparmor.d/abstractions/sys/hwmon-humidity new file mode 100644 index 0000000000..d3870ff91e --- /dev/null +++ b/apparmor.d/abstractions/sys/hwmon-humidity @@ -0,0 +1,18 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Humidity +# +# Humidity enumeration starts from 1 not 0 + + abi , + + include + + @{sys}/devices/**/hwmon@{int}/humidity@{int}_enable r, + @{sys}/devices/**/hwmon@{int}/humidity@{int}_input r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/sys/hwmon-humidity:w b/apparmor.d/abstractions/sys/hwmon-humidity:w new file mode 100644 index 0000000000..82974d213e --- /dev/null +++ b/apparmor.d/abstractions/sys/hwmon-humidity:w @@ -0,0 +1,15 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Humidity +# +# Humidity enumeration starts from 1 not 0 + + abi , + + @{sys}/devices/**/hwmon@{int}/humidity@{int}_enable rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/sys/hwmon-intrusion b/apparmor.d/abstractions/sys/hwmon-intrusion new file mode 100644 index 0000000000..af81e6ec20 --- /dev/null +++ b/apparmor.d/abstractions/sys/hwmon-intrusion @@ -0,0 +1,18 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Intrusion detection +# +# Intrusion detection enumeration starts from 1 not 0 + + abi , + + include + + @{sys}/devices/**/hwmon@{int}/intrusion@{int}_alarm r, + @{sys}/devices/**/hwmon@{int}/intrusion@{int}_beep r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/sys/hwmon-intrusion:w b/apparmor.d/abstractions/sys/hwmon-intrusion:w new file mode 100644 index 0000000000..5b9d353774 --- /dev/null +++ b/apparmor.d/abstractions/sys/hwmon-intrusion:w @@ -0,0 +1,16 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Intrusion detection +# +# Intrusion detection enumeration starts from 1 not 0 + + abi , + + @{sys}/devices/**/hwmon@{int}/intrusion@{int}_alarm rw, + @{sys}/devices/**/hwmon@{int}/intrusion@{int}_beep rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/sys/hwmon-power b/apparmor.d/abstractions/sys/hwmon-power new file mode 100644 index 0000000000..b8482d0c6c --- /dev/null +++ b/apparmor.d/abstractions/sys/hwmon-power @@ -0,0 +1,39 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Power +# +# Power enumeration starts from 1 not 0 + + abi , + + include + + @{sys}/devices/**/hwmon@{int}/power@{int}_accuracy r, + @{sys}/devices/**/hwmon@{int}/power@{int}_average r, + @{sys}/devices/**/hwmon@{int}/power@{int}_average_highest r, + @{sys}/devices/**/hwmon@{int}/power@{int}_average_interval r, + @{sys}/devices/**/hwmon@{int}/power@{int}_average_interval_max r, + @{sys}/devices/**/hwmon@{int}/power@{int}_average_interval_min r, + @{sys}/devices/**/hwmon@{int}/power@{int}_average_lowest r, + @{sys}/devices/**/hwmon@{int}/power@{int}_average_max r, + @{sys}/devices/**/hwmon@{int}/power@{int}_average_min r, + @{sys}/devices/**/hwmon@{int}/power@{int}_cap r, + @{sys}/devices/**/hwmon@{int}/power@{int}_cap_hyst r, + @{sys}/devices/**/hwmon@{int}/power@{int}_cap_max r, + @{sys}/devices/**/hwmon@{int}/power@{int}_cap_min r, + @{sys}/devices/**/hwmon@{int}/power@{int}_crit r, + @{sys}/devices/**/hwmon@{int}/power@{int}_enable r, + @{sys}/devices/**/hwmon@{int}/power@{int}_input r, + @{sys}/devices/**/hwmon@{int}/power@{int}_input_highest r, + @{sys}/devices/**/hwmon@{int}/power@{int}_input_lowest r, + @{sys}/devices/**/hwmon@{int}/power@{int}_max r, + + # The lines below are not in kernel doc, but present in real system for CPU hwmon + @{sys}/devices/**/hwmon@{int}/power@{int}_cap_default r, + @{sys}/devices/**/hwmon@{int}/power@{int}_label r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/sys/hwmon-power:w b/apparmor.d/abstractions/sys/hwmon-power:w new file mode 100644 index 0000000000..4267e6b0c3 --- /dev/null +++ b/apparmor.d/abstractions/sys/hwmon-power:w @@ -0,0 +1,23 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Power +# +# Power enumeration starts from 1 not 0 + + abi , + + @{sys}/devices/**/hwmon@{int}/power@{int}_average_interval rw, + @{sys}/devices/**/hwmon@{int}/power@{int}_average_max rw, + @{sys}/devices/**/hwmon@{int}/power@{int}_average_min rw, + @{sys}/devices/**/hwmon@{int}/power@{int}_cap rw, + @{sys}/devices/**/hwmon@{int}/power@{int}_cap_hyst rw, + @{sys}/devices/**/hwmon@{int}/power@{int}_crit rw, + @{sys}/devices/**/hwmon@{int}/power@{int}_enable rw, + @{sys}/devices/**/hwmon@{int}/power@{int}_max rw, + @{sys}/devices/**/hwmon@{int}/power@{int}_reset_history w, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/sys/hwmon-pwm b/apparmor.d/abstractions/sys/hwmon-pwm new file mode 100644 index 0000000000..095edfd713 --- /dev/null +++ b/apparmor.d/abstractions/sys/hwmon-pwm @@ -0,0 +1,27 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# PWM +# +# PWM enumeration starts from 1 not 0 + + abi , + + include + + @{sys}/devices/**/hwmon@{int}/pwm@{int} r, + @{sys}/devices/**/hwmon@{int}/pwm@{int}_auto_channels_temp r, + @{sys}/devices/**/hwmon@{int}/pwm@{int}_auto_point@{int}_pwm r, + @{sys}/devices/**/hwmon@{int}/pwm@{int}_auto_point@{int}_temp r, + @{sys}/devices/**/hwmon@{int}/pwm@{int}_auto_point@{int}_temp_hyst r, + @{sys}/devices/**/hwmon@{int}/pwm@{int}_enable r, + @{sys}/devices/**/hwmon@{int}/pwm@{int}_freq r, + @{sys}/devices/**/hwmon@{int}/pwm@{int}_mode r, + @{sys}/devices/**/hwmon@{int}/temp@{int}_auto_point@{int}_pwm r, + @{sys}/devices/**/hwmon@{int}/temp@{int}_auto_point@{int}_temp r, + @{sys}/devices/**/hwmon@{int}/temp@{int}_auto_point@{int}_temp_hyst r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/sys/hwmon-pwm:w b/apparmor.d/abstractions/sys/hwmon-pwm:w new file mode 100644 index 0000000000..ca24a4616a --- /dev/null +++ b/apparmor.d/abstractions/sys/hwmon-pwm:w @@ -0,0 +1,25 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# PWM +# +# PWM enumeration starts from 1 not 0 + + abi , + + @{sys}/devices/**/hwmon@{int}/pwm@{int} rw, + @{sys}/devices/**/hwmon@{int}/pwm@{int}_auto_channels_temp rw, + @{sys}/devices/**/hwmon@{int}/pwm@{int}_auto_point@{int}_pwm rw, + @{sys}/devices/**/hwmon@{int}/pwm@{int}_auto_point@{int}_temp rw, + @{sys}/devices/**/hwmon@{int}/pwm@{int}_auto_point@{int}_temp_hyst rw, + @{sys}/devices/**/hwmon@{int}/pwm@{int}_enable rw, + @{sys}/devices/**/hwmon@{int}/pwm@{int}_freq rw, + @{sys}/devices/**/hwmon@{int}/pwm@{int}_mode rw, + @{sys}/devices/**/hwmon@{int}/temp@{int}_auto_point@{int}_pwm rw, + @{sys}/devices/**/hwmon@{int}/temp@{int}_auto_point@{int}_temp rw, + @{sys}/devices/**/hwmon@{int}/temp@{int}_auto_point@{int}_temp_hyst rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/sys/hwmon-temp b/apparmor.d/abstractions/sys/hwmon-temp new file mode 100644 index 0000000000..423b5cba1b --- /dev/null +++ b/apparmor.d/abstractions/sys/hwmon-temp @@ -0,0 +1,33 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Temperatures +# +# Temperatures enumeration starts from 1 not 0 + + abi , + + include + + @{sys}/devices/**/hwmon@{int}/temp@{int}_crit r, + @{sys}/devices/**/hwmon@{int}/temp@{int}_crit_hyst r, + @{sys}/devices/**/hwmon@{int}/temp@{int}_emergency r, + @{sys}/devices/**/hwmon@{int}/temp@{int}_emergency_hyst r, + @{sys}/devices/**/hwmon@{int}/temp@{int}_enable r, + @{sys}/devices/**/hwmon@{int}/temp@{int}_highest r, + @{sys}/devices/**/hwmon@{int}/temp@{int}_input r, + @{sys}/devices/**/hwmon@{int}/temp@{int}_label r, + @{sys}/devices/**/hwmon@{int}/temp@{int}_lcrit r, + @{sys}/devices/**/hwmon@{int}/temp@{int}_lcrit_hyst r, + @{sys}/devices/**/hwmon@{int}/temp@{int}_lowest r, + @{sys}/devices/**/hwmon@{int}/temp@{int}_max r, + @{sys}/devices/**/hwmon@{int}/temp@{int}_max_hyst r, + @{sys}/devices/**/hwmon@{int}/temp@{int}_min r, + @{sys}/devices/**/hwmon@{int}/temp@{int}_min_hyst r, + @{sys}/devices/**/hwmon@{int}/temp@{int}_offset r, + @{sys}/devices/**/hwmon@{int}/temp@{int}_type r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/sys/hwmon-temp:w b/apparmor.d/abstractions/sys/hwmon-temp:w new file mode 100644 index 0000000000..1ef37a0f19 --- /dev/null +++ b/apparmor.d/abstractions/sys/hwmon-temp:w @@ -0,0 +1,29 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Temperatures +# +# Temperatures enumeration starts from 1 not 0 + + abi , + + @{sys}/devices/**/hwmon@{int}/temp@{int}_type rw, + @{sys}/devices/**/hwmon@{int}/temp@{int}_min rw, + @{sys}/devices/**/hwmon@{int}/temp@{int}_max rw, + @{sys}/devices/**/hwmon@{int}/temp@{int}_min_hyst rw, + @{sys}/devices/**/hwmon@{int}/temp@{int}_max_hyst rw, + @{sys}/devices/**/hwmon@{int}/temp@{int}_crit rw, + @{sys}/devices/**/hwmon@{int}/temp@{int}_crit_hyst rw, + @{sys}/devices/**/hwmon@{int}/temp@{int}_emergency rw, + @{sys}/devices/**/hwmon@{int}/temp@{int}_emergency_hyst rw, + @{sys}/devices/**/hwmon@{int}/temp@{int}_lcrit rw, + @{sys}/devices/**/hwmon@{int}/temp@{int}_lcrit_hyst rw, + @{sys}/devices/**/hwmon@{int}/temp@{int}_offset rw, + @{sys}/devices/**/hwmon@{int}/temp@{int}_reset_history w, + @{sys}/devices/**/hwmon@{int}/temp_reset_history w, + @{sys}/devices/**/hwmon@{int}/temp@{int}_enable rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/sys/hwmon-voltages b/apparmor.d/abstractions/sys/hwmon-voltages new file mode 100644 index 0000000000..c8d6ba9e1a --- /dev/null +++ b/apparmor.d/abstractions/sys/hwmon-voltages @@ -0,0 +1,26 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Voltages + + abi , + + include + + @{sys}/devices/**/hwmon@{int}/cpu@{int}_vid r, + @{sys}/devices/**/hwmon@{int}/in@{int}_average r, + @{sys}/devices/**/hwmon@{int}/in@{int}_crit r, + @{sys}/devices/**/hwmon@{int}/in@{int}_enable r, + @{sys}/devices/**/hwmon@{int}/in@{int}_highest r, + @{sys}/devices/**/hwmon@{int}/in@{int}_input r, + @{sys}/devices/**/hwmon@{int}/in@{int}_label r, + @{sys}/devices/**/hwmon@{int}/in@{int}_lcrit r, + @{sys}/devices/**/hwmon@{int}/in@{int}_lowest r, + @{sys}/devices/**/hwmon@{int}/in@{int}_max r, + @{sys}/devices/**/hwmon@{int}/in@{int}_min r, + @{sys}/devices/**/hwmon@{int}/vrm r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/sys/hwmon-voltages:w b/apparmor.d/abstractions/sys/hwmon-voltages:w new file mode 100644 index 0000000000..0b8e1374d9 --- /dev/null +++ b/apparmor.d/abstractions/sys/hwmon-voltages:w @@ -0,0 +1,19 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Voltages + + abi , + + @{sys}/devices/**/hwmon@{int}/in_reset_history w, + @{sys}/devices/**/hwmon@{int}/in@{int}_crit rw, + @{sys}/devices/**/hwmon@{int}/in@{int}_enable rw, + @{sys}/devices/**/hwmon@{int}/in@{int}_lcrit rw, + @{sys}/devices/**/hwmon@{int}/in@{int}_max rw, + @{sys}/devices/**/hwmon@{int}/in@{int}_min rw, + @{sys}/devices/**/hwmon@{int}/in@{int}_reset_history w, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/sys/hwmon:w b/apparmor.d/abstractions/sys/hwmon:w new file mode 100644 index 0000000000..ea93705d6c --- /dev/null +++ b/apparmor.d/abstractions/sys/hwmon:w @@ -0,0 +1,15 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Global attributes +# +# See https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface + + abi , + + @{sys}/devices/**/hwmon@{int}/update_interval w, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/sys/input b/apparmor.d/abstractions/sys/input new file mode 100644 index 0000000000..767e04b3ae --- /dev/null +++ b/apparmor.d/abstractions/sys/input @@ -0,0 +1,19 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + # Allow reading for supported event reports for all input devices. See + # https://www.kernel.org/doc/Documentation/input/event-codes.txt + @{sys}/devices/**/input@{int}/capabilities/* r, + + @{sys}/devices/**/input@{int}/ r, + @{sys}/devices/**/input/input@{int}/event@{int}/uevent r, + @{sys}/devices/**/input/input@{int}/properties r, + @{sys}/devices/**/input/input@{int}/uevent r, + @{sys}/devices/virtual/input/mice/uevent r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/sys/power-supply b/apparmor.d/abstractions/sys/power-supply new file mode 100644 index 0000000000..2ca2e76ae3 --- /dev/null +++ b/apparmor.d/abstractions/sys/power-supply @@ -0,0 +1,22 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Listing for power supply devices. Used to enumerate power sources and +# determine if the system is on AC or battery. + + abi , + + @{sys}/class/power_supply/ r, + + @{sys}/devices/**/power_supply/AC/ r, + @{sys}/devices/**/power_supply/AC/online r, + @{sys}/devices/**/power_supply/AC/type r, + + @{sys}/devices/**/power_supply/BAT@{int}/ r, + @{sys}/devices/**/power_supply/BAT@{int}/online r, + @{sys}/devices/**/power_supply/BAT@{int}/type r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/tests b/apparmor.d/abstractions/tests new file mode 100644 index 0000000000..d28eb91a26 --- /dev/null +++ b/apparmor.d/abstractions/tests @@ -0,0 +1,51 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# LOGPROF-SUGGEST: no + +# Common temporary tests directories used by autopkgtest. +# +# !!! warning +# +# Do not use it manually, It is automatically included in the base abstraction +# when the 'test' prebuild flag is set. +# +# !!! note +# +# When needed, this abstraction is included in the `base` / `base-strict` abstractions. +# It is not necessary to include it manually. +# + + abi , + + # @{exec_path}.distrib mrix, + + @{lib}/installed-tests/ r, + @{lib}/installed-tests/** rw, + + /usr/share/installed-tests/{,**} r, + + owner /m-a/{,**} rwlk, + + owner /test-*/{,**} rw, + owner /test/{,**} rw, + + owner /trigger{,s}/{,**} rw, + + /tmp/autopkgtest* rwlkmix, + /tmp/autopkgtest*/ rw, + /tmp/autopkgtest*/** rwlkmix, + + /tmp/shunit.@{rand6}/ rw, + /tmp/shunit.@{rand6}/** rwlk, + + /tmp/test*/ rw, + priority=-1 /tmp/test*/** rwlkmix, + /tmp/*test*/ rw, + priority=-1 /tmp/*test*/** rwlkmix, + + owner /tmp/dbusmock_data_*/{,**} rwlk, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/themes b/apparmor.d/abstractions/themes new file mode 100644 index 0000000000..13fe70bc6a --- /dev/null +++ b/apparmor.d/abstractions/themes @@ -0,0 +1,14 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + /usr/share/themes/{,**} r, + + owner @{HOME}/.themes/{,**} r, + owner @{user_share_dirs}/themes/{,**} r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/thumbnails-cache-write b/apparmor.d/abstractions/thumbnails-cache-write index 5e64fc66f9..1cee5aefcb 100644 --- a/apparmor.d/abstractions/thumbnails-cache-write +++ b/apparmor.d/abstractions/thumbnails-cache-write @@ -9,8 +9,9 @@ owner @{user_cache_dirs}/thumbnails/ w, owner @{user_cache_dirs}/thumbnails/{fail,*large,normal}/ w, + owner @{user_cache_dirs}/thumbnails/{fail,*large,normal}/.goutputstream-@{rand6} rw, owner @{user_cache_dirs}/thumbnails/{fail,*large,normal}/*.png wl, - owner @{user_cache_dirs}/thumbnails/{fail,*large,normal}/*.png.@{rand6} w, + owner @{user_cache_dirs}/thumbnails/{fail,*large,normal}/*.png.@{rand6} wl, owner @{user_cache_dirs}/thumbnails/{fail,*large,normal}/#@{int} w, owner @{user_cache_dirs}/thumbnails/{fail,*large,normal}/gnome-thumbnail-factory/ w, owner @{user_cache_dirs}/thumbnails/{fail,*large,normal}/gnome-thumbnail-factory/*.png w, diff --git a/apparmor.d/abstractions/tpm b/apparmor.d/abstractions/tpm new file mode 100644 index 0000000000..4f91162005 --- /dev/null +++ b/apparmor.d/abstractions/tpm @@ -0,0 +1,18 @@ +# 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 , + + @{sys}/class/tpmrm/ r, + + /dev/tpm@{int} rw, + /dev/tpmrm@{int} rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/trash-strict b/apparmor.d/abstractions/trash-strict index a2b024d3ec..367a83680c 100644 --- a/apparmor.d/abstractions/trash-strict +++ b/apparmor.d/abstractions/trash-strict @@ -5,8 +5,8 @@ # Already upstreamed. Different because recent change does not play well # with upstream's version. - -# There is no 'owner' rule on expunged folders because some internally sandboxed +# +# There is no `owner` rule on expunged folders because some internally sandboxed # app (using bwrap) run on a different private user. abi , @@ -22,7 +22,7 @@ # Home trash location owner @{user_share_dirs}/Trash/ rw, owner @{user_share_dirs}/Trash/#@{int} rw, - owner @{user_share_dirs}/Trash/directorysizes{,.*} rwl -> @{user_share_dirs}/Trash/#@{int}, + owner @{user_share_dirs}/Trash/directorysizes{,.*} rwl, owner @{user_share_dirs}/Trash/files/{,**} rw, owner @{user_share_dirs}/Trash/info/ rw, owner @{user_share_dirs}/Trash/info/*.trashinfo{,.*} rw, @@ -35,7 +35,7 @@ owner @{MOUNTS}/.Trash/ rw, owner @{MOUNTS}/.Trash/@{uid}/ rw, owner @{MOUNTS}/.Trash/@{uid}/#@{int} rw, - owner @{MOUNTS}/.Trash/@{uid}/directorysizes{,.*} rwl -> @{MOUNTS}/.Trash/@{uid}/#@{int}, + owner @{MOUNTS}/.Trash/@{uid}/directorysizes{,.*} rwl, owner @{MOUNTS}/.Trash/@{uid}/files/{,**} rw, owner @{MOUNTS}/.Trash/@{uid}/info/ rw, owner @{MOUNTS}/.Trash/@{uid}/info/*.trashinfo{,.*} rw, @@ -47,7 +47,7 @@ # Partitions' trash location when the admin doesn't create the .Trash/ folder in the top lvl dir owner @{MOUNTS}/.Trash-@{uid}/ rw, owner @{MOUNTS}/.Trash-@{uid}/#@{int} rw, - owner @{MOUNTS}/.Trash-@{uid}/directorysizes{,.*} rwl -> @{MOUNTS}/.Trash-@{uid}/#@{int}, + owner @{MOUNTS}/.Trash-@{uid}/directorysizes{,.*} rwl, owner @{MOUNTS}/.Trash-@{uid}/files/{,**} rw, owner @{MOUNTS}/.Trash-@{uid}/info/ rw, owner @{MOUNTS}/.Trash-@{uid}/info/*.trashinfo{,.*} rw, @@ -60,7 +60,7 @@ owner @{MOUNTS}/*/.Trash/ rw, owner @{MOUNTS}/*/.Trash/@{uid}/ rw, owner @{MOUNTS}/*/.Trash/@{uid}/#@{int} rw, - owner @{MOUNTS}/*/.Trash/@{uid}/directorysizes{,.*} rwl -> @{MOUNTS}/*/.Trash/@{uid}/#@{int}, + owner @{MOUNTS}/*/.Trash/@{uid}/directorysizes{,.*} rwl, owner @{MOUNTS}/*/.Trash/@{uid}/files/{,**} rw, owner @{MOUNTS}/*/.Trash/@{uid}/info/ rw, owner @{MOUNTS}/*/.Trash/@{uid}/info/*.trashinfo{,.*} rw, @@ -72,7 +72,7 @@ # Removable media's trash location when the admin doesn't create the .Trash/ folder in the top lvl dir owner @{MOUNTS}/*/.Trash-@{uid}/ rw, owner @{MOUNTS}/*/.Trash-@{uid}/#@{int} rw, - owner @{MOUNTS}/*/.Trash-@{uid}/directorysizes{,.*} rwl -> @{MOUNTS}/*/.Trash-@{uid}/#@{int}, + owner @{MOUNTS}/*/.Trash-@{uid}/directorysizes{,.*} rwl, owner @{MOUNTS}/*/.Trash-@{uid}/files/{,**} rw, owner @{MOUNTS}/*/.Trash-@{uid}/info/ rw, owner @{MOUNTS}/*/.Trash-@{uid}/info/*.trashinfo{,.*} rw, diff --git a/apparmor.d/abstractions/uinput b/apparmor.d/abstractions/uinput new file mode 100644 index 0000000000..b97d1eb8a6 --- /dev/null +++ b/apparmor.d/abstractions/uinput @@ -0,0 +1,16 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2020 Canonical Ltd +# Copyright (C) 2021-2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Allow write access to the uinput device for emulating input devices from +# userspace for sending input events. + + abi , + + /dev/uinput rw, + /dev/input/uinput rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/upower-observe b/apparmor.d/abstractions/upower-observe new file mode 100644 index 0000000000..a4ff029587 --- /dev/null +++ b/apparmor.d/abstractions/upower-observe @@ -0,0 +1,14 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Can query UPower for power devices, history and statistics. + + abi , + + include + include + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/user-data b/apparmor.d/abstractions/user-data deleted file mode 100644 index 6406b3e84a..0000000000 --- a/apparmor.d/abstractions/user-data +++ /dev/null @@ -1,49 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - -# Gives access to non-hidden files in user's $HOME. -# Warning: experiemental, only for abi 4+, requires a prompting client. - - abi , - - # Allow accessing the GNOME crypto services prompt APIs as used by - # applications using libgcr (such as pinentry-gnome3) for secure pin - # entry to unlock GPG keys etc. See: - # https://developer.gnome.org/gcr/unstable/GcrPrompt.html - # https://developer.gnome.org/gcr/unstable/GcrSecretExchange.html - # https://github.com/snapcore/snapd/pull/7673#issuecomment-592229711 - dbus send bus=session path=/org/gnome/keyring/Prompter - interface=org.gnome.keyring.internal.Prompter - member={BeginPrompting,PerformPrompt,StopPrompting} - peer=(name="{@{busname}", label=pinentry-*), - dbus receive bus=session path=/org/gnome/keyring/Prompt/p@{int} - interface=org.gnome.keyring.internal.Prompter.Callback - member={PromptReady,PromptDone} - peer=(name="{@{busname}", label=pinentry-*), - - # Allow read access to toplevel $HOME & mounts for the user. - prompt owner @{HOME}/ r, - prompt owner @{MOUNTS}/ r, - - # Allow read/write access to all files in @{HOME}, except snap application - # data in @{HOME}/snap and toplevel hidden directories in @{HOME}. - prompt owner @{HOME}/[^s.]** rwlk, - prompt owner @{HOME}/s[^n]** rwlk, - prompt owner @{HOME}/sn[^a]** rwlk, - prompt owner @{HOME}/sna[^p]** rwlk, - prompt owner @{HOME}/snap[^/]** rwlk, - prompt owner @{HOME}/{s,sn,sna}{,/} rwlk, - - # Allow access to mounts (/mnt/*/, /media/*/, @{run}/media/@{user}/*/, gvfs) - # for non-hidden files owned by the user. - prompt owner @{MOUNTS}/[^.]** rwlk, - - # Disallow writes to the well-known directory included in - # the user's PATH on several distributions - audit deny @{HOME}/bin/{,**} wl, - audit deny @{HOME}/bin wl, - - include if exists - -# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/user-dirs b/apparmor.d/abstractions/user-dirs new file mode 100644 index 0000000000..d33a6764c1 --- /dev/null +++ b/apparmor.d/abstractions/user-dirs @@ -0,0 +1,16 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + /etc/xdg/user-dirs.conf r, + /etc/xdg/user-dirs.defaults r, + + owner @{desktop_config_dirs}/user-dirs.dirs r, + + owner @{user_config_dirs}/user-dirs.dirs r, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/user-read b/apparmor.d/abstractions/user-read index bd350186b9..94b677d27a 100644 --- a/apparmor.d/abstractions/user-read +++ b/apparmor.d/abstractions/user-read @@ -2,7 +2,10 @@ # Copyright (C) 2021-2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only -# Warning: This abstraction gives unrestricted read access on all non hidden user directories. +# !!! warning +# +# This abstraction gives unrestricted read access on all non hidden user directories. +# abi , diff --git a/apparmor.d/abstractions/user-read-strict b/apparmor.d/abstractions/user-read-strict index f7eb186b50..9626bb0bcc 100644 --- a/apparmor.d/abstractions/user-read-strict +++ b/apparmor.d/abstractions/user-read-strict @@ -8,6 +8,7 @@ abi , owner @{HOME}/ r, + owner @{HOME}/[^.]* rk, owner @{MOUNTS}/ r, owner @{HOME}/@{XDG_DESKTOP_DIR}/{,**} rk, diff --git a/apparmor.d/abstractions/user-write-strict b/apparmor.d/abstractions/user-write-strict index 026825b27a..88d52203e7 100644 --- a/apparmor.d/abstractions/user-write-strict +++ b/apparmor.d/abstractions/user-write-strict @@ -8,6 +8,7 @@ abi , owner @{HOME}/ r, + owner @{HOME}/[^.]* wl, owner @{MOUNTS}/ r, owner @{HOME}/@{XDG_DESKTOP_DIR}/{,**} wl, diff --git a/apparmor.d/abstractions/vulkan-strict b/apparmor.d/abstractions/vulkan-strict index d4dd2fae64..3c8beb362d 100644 --- a/apparmor.d/abstractions/vulkan-strict +++ b/apparmor.d/abstractions/vulkan-strict @@ -20,6 +20,7 @@ owner @{user_cache_dirs}/gtk-4.0/vulkan-pipeline-cache/@{uuid}.@{int} rw, owner @{user_cache_dirs}/radv_builtin_shaders{32,64} r, # Vulkan radv shaders cache owner @{user_cache_dirs}/radv_builtin_shaders{32,64}@{rand6} w, + owner @{user_cache_dirs}/radv_builtin_shaders/index rw, owner @{user_share_dirs}/vulkan/ rw, owner @{user_share_dirs}/vulkan/implicit_layer.d/ rw, @@ -28,7 +29,9 @@ @{sys}/class/ r, @{sys}/class/drm/ r, @{sys}/devices/@{pci}/drm/ r, - @{sys}/devices/@{pci}/drm/card@{int}/gt_{min,cur,max}_freq_mhz r, + @{sys}/devices/@{pci}/drm/card@{int}/gt_cur_freq_mhz r, + @{sys}/devices/@{pci}/drm/card@{int}/gt_max_freq_mhz r, + @{sys}/devices/@{pci}/drm/card@{int}/gt_min_freq_mhz r, @{sys}/devices/@{pci}/drm/card@{int}/metrics/ r, @{sys}/devices/@{pci}/drm/card@{int}/metrics/@{uuid}/id r, diff --git a/apparmor.d/abstractions/vulkan.d/complete b/apparmor.d/abstractions/vulkan.d/complete index 8e5b68c08b..67f83516e1 100644 --- a/apparmor.d/abstractions/vulkan.d/complete +++ b/apparmor.d/abstractions/vulkan.d/complete @@ -1,4 +1,5 @@ # apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only /etc/glvnd/egl_vendor.d/{,*.json} r, diff --git a/apparmor.d/abstractions/wayland-strict b/apparmor.d/abstractions/wayland-strict new file mode 100644 index 0000000000..0855e35f36 --- /dev/null +++ b/apparmor.d/abstractions/wayland-strict @@ -0,0 +1,34 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2016 intrigeri +# Copyright (C) 2021-2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + abi , + + # Needed when using QT_QPA_PLATFORM=wayland-egl (MESA dri config) + /etc/drirc r, + + # Allow access to the Wayland compositor server socket + owner @{run}/user/@{uid}/wayland-@{int} rw, + owner @{run}/user/@{uid}/wayland-@{int}.lock rwk, + owner @{run}/user/@{uid}/wayland-cursor-shared-@{int} rw, + owner @{run}/user/@{uid}/wayland-proxy-@{int} rw, + + # Compositors specific socket path + owner @{run}/user/@{uid}/.mutter-Xwaylandauth.@{rand6} r, + owner @{run}/user/@{uid}/mesa-shared-@{int} rw, + owner @{run}/user/@{uid}/mutter-shared-@{int} rw, + owner @{run}/user/@{uid}/sdl-shared-@{int} rw, + owner @{run}/user/@{uid}/weston-shared-@{int} rw, + owner @{run}/user/@{uid}/xwayland-shared-@{int} rw, + + # Compositors based on wlroots + owner /dev/shm/@{uuid} rw, + owner /dev/shm/dunst-@{rand6} rw, + owner /dev/shm/grim-@{rand6} rw, + owner /dev/shm/sway* rw, + owner /dev/shm/wlroots-@{rand6} rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/webkit b/apparmor.d/abstractions/webkit index c4410d0267..96a5b8eaa6 100644 --- a/apparmor.d/abstractions/webkit +++ b/apparmor.d/abstractions/webkit @@ -2,18 +2,22 @@ # Copyright (C) 2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only -# Minimal set of rules for webkit UI. +# Minimal set of rules for webkit GTK UI. abi , + include + mount options=(rw rbind) /bindfile@{rand6} -> /newroot/.flatpak-info, - @{bin}/xdg-dbus-proxy rix, + @{bin}/xdg-dbus-proxy rix, # TODO: stack me @{lib}/{,@{multiarch}/}webkit{2,}gtk-*/WebKitNetworkProcess rix, @{lib}/{,@{multiarch}/}webkit{2,}gtk-*/WebKitWebProcess rix, owner /bindfile@{rand6} rw, + + owner /.flatpak-info r, owner @{att}/.flatpak-info r, owner @{run}/user/@{uid}/.dbus-proxy/{system,session,a11y}-bus-proxy-@{rand6} rw, @@ -21,11 +25,17 @@ owner @{run}/user/@{uid}/.flatpak/ w, owner @{run}/user/@{uid}/.flatpak/webkit-*/{,bwrapinfo.json} rw, + owner @{att}@{run}/user/@{uid}/bus rw, + owner @{att}@{run}/user/@{uid}/webkitgtk/a11y-proxy-@{rand6} rw, + owner @{att}@{run}/user/@{uid}/webkitgtk/bus-proxy-@{rand6} rw, + owner @{run}/user/@{uid}/webkitgtk/ w, owner @{run}/user/@{uid}/webkitgtk/a11y-proxy-@{rand6} rw, owner @{run}/user/@{uid}/webkitgtk/bus-proxy-@{rand6} rw, owner @{run}/user/@{uid}/webkitgtk/dbus-proxy-@{rand6} rw, + @{sys}/firmware/acpi/pm_profile r, + include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/wine b/apparmor.d/abstractions/wine index 139b034502..58245a663c 100644 --- a/apparmor.d/abstractions/wine +++ b/apparmor.d/abstractions/wine @@ -9,12 +9,26 @@ owner @{user_share_dirs}/applications/wine/ rw, owner @{user_share_dirs}/applications/wine/**/ rw, + owner @{user_cache_dirs}/wine/* r, + owner @{tmp}/.wine-@{uid}/ rw, - owner @{tmp}/.wine-@{uid}/** rwk, + owner @{tmp}/.wine-@{uid}/server-*/ rw, + owner @{tmp}/.wine-@{uid}/server-*/lock rwk, + owner @{tmp}/.wine-@{uid}/server-*/socket rw, + owner @{tmp}/.wine-@{uid}/server-*/tmpmap-@{hex8} mrw, + owner @{att}/@{tmp}/.wine-@{uid}/server-*/socket rw, + + owner @{tmp}/@{word8} rw, + owner @{tmp}/protonfixes_test.log w, + owner @{tmp}/protonfixes-gtk-@{word8}/{,**} rw, owner /dev/shm/wine-@{hex6}-fsync rw, owner /dev/shm/wine-@{hex6}@{h}-fsync rw, + # NT synchronization driver (performance improvement for games) + # https://www.phoronix.com/news/Linux-6.14-NTSYNC-Driver-Ready + /dev/ntsync r, + include if exists # vim:syntax=apparmor diff --git a/apparmor.d/abstractions/wutmp.d/complete b/apparmor.d/abstractions/wutmp.d/complete new file mode 100644 index 0000000000..b1e832262a --- /dev/null +++ b/apparmor.d/abstractions/wutmp.d/complete @@ -0,0 +1,9 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + + /var/log/ r, + /var/log/wtmp.db rwk, + /var/log/wtmp.db-journal rw, + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/xfce b/apparmor.d/abstractions/xfce index 3046c8f6d5..3cda268a5d 100644 --- a/apparmor.d/abstractions/xfce +++ b/apparmor.d/abstractions/xfce @@ -4,17 +4,32 @@ abi , - include - include - include - include + # Common abstractions for any desktop environment + include + include + include + include + include + include + include + include + include + include + include + include + include + include + include + include + include + include + include + include include include - /usr/share/xfce{,4}/ r, - - owner @{user_config_dirs}/xfce4/help{,ers}.rc rw, - owner @{user_config_dirs}/xfce4/help{,ers}.rc.@{int}.tmp rw, + # XFCE specific rules + include include if exists diff --git a/apparmor.d/abstractions/xfce-base b/apparmor.d/abstractions/xfce-base new file mode 100644 index 0000000000..04233c84bb --- /dev/null +++ b/apparmor.d/abstractions/xfce-base @@ -0,0 +1,16 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Minimal xfce specific rules. + + abi , + + /usr/share/xfce{,4}/ r, + + owner @{user_config_dirs}/xfce4/help{,ers}.rc rw, + owner @{user_config_dirs}/xfce4/help{,ers}.rc.@{int}.tmp rw, + + include if exists + +# vim:syntax=apparmor diff --git a/apparmor.d/abstractions/zsh b/apparmor.d/abstractions/zsh index a22895c91a..699b797221 100644 --- a/apparmor.d/abstractions/zsh +++ b/apparmor.d/abstractions/zsh @@ -3,30 +3,58 @@ # Copyright (C) 2021-2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only -# This abstraction is only required when an interactive shell is started. +# This abstraction is only required when zshrc is loaded (e.g. interactive shell). # Classic shell scripts do not need it. abi , @{lib}/@{multiarch}/zsh/@{int}/zsh/*.so mr, - /usr/share/zsh/{,**} r, /usr/local/share/zsh/{,**} r, + /usr/share/oh-my-zsh/{,**} r, + /usr/share/zsh-theme-*/{,**} r, + /usr/share/zsh/{,**} r, /etc/zsh/* r, - owner @{HOME}/.zshrc r, - owner @{HOME}/.zshenv r, + /home/ r, + + owner @{HOME}/ r, + owner @{HOME}/.zcompdump-* rw, owner @{HOME}/.zsh_history rw, owner @{HOME}/.zsh_history.LOCK rwk, + owner @{HOME}/.zsh_history.new rw, + owner @{HOME}/.zshenv r, + owner @{HOME}/.zshrc r, owner @{HOME}/.oh-my-zsh/{,**} r, owner @{HOME}/.oh-my-zsh/log/update.lock/ w, - owner @{HOME}/.zcompdump-* rw, + owner @{user_cache_dirs}/oh-my-zsh/{,**} r, + owner @{user_cache_dirs}/oh-my-zsh/completions/* rw, - owner @{user_config_dirs}/zsh/.zcompdump-* rw, + owner @{user_cache_dirs}/p10k-@{user}/{,**} rw, + owner @{user_cache_dirs}/p10k-dump-@{user}.zsh{,.*} rw, + owner @{user_cache_dirs}/p10k-instant-prompt-@{user}.zsh{,.*} rw, + + owner @{user_config_dirs}/zsh/.zcompdump* rw, + owner @{user_config_dirs}/zsh/.zcompdump*.lock/ rw, owner @{user_config_dirs}/zsh/{,**} r, + owner @{user_config_dirs}/zsh/ohmyzsh/cache/** rw, + + owner @{user_share_dirs}/zsh/history rw, + owner @{user_share_dirs}/zsh/history.LOCK rwk, + owner @{user_share_dirs}/zsh/history.new rw, + + owner @{tmp}/gitstatus.POWERLEVEL9K.*.fifo rw, + owner @{tmp}/gitstatus.POWERLEVEL9K.*.lock rwk, + + owner @{tmp}/@{user}-code-zsh/.zcompdump* rw, + owner @{tmp}/@{user}-code-zsh/.zsh* r, + owner @{tmp}/zsh@{rand6} rw, + + @{PROC}/version r, + owner @{PROC}/@{pid}/loginuid r, include if exists diff --git a/apparmor.d/groups/_full/bwrap b/apparmor.d/groups/_full/bwrap deleted file mode 100644 index 0a4b9efdfd..0000000000 --- a/apparmor.d/groups/_full/bwrap +++ /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 - -# Default profile for bwrap. - -abi , - -include - -@{exec_path} = @{bin}/bwrap -profile bwrap @{exec_path} flags=(attach_disconnected,mediate_deleted) { - include - include - include - include - include - - capability dac_override, - capability dac_read_search, - capability sys_resource, - - network inet dgram, - network inet6 dgram, - network inet stream, - network inet6 stream, - - ptrace peer=bwrap//&bwrap-app, - - signal peer=bwrap//&bwrap-app, - signal (receive) set=(kill), - - @{bin}/** rm, - @{lib}/** rm, - /opt/*/** rm, - /usr/share/*/* rm, - - @{bin}/** Px -> bwrap//&bwrap-app, - @{bin}/xdg-dbus-proxy Px -> bwrap//&xdg-dbus-proxy, - # @{lib}/** Px -> bwrap//&bwrap-app, - /opt/*/** Px -> bwrap//&bwrap-app, - /usr/share/*/* Px -> bwrap//&bwrap-app, - - /usr/.ref rk, - - /bindfile@{rand6} rw, - - owner /var/cache/ w, - - owner @{run}/ld-so-cache-dir/* rw, - - include if exists - include if exists -} - -# vim:syntax=apparmor diff --git a/apparmor.d/groups/_full/bwrap-app b/apparmor.d/groups/_full/bwrap-app deleted file mode 100644 index b6d45478a4..0000000000 --- a/apparmor.d/groups/_full/bwrap-app +++ /dev/null @@ -1,36 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - -# Default profile for user sandboxed application - -abi , - -include - -profile bwrap-app flags=(attach_disconnected,mediate_deleted) { - include - include - - network inet dgram, - network inet6 dgram, - network inet stream, - network inet6 stream, - network netlink raw, - - ptrace peer=bwrap//&bwrap-app, - - signal peer=bwrap//&bwrap-app, - - @{bin}/** rmix, - @{lib}/** rmix, - /opt/*/** rmix, - /usr/share/*/* rmix, - - owner /var/cache/ w, - - include if exists - include if exists -} - -# vim:syntax=apparmor diff --git a/apparmor.d/groups/_full/default b/apparmor.d/groups/_full/default deleted file mode 100644 index acdfc0bfff..0000000000 --- a/apparmor.d/groups/_full/default +++ /dev/null @@ -1,122 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - -# Default profile for unconfined programs - -abi , - -include - -@{exec_path} = /** -profile default @{exec_path} flags=(attach_disconnected,mediate_deleted) { - include - include - include - include - include - include - include - include - include - include - include - include - include - - capability dac_override, - capability dac_read_search, - - network inet dgram, - network inet6 dgram, - network inet stream, - network inet6 stream, - network netlink dgram, - network netlink raw, - - signal receive set=hup, - - @{bin}/bwrap rPx -> bwrap, - @{bin}/pipewire-pulse rPx -> systemd//&pipewire-pulse, - @{bin}/pulseaudio rPx -> systemd//&pulseaudio, - @{bin}/su rPx -> default-sudo, - @{bin}/sudo rPx -> default-sudo, - @{bin}/systemctl rix, - @{coreutils_path} rix, - @{shells_path} rix, - - @{pager_path} rPx -> child-pager, - -# @{open_path} rPx -> child-open, - - audit @{bin}/** Pix, - audit @{lib}/** Pix, - audit /opt/*/** Pix, - audit /usr/share/*/* Pix, - - @{bin}/{,**} r, - @{lib}/{,**} r, - /usr/share/** r, - - /etc/xdg/** r, - - # Full access to user's data - / r, - /*/ r, - @{MOUNTDIRS}/ r, - @{MOUNTS}/ r, - @{MOUNTS}/** rwl, - owner @{HOME}/{,**} rwlk, - owner @{run}/user/@{uid}/{,**} rw, - owner @{tmp}/{,**} rwk, - owner @{run}/user/@{uid}/{,**} rwlk, - - @{run}/motd.dynamic.new rw, - - @{run}/udev/data/+input:input@{int} r, # for mouse, keyboard, touchpad - - @{run}/udev/data/c13:@{int} r, # for /dev/input/* - - @{sys}/ r, - @{sys}/bus/ r, - @{sys}/bus/pci/devices/ r, - @{sys}/class/ r, - @{sys}/class/drm/ r, - @{sys}/class/hidraw/ r, - @{sys}/class/input/ r, - @{sys}/class/power_supply/ r, - @{sys}/devices/**/input@{int}/ r, - @{sys}/devices/**/input@{int}/capabilities/* r, - @{sys}/devices/**/input/input@{int}/ r, - @{sys}/devices/**/uevent r, - @{sys}/devices/virtual/dmi/id/chassis_type r, - @{sys}/firmware/acpi/pm_profile r, - @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/session.slice/dbus.service/memory.* r, - - @{PROC}/cmdline r, - @{PROC}/sys/kernel/seccomp/actions_avail r, - @{PROC}/zoneinfo r, - owner @{PROC}/@{pid}/cgroup r, - owner @{PROC}/@{pid}/gid_map w, - owner @{PROC}/@{pid}/limits r, - owner @{PROC}/@{pid}/loginuid r, - owner @{PROC}/@{pid}/mem r, - owner @{PROC}/@{pid}/mountinfo r, - owner @{PROC}/@{pid}/mounts r, - owner @{PROC}/@{pid}/oom_{,score_}adj rw, - owner @{PROC}/@{pid}/stat r, - owner @{PROC}/@{pid}/task/@{tid}/comm rw, - owner @{PROC}/@{pids}/cmdline r, - owner @{PROC}/@{pids}/environ r, - owner @{PROC}/@{pids}/task/ r, - - /dev/ r, - /dev/ptmx rwk, - /dev/tty rwk, - owner /dev/tty@{int} rw, - - include if exists - include if exists -} - -# vim:syntax=apparmor diff --git a/apparmor.d/groups/_full/default-sudo b/apparmor.d/groups/_full/default-sudo deleted file mode 100644 index 6091919708..0000000000 --- a/apparmor.d/groups/_full/default-sudo +++ /dev/null @@ -1,42 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - -abi , - -include - -profile default-sudo { - include - include - - capability chown, - capability mknod, - capability sys_ptrace, - - network inet dgram, - network inet6 dgram, - - ptrace (read), - - @{bin}/su mr, - - @{bin}/** Px, - @{lib}/** Px, - /opt/*/** Px, - - /var/db/sudo/lectured/ r, - /var/lib/extrausers/shadow r, - /var/lib/sudo/lectured/ r, - owner /var/db/sudo/lectured/@{uid} rw, - owner /var/lib/sudo/lectured/* rw, - - owner @{HOME}/.sudo_as_admin_successful rw, - - @{run}/ r, - @{run}/systemd/sessions/* r, - - include if exists -} - -# vim:syntax=apparmor diff --git a/apparmor.d/groups/_full/sd b/apparmor.d/groups/_full/sd new file mode 100644 index 0000000000..1e910e79ad --- /dev/null +++ b/apparmor.d/groups/_full/sd @@ -0,0 +1,263 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +#aa:lint ignore=too-wide + +# *Part of the `systemd` (as PID 1) profile.* +# +# `sd` is a profile for **S**ystem**D**-executor run as root, it is used to run +# all services files and to encapsulate stacked services profiles (hence the +# short name). +# +# It aims at reducing the size of the `systemd` profile. +# +# !!! info +# +# Distributions and other programs can add rules in the `usr/sd.d` directory +# + +abi , + +include + +@{exec_path} = @{bin}/systemd-executor +profile sd flags=(attach_disconnected,mediate_deleted,complain) { + include + include + include + include + include + include + include + include + + userns, + + capability audit_control, + capability audit_write, + capability bpf, + capability chown, + capability dac_override, + capability dac_read_search, + capability fowner, + capability fsetid, + capability kill, + capability linux_immutable, + capability mknod, + capability net_admin, + capability net_bind_service, + capability net_raw, + capability perfmon, + capability setfcap, + capability setgid, + capability setpcap, + capability setuid, + capability sys_admin, + capability sys_nice, + capability sys_ptrace, + capability sys_rawio, + capability sys_resource, + capability sys_time, + capability sys_tty_config, + capability syslog, + + network alg seqpacket, # kernel crypto API + network bluetooth, + network inet dgram, + network inet stream, + network inet6 dgram, + network inet6 raw, + network inet6 stream, + network netlink raw, + network packet dgram, + network packet raw, + network qipcrtr dgram, + + mount -> @{run}/systemd/mount-rootfs/{,**}, + mount -> @{run}/systemd/namespace-@{rand6}/{,**}, + mount options=(rw move) /dev/shm/ -> @{run}/credentials/*/, + mount options=(rw rshared) -> /, + mount options=(rw make-rslave) /, + mount options=(rw make-rslave) /dev/, + mount options=(rw slave) -> @{run}/systemd/incoming/, + mount fstype=tmpfs options=(rw nodev noexec nosuid nosymfollow) tmpfs -> /dev/shm/, + mount fstype=tmpfs options=(rw nodev strictatime) tmpfs -> @{run}/systemd/unit-private-tmp/, + + remount /dev/shm/, + remount @{run}/systemd/mount-rootfs/{,**}, + + umount /, + umount /dev/shm/, + umount @{run}/systemd/mount-rootfs/{,**}, + umount @{run}/systemd/namespace-@{rand6}/{,**}, + + pivot_root oldroot=/run/systemd/mount-rootfs/ @{run}/systemd/mount-rootfs/, + + change_profile, + + mqueue (read getattr) type=posix /, + + signal (send, receive), + + ptrace read, + + unix type=dgram peer=(label=@{p_systemd}), + unix type=dgram peer=(label=systemd-timesyncd), + unix type=stream, + + dbus bus=system, + + @{exec_path} mr, + + @{bin}/** mPx, + @{sbin}/** mPx, + @{lib}/** Px, + /etc/cron.*/* Px, + /etc/init.d/* Px, + /etc/update-motd.d/* Px, + /usr/share/*/** Px, + + # Systemd user: systemd --user + @{lib}/systemd/systemd px -> systemd-user, + + # Mount operations from services and systemd + @{bin}/mount Px -> sd-mount, + @{bin}/umount Px -> sd-umount, + + # Unit services using systemctl + @{bin}/systemctl Cx -> systemctl, + + # Unit services + @{bin}/kill Cx -> kill, + + # Used by very basic services, ideally should be replaced by a unit profiles + @{sh_path} ix, + @{bin}/false ix, + @{bin}/true ix, + + # Required due to stacked profiles + @{bin}/find ix, + @{bin}/gzip ix, + @{bin}/install ix, + @{bin}/readlink ix, + @{lib}/colord-sane ix, + @{lib}/systemd/systemd-nsresourcework ix, + @{lib}/systemd/systemd-userwork ix, + @{sbin}/grpck ix, + @{sbin}/pwck ix, + + / r, + @{att}/ r, + @{bin}/{,**} r, + @{lib}/{,**} r, + @{sbin}/{,*} r, + /usr/local/{,**} r, + /usr/share/** r, + /etc/*/ w, + /etc/** rk, + /home/ r, + + @{efi}/ r, + @{efi}/** rw, + + @{att}/var/lib/systemd/*/ r, + + /var/cache/*/ rw, + /var/cache/*/** rwk, + /var/lib/*/ rw, + /var/lib/*/** rwlk, + /var/lib/systemd/*/ r, + /var/log/ r, + /var/log/** rw, + /var/log/journal/** rwl -> /var/log/journal/**, + /var/spool/cron/atjobs/ r, + + @{att}@{desktop_share_dirs}/icc/edid-@{hex32}.icc r, + @{att}@{user_share_dirs}/icc/edid-@{hex32}.icc r, + + @{att}@{run}/systemd/coredump rw, + @{att}@{run}/systemd/io.systemd.ManagedOOM rw, + @{att}@{run}/systemd/userdb/io.systemd.DynamicUser rw, + @{att}@{run}/systemd/userdb/io.systemd.Home rw, + @{att}@{run}/systemd/userdb/io.systemd.Multiplexer rw, + + @{run}/ rw, + @{run}/* rw, + @{run}/*/ rw, + @{run}/*/* rw, + @{run}/*/*/ rw, + @{run}/ubuntu-advantage/** rw, # stacked + @{run}/systemd/{,**} rw, + owner @{run}/*/** rw, + + @{run}/udev/**/ r, + @{run}/udev/data/+*:* r, # Identifies all subsystems + @{run}/udev/data/c@{int}:@{int} r, # Identifies all character devices + @{run}/udev/data/n@{int} r, # For network interfaces + + @{sys}/** r, + @{sys}/fs/bpf/systemd/{,**} w, + @{sys}/firmware/efi/efivars/** w, + @{sys}/fs/cgroup/{,**} w, + + @{PROC}/@{pids}/attr/apparmor/exec w, + @{PROC}/@{pids}/attr/current r, + @{PROC}/@{pids}/cgroup r, + @{PROC}/@{pids}/cmdline r, + @{PROC}/@{pids}/comm r, + @{PROC}/@{pids}/environ r, + @{PROC}/@{pids}/fd/ r, + @{PROC}/@{pids}/fdinfo/@{int} r, + @{PROC}/@{pids}/gid_map w, + @{PROC}/@{pids}/limits r, + @{PROC}/@{pids}/loginuid rw, + @{PROC}/@{pids}/mountinfo r, + @{PROC}/@{pids}/oom_score_adj rw, + @{PROC}/@{pids}/sessionid r, + @{PROC}/@{pids}/setgroups r, + @{PROC}/@{pids}/setgroups w, + @{PROC}/@{pids}/stat r, + @{PROC}/@{pids}/status r, + @{PROC}/@{pids}/uid_map r, + @{PROC}/@{pids}/uid_map w, + @{PROC}/cmdline r, + @{PROC}/interrupts r, + @{PROC}/irq/@{int}/node r, + @{PROC}/irq/@{int}/smp_affinity r, + @{PROC}/kmsg r, + @{PROC}/modules r, + @{PROC}/pressure/* r, + @{PROC}/swaps r, + @{PROC}/sys/** r, + @{PROC}/sys/kernel/random/write_wakeup_threshold w, + @{PROC}/sys/net/ipv{4,6}/** rw, + @{PROC}/sysvipc/* r, + @{PROC}/version r, + @{PROC}/version_signature r, + + /dev/** rwk, + + profile systemctl flags=(attach_disconnected,mediate_deleted,complain) { + include + include + + include if exists + include if exists + } + + profile kill flags=(attach_disconnected,mediate_deleted,complain) { + include + + signal send, + + @{bin}/kill mr, + + include if exists + } + + include if exists + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/_full/sd-mount b/apparmor.d/groups/_full/sd-mount new file mode 100644 index 0000000000..a0b962b3de --- /dev/null +++ b/apparmor.d/groups/_full/sd-mount @@ -0,0 +1,71 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# *Part of the `systemd` (as PID 1) profile.* +# +# `sd-mount` is a subprofile of `sd` responsible to handle mounting operation. +# +# !!! info +# +# Distributions and other programs can add rules in the `usr/sd-mount.d` directory +# + +abi , + +include + +@{exec_path} = @{bin}/mount +profile sd-mount flags=(complain) { + include + include + + capability dac_read_search, + capability sys_admin, + + mount -> @{efi}/, + mount -> @{HOME}/{,**}, + mount -> @{HOMEDIRS}/, + mount -> @{MOUNTDIRS}/, + mount -> @{MOUNTS}/{,**}, + mount fstype=binfmt_misc options=(rw nodev noexec nosuid) binfmt_misc -> @{PROC}/sys/fs/binfmt_misc/, + mount fstype=configfs options=(rw nodev noexec nosuid) configfs -> @{sys}/kernel/config/, + mount fstype=debugfs options=(rw nodev noexec nosuid) debugfs -> @{sys}/kernel/debug/, + mount fstype=fusectl options=(rw nodev noexec nosuid) fusectl -> @{sys}/fs/fuse/connections/, + mount fstype=hugetlbfs options=(rw nosuid nodev) hugetlbfs -> /dev/hugepages/, + mount fstype=mqueue options=(rw nodev noexec nosuid) -> /dev/mqueue/, + mount fstype=squashfs options=(ro nodev) /dev/loop@{int} -> /snap/*/@{int}/, + mount fstype=tmpfs options=(rw nodev noexec nosuid) tmpfs -> @{run}/lock/, + mount fstype=tmpfs options=(rw nodev nosuid strictatime) tmpfs -> /tmp/, + mount fstype=tracefs options=(rw nodev noexec nosuid) tracefs -> @{sys}/kernel/tracing/, + + mount options=(rw move) -> @{efi}, + mount options=(rw move) -> @{HOME}/{,**}, + mount options=(rw move) -> @{HOMEDIRS}/, + mount options=(rw move) -> @{MOUNTDIRS}/, + mount options=(rw move) -> @{MOUNTS}/{,**}, + mount options=(rw move) -> @{sys}/fs/fuse/connections/, + mount options=(rw move) -> @{sys}/kernel/config/, + mount options=(rw move) -> @{sys}/kernel/debug/, + mount options=(rw move) -> @{sys}/kernel/tracing/, + mount options=(rw move) -> /dev/hugepages/, + mount options=(rw move) -> /dev/mqueue/, + mount options=(rw move) -> /tmp/, + + @{exec_path} mr, + + /var/lib/snapd/snaps/*.snap r, + + @{run}/ r, + owner @{run}/mount/ rw, + owner @{run}/mount/utab{,.*} rwk, + + @{PROC}/@{pid}/mountinfo r, + + /dev/loop-control rw, + + include if exists + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/_full/sd-umount b/apparmor.d/groups/_full/sd-umount new file mode 100644 index 0000000000..c0518d1d35 --- /dev/null +++ b/apparmor.d/groups/_full/sd-umount @@ -0,0 +1,34 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# *Part of the `systemd` (as PID 1) profile.* +# +# `sd-umount` is a subprofile of `sd` responsible to handle unmounting operation. +# +# !!! info +# +# Distributions and other programs can add rules in the `usr/sd-umount.d` directory +# + +abi , + +include + +@{exec_path} = @{bin}/umount +profile sd-umount flags=(complain) { + include + + capability sys_admin, + + umount @{efi}, + + @{exec_path} mr, + + @{PROC}/@{pid}/mountinfo r, + + include if exists + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/_full/sdu b/apparmor.d/groups/_full/sdu new file mode 100644 index 0000000000..62f29bfc6d --- /dev/null +++ b/apparmor.d/groups/_full/sdu @@ -0,0 +1,142 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# *Part of the `systemd-user` profile.* +# +# `sdu` is a profile for **S**ystem**D**-executor run as **U**ser, it is used to +# run all services files and to encapsulate stacked services profiles (hence the +# short name). +# +# It aims at reducing the size of the `systemd-user` profile. +# +# !!! info +# +# Distributions and other programs can add rules in the `usr/sdu.d` directory +# + +abi , + +include + +@{exec_path} = @{bin}/systemd-executor +profile sdu flags=(attach_disconnected,mediate_deleted) { + include + include + include + include + include + include + include + include + + network netlink raw, + + change_profile, + + ptrace read, + + unix type=dgram peer=(label=@{p_systemd_user}), + + #aa:dbus talk bus=system name=org label="*" + dbus bus=session, + + @{exec_path} mr, + + @{bin}/** mPx, + @{sbin}/** mPx, + @{lib}/** Px, + /etc/cron.*/* Px, + /opt/*/** Px, + /usr/share/*/** Px, + + # Unit services using systemctl + @{bin}/systemctl Cx -> systemctl, + + # Shell based user unit services + @{sh_path} Cx -> shell, + + # Dbus needs to be started without environment scrubbing + @{bin}/dbus-broker px -> dbus-session, + @{bin}/dbus-broker-launch px -> dbus-session, + @{bin}/dbus-daemon px -> dbus-session, + @{lib}/dbus-1.0/dbus-daemon-launch-helper px -> dbus-session, + + / r, + @{bin}/* r, + @{sbin}/* r, + /usr/share/** r, + + owner @{desktop_local_dirs}/ w, + owner @{desktop_local_dirs}/state/ w, + owner @{desktop_local_dirs}/state/wireplumber/{,**} rw, + + owner @{run}/user/@{uid}/pipewire-@{int} rw, + owner @{run}/user/@{uid}/pipewire-@{int}-manager rw, + owner @{run}/user/@{uid}/pipewire-@{int}-manager.lock rwk, + owner @{run}/user/@{uid}/pipewire-@{int}.lock rwk, + owner @{run}/user/@{uid}/pulse/pid rw, + + owner @{user_state_dirs}/wireplumber/ rw, + owner @{user_state_dirs}/wireplumber/stream-properties rw, + owner @{user_state_dirs}/wireplumber/stream-properties.@{rand6} rw, + + @{run}/systemd/users/@{uid} r, + @{run}/systemd/users/@{int} 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, + @{sys}/devices/system/node/ r, + @{sys}/devices/system/node/node@{int}/meminfo r, + @{sys}/devices/virtual/sound/seq/uevent r, + @{sys}/devices/virtual/sound/timer/uevent r, + + @{sys}/module/apparmor/parameters/enabled r, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/{,**} rw, + + @{PROC}/pressure/* r, + @{PROC}/sys/fs/nr_open r, + owner @{PROC}/@{pid}/attr/apparmor/exec w, + owner @{PROC}/@{pid}/fd/ r, + owner @{PROC}/@{pid}/oom_score_adj rw, + owner @{PROC}/@{pid}/task/@{tid}/comm rw, + + /dev/kmsg w, + + deny capability net_admin, + + profile shell flags=(attach_disconnected,mediate_deleted) { + include + + @{sh_path} mr, + @{bin}/systemctl Px -> sdu//systemctl, + + include if exists + } + + profile systemctl flags=(attach_disconnected,mediate_deleted) { + include + include + + owner @{run}/user/@{uid}/systemd/private rw, + + deny capability net_admin, + + include if exists + include if exists + } + + include if exists + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/_full/systemd b/apparmor.d/groups/_full/systemd index d055135bde..b76db1a239 100644 --- a/apparmor.d/groups/_full/systemd +++ b/apparmor.d/groups/_full/systemd @@ -5,33 +5,68 @@ # Profile for systemd (PID 1), it does not specify an attachment path because # it is directly loaded by systemd. - -# Only use this profile with a fully configured system. Otherwise it **WILL** -# break your computer. See https://apparmor.pujol.io/full-system-policy/. - -# Distributions and other programs can add rules in the usr/systemd.d directory - -# TODO: rework this to get a controlled environment: (cf security model) -# - No global allow anymore: in high security environments, we must manage the list -# of program/service that can be started by systemd and ensure that they are all -# listed and confined. Programs not listed will not be able to start. -# - Outside common systemd service, the list may have to be automatically -# generated at install time, in `/etc/apparmor.d/usr/systemd.d/exec` -# - Stop disabling nnp flags in systemd dropin files. -# - Each systemd services in `systemd-service` (when the service is more complex than foo.service -> Exec=/usr/bin/foo) -# need they own profile, profile name configured as a dropin unit file. -# - When this is done: the fallback profile as root will not be needed. +# +# !!! danger +# +# Only use this profile with a fully configured system. Otherwise it **WILL** +# break your computer. See https://apparmor.pujol.io/full-system-policy/. +# +# !!! info +# +# Distributions and other programs can add rules in the `usr/systemd.d` directory +# +# Overall architecture of the systemd profiles: +# +# ``` +# systemd # PID 1, entrypoint, requires "Early policy" +# ├── systemd # To restart itself +# ├── systemd-generators-* # Systemd system and environment generators +# └── sd # Internal service starter and config handler, handles all services +# ├── Px or px, # Any service with profile +# ├── Px -> # Any service without profile defined in the unit file (see systemd/full/systemd) +# ├── &* # Stacked service as defined in the unit file (see systemd/full/systemd) +# ├── sd-mount # Handles all mounts from services +# ├── sd//systemctl # Internal system systemctl +# └── systemd-user # Profile for 'systemd --user' +# ├── systemd-user # To restart itself +# ├── systemd-user-generators-* # Systemd user and environment generators +# └── sdu # Handles all user services +# ├── Px or px, # Any user service with profile +# ├── Px -> # Any user service without profile defined in the unit file (see systemd/full/systemd) +# ├── &* # Stacked user service as defined in the unit file (see systemd/full/systemd) +# └── sdu//systemctl # Internal user systemctl +# ``` +# +# Advantages: +# +# - Differentiate systemd (PID 1) and `system --user` +# - Keep `systemd` and systemd-user as mininal as possible, and transition to less privileged profiles. +# - Allow the executor profiles to handle stacked profiles. +# - Most additions need to be done in the `sd`/`sdu` profile, not in `systemd`/`systemd-user`. +# - Dedicated `sd-mount` profile for most mount from the unit services. +# +# !!! warning "Work in Progress" +# +# This profile stack can be changed to provide a more controlled environment: +# +# - No global allow anymore: in high security environments, we must manage the list +# of program/service that can be started by systemd and ensure that they are all +# listed and confined. Programs not listed will not be able to start. +# - Outside common systemd service, the list may have to be automatically +# generated at install time, in `/etc/apparmor.d/usr/systemd.d/exec` +# abi , include -profile systemd flags=(attach_disconnected,mediate_deleted) { +@{exec_path} = @{lib}/systemd/systemd +profile systemd flags=(attach_disconnected,mediate_deleted,complain) { include - include include include include + include include capability audit_control, @@ -43,16 +78,13 @@ profile systemd flags=(attach_disconnected,mediate_deleted) { capability dac_read_search, capability fowner, capability fsetid, - capability mknod, + capability kill, capability net_admin, + capability net_bind_service, capability perfmon, - capability setfcap, - capability setgid, capability setpcap, - capability setuid, capability sys_admin, - capability sys_chroot, - capability sys_nice, + capability sys_boot, capability sys_ptrace, capability sys_resource, capability sys_tty_config, @@ -62,218 +94,119 @@ profile systemd flags=(attach_disconnected,mediate_deleted) { network inet6 dgram, network inet6 stream, network netlink raw, + network vsock stream, mount fstype=autofs systemd-1 -> @{PROC}/sys/fs/binfmt_misc/, - mount fstype=autofs systemd-1 -> /efi/, - mount fstype=binfmt_misc options=(rw nodev noexec nosuid) binfmt_misc -> @{PROC}/sys/fs/binfmt_misc/, - mount fstype=configfs options=(rw nodev noexec nosuid) configfs -> @{sys}/kernel/config/, - mount fstype=debugfs options=(rw nodev noexec nosuid) debugfs -> @{sys}/kernel/debug/, - mount fstype=fusectl options=(rw nodev noexec nosuid) fusectl -> @{sys}/fs/fuse/connections/, - mount fstype=hugetlbfs options=(rw nosuid nodev) hugetlbfs -> /dev/hugepages/, - mount fstype=mqueue options=(rw nodev noexec nosuid) -> /dev/mqueue/, - mount fstype=proc options=(rw nosuid nodev noexec) proc -> @{run}/systemd/namespace-@{rand6}/, - mount fstype=sysfs options=(rw nosuid nodev noexec) sysfs -> @{run}/systemd/namespace-@{rand6}/, - mount fstype=tmpfs tmpfs -> /dev/shm/, + mount fstype=autofs systemd-1 -> @{efi}/, mount fstype=tmpfs tmpfs -> /tmp/, - mount fstype=tmpfs options=(rw nosuid nodev noexec strictatime) tmpfs -> @{run}/systemd/mount-rootfs/@{run}/credentials/, - mount fstype=tmpfs options=(rw nosuid nodev noexec) tmpfs -> /dev/shm/, - mount fstype=tmpfs options=(rw nosuid noexec strictatime) tmpfs -> @{run}/systemd/namespace-@{rand6}/dev/, - mount fstype=tracefs options=(rw nodev noexec nosuid) tracefs -> @{sys}/kernel/tracing/, - mount fstype=vfat -> /boot/efi/, - mount options=(rw bind) /dev/** -> /tmp/namespace-dev-@{rand6}/**, - mount options=(rw bind) /dev/** -> @{run}/systemd/namespace-@{rand6}/dev/**, - mount options=(rw bind) @{run}/systemd/propagate/*/ -> @{run}/systemd/mount-rootfs/@{run}/systemd/incoming/, - mount options=(rw move) -> @{sys}/fs/fuse/connections/, - mount options=(rw move) -> @{sys}/kernel/config/, - mount options=(rw move) -> @{sys}/kernel/debug/, - mount options=(rw move) -> @{sys}/kernel/tracing/, - mount options=(rw move) -> /dev/hugepages/, - mount options=(rw move) -> /dev/mqueue/, - mount options=(rw move) -> /efi/, - mount options=(rw move) -> /tmp/, - mount options=(rw move) @{run}/systemd/namespace-@{rand6}/{,**} -> @{run}/systemd/mount-rootfs/{,**}, - mount options=(rw rbind) -> @{run}/systemd/mount-rootfs/{,**}, - mount options=(rw rbind) -> @{run}/systemd/unit-root/{,**}, - mount options=(rw rshared) -> /, - mount options=(rw rslave) -> /, - mount options=(rw rslave) -> /dev/, - mount options=(rw slave) -> @{run}/systemd/incoming/, + mount options=(rw make-rslave) /, remount @{HOME}/{,**}, remount @{HOMEDIRS}/, remount @{MOUNTDIRS}/, remount @{MOUNTS}/{,**}, - remount @{run}/systemd/mount-rootfs/{,**}, - remount @{run}/systemd/unit-root/{,**}, - remount /, remount /snap/{,**}, - remount options=(ro bind) /boot/efi/, - remount options=(ro noexec noatime bind) /var/snap/{,**}, - remount options=(ro nosuid bind) /dev/, - remount options=(ro nosuid nodev bind) /dev/hugepages/, - remount options=(ro nosuid nodev bind) /var/, - remount options=(ro nosuid nodev noexec bind) /boot/, - remount options=(ro nosuid nodev noexec bind) /dev/mqueue/, - remount options=(ro nosuid nodev noexec bind) /efi/, - remount options=(ro nosuid noexec bind) /dev/pts/, + remount options=(ro bind nodev noexec nosuid) /dev/mqueue/, + remount options=(ro bind nodev nosuid) /dev/hugepages/, + remount options=(ro bind noexec nosuid) /dev/pts/, + remount options=(ro bind nosuid) /dev/, + remount options=(ro bind) @{efi}/, + remount options=(ro bind) /, - umount /, - umount /dev/shm/, umount @{PROC}/sys/fs/binfmt_misc/, - umount @{run}/systemd/mount-rootfs/{,**}, - umount @{run}/systemd/namespace-@{rand6}/{,**}, - umount @{run}/systemd/unit-root/{,**}, - - pivot_root oldroot=@{run}/systemd/mount-rootfs/ @{run}/systemd/mount-rootfs/, - pivot_root oldroot=@{run}/systemd/unit-root/ @{run}/systemd/unit-root/, + umount @{run}/credentials/*/, mqueue (read getattr) type=posix /, - change_profile, - - signal receive set=(rtmin+23) peer=plymouthd, - signal receive set=(term hup cont), signal send, ptrace (read, readby), - unix send type=dgram, - - unix receive type=dgram peer=(label=systemd-timesyncd), - unix (send, receive, connect) type=stream peer=(label=plymouthd, addr=@/org/freedesktop/plymouthd), + unix type=dgram, + unix type=stream, #aa:dbus own bus=system name=org.freedesktop.systemd1 - # For stacked profiles - #aa:dbus own bus=system name=org.freedesktop.network1 - #aa:dbus own bus=system name=org.freedesktop.oom1 - #aa:dbus own bus=system name=org.freedesktop.resolve1 - #aa:dbus own bus=system name=org.freedesktop.timesync1 - - @{bin}/** Px, - @{lib}/** Px, - /etc/cron.*/* Px, - /etc/init.d/* Px, - /etc/update-motd.d/* Px, - /usr/share/*/** Px, - - # Systemd internal service started and config handler (sandboxing, namespacing, cgroup, etc.) - @{lib}/systemd/systemd-executor ix, - - # Systemd user: systemd --user - @{lib}/systemd/systemd px -> systemd-user, - - # Unit services using systemctl - @{bin}/systemctl Cx -> systemctl, + @{exec_path} mrix, + @{sh_path} mr, - # Unit services - @{bin}/mount ix, - @{bin}/kill ix, + # Systemd internal service starter and config handler (sandboxing, namespacing, cgroup, etc.) + @{lib}/systemd/systemd-executor mPx -> sd, - # Shell based systemd unit services - # TODO: create unit profile for all of them - @{bin}/ldconfig Px -> systemd-service, - @{bin}/mandb Px -> systemd-service, - @{bin}/savelog Px -> systemd-service, - @{coreutils_path} Px -> systemd-service, - @{sh_path} Px -> systemd-service, - - # Systemd profiles that need be stacked - #aa:stack systemd-networkd systemd-oomd systemd-resolved systemd-timesyncd - @{lib}/systemd/systemd-networkd px -> systemd//&systemd-networkd, - @{lib}/systemd/systemd-oomd px -> systemd//&systemd-oomd, - @{lib}/systemd/systemd-resolved px -> systemd//&systemd-resolved, - @{lib}/systemd/systemd-timesyncd px -> systemd//&systemd-timesyncd, - - @{lib}/ r, - / r, - /*/ r, - /boot/efi/ r, - /snap/*/@{int}/ r, - /var/cache/*/ r, - /var/lib/*/ r, - /var/tmp/ r, + # Systemd system generators. Profiles must exist + @{lib}/netplan/generate mPx, + @{lib}/systemd/system-environment-generators/* mPx, + @{lib}/systemd/system-generators/* mPx, @{etc_ro}/environment r, @{etc_ro}/environment.d/{,**} r, /etc/acpi/events/{,**} r, /etc/binfmt.d/{,**} r, /etc/conf.d/{,**} r, - /etc/credstore.encrypted/{,**} r, - /etc/credstore/{,**} r, /etc/default/{,**} r, /etc/machine-id r, /etc/modules-load.d/{,**} r, /etc/networkd-dispatcher/{,**} r, /etc/systemd/{,**} r, + /etc/systemd/system/** w, /etc/udev/hwdb.d/{,**} r, - /etc/systemd/system/multi-user.target.wants/{,*} w, - /var/log/dmesg rw, - /var/lib/systemd/{,**} rw, - owner /var/tmp/systemd-private-*/{,**} rw, + #aa:only pacman + # It is unclear why this is needed here and not in sd + /etc/pacman.d/gnupg/S.dirmngr w, + /etc/pacman.d/gnupg/S.gpg-agent w, + /etc/pacman.d/gnupg/S.gpg-agent.browser w, + /etc/pacman.d/gnupg/S.gpg-agent.extra w, + /etc/pacman.d/gnupg/S.gpg-agent.ssh w, + /etc/pacman.d/gnupg/S.keyboxd w, + + @{efi}/ r, + /snap/*/@{int}/ r, - /tmp/namespace-dev-@{rand6}/{,**} rw, - /tmp/systemd-private-*/{,**} rw, + /tmp/ r, + /var/tmp/ r, + owner /tmp/systemd-private-*/{,**} rw, + owner /var/tmp/systemd-private-*/{,**} rw, - @{att}/@{run}/systemd/journal/socket r, - @{att}/@{run}/systemd/journal/dev-log r, + @{att}@{run}/systemd/journal/dev-log r, + @{att}@{run}/systemd/journal/socket r, + @{att}@{run}/systemd/notify r, @{run}/ rw, - @{run}/*.socket w, + @{run}/* rw, @{run}/*/ rw, @{run}/*/* rw, - @{run}/auditd.pid r, @{run}/credentials/{,**} rw, - @{run}/initctl rw, @{run}/systemd/{,**} rw, - @{run}/udev/data/+bluetooth:* r, - @{run}/udev/data/+backlight:* r, - @{run}/udev/data/+leds:*backlight* r, - - @{run}/udev/data/+module:configfs r, - @{run}/udev/data/+module:fuse r, + @{run}/udev/data/+module:* r, # Identifies kernel modules loaded by udev @{run}/udev/data/c4:@{int} r, # For TTY devices @{run}/udev/data/c5:@{int} r, # for /dev/tty, /dev/console, /dev/ptmx @{run}/udev/data/c10:@{int} r, # For non-serial mice, misc features @{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 - @{run}/udev/data/n@{int} r, + @{run}/udev/data/n@{int} r, # For network interfaces @{run}/udev/tags/systemd/ r, + @{sys}/**/uevent r, @{sys}/bus/ r, @{sys}/class/ r, @{sys}/class/power_supply/ r, - @{sys}/class/sound/ r, - @{sys}/devices/@{pci}/** r, - @{sys}/devices/**/net/** r, - @{sys}/devices/**/uevent r, - @{sys}/devices/virtual/dmi/id/{sys,board,bios}_vendor r, - @{sys}/devices/virtual/dmi/id/product_name r, - @{sys}/devices/virtual/dmi/id/product_version r, @{sys}/devices/virtual/tty/console/active r, + @{sys}/firmware/efi/efivars/LoaderSystemToken-@{uuid} rw, @{sys}/fs/cgroup/{,**} rw, @{sys}/fs/fuse/connections/ r, @{sys}/fs/pstore/ r, @{sys}/kernel/**/ r, - @{sys}/module/**/uevent r, @{sys}/module/apparmor/parameters/enabled r, + @{sys}/module/vt/parameters/default_utf8 r, @{PROC}/@{pid}/cgroup r, @{PROC}/@{pid}/cmdline r, @{PROC}/@{pid}/comm r, - @{PROC}/@{pid}/coredump_filter r, - @{PROC}/@{pid}/environ r, @{PROC}/@{pid}/fd/ r, - @{PROC}/@{pid}/fdinfo/@{int} r, - @{PROC}/@{pid}/gid_map rw, - @{PROC}/@{pid}/loginuid rw, - @{PROC}/@{pid}/mountinfo r, - @{PROC}/@{pid}/setgroups rw, @{PROC}/@{pid}/stat r, - @{PROC}/@{pid}/uid_map rw, @{PROC}/cmdline r, @{PROC}/devices r, @{PROC}/pressure/* r, @@ -281,32 +214,33 @@ profile systemd flags=(attach_disconnected,mediate_deleted) { @{PROC}/sys/fs/binfmt_misc/ r, @{PROC}/sys/fs/nr_open r, @{PROC}/sys/kernel/* r, - @{PROC}/sysvipc/{shm,sem,msg} r, - owner @{PROC}/@{pid}/limits r, - owner @{PROC}/@{pid}/oom_score_adj rw, + @{PROC}/sys/kernel/random/boot_id r, + @{PROC}/sysvipc/msg r, + @{PROC}/sysvipc/sem r, + @{PROC}/sysvipc/shm r, + owner @{PROC}/@{pid}/mountinfo r, + owner @{PROC}/1/coredump_filter r, + owner @{PROC}/1/fdinfo/@{int} r, + owner @{PROC}/1/gid_map r, + owner @{PROC}/1/oom_score_adj rw, + owner @{PROC}/1/setgroups r, + owner @{PROC}/1/uid_map r, /dev/autofs r, + /dev/dri/card@{int} rw, + /dev/initctl w, /dev/input/ r, /dev/kmsg w, - /dev/tty@{int} rw, + /dev/tty rw, + /dev/tty@{u8} rw, owner /dev/console rwk, - owner /dev/dri/card@{int} rw, owner /dev/hugepages/ rw, - owner /dev/initctl rw, owner /dev/input/event@{int} rw, owner /dev/mqueue/ rw, owner /dev/rfkill rw, - owner /dev/shm/ rw, + owner /dev/shm/ r, owner /dev/ttyS@{int} rwk, - profile systemctl { - include - include - - include if exists - include if exists - } - include if exists include if exists } diff --git a/apparmor.d/groups/_full/systemd-service b/apparmor.d/groups/_full/systemd-service deleted file mode 100644 index dfe3000bcd..0000000000 --- a/apparmor.d/groups/_full/systemd-service +++ /dev/null @@ -1,77 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - -# Profile for generic systemd unit services. Only used by tiny systemd services -# that start a shell or use context specific programs. - -# It does not specify an attachment path because it is intended to be used only -# via "Px -> systemd-service" exec transitions from the systemd profile. - -abi , - -include - -profile systemd-service flags=(attach_disconnected) { - include - include - include - - capability dac_read_search, - capability chown, - capability fsetid, - - @{bin}/ldconfig rix, - @{bin}/savelog rix, - @{bin}/systemctl rix, - @{bin}/gzip rix, - @{coreutils_path} rix, - @{sh_path} rmix, - - # ifup@.service - @{bin}/ifup rPx, - - # shadow.service - @{bin}/pwck rPx, - @{bin}/grpck rPx, - - @{bin}/grub-editenv rPx, - @{bin}/ibus-daemon rPx, - - @{bin}/* r, - @{lib}/ r, - - /var/cache/ldconfig/{,**} rw, - - / r, - - /boot/grub/grubenv rw, - /boot/grub/ w, - - /var/spool/cron/atjobs/ r, - - /var/log/ r, - /var/log/dmesg rw, - /var/log/dmesg.* rwl -> /var/log/dmesg, - - # man-db.service - /usr/{,local/}share/man/{,**} r, - /etc/manpath.config r, - /var/cache/man/{,**} rwk, - - # snapd.system-shutdown.service - @{run}/initramfs/shutdown rw, - @{run}/initramfs/ rw, - - # cockpit.socket - @{run}/cockpit/@{rand8} rw, - @{run}/cockpit/motd w, - - @{PROC}/cmdline r, - @{PROC}/sys/kernel/osrelease r, - - include if exists - include if exists -} - -# vim:syntax=apparmor diff --git a/apparmor.d/groups/_full/systemd-user b/apparmor.d/groups/_full/systemd-user index e3ae3acb40..d41ebb3b06 100644 --- a/apparmor.d/groups/_full/systemd-user +++ b/apparmor.d/groups/_full/systemd-user @@ -2,119 +2,91 @@ # Copyright (C) 2023-2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only +#aa:lint ignore=too-wide + # Profile for 'systemd --user', not PID 1 but the user manager for any UID. # It does not specify an attachment path because it is intended to be used only -# via "px -> systemd-user" exec transitions from the `systemd` profile. - -# Only use this profile with a fully configured system. Otherwise it **WILL** -# break your computer. See https://apparmor.pujol.io/full-system-policy/. - -# Distributions and other programs can add rules in the usr/systemd-user.d directory - -# TODO: rework this to get a controlled environment. cf comments in systemd profile. +# via `px -> systemd-user` exec transitions from the `systemd` profile. +# +# !!! danger +# +# Only use this profile with a fully configured system. Otherwise it **WILL** +# break your computer. See https://apparmor.pujol.io/full-system-policy/. +# +# !!! info +# +# Distributions and other programs can add rules in the `usr/systemd-user.d` directory +# abi , include @{exec_path} = @{lib}/systemd/systemd -profile systemd-user flags=(attach_disconnected,mediate_deleted) { +profile systemd-user flags=(attach_disconnected,mediate_deleted,complain) { include include include include include + include network netlink raw, - signal send set=(term, cont, kill), - signal receive set=hup peer=@{p_systemd}, + signal send, - ptrace read peer=@{p_systemd}, + ptrace read, + + unix type=dgram peer=(label=@{p_sdu}), unix bind type=stream addr=@@{udbus}/bus/systemd/bus-system, unix bind type=stream addr=@@{udbus}/bus/systemd/bus-api-user, #aa:dbus own bus=session name=org.freedesktop.systemd1 - @{exec_path} mr, - - @{bin}/** Px, - @{lib}/** Px, - /etc/cron.*/* Px, - /opt/*/** Px, - /usr/share/*/** Px, - - # Systemd internal service started and config handler (sandboxing, namespacing, cgroup, etc.) - @{lib}/systemd/systemd-executor ix, - - # Unit services using systemctl - @{bin}/systemctl Cx -> systemctl, + dbus receive bus=session + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), - # Shell based ystemd unit services - @{coreutils_path} Px -> systemd-user-service, - @{sh_path} Px -> systemd-user-service, + @{exec_path} mrix, - # Dbus needs to be started without environment scrubbing - @{bin}/dbus-broker px -> dbus-session, - @{bin}/dbus-broker-launch px -> dbus-session, - @{bin}/dbus-daemon px -> dbus-session, - @{lib}/dbus-1.0/dbus-daemon-launch-helper px -> dbus-session, + # Systemd internal service starter and config handler (sandboxing, namespacing, cgroup, etc.) + @{lib}/systemd/systemd-executor mPx -> sdu, - # Audio profiles need to be stacked - #aa:stack pipewire pipewire-media-session pipewire-pulse pulseaudio wireplumber - @{bin}/pipewire Px -> systemd-user//&pipewire, - @{bin}/pipewire-media-session Px -> systemd-user//&pipewire-media-session, - @{bin}/pipewire-pulse Px -> systemd-user//&pipewire-pulse, - @{bin}/pulseaudio Px -> systemd-user//&pulseaudio, - @{bin}/wireplumber Px -> systemd-user//&wireplumber, - - /usr/ r, - /usr/share/defaults/**.conf r, + # Systemd user generators. Profiles must exist + @{lib}/systemd/user-environment-generators/* Px, + @{lib}/systemd/user-generators/* Px, + @{etc_ro}/environment r, /etc/systemd/user.conf r, /etc/systemd/user.conf.d/{,**} r, /etc/systemd/user/{,**} r, - / r, - - owner @{HOME}/.local/ w, - owner @{user_config_dirs}/systemd/user/{,**} rw, - @{run}/systemd/users/@{uid} r, owner @{run}/user/@{uid}/ rw, owner @{run}/user/@{uid}/** rwkl, @{run}/mount/utab r, - @{run}/systemd/notify w, + @{run}/systemd/oom/io.systemd.ManagedOOM rw, - @{run}/udev/data/+backlight:* r, - @{run}/udev/data/+leds:*backlight* r, - @{run}/udev/data/+module:configfs r, - @{run}/udev/data/+module:fuse r, - @{run}/udev/data/b254:@{int} r, # for /dev/zram* + @{run}/udev/data/+module:* r, # Identifies kernel modules loaded by udev @{run}/udev/data/c4:@{int} r, # For TTY devices @{run}/udev/data/c5:@{int} r, # for /dev/tty, /dev/console, /dev/ptmx @{run}/udev/data/c10:@{int} r, # For non-serial mice, misc features + @{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 - @{run}/udev/data/n@{int} r, + @{run}/udev/data/n@{int} r, # For network interfaces @{run}/udev/tags/systemd/ r, - @{sys}/devices/virtual/dmi/id/bios_vendor r, - @{sys}/devices/virtual/dmi/id/board_vendor r, - @{sys}/devices/virtual/dmi/id/product_name r, - @{sys}/devices/virtual/dmi/id/sys_vendor r, - @{sys}/devices/**/uevent r, @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/{,**} r, - @{sys}/module/apparmor/parameters/enabled r, owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/{,**} rw, - @{PROC}/@{pid}/cmdline r, - @{PROC}/@{pids}/cgroup r, - @{PROC}/@{pids}/comm r, - @{PROC}/@{pids}/stat r, + @{PROC}/@{pid}/cgroup r, + @{PROC}/@{pid}/comm r, + @{PROC}/@{pid}/stat r, @{PROC}/1/environ r, @{PROC}/cmdline r, @{PROC}/pressure/* r, @@ -124,20 +96,15 @@ profile systemd-user flags=(attach_disconnected,mediate_deleted) { @{PROC}/sys/kernel/overflowgid r, @{PROC}/sys/kernel/overflowuid r, @{PROC}/sys/kernel/pid_max r, + @{PROC}/sys/kernel/random/boot_id r, @{PROC}/sys/kernel/threads-max r, - owner @{PROC}/@{pid}/coredump_filter r, + owner @{PROC}/@{pid}/cmdline r, owner @{PROC}/@{pid}/fdinfo/@{int} r, owner @{PROC}/@{pid}/gid_map r, owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/oom_score_adj rw, - owner @{PROC}/@{pid}/stat r, - owner @{PROC}/@{pid}/task/@{tid}/comm rw, owner @{PROC}/@{pid}/uid_map r, owner @{PROC}/@{pids}/fd/ r, - owner @{PROC}/@{pids}/oom_score_adj rw, - - /dev/kmsg w, - /dev/tty rw, deny capability bpf, deny capability dac_override, @@ -146,18 +113,9 @@ profile systemd-user flags=(attach_disconnected,mediate_deleted) { deny capability net_admin, deny capability perfmon, deny capability sys_admin, + deny capability sys_boot, deny capability sys_resource, - profile systemctl { - include - include - - deny capability net_admin, - - include if exists - include if exists - } - include if exists include if exists } diff --git a/apparmor.d/groups/_full/systemd-user-service b/apparmor.d/groups/_full/systemd-user-service deleted file mode 100644 index 0cb9efa493..0000000000 --- a/apparmor.d/groups/_full/systemd-user-service +++ /dev/null @@ -1,23 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - -# Profile for generic systemd unit services. Only used by tiny systemd services -# that start a shell or use context specific programs. - -# It does not specify an attachment path because it is intended to be used only -# via "Px -> systemd-user-service" exec transitions from the systemd-user profile. - -abi , - -include - -profile systemd-user-service flags=(attach_disconnected) { - include - include - - include if exists - include if exists -} - -# vim:syntax=apparmor diff --git a/apparmor.d/groups/akonadi/akonadi_archivemail_agent b/apparmor.d/groups/akonadi/akonadi_archivemail_agent index ed72aa21b5..af2663f8e7 100644 --- a/apparmor.d/groups/akonadi/akonadi_archivemail_agent +++ b/apparmor.d/groups/akonadi/akonadi_archivemail_agent @@ -13,6 +13,8 @@ profile akonadi_archivemail_agent @{exec_path} { include include + ptrace read peer=akonadi_control, + @{exec_path} mr, /usr/share/akonadi/plugins/serializer/{,*.desktop} r, diff --git a/apparmor.d/groups/akonadi/akonadi_followupreminder_agent b/apparmor.d/groups/akonadi/akonadi_followupreminder_agent index be897ee9ea..92bb61f136 100644 --- a/apparmor.d/groups/akonadi/akonadi_followupreminder_agent +++ b/apparmor.d/groups/akonadi/akonadi_followupreminder_agent @@ -17,6 +17,8 @@ profile akonadi_followupreminder_agent @{exec_path} { network inet6 dgram, network netlink dgram, + ptrace read peer=akonadi_control, + @{exec_path} mr, owner @{user_config_dirs}/akonadi_followupreminder_agentrc r, diff --git a/apparmor.d/groups/akonadi/akonadi_indexing_agent b/apparmor.d/groups/akonadi/akonadi_indexing_agent index 32a3327937..8e70d9ff4d 100644 --- a/apparmor.d/groups/akonadi/akonadi_indexing_agent +++ b/apparmor.d/groups/akonadi/akonadi_indexing_agent @@ -13,6 +13,8 @@ profile akonadi_indexing_agent @{exec_path} { include include + ptrace read peer=akonadi_control, + @{exec_path} mr, @{bin}/akonadi_html_to_text rix, diff --git a/apparmor.d/groups/akonadi/akonadi_maildispatcher_agent b/apparmor.d/groups/akonadi/akonadi_maildispatcher_agent index c353ea8197..b5efb86139 100644 --- a/apparmor.d/groups/akonadi/akonadi_maildispatcher_agent +++ b/apparmor.d/groups/akonadi/akonadi_maildispatcher_agent @@ -21,6 +21,8 @@ profile akonadi_maildispatcher_agent @{exec_path} { network netlink dgram, network netlink raw, + ptrace read peer=akonadi_control, + @{exec_path} mr, /usr/share/akonadi/plugins/{,**} r, diff --git a/apparmor.d/groups/akonadi/akonadi_mailfilter_agent b/apparmor.d/groups/akonadi/akonadi_mailfilter_agent index d1a2f008f8..6098d1b2bf 100644 --- a/apparmor.d/groups/akonadi/akonadi_mailfilter_agent +++ b/apparmor.d/groups/akonadi/akonadi_mailfilter_agent @@ -13,7 +13,8 @@ profile akonadi_mailfilter_agent @{exec_path} { include include - ptrace (read) peer=akonadi_archivemail_agent, + ptrace read peer=akonadi_archivemail_agent, + ptrace read peer=akonadi_control, @{exec_path} mr, diff --git a/apparmor.d/groups/akonadi/akonadi_mailmerge_agent b/apparmor.d/groups/akonadi/akonadi_mailmerge_agent index 2083318e7c..e0be972fc2 100644 --- a/apparmor.d/groups/akonadi/akonadi_mailmerge_agent +++ b/apparmor.d/groups/akonadi/akonadi_mailmerge_agent @@ -18,6 +18,8 @@ profile akonadi_mailmerge_agent @{exec_path} { network netlink raw, network netlink dgram, + ptrace read peer=akonadi_control, + @{exec_path} mr, owner @{user_config_dirs}/akonadi/ rw, diff --git a/apparmor.d/groups/akonadi/akonadi_migration_agent b/apparmor.d/groups/akonadi/akonadi_migration_agent index 55fedf4eaa..9653b30488 100644 --- a/apparmor.d/groups/akonadi/akonadi_migration_agent +++ b/apparmor.d/groups/akonadi/akonadi_migration_agent @@ -13,6 +13,8 @@ profile akonadi_migration_agent @{exec_path} { include include + ptrace read peer=akonadi_control, + @{exec_path} mr, owner @{user_config_dirs}/akonadi-migrationrc r, diff --git a/apparmor.d/groups/akonadi/akonadi_newmailnotifier_agent b/apparmor.d/groups/akonadi/akonadi_newmailnotifier_agent index 28ce1123c9..33df7f461a 100644 --- a/apparmor.d/groups/akonadi/akonadi_newmailnotifier_agent +++ b/apparmor.d/groups/akonadi/akonadi_newmailnotifier_agent @@ -13,6 +13,8 @@ profile akonadi_newmailnotifier_agent @{exec_path} { include include + ptrace read peer=akonadi_control, + @{exec_path} mr, /usr/share/akonadi/plugins/serializer/{,*.desktop} r, diff --git a/apparmor.d/groups/akonadi/akonadi_notes_agent b/apparmor.d/groups/akonadi/akonadi_notes_agent index 8e8665e404..2aff713ac1 100644 --- a/apparmor.d/groups/akonadi/akonadi_notes_agent +++ b/apparmor.d/groups/akonadi/akonadi_notes_agent @@ -18,6 +18,8 @@ profile akonadi_notes_agent @{exec_path} { network netlink raw, network netlink dgram, + ptrace read peer=akonadi_control, + @{exec_path} mr, owner @{user_config_dirs}/akonadi_*_agentrc r, diff --git a/apparmor.d/groups/akonadi/akonadi_sendlater_agent b/apparmor.d/groups/akonadi/akonadi_sendlater_agent index 2053bf298c..d93ce41ea2 100644 --- a/apparmor.d/groups/akonadi/akonadi_sendlater_agent +++ b/apparmor.d/groups/akonadi/akonadi_sendlater_agent @@ -18,6 +18,8 @@ profile akonadi_sendlater_agent @{exec_path} { network netlink raw, network netlink dgram, + ptrace read peer=akonadi_control, + @{exec_path} mr, owner @{user_config_dirs}/akonadi_sendlater_agentrc r, diff --git a/apparmor.d/groups/akonadi/akonadi_unifiedmailbox_agent b/apparmor.d/groups/akonadi/akonadi_unifiedmailbox_agent index 4e0e5820a2..38fcfbf910 100644 --- a/apparmor.d/groups/akonadi/akonadi_unifiedmailbox_agent +++ b/apparmor.d/groups/akonadi/akonadi_unifiedmailbox_agent @@ -13,6 +13,8 @@ profile akonadi_unifiedmailbox_agent @{exec_path} { include include + ptrace read peer=akonadi_control, + @{exec_path} mr, owner "@{user_config_dirs}/Unknown Organization/akonadi_unifiedmailbox_agent.conf_changes.dat" r, # see https://bugs.kde.org/show_bug.cgi?id=452565 diff --git a/apparmor.d/groups/apparmor/aa-enforce b/apparmor.d/groups/apparmor/aa-enforce index da4d634606..1f83680457 100644 --- a/apparmor.d/groups/apparmor/aa-enforce +++ b/apparmor.d/groups/apparmor/aa-enforce @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/aa-enforce @{bin}/aa-complain @{bin}/aa-audit @{bin}/aa-disable +@{exec_path} = @{sbin}/aa-enforce @{sbin}/aa-complain @{sbin}/aa-audit @{sbin}/aa-disable profile aa-enforce @{exec_path} { include include @@ -16,8 +16,8 @@ profile aa-enforce @{exec_path} { @{exec_path} mr, - @{bin}/ r, - @{bin}/apparmor_parser rPx, + @{sbin}/ r, + @{sbin}/apparmor_parser rPx, /usr/share/terminfo/** r, @@ -31,7 +31,7 @@ profile aa-enforce @{exec_path} { owner /var/lib/snapd/apparmor/{,**} rw, owner @{tmp}/@{rand8} rw, - owner @{tmp}/apparmor-bugreport-@{rand8}.txt rw, + owner @{tmp}/apparmor-bugreport-@{word8}.txt rw, @{PROC}/@{pid}/fd/ r, diff --git a/apparmor.d/groups/apparmor/aa-log b/apparmor.d/groups/apparmor/aa-log index 03352e8bfd..30d90ef911 100644 --- a/apparmor.d/groups/apparmor/aa-log +++ b/apparmor.d/groups/apparmor/aa-log @@ -7,9 +7,10 @@ abi , include @{exec_path} = @{bin}/aa-log -profile aa-log @{exec_path} { +profile aa-log @{exec_path} flags=(attach_disconnected) { include include + include include capability dac_read_search, @@ -18,17 +19,20 @@ profile aa-log @{exec_path} { @{bin}/journalctl rCx -> journalctl, + /usr/share/tcltk/{,**} r, + /var/log/audit/* r, /var/log/syslog* r, - @{sys}/kernel/mm/transparent_hugepage/hpage_pmd_size r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/*.scope/cpu.max r, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, profile journalctl { include include + capability mknod, capability sys_resource, @{bin}/journalctl mr, diff --git a/apparmor.d/groups/apparmor/aa-notify b/apparmor.d/groups/apparmor/aa-notify index 5b41f7b7c2..81f564ce96 100644 --- a/apparmor.d/groups/apparmor/aa-notify +++ b/apparmor.d/groups/apparmor/aa-notify @@ -7,13 +7,13 @@ abi , include @{exec_path} = @{bin}/aa-notify -profile aa-notify @{exec_path} { +profile aa-notify @{exec_path} flags=(attach_disconnected) { include - include include include include include + include include capability setgid, @@ -30,8 +30,10 @@ profile aa-notify @{exec_path} { @{open_path} Cx -> open, @{bin}/ r, + @{sbin}/ r, /usr/share/apparmor/** r, + /usr/share/tcltk/** r, /usr/share/terminfo/** r, @{etc_ro}/inputrc r, @@ -39,17 +41,23 @@ profile aa-notify @{exec_path} { /etc/apparmor.d/{,**} r, /etc/apparmor/*.conf r, - /var/log/audit/audit.log r, + /var/lib/snapd/apparmor/snap-confine/ r, + /var/lib/snapd/apparmor/snap-confine/cap-bpf r, + + /var/log/audit/* r, + /var/log/syslog* r, + /var/log/kern.log r, owner @{HOME}/.inputrc r, owner @{HOME}/.terminfo/@{int}/dumb r, owner @{tmp}/@{word8} rw, - owner @{tmp}/apparmor-bugreport-@{rand8}.txt rw, + owner @{tmp}/apparmor-bugreport-@{word8}.txt rw, - @{PROC}/ r, - @{PROC}/@{pid}/stat r, - @{PROC}/@{pid}/cmdline r, + @{PROC}/ r, + @{PROC}/@{pid}/stat r, + @{PROC}/@{pid}/cmdline r, + owner @{PROC}/@{pid}/mounts r, profile open { include @@ -63,7 +71,7 @@ profile aa-notify @{exec_path} { profile editor { include include - include + include include include @@ -75,7 +83,6 @@ profile aa-notify @{exec_path} { owner @{user_share_dirs}/org.gnome.TextEditor/{,**} rw, owner @{PROC}/@{pid}/mountinfo r, - owner @{PROC}/@{pid}/stat r, deny @{user_share_dirs}/gvfs-metadata/* r, @@ -89,7 +96,7 @@ profile aa-notify @{exec_path} { ptrace read peer=aa-notify, - @{bin}/apparmor_parser Px, + @{sbin}/apparmor_parser Px, @{lib}/@{python_name}/site-packages/apparmor/update_profile.py ix, /usr/share/apparmor/** r, @@ -102,6 +109,8 @@ profile aa-notify @{exec_path} { /etc/apparmor.d/** rw, /etc/apparmor/* r, + @{PROC}/@{pid}/mounts r, + include if exists } diff --git a/apparmor.d/groups/apparmor/aa-status b/apparmor.d/groups/apparmor/aa-status index a48dc693c3..0c2e400257 100644 --- a/apparmor.d/groups/apparmor/aa-status +++ b/apparmor.d/groups/apparmor/aa-status @@ -6,8 +6,8 @@ abi , include -@{exec_path} = @{bin}/aa-status @{bin}/apparmor_status -profile aa-status @{exec_path} { +@{exec_path} = @{sbin}/aa-status @{sbin}/apparmor_status +profile aa-status @{exec_path} flags=(attach_disconnected) { include include @@ -22,11 +22,11 @@ profile aa-status @{exec_path} { @{sys}/module/apparmor/parameters/enabled r, @{PROC}/ r, - @{PROC}/@{pids}/attr/apparmor/current r, - @{PROC}/@{pids}/attr/current r, + @{PROC}/@{pid}/attr/apparmor/current r, + @{PROC}/@{pid}/attr/current r, owner @{PROC}/@{pid}/mounts r, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/apparmor/aa-teardown b/apparmor.d/groups/apparmor/aa-teardown index b625ad8c6f..059766181e 100644 --- a/apparmor.d/groups/apparmor/aa-teardown +++ b/apparmor.d/groups/apparmor/aa-teardown @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/aa-teardown +@{exec_path} = @{sbin}/aa-teardown profile aa-teardown @{exec_path} { include include diff --git a/apparmor.d/groups/apparmor/aa-unconfined b/apparmor.d/groups/apparmor/aa-unconfined index 08c401270f..7308a5ef03 100644 --- a/apparmor.d/groups/apparmor/aa-unconfined +++ b/apparmor.d/groups/apparmor/aa-unconfined @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/aa-unconfined +@{exec_path} = @{sbin}/aa-unconfined profile aa-unconfined @{exec_path} flags=(attach_disconnected) { include include @@ -21,7 +21,7 @@ profile aa-unconfined @{exec_path} flags=(attach_disconnected) { @{bin}/ r, @{bin}/netstat Px, - @{bin}/ss Px, + @{sbin}/ss Px, /usr/share/terminfo/** r, @@ -29,7 +29,7 @@ profile aa-unconfined @{exec_path} flags=(attach_disconnected) { @{etc_ro}/inputrc r, owner @{tmp}/@{rand8} rw, - owner @{tmp}/apparmor-bugreport-@{rand8}.txt rw, + owner @{tmp}/apparmor-bugreport-@{word8}.txt rw, owner /var/tmp/@{rand8} rw, @{PROC}/ r, diff --git a/apparmor.d/groups/apparmor/apparmor.systemd b/apparmor.d/groups/apparmor/apparmor.systemd index 79b3f1a861..f58512a027 100644 --- a/apparmor.d/groups/apparmor/apparmor.systemd +++ b/apparmor.d/groups/apparmor/apparmor.systemd @@ -19,14 +19,14 @@ profile apparmor.systemd @{exec_path} { @{sh_path} rix, @{bin}/{,e}grep rix, - @{bin}/aa-status rPx, - @{bin}/apparmor_parser rPx, + @{sbin}/aa-status rPx, + @{sbin}/apparmor_parser rPx, @{bin}/getconf rix, @{bin}/ls rix, @{bin}/sed rix, @{bin}/cat rix, @{bin}/sort rix, - @{bin}/sysctl rix, + @{sbin}/sysctl rCx -> sysctl, @{bin}/systemd-detect-virt rPx, @{bin}/xargs rix, @@ -43,10 +43,19 @@ profile apparmor.systemd @{exec_path} { @{PROC}/@{pids}/maps r, @{PROC}/@{pids}/mounts r, @{PROC}/mounts r, - @{PROC}/sys/kernel/apparmor_restrict_unprivileged_userns r, /dev/tty rw, + profile sysctl { + include + + @{sbin}/sysctl mr, + + @{PROC}/sys/kernel/apparmor_restrict_unprivileged_userns r, + + include if exists + } + include if exists } diff --git a/apparmor.d/groups/apparmor/apparmor_parser b/apparmor.d/groups/apparmor/apparmor_parser index dc15d48b9e..ff6af6b136 100644 --- a/apparmor.d/groups/apparmor/apparmor_parser +++ b/apparmor.d/groups/apparmor/apparmor_parser @@ -6,9 +6,9 @@ abi , include -@{lib_dirs} = @{lib}/ /snap/snapd/@{int}@{lib} +@{lib_dirs} = @{lib}/ /snap/{snapd,core}/{,x}@{int}@{lib} -@{exec_path} = @{bin}/apparmor_parser @{lib_dirs}/snapd/apparmor_parser +@{exec_path} = @{sbin}/apparmor_parser @{lib_dirs}/snapd/apparmor_parser profile apparmor_parser @{exec_path} flags=(attach_disconnected) { include include @@ -21,15 +21,18 @@ profile apparmor_parser @{exec_path} flags=(attach_disconnected) { @{lib_dirs}/snapd/apparmor.d/{,**} r, @{lib_dirs}/snapd/apparmor/{,**} r, + /opt/*/resources/apparmor_* r, + /opt/*/resources/apparmor-profile r, + + /usr/share/apparmor-features/{,**} r, + /usr/share/apparmor/{,**} r, + /etc/apparmor.d/{,**} r, /etc/apparmor.d/cache.d/{,**} rw, /etc/apparmor/{,**} r, /etc/apparmor/cache.d/{,**} rw, /etc/apparmor/earlypolicy/{,**} rw, - /usr/share/apparmor-features/{,**} r, - /usr/share/apparmor/{,**} r, - owner /snap/core@{int}/@{int}/etc/apparmor.d/{,**} r, owner /snap/core@{int}/@{int}/etc/apparmor/* r, owner /var/cache/apparmor/{,**} rw, @@ -45,8 +48,8 @@ profile apparmor_parser @{exec_path} flags=(attach_disconnected) { @{PROC}/sys/kernel/osrelease r, owner @{PROC}/@{pid}/mounts r, - deny network netlink raw, # file_inherit - deny /apparmor/.null rw, + # Inherit Silencer + deny network netlink raw, include if exists } diff --git a/apparmor.d/groups/apt/apt b/apparmor.d/groups/apt/apt index fc5d1b3ccb..8437393663 100644 --- a/apparmor.d/groups/apt/apt +++ b/apparmor.d/groups/apt/apt @@ -7,13 +7,13 @@ abi , include -@{exec_path} = @{bin}/apt @{bin}/apt-get @{bin}/aptd +@{exec_path} = @{bin}/apt @{bin}/apt-get @{sbin}/aptd profile apt @{exec_path} flags=(attach_disconnected) { include - include + include include - include - include + include + include include include include @@ -35,8 +35,9 @@ profile apt @{exec_path} flags=(attach_disconnected) { unix bind type=stream addr=@@{udbus}/bus/apt-get/system, unix bind type=stream addr=@@{udbus}/bus/apt/system, + unix bind type=stream addr=@@{udbus}/bus/aptd/system, - unix type=stream peer=(label=snap), + unix type=stream peer=(label=@{p_snap}), unix (send, receive) type=stream peer=(label=apt-esm-json-hook), unix (send, receive) type=stream peer=(label=snapd), @@ -55,19 +56,21 @@ profile apt @{exec_path} flags=(attach_disconnected) { dbus send bus=system interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name="{:*,org.freedesktop.DBus}"), + peer=(name="{@{busname},org.freedesktop.DBus}"), @{exec_path} mr, @{python_path} mr, @{bin}/ r, + @{sbin}/ r, @{sh_path} rix, @{bin}/{,e}grep rix, + @{bin}/cat rix, @{bin}/echo rix, + @{bin}/false rix, @{bin}/gdbus rix, @{bin}/id rix, - @{bin}/ischroot rix, @{bin}/test rix, @{bin}/touch rix, @@ -80,17 +83,19 @@ profile apt @{exec_path} flags=(attach_disconnected) { @{bin}/df rPx, @{bin}/dmesg rPx, @{bin}/dpkg rPx, - @{bin}/dpkg-preconfigure rPx, @{bin}/dpkg-source rcx -> dpkg-source, @{bin}/etckeeper rPx, + @{bin}/fakeroot-sysv rCx -> fakeroot-sysv, + @{bin}/ischroot rPx, @{bin}/localepurge rPx, @{bin}/ps rPx, - @{bin}/snap rPUx, - @{bin}/systemctl rCx -> systemctl, + @{bin}/snap rPx, + @{bin}/systemctl rCx -> systemctl, @{bin}/update-command-not-found rPx, @{lib}/cnf-update-db rPx, @{lib}/needrestart/apt-pinvoke rPx, @{lib}/zsys-system-autosnapshot rPx, + @{sbin}/dpkg-preconfigure rPx, # For building the source after the download process is finished (apt-get source --compile) @{bin}/dpkg-buildpackage rPUx, @@ -115,8 +120,9 @@ profile apt @{exec_path} flags=(attach_disconnected) { #aa:only whonix @{lib}/uwt/uwtwrapper rix, - /usr/share/xml/iso-codes/{,**} r, + /usr/share/doc/*/changelog.Debian.gz r, /usr/share/language-selector/data/pkg_depends r, + /usr/share/xml/iso-codes/{,**} r, /etc/apt/sources.list rwk, /etc/machine-id r, @@ -138,27 +144,38 @@ profile apt @{exec_path} flags=(attach_disconnected) { /var/log/apt/{,**} rw, /var/log/ubuntu-advantage-apt-hook.log w, + @{efi}/ r, + # For package building @{user_build_dirs}/** rwkl -> @{user_build_dirs}/**, - /tmp/ r, - /tmp/apt-changelog-*/ w, - /tmp/apt-changelog-*/*.changelog w, - owner @{tmp}/apt-changelog-*/.apt-acquire-privs-test.* rw, - owner @{tmp}/apt-dpkg-install-*/ rw, - owner @{tmp}/apt-dpkg-install-*/@{int}-*.deb w, - owner @{tmp}/apt.conf.* rw, - owner @{tmp}/apt.data.* rw, + /tmp/ r, + /tmp/@{rand8} rw, + @{tmp}/apt* rw, + @{tmp}/apt*/{,**} rw, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, @{PROC}/@{pids}/cmdline r, @{PROC}/@{pids}/mountinfo r, + @{PROC}/@{pids}/stat r, + @{PROC}/@{pids}/status r, owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/mounts r, /dev/ptmx rw, + profile fakeroot-sysv { + include + + @{bin}/fakeroot-sysv mr, + + @{bin}/dpkg Px, + @{bin}/faked-sysv rix, + + include if exists + } + profile editor flags=(complain) { include include @@ -170,18 +187,7 @@ profile apt @{exec_path} flags=(attach_disconnected) { profile pager { include - include - - capability dac_read_search, - - @{bin}/ r, - @{sh_path} rix, - @{pager_path} rmix, - @{bin}/which{,.debianutils} rix, - - /root/ r, # For shell pwd - - owner @{HOME}/.less* rw, + include owner @{tmp}/apt-changelog-*/ r, owner @{tmp}/apt-changelog-*/*.changelog r, @@ -196,16 +202,12 @@ profile apt @{exec_path} flags=(attach_disconnected) { @{bin}/dpkg-source mr, - @{bin}/bunzip2 rix, - @{bin}/chmod rix, - @{bin}/gunzip rix, - @{bin}/gzip rix, - @{bin}/patch rix, - @{bin}/rm rix, - @{bin}/tar rix, - @{bin}/xz rix, + @{archive_path} rix, + @{bin}/chmod rix, + @{bin}/patch rix, + @{bin}/rm rix, - /etc/dpkg/origins/debian r, + /etc/dpkg/origins/* r, owner @{user_build_dirs}/** rwkl -> @{user_build_dirs}/**, owner @{HOME}/** rwkl -> @{HOME}/**, @@ -213,6 +215,9 @@ profile apt @{exec_path} flags=(attach_disconnected) { audit deny owner @{HOME}/.*/ rw, audit deny owner @{HOME}/.*/** mrwkl, + #aa:only test + /tmp/tmp.@{word10}/** rwlk, + include if exists } @@ -223,6 +228,8 @@ profile apt @{exec_path} flags=(attach_disconnected) { capability net_admin, capability sys_resource, + ptrace read peer=@{p_systemd}, + signal (send) set=(cont, term) peer=systemd-tty-ask-password-agent, @{bin}/systemd-tty-ask-password-agent rPx, diff --git a/apparmor.d/groups/apt/apt-cache b/apparmor.d/groups/apt/apt-cache index 1251fe4492..ea6eb2fa27 100644 --- a/apparmor.d/groups/apt/apt-cache +++ b/apparmor.d/groups/apt/apt-cache @@ -10,7 +10,7 @@ include @{exec_path} = @{bin}/apt-cache profile apt-cache @{exec_path} { include - include + include include @{exec_path} mr, @@ -23,7 +23,7 @@ profile apt-cache @{exec_path} { /var/lib/dpkg/** r, /var/lib/dpkg/lock{,-frontend} rwk, - /var/cache/apt/ r, + /var/cache/apt/ rw, /var/cache/apt/** rwk, owner @{PROC}/@{pid}/fd/ r, diff --git a/apparmor.d/groups/apt/apt-cdrom b/apparmor.d/groups/apt/apt-cdrom index a99b964c73..0ce1462615 100644 --- a/apparmor.d/groups/apt/apt-cdrom +++ b/apparmor.d/groups/apt/apt-cdrom @@ -10,7 +10,7 @@ include @{exec_path} = @{bin}/apt-cdrom profile apt-cdrom @{exec_path} flags=(complain) { include - include + include include capability dac_read_search, diff --git a/apparmor.d/groups/apt/apt-config b/apparmor.d/groups/apt/apt-config index 505a4b0378..fe04c176ac 100644 --- a/apparmor.d/groups/apt/apt-config +++ b/apparmor.d/groups/apt/apt-config @@ -10,15 +10,13 @@ include @{exec_path} = @{bin}/apt-config profile apt-config @{exec_path} { include - include + include include @{exec_path} mr, @{bin}/dpkg rPx -> child-dpkg, - owner @{tmp}/tmp*/apt.conf r, - owner @{PROC}/@{pid}/fd/ r, include if exists diff --git a/apparmor.d/groups/apt/apt-extracttemplates b/apparmor.d/groups/apt/apt-extracttemplates index beb563f31e..6fbfad65ba 100644 --- a/apparmor.d/groups/apt/apt-extracttemplates +++ b/apparmor.d/groups/apt/apt-extracttemplates @@ -10,8 +10,8 @@ include @{exec_path} = @{bin}/apt-extracttemplates @{lib}/apt/apt-extracttemplates profile apt-extracttemplates @{exec_path} { include + include include - include capability dac_read_search, diff --git a/apparmor.d/groups/apt/apt-file b/apparmor.d/groups/apt/apt-file index bc140acd14..6551f21a73 100644 --- a/apparmor.d/groups/apt/apt-file +++ b/apparmor.d/groups/apt/apt-file @@ -10,7 +10,7 @@ include @{exec_path} = @{bin}/apt-file profile apt-file @{exec_path} { include - include + include include @{exec_path} r, diff --git a/apparmor.d/groups/apt/apt-forktracer b/apparmor.d/groups/apt/apt-forktracer index 2fbb5d95bd..77046ff2d2 100644 --- a/apparmor.d/groups/apt/apt-forktracer +++ b/apparmor.d/groups/apt/apt-forktracer @@ -10,14 +10,16 @@ include @{exec_path} = @{bin}/apt-forktracer profile apt-forktracer @{exec_path} { include - include + include include @{exec_path} mr, @{bin}/ r, - @{bin}/dpkg rPx -> child-dpkg, - @{bin}/apt-cache rPx, + @{sh_path} rix, + @{bin}/apt-cache rPx, + @{bin}/dpkg rPx -> child-dpkg, + @{bin}/lsb_release rPx, /usr/share/apt-forktracer/{,**} r, /usr/share/distro-info/debian.csv r, diff --git a/apparmor.d/groups/apt/apt-ftparchive b/apparmor.d/groups/apt/apt-ftparchive index f7e9b46515..a60bf9a06d 100644 --- a/apparmor.d/groups/apt/apt-ftparchive +++ b/apparmor.d/groups/apt/apt-ftparchive @@ -10,12 +10,10 @@ include @{exec_path} = @{bin}/apt-ftparchive profile apt-ftparchive @{exec_path} { include + include @{exec_path} mr, - /etc/apt/apt.conf r, - /etc/apt/apt.conf.d/{,*} r, - # For package building @{user_build_dirs}/** rwkl -> @{user_build_dirs}/**, diff --git a/apparmor.d/groups/apt/apt-helper b/apparmor.d/groups/apt/apt-helper index 5a2d7dd55a..f73186d906 100644 --- a/apparmor.d/groups/apt/apt-helper +++ b/apparmor.d/groups/apt/apt-helper @@ -9,22 +9,34 @@ include @{exec_path} = @{lib}/apt/apt-helper profile apt-helper @{exec_path} { include - include + include + include + + capability setgid, + capability setuid, + + signal send set=int peer=apt-methods-http, @{exec_path} mr, @{bin}/nm-online rPx, @{bin}/systemctl rCx -> systemctl, @{lib}/systemd/systemd-networkd-wait-online rPx, + @{lib}/apt/methods/http Px, owner @{PROC}/@{pid}/fd/ r, + /tmp/tmp@{word8}/stampdir/partial/canary-file.txt w, + /tmp/tmp@{word8}/partial/canary-file.txt w, + profile systemctl { include include capability net_admin, + ptrace read peer=@{p_systemd}, + include if exists } diff --git a/apparmor.d/groups/apt/apt-listbugs b/apparmor.d/groups/apt/apt-listbugs index 7ce8961b99..883724961b 100644 --- a/apparmor.d/groups/apt/apt-listbugs +++ b/apparmor.d/groups/apt/apt-listbugs @@ -48,15 +48,11 @@ profile apt-listbugs @{exec_path} { @{PROC}/@{pid}/loginuid r, # The following is needed when apt-listbugs uses debcconf GUI frontends. - include - include - include - include + include capability dac_read_search, - @{bin}/lsb_release rPx -> lsb_release, + @{bin}/lsb_release rPx, @{bin}/hostname rix, owner @{PROC}/@{pid}/mounts r, - @{HOME}/.Xauthority r, include if exists } diff --git a/apparmor.d/groups/apt/apt-listchanges b/apparmor.d/groups/apt/apt-listchanges index dbbba9d4db..071ce29197 100644 --- a/apparmor.d/groups/apt/apt-listchanges +++ b/apparmor.d/groups/apt/apt-listchanges @@ -14,7 +14,7 @@ profile apt-listchanges @{exec_path} { include include - #capability sys_tty_config, + capability dac_read_search, @{exec_path} r, @{python_path} r, @@ -26,13 +26,14 @@ profile apt-listchanges @{exec_path} { # Do not strip env to avoid errors like the following: # ERROR: ld.so: object 'libfakeroot-sysv.so' from LD_PRELOAD cannot be preloaded (cannot open # shared object file): ignored. - @{bin}/dpkg-deb rpx, - # - @{pager_path} rCx -> pager, - # Send results using email - @{bin}/exim4 rPx, + @{bin}/dpkg-deb px, + + @{pager_path} Cx -> pager, + @{bin}/dpkg Px -> child-dpkg, + @{sbin}/exim4 Px, # Send results using email /usr/share/apt-listchanges/{,**} r, + /usr/share/doc/{,**} r, /etc/apt/listchanges.conf r, /etc/apt/listchanges.conf.d/{,*} r, @@ -45,56 +46,26 @@ profile apt-listchanges @{exec_path} { /var/lib/dpkg/status r, - /var/lib/apt/listchanges{,-new}.db rw, + /var/lib/apt/listchanges rwk, + /var/lib/apt/listchanges-new rw, + /var/lib/apt/listchanges-new.db rw, + /var/lib/apt/listchanges-old rwl -> /var/lib/apt/listchanges, /var/lib/apt/listchanges-old.db rwl -> /var/lib/apt/listchanges.db, + /var/lib/apt/listchanges.db rw, /var/cache/apt/archives/ r, - owner @{PROC}/@{pid}/fd/ r, - /tmp/ r, - owner @{tmp}/* rw, - owner @{tmp}/apt-listchanges*/ rw, - owner @{tmp}/apt-listchanges*/**/ rw, - owner @{tmp}/apt-listchanges*/*/*/*/*/changelog.gz rw, - owner @{tmp}/apt-listchanges*/*/*/*/*/changelog.Debian*.gz rw, - owner @{tmp}/apt-listchanges*/*/*/*/*/NEWS.Debian.gz rw, - owner @{tmp}/apt-listchanges*/*/*/*/*/*/changelog.gz rw, - owner @{tmp}/apt-listchanges*/*/*/*/*/*/changelog/changelog_to_file rw, - owner @{tmp}/apt-listchanges*/*/*/*/*/*/changelog/simple_changelog rw, - owner @{tmp}/apt-listchanges*/*/*/*/*/*/*-local/debian/changelog rw, - - # The following is needed when apt-listchanges uses debcconf GUI frontends. - include - include - include - include - capability dac_read_search, - @{bin}/lsb_release rPx -> lsb_release, - @{bin}/hostname rix, - owner @{PROC}/@{pid}/mounts r, - @{HOME}/.Xauthority r, + owner @{tmp}/@{word8} rw, + owner @{tmp}/apt-listchanges@{word8}/ rw, + owner @{tmp}/apt-listchanges@{word8}/** rw, + owner @{PROC}/@{pid}/fd/ r, profile pager { include - include - - capability dac_read_search, - #capability sys_tty_config, - - @{pager_path} mrix, - - @{bin}/ r, - @{sh_path} rix, - @{bin}/which{,.debianutils} rix, - - owner @{HOME}/.less* rw, - - # For shell pwd - /root/ r, + include - /tmp/ r, owner @{tmp}/apt-listchanges-tmp*.txt r, include if exists diff --git a/apparmor.d/groups/apt/apt-mark b/apparmor.d/groups/apt/apt-mark index 4af469c306..bff820d5ef 100644 --- a/apparmor.d/groups/apt/apt-mark +++ b/apparmor.d/groups/apt/apt-mark @@ -10,7 +10,7 @@ include @{exec_path} = @{bin}/apt-mark profile apt-mark @{exec_path} { include - include + include @{exec_path} mr, @@ -25,7 +25,7 @@ profile apt-mark @{exec_path} { /var/cache/apt/ r, /var/cache/apt/** rwk, - /dev/pts/@{int} rw, + /dev/pts/@{u16} rw, include if exists } diff --git a/apparmor.d/groups/apt/apt-methods-cdrom b/apparmor.d/groups/apt/apt-methods-cdrom index 9cf47e758a..8dcd9d09b8 100644 --- a/apparmor.d/groups/apt/apt-methods-cdrom +++ b/apparmor.d/groups/apt/apt-methods-cdrom @@ -19,10 +19,10 @@ profile apt-methods-cdrom @{exec_path} { capability setgid, capability setuid, - signal (receive) peer=apt, - signal (receive) peer=apt-get, - signal (receive) peer=aptitude, - signal (receive) peer=synaptic, + signal receive peer=apt, + signal receive peer=apt-get, + signal receive peer=aptitude, + signal receive peer=synaptic, @{exec_path} mr, @@ -39,7 +39,7 @@ profile apt-methods-cdrom @{exec_path} { @{user_build_dirs}/** rwkl -> @{user_build_dirs}/**, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/apt/apt-methods-copy b/apparmor.d/groups/apt/apt-methods-copy index 6d906bf801..db7e7bfddf 100644 --- a/apparmor.d/groups/apt/apt-methods-copy +++ b/apparmor.d/groups/apt/apt-methods-copy @@ -10,6 +10,7 @@ include @{exec_path} = @{lib}/apt/methods/copy profile apt-methods-copy @{exec_path} { include + include include include @@ -20,10 +21,10 @@ profile apt-methods-copy @{exec_path} { capability setgid, capability setuid, - signal (receive) peer=apt, - signal (receive) peer=apt-get, - signal (receive) peer=aptitude, - signal (receive) peer=synaptic, + signal receive peer=apt, + signal receive peer=apt-get, + signal receive peer=aptitude, + signal receive peer=synaptic, @{exec_path} mr, @@ -35,13 +36,6 @@ profile apt-methods-copy @{exec_path} { /etc/ r, /root/ r, - /etc/apt/apt.conf.d/{,*} r, - /etc/apt/apt.conf r, - - /usr/share/dpkg/cputable r, - /usr/share/dpkg/tupletable r, - - /var/lib/apt/lists/{,**} r, owner /var/lib/apt/lists/* rw, owner /var/lib/apt/lists/partial/* rw, @@ -49,7 +43,7 @@ profile apt-methods-copy @{exec_path} { @{user_build_dirs}/** rwkl -> @{user_build_dirs}/**, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, /var/log/cron-apt/temp w, include if exists diff --git a/apparmor.d/groups/apt/apt-methods-file b/apparmor.d/groups/apt/apt-methods-file index 3c2489a324..c263a6169a 100644 --- a/apparmor.d/groups/apt/apt-methods-file +++ b/apparmor.d/groups/apt/apt-methods-file @@ -10,9 +10,12 @@ include @{exec_path} = @{lib}/apt/methods/file profile apt-methods-file @{exec_path} { include + include include include + capability dac_read_search, + # The "_apt" user is created by the postinst script of the "apt" package. It's the owner of the # dirs "/var/cache/apt/archives/partial/" and "/var/lib/apt/lists/partial/" . The "_apt" user is # used by APT to download packages, package list, and other things using APT methods as an @@ -20,30 +23,25 @@ profile apt-methods-file @{exec_path} { capability setgid, capability setuid, - signal (receive) peer=apt-get, - signal (receive) peer=apt, - signal (receive) peer=aptitude, - signal (receive) peer=packagekitd, - signal (receive) peer=synaptic, + signal receive peer=apt-get, + signal receive peer=apt, + signal receive peer=aptitude, + signal receive peer=@{p_packagekitd}, + signal receive peer=synaptic, @{exec_path} mr, @{lib}/apt/apt-helper rix, /etc/apt/apt-mirrors.txt r, - /etc/apt/apt.conf r, - /etc/apt/apt.conf.d/{,*} r, /etc/apt/mirrors/* r, - /usr/share/dpkg/cputable r, - /usr/share/dpkg/tupletable r, - # For shell pwd / r, /etc/ r, /root/ r, - /var/lib/apt/lists/{,**} rw, + owner /var/lib/apt/lists/auxfiles/* rw, owner /var/lib/apt/lists/partial/* rw, /var/log/cron-apt/temp w, @@ -51,7 +49,7 @@ profile apt-methods-file @{exec_path} { # For package building @{user_build_dirs}/** rwkl -> @{user_build_dirs}/**, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/apt/apt-methods-ftp b/apparmor.d/groups/apt/apt-methods-ftp index 47c679ea17..33ee5517dd 100644 --- a/apparmor.d/groups/apt/apt-methods-ftp +++ b/apparmor.d/groups/apt/apt-methods-ftp @@ -19,10 +19,10 @@ profile apt-methods-ftp @{exec_path} { capability setgid, capability setuid, - signal (receive) peer=apt, - signal (receive) peer=apt-get, - signal (receive) peer=aptitude, - signal (receive) peer=synaptic, + signal receive peer=apt, + signal receive peer=apt-get, + signal receive peer=aptitude, + signal receive peer=synaptic, @{exec_path} mr, @@ -39,7 +39,7 @@ profile apt-methods-ftp @{exec_path} { @{user_build_dirs}/** rwkl -> @{user_build_dirs}/**, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/apt/apt-methods-gpgv b/apparmor.d/groups/apt/apt-methods-gpgv index f4e77fa4d2..2ce9c6bb43 100644 --- a/apparmor.d/groups/apt/apt-methods-gpgv +++ b/apparmor.d/groups/apt/apt-methods-gpgv @@ -20,11 +20,12 @@ profile apt-methods-gpgv @{exec_path} { capability setgid, capability setuid, - signal (receive) peer=apt-get, - signal (receive) peer=apt, - signal (receive) peer=aptitude, - signal (receive) peer=packagekitd, - signal (receive) peer=synaptic, + signal receive peer=apt-get, + signal receive peer=apt, + signal receive peer=aptitude, + signal receive peer=@{p_packagekitd}, + signal receive peer=role_*, + signal receive peer=synaptic, @{exec_path} mr, @@ -36,6 +37,7 @@ profile apt-methods-gpgv @{exec_path} { @{bin}/gpg-connect-agent rix, @{bin}/gpgconf rix, @{bin}/gpgv rix, + @{bin}/gpgv-sq rix, @{bin}/{m,g,}awk rix, @{bin}/base64 rix, @@ -89,7 +91,7 @@ profile apt-methods-gpgv @{exec_path} { @{PROC}/@{pid}/fd/ r, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, /var/log/cron-apt/temp w, include if exists diff --git a/apparmor.d/groups/apt/apt-methods-http b/apparmor.d/groups/apt/apt-methods-http index 0638120bad..364e582b58 100644 --- a/apparmor.d/groups/apt/apt-methods-http +++ b/apparmor.d/groups/apt/apt-methods-http @@ -8,7 +8,7 @@ abi , include @{exec_path} = @{lib}/apt/methods/http{,s} -profile apt-methods-http @{exec_path} { +profile apt-methods-http @{exec_path} flags=(attach_disconnected) { include include include @@ -23,14 +23,17 @@ profile apt-methods-http @{exec_path} { network inet6 stream, network netlink raw, - signal (receive) peer=apt-get, - signal (receive) peer=apt, - signal (receive) peer=aptitude, - signal (receive) peer=packagekitd, - signal (receive) peer=synaptic, - signal (receive) peer=ubuntu-advantage, - signal (receive) peer=unattended-upgrade, - signal (receive) peer=update-manager, + signal receive peer=@{p_apt_news}, + signal receive peer=@{p_packagekitd}, + signal receive peer=apt-get, + signal receive peer=apt-helper, + signal receive peer=apt, + signal receive peer=aptitude, + signal receive peer=role_*, + signal receive peer=synaptic, + signal receive peer=ubuntu-advantage, + signal receive peer=unattended-upgrade, + signal receive peer=update-manager, ptrace (read), @@ -65,16 +68,25 @@ profile apt-methods-http @{exec_path} { # For package building @{user_build_dirs}/** rwkl -> @{user_build_dirs}/**, + #aa:only ubuntu + /tmp/ubuntu-release-upgrader-@{rand8}/*.tar.gz rw, + /tmp/ubuntu-release-upgrader-@{rand8}/*.tar.gz.gpg rw, + /tmp/ r, - owner @{tmp}/aptitude-root.*/aptitude-download-* rw, owner @{tmp}/apt-changelog-*/*.changelog rw, + owner @{tmp}/aptitude-root.*/aptitude-download-* rw, - @{run}/ubuntu-advantage/aptnews.json rw, + #aa:only ubuntu + @{run}/ubuntu-advantage/aptnews.json rw, + owner @{run}/ubuntu-advantage/apt-news/aptnews.json rw, @{PROC}/1/cgroup r, @{PROC}/@{pid}/cgroup r, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, + + #aa;only test + owner /tmp/tmp@{word8}/{,**} rwlk, include if exists } diff --git a/apparmor.d/groups/apt/apt-methods-mirror b/apparmor.d/groups/apt/apt-methods-mirror index d8e3adce35..dfe83b9d4e 100644 --- a/apparmor.d/groups/apt/apt-methods-mirror +++ b/apparmor.d/groups/apt/apt-methods-mirror @@ -20,11 +20,11 @@ profile apt-methods-mirror @{exec_path} { capability setgid, capability setuid, - signal (receive) peer=apt-get, - signal (receive) peer=apt, - signal (receive) peer=aptitude, - signal (receive) peer=packagekitd, - signal (receive) peer=synaptic, + signal receive peer=apt-get, + signal receive peer=apt, + signal receive peer=aptitude, + signal receive peer=@{p_packagekitd}, + signal receive peer=synaptic, @{exec_path} mr, @@ -44,7 +44,7 @@ profile apt-methods-mirror @{exec_path} { # For package building @{user_build_dirs}/** rwkl -> @{user_build_dirs}/**, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/apt/apt-methods-rred b/apparmor.d/groups/apt/apt-methods-rred index 85da35efcb..a5cf779ba9 100644 --- a/apparmor.d/groups/apt/apt-methods-rred +++ b/apparmor.d/groups/apt/apt-methods-rred @@ -20,11 +20,11 @@ profile apt-methods-rred @{exec_path} { capability setgid, capability setuid, - signal (receive) peer=apt, - signal (receive) peer=apt-get, - signal (receive) peer=aptitude, - signal (receive) peer=synaptic, - signal (receive) set=(int) peer=packagekitd, + signal receive peer=apt, + signal receive peer=apt-get, + signal receive peer=aptitude, + signal receive peer=synaptic, + signal receive set=(int) peer=@{p_packagekitd}, @{exec_path} mr, @@ -50,7 +50,7 @@ profile apt-methods-rred @{exec_path} { @{user_build_dirs}/** rwkl -> @{user_build_dirs}/**, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, /var/log/cron-apt/temp w, include if exists diff --git a/apparmor.d/groups/apt/apt-methods-rsh b/apparmor.d/groups/apt/apt-methods-rsh index 95d70b31f8..403271e8a4 100644 --- a/apparmor.d/groups/apt/apt-methods-rsh +++ b/apparmor.d/groups/apt/apt-methods-rsh @@ -19,10 +19,10 @@ profile apt-methods-rsh @{exec_path} { capability setgid, capability setuid, - signal (receive) peer=apt, - signal (receive) peer=apt-get, - signal (receive) peer=aptitude, - signal (receive) peer=synaptic, + signal receive peer=apt, + signal receive peer=apt-get, + signal receive peer=aptitude, + signal receive peer=synaptic, @{exec_path} mr, @@ -39,7 +39,7 @@ profile apt-methods-rsh @{exec_path} { @{user_build_dirs}/** rwkl -> @{user_build_dirs}/**, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/apt/apt-methods-sqv b/apparmor.d/groups/apt/apt-methods-sqv new file mode 100644 index 0000000000..bc663e2443 --- /dev/null +++ b/apparmor.d/groups/apt/apt-methods-sqv @@ -0,0 +1,48 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2019-2021 Mikhail Morfikov +# Copyright (C) 2021-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/apt/methods/sqv +profile apt-methods-sqv @{exec_path} { + include + include + include + + # To handle the _apt user + capability setgid, + capability setuid, + + signal receive set=int peer=apt, + signal receive set=int peer=packagekitd, + + @{exec_path} mr, + + @{bin}/sqv ix, + + /usr/share/apt/default-sequoia.config r, + /usr/share/keyrings/ r, + /usr/share/keyrings/*.{gpg,pgp,asc} r, + + /etc/apt/keyrings/ r, + /etc/apt/keyrings/*.{gpg,asc} r, + /etc/apt/trusted.gpg r, + /etc/apt/trusted.gpg.d/{,*.{gpg,asc}} r, + + owner /var/lib/apt/lists/{,**} r, + + owner /tmp/apt.data.@{rand6} rw, + owner /tmp/apt.sig.@{rand6} rw, + owner /tmp/apt.sqverr.@{rand6} rw, + owner /tmp/apt.sqvout.@{rand6} rw, + + @{PROC}/@{pid}/fd/ r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/apt/apt-methods-store b/apparmor.d/groups/apt/apt-methods-store index 4c414f07c1..079454eb3f 100644 --- a/apparmor.d/groups/apt/apt-methods-store +++ b/apparmor.d/groups/apt/apt-methods-store @@ -20,11 +20,12 @@ profile apt-methods-store @{exec_path} { capability setgid, capability setuid, - signal (receive) peer=apt-get, - signal (receive) peer=apt, - signal (receive) peer=aptitude, - signal (receive) peer=packagekitd, - signal (receive) peer=synaptic, + signal receive peer=apt-get, + signal receive peer=apt, + signal receive peer=aptitude, + signal receive peer=@{p_packagekitd}, + signal receive peer=role_*, + signal receive peer=synaptic, @{exec_path} mr, @@ -56,7 +57,7 @@ profile apt-methods-store @{exec_path} { owner @{tmp}/apt-changelog-*/*.changelog{,.*} rw, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, owner /var/log/cron-apt/temp w, include if exists diff --git a/apparmor.d/groups/apt/apt-overlay b/apparmor.d/groups/apt/apt-overlay index 4ba9e57d70..7f59635eb1 100644 --- a/apparmor.d/groups/apt/apt-overlay +++ b/apparmor.d/groups/apt/apt-overlay @@ -30,7 +30,6 @@ profile apt-overlay @{exec_path} { /root/ r, owner @{PROC}/@{pids}/loginuid r, - owner @{PROC}/@{pids}/maps r, include if exists } diff --git a/apparmor.d/groups/apt/apt-show-versions b/apparmor.d/groups/apt/apt-show-versions index 16dc584b33..ccd80c60fa 100644 --- a/apparmor.d/groups/apt/apt-show-versions +++ b/apparmor.d/groups/apt/apt-show-versions @@ -10,7 +10,7 @@ include @{exec_path} = @{bin}/apt-show-versions profile apt-show-versions @{exec_path} { include - include + include include include @@ -37,7 +37,7 @@ profile apt-show-versions @{exec_path} { @{user_build_dirs}/** rwkl -> @{user_build_dirs}/**, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, owner /var/log/cron-apt/temp w, include if exists diff --git a/apparmor.d/groups/apt/apt-systemd-daily b/apparmor.d/groups/apt/apt-systemd-daily index 04907876eb..4cae22cba2 100644 --- a/apparmor.d/groups/apt/apt-systemd-daily +++ b/apparmor.d/groups/apt/apt-systemd-daily @@ -25,7 +25,7 @@ profile apt-systemd-daily @{exec_path} { @{bin}/env rix, @{bin}/find rix, @{bin}/flock rix, - @{bin}/grep rix, + @{bin}/{,e}grep rix, @{bin}/gzip rix, @{bin}/ls rix, @{bin}/mv rix, @@ -37,7 +37,7 @@ profile apt-systemd-daily @{exec_path} { @{bin}/touch rix, @{bin}/uniq rix, @{bin}/wc rix, - @{bin}/which{,.debianutils} rix, + @{bin}/which{,.debianutils} rix, @{bin}/xargs rix, @{bin}/apt-config rPx, @@ -67,6 +67,7 @@ profile apt-systemd-daily @{exec_path} { /var/cache/apt/archives/*.deb rw, /var/cache/apt/backup/ r, + @{PROC}/@{pids}/mountinfo r, owner @{PROC}/@{pid}/fd/ r, include if exists diff --git a/apparmor.d/groups/apt/aptitude b/apparmor.d/groups/apt/aptitude index 29a1309c79..fb2560553f 100644 --- a/apparmor.d/groups/apt/aptitude +++ b/apparmor.d/groups/apt/aptitude @@ -8,11 +8,11 @@ abi , include @{exec_path} = @{bin}/aptitude{,-curses} -profile aptitude @{exec_path} flags=(complain) { +profile aptitude @{exec_path} { include + include include include - include # To remove the following errors: # W: chmod 0700 of directory /var/lib/apt/lists/partial failed - SetupAPTPartialDirectory @@ -75,7 +75,7 @@ profile aptitude @{exec_path} flags=(complain) { @{bin}/apt-listbugs rPx, @{bin}/apt-listchanges rPx, @{bin}/apt-show-versions rPx, - @{bin}/dpkg-preconfigure rPx, + @{sbin}/dpkg-preconfigure rPx, @{bin}/debtags rPx, @{bin}/localepurge rPx, @{bin}/appstreamcli rPx, @@ -153,7 +153,7 @@ profile aptitude @{exec_path} flags=(complain) { # aptitude[]: /dev/tty2: Permission denied # aptitude[]: *** err # aptitude[]: Oh, oh, it's an error! possibly I die! - /dev/tty@{int} rw, + /dev/tty@{u8} rw, /dev/ptmx rw, @@ -169,20 +169,10 @@ profile aptitude @{exec_path} flags=(complain) { profile pager { include - include + include - @{bin}/ r, - @{editor_path} mrix, - @{sh_path} rix, - - @{bin}/which{,.debianutils} rix, - - owner @{HOME}/.less* rw, owner @{tmp}/aptitude-*.@{pid}:*/aptitude-download-* rw, - # For shell pwd - /root/ r, - include if exists } diff --git a/apparmor.d/groups/apt/aptitude-create-state-bundle b/apparmor.d/groups/apt/aptitude-create-state-bundle index c700e325fb..a2f5e2050c 100644 --- a/apparmor.d/groups/apt/aptitude-create-state-bundle +++ b/apparmor.d/groups/apt/aptitude-create-state-bundle @@ -16,7 +16,7 @@ profile aptitude-create-state-bundle @{exec_path} { @{exec_path} r, @{sh_path} rix, - @{bin}/which{,.debianutils} rix, + @{bin}/which{,.debianutils} rix, @{bin}/tar rix, @{bin}/bzip2 rix, @{bin}/gzip rix, diff --git a/apparmor.d/groups/apt/command-not-found b/apparmor.d/groups/apt/command-not-found index 35f8940eea..1edeca110d 100644 --- a/apparmor.d/groups/apt/command-not-found +++ b/apparmor.d/groups/apt/command-not-found @@ -12,7 +12,7 @@ include @{exec_path} += @{lib}/command-not-found profile command-not-found @{exec_path} { include - include + include include include include @@ -22,7 +22,7 @@ profile command-not-found @{exec_path} { @{exec_path} r, @{python_path} r, - @{bin}/lsb_release rPx -> lsb_release, + @{bin}/lsb_release rPx, @{bin}/snap rPx, @{lib}/ r, @@ -34,7 +34,7 @@ profile command-not-found @{exec_path} { owner @{PROC}/@{pid}/fd/ r, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/apt/deb-systemd-helper b/apparmor.d/groups/apt/deb-systemd-helper new file mode 100644 index 0000000000..65d6705ebb --- /dev/null +++ b/apparmor.d/groups/apt/deb-systemd-helper @@ -0,0 +1,52 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/deb-systemd-helper +profile deb-systemd-helper @{exec_path} { + include + include + include + + @{exec_path} mr, + + @{bin}/systemctl rCx -> systemctl, + + /etc/systemd/system/{,**} rw, + /etc/systemd/user/{,**} rw, + + /var/lib/systemd/deb-systemd-helper-enabled/{,**} rw, + /var/lib/systemd/deb-systemd-helper-masked/{,**} rw, + /var/lib/systemd/deb-systemd-user-helper-enabled/{,**} rw, + + /tmp/tmp.@{rand10} rw, + + profile systemctl { + include + include + + capability net_admin, + + /etc/ r, + /etc/systemd/ r, + /etc/systemd/system/ r, + /etc/systemd/system/* rw, + /etc/systemd/system/*.requires/ rw, + /etc/systemd/system/*.requires/* rw, + /etc/systemd/system/*.wants/ rw, + /etc/systemd/system/*.wants/* rw, + /etc/systemd/user/ r, + /etc/systemd/user/*.wants/ rw, + /etc/systemd/user/*.wants/* rw, + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/apt/deb-systemd-invoke b/apparmor.d/groups/apt/deb-systemd-invoke new file mode 100644 index 0000000000..4ab20933cc --- /dev/null +++ b/apparmor.d/groups/apt/deb-systemd-invoke @@ -0,0 +1,49 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/deb-systemd-invoke +profile deb-systemd-invoke @{exec_path} { + include + include + include + + capability net_admin, + capability sys_resource, + + ptrace read peer=@{p_systemd}, + + signal send set=(cont term) peer=systemd-tty-ask-password-agent, + + unix type=stream peer=(label=dbus-system), + unix type=stream peer=(label=deb-systemd-invoke//run), + unix type=stream peer=(label=systemd-stdio-bridge), + + @{exec_path} mr, + + @{sh_path} rix, + @{bin}/dpkg Px -> child-dpkg, + @{bin}/sed rix, + @{bin}/systemctl rix, #aa:lint ignore=transition + @{bin}/systemd-tty-ask-password-agent Px, + + @{bin}/systemd-run Cx -> run, + + /tmp/tmp.@{rand10} rw, + + profile run { + include + + capability net_admin, + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/apt/debconf-apt-progress b/apparmor.d/groups/apt/debconf-apt-progress index d60668c036..1d88c829b6 100644 --- a/apparmor.d/groups/apt/debconf-apt-progress +++ b/apparmor.d/groups/apt/debconf-apt-progress @@ -10,42 +10,12 @@ include @{exec_path} = @{bin}/debconf-apt-progress profile debconf-apt-progress @{exec_path} flags=(complain) { include - include + include @{exec_path} r, @{bin}/apt-get rPx, - # Think what to do about this (#FIXME#) - /usr/share/debconf/frontend rPx, - #/usr/share/debconf/frontend rCx -> frontend, - - profile frontend flags=(complain) { - include - include - include - include - - /usr/share/debconf/frontend r, - - @{bin}/debconf-apt-progress rPx, - - @{sh_path} rix, - @{bin}/stty rix, - @{bin}/locale rix, - - # The following is needed when debconf uses dialog/whiptail frontend. - @{bin}/whiptail rPx, - - /etc/debconf.conf r, - owner /var/cache/debconf/{config,passwords,templates}.dat{,-new,-old} rwk, - /usr/share/debconf/templates/adequate.templates r, - - /etc/shadow r, - - include if exists - } - include if exists } diff --git a/apparmor.d/groups/apt/debconf-escape b/apparmor.d/groups/apt/debconf-escape new file mode 100644 index 0000000000..8ec6340259 --- /dev/null +++ b/apparmor.d/groups/apt/debconf-escape @@ -0,0 +1,20 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/debconf-escape +profile debconf-escape @{exec_path} { + include + include + include + + @{exec_path} mr, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/apt/debconf-frontend b/apparmor.d/groups/apt/debconf-frontend new file mode 100644 index 0000000000..501e6f290c --- /dev/null +++ b/apparmor.d/groups/apt/debconf-frontend @@ -0,0 +1,71 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2019-2021 Mikhail Morfikov +# Copyright (C) 2022-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = /usr/share/debconf/frontend +profile debconf-frontend @{exec_path} flags=(complain) { + include + include + include + + capability dac_read_search, + + @{exec_path} r, + + @{bin}/hostname ix, + @{bin}/lsb_release Px, + @{bin}/stty ix, + @{sbin}/update-secureboot-policy Px, + + # Debconf apps + @{bin}/adequate Px, + @{bin}/debconf-apt-progress Px, + @{bin}/linux-check-removal Px, + @{bin}/ucf Px, + @{sbin}/aspell-autobuildhash Px, + @{sbin}/pam-auth-update Px, + @{lib}/tasksel/tasksel-debconf Px -> tasksel, + /usr/share/debian-security-support/check-support-status.hook Px, + + # Grub + @{lib}/grub/grub-multi-install Px, + /usr/share/grub/grub-check-signatures Px, + + # Package maintainer's scripts + /var/lib/dpkg/info/*.@{dpkg_script_ext} Px, + /var/lib/dpkg/info/*.control r, + /var/lib/dpkg/tmp.ci/@{dpkg_script_ext} Px -> dpkg-scripts, + + # DKMS scipts + @{lib}/dkms/common.postinst rPUx, + @{lib}/dkms/dkms-* rPUx, + @{lib}/dkms/dkms_* rPUx, + + /etc/libpaper.d/texlive-base rPUx, + + /usr/share/debconf/{,**} r, + + /etc/inputrc r, + /etc/shadow r, + + owner /var/cache/debconf/* rwk, + + owner @{tmp}/file* w, + owner @{tmp}/tmp.@{rand10} rw, + owner @{tmp}/updateppds.@{rand6} rw, + + @{HOME}/.Xauthority r, + + @{run}/user/@{uid}/pk-debconf-socket rw, + + owner @{PROC}/@{pid}/mounts r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/apt/deborphan b/apparmor.d/groups/apt/deborphan index 236069e992..ae6e0f0277 100644 --- a/apparmor.d/groups/apt/deborphan +++ b/apparmor.d/groups/apt/deborphan @@ -18,7 +18,7 @@ profile deborphan @{exec_path} { /var/lib/dpkg/status r, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, owner @{HOME}/.synaptic/selections.{update,proceed} w, include if exists diff --git a/apparmor.d/groups/apt/debsecan b/apparmor.d/groups/apt/debsecan index c9448c7fb9..c67b1dfb5e 100644 --- a/apparmor.d/groups/apt/debsecan +++ b/apparmor.d/groups/apt/debsecan @@ -27,7 +27,7 @@ profile debsecan @{exec_path} { @{sh_path} rix, # Send results using email - @{bin}/exim4 rPx, + @{sbin}/exim4 rPx, /etc/apt/apt.conf.d/{,*} r, /etc/apt/apt.conf r, diff --git a/apparmor.d/groups/apt/debsums b/apparmor.d/groups/apt/debsums index 01e9ac1526..a617cbc667 100644 --- a/apparmor.d/groups/apt/debsums +++ b/apparmor.d/groups/apt/debsums @@ -12,40 +12,33 @@ profile debsums @{exec_path} { include include - # Needed to read files owned by other users than root. capability dac_read_search, @{exec_path} r, @{sh_path} rix, - @{bin}/{m,g,}awk rix, + @{bin}/{m,g,}awk ix, # Do not strip env to avoid errors like the following: # ERROR: ld.so: object 'libfakeroot-sysv.so' from LD_PRELOAD cannot be preloaded (cannot open # shared object file): ignored. - @{bin}/dpkg-query rpx, + @{bin}/dpkg-query px, # - @{bin}/dpkg rPx -> child-dpkg, - @{bin}/dpkg-divert rPx -> child-dpkg-divert, - - /etc/dpkg/dpkg.cfg.d/{,*} r, - /etc/dpkg/dpkg.cfg r, - - /etc/locale.nopurge r, - - /var/lib/dpkg/info/* r, + @{bin}/dpkg Px -> child-dpkg, + @{bin}/dpkg-divert Px -> child-dpkg-divert, # For shell pwd / r, /root/ r, + #aa:lint ignore=too-wide # Scanning files @{bin}/{,*} r, /usr/{,**} r, /etc/{,**} r, /var/lib/{,**} r, /opt/{,**} r, - /boot/{,**} r, + @{efi}/{,**} r, /lib*/{,**} r, include if exists diff --git a/apparmor.d/groups/apt/debtags b/apparmor.d/groups/apt/debtags index 3e3fd2ab97..53e5964bde 100644 --- a/apparmor.d/groups/apt/debtags +++ b/apparmor.d/groups/apt/debtags @@ -10,8 +10,8 @@ include @{exec_path} = @{bin}/debtags profile debtags @{exec_path} { include + include include - include include #capability sys_tty_config, diff --git a/apparmor.d/groups/apt/dpkg b/apparmor.d/groups/apt/dpkg index 93f5ebca5b..2874cb14ee 100644 --- a/apparmor.d/groups/apt/dpkg +++ b/apparmor.d/groups/apt/dpkg @@ -18,36 +18,43 @@ profile dpkg @{exec_path} { capability fowner, capability fsetid, capability setgid, + capability sys_ptrace, + + ptrace read peer=apt, @{exec_path} mr, @{sh_path} rix, - @{bin}/cat rix, - @{bin}/deb-systemd-helper rix, - @{bin}/deb-systemd-invoke rix, - @{bin}/rm rix, - - @{bin}/dpkg-deb rpx, - @{bin}/dpkg-query rpx, - @{bin}/dpkg-split rpx, - @{bin}/systemctl rCx -> systemctl, - @{lib}/needrestart/dpkg-status rPx, - /usr/share/debian-security-support/check-support-status.hook rPx, - - @{pager_path} rPx -> child-pager, + @{bin}/cat ix, + @{bin}/deb-systemd-helper Px, + @{bin}/deb-systemd-invoke Px, + @{bin}/diff ix, + @{bin}/rm ix, + + @{bin}/dpkg-deb px, + @{bin}/dpkg-divert px, + @{bin}/dpkg-maintscript-helper px, + @{bin}/dpkg-query px, + @{bin}/dpkg-split px, + @{bin}/dpkg-trigger px, + @{bin}/systemctl Cx -> systemctl, + @{lib}/needrestart/dpkg-status Px, + @{pager_path} Px -> child-pager, + /usr/share/debian-security-support/check-support-status.hook Px, # Package maintainer's scripts - /var/lib/dpkg/info/*.@{dpkg_script_ext} rPUx, + /var/lib/dpkg/info/*.@{dpkg_script_ext} Px, /var/lib/dpkg/info/*.control r, - /var/lib/dpkg/tmp.ci/@{dpkg_script_ext} rPUx, + /var/lib/dpkg/tmp.ci/@{dpkg_script_ext} Px, # For shell pwd /root/ r, + #aa:lint ignore=too-wide # Install/update packages / r, /*{,/} rw, - /boot/** rwl -> /boot/**, + @{efi}/** rwl -> @{efi}/**, /etc/** rwl -> /etc/**, /opt/** rwl -> /opt/**, /srv/** rwl -> /srv/**, @@ -61,7 +68,10 @@ profile dpkg @{exec_path} { @{PROC}/sys/kernel/random/boot_id r, owner @{PROC}/@{pid}/fd/ r, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, + + #aa:only test + /tmp/tmp@{word8}tmp/{,**} rwlk, profile systemctl { include diff --git a/apparmor.d/groups/apt/dpkg-architecture b/apparmor.d/groups/apt/dpkg-architecture index a582572714..b1a23f2227 100644 --- a/apparmor.d/groups/apt/dpkg-architecture +++ b/apparmor.d/groups/apt/dpkg-architecture @@ -16,10 +16,9 @@ profile dpkg-architecture @{exec_path} { capability dac_read_search, @{exec_path} r, - /usr/bin/perl r, - @{bin}/{,@{multiarch}-}gcc-[0-9]* rix, - @{lib}/llvm-[0-9]*/bin/clang rix, + @{bin}/{,@{multiarch}-}gcc-[0-9]* ix, + @{lib}/llvm-[0-9]*/bin/clang ix, @{bin}/ccache rCx -> ccache, @{bin}/dpkg rPx -> child-dpkg, @@ -28,9 +27,7 @@ profile dpkg-architecture @{exec_path} { /etc/debian_version r, - # file_inherit - owner @{tmp}/* rw, - + audit owner @{tmp}/* rw, profile ccache { include diff --git a/apparmor.d/groups/apt/dpkg-buildflags b/apparmor.d/groups/apt/dpkg-buildflags index 467d0d50e0..16db9158ab 100644 --- a/apparmor.d/groups/apt/dpkg-buildflags +++ b/apparmor.d/groups/apt/dpkg-buildflags @@ -8,19 +8,29 @@ abi , include @{exec_path} = @{bin}/dpkg-buildflags -profile dpkg-buildflags @{exec_path} flags=(complain) { +profile dpkg-buildflags @{exec_path} flags=(attach_disconnected) { include + include include @{exec_path} r, - /etc/dpkg/origins/debian r, + @{bin}/dpkg Px -> child-dpkg, + @{bin}/@{multiarch}gcc-@{int} mrix, + /usr/share/lto-disabled-list/lto-disabled-list r, + + /usr/share/dpkg/abitable r, /usr/share/dpkg/cputable r, + /usr/share/dpkg/ostable r, /usr/share/dpkg/tupletable r, + /etc/dpkg/origins/* r, + owner @{user_config_dirs}/dpkg/buildflags.conf r, + owner @{user_build_dirs}/**/debian/{,**} r, + include if exists } diff --git a/apparmor.d/groups/apt/dpkg-checkbuilddeps b/apparmor.d/groups/apt/dpkg-checkbuilddeps index 6f54d39672..6129499af0 100644 --- a/apparmor.d/groups/apt/dpkg-checkbuilddeps +++ b/apparmor.d/groups/apt/dpkg-checkbuilddeps @@ -10,17 +10,23 @@ include @{exec_path} = @{bin}/dpkg-checkbuilddeps profile dpkg-checkbuilddeps @{exec_path} flags=(complain) { include + include + include include @{exec_path} r, - /etc/dpkg/origins/debian r, - - /var/lib/dpkg/status r, + @{bin}/dpkg rPx, + @{bin}/@{multiarch}gcc-@{int} mrix, + /usr/share/dpkg/ostable r, /usr/share/dpkg/cputable r, /usr/share/dpkg/tupletable r, + /etc/dpkg/origins/* r, + + /var/lib/dpkg/status r, + # For package building owner @{user_build_dirs}/**/debian/control r, diff --git a/apparmor.d/groups/apt/dpkg-db-backup b/apparmor.d/groups/apt/dpkg-db-backup new file mode 100644 index 0000000000..6ab1083cf5 --- /dev/null +++ b/apparmor.d/groups/apt/dpkg-db-backup @@ -0,0 +1,43 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/dpkg/dpkg-db-backup +profile dpkg-db-backup @{exec_path} { + include + include + include + + @{exec_path} mr, + + @{sh_path} rix, + @{bin}/basename rix, + @{bin}/cmp rix, + @{bin}/cp rix, + @{bin}/date rix, + @{bin}/dirname rix, + @{bin}/gzip rix, + @{bin}/mv rix, + @{bin}/rm rix, + @{bin}/savelog rix, + @{bin}/tar rix, + @{bin}/touch rix, + + /usr/share/dpkg/{,**} r, + + /var/lib/dpkg/ r, + /var/lib/dpkg/alternatives/{,*} r, + /var/lib/dpkg/arch r, + /var/lib/dpkg/diversions r, + /var/lib/dpkg/statoverride r, + + /var/backups/{,**} rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/apt/dpkg-deb b/apparmor.d/groups/apt/dpkg-deb index 4fedbcd5f8..9b4e886bdc 100644 --- a/apparmor.d/groups/apt/dpkg-deb +++ b/apparmor.d/groups/apt/dpkg-deb @@ -32,6 +32,12 @@ profile dpkg-deb @{exec_path} { owner @{tmp}/dpkg-deb.@{rand6} rw, owner @{tmp}/dpkg-deb.@{rand6}/ rw, owner @{tmp}/dpkg-deb.@{rand6}/* rw, + owner @{tmp}/tmp@{rand8}/aptroot/**.deb r, + + #aa:only test + /tmp/@{rand10}/{,**} rw, + /tmp/tmp.@{rand10}/{,**} rw, + /tmp/tmp@{word8}/{,**} rw, include if exists } diff --git a/apparmor.d/groups/apt/dpkg-divert b/apparmor.d/groups/apt/dpkg-divert index 6712b8b7c7..b0c288295e 100644 --- a/apparmor.d/groups/apt/dpkg-divert +++ b/apparmor.d/groups/apt/dpkg-divert @@ -14,6 +14,10 @@ profile dpkg-divert @{exec_path} { @{exec_path} mr, + @{bin}/* rw, + @{sbin}/* rw, + @{lib}/* rw, + /var/lib/dpkg/** r, /usr/share/*/** rw, @@ -22,6 +26,7 @@ profile dpkg-divert @{exec_path} { /var/lib/dpkg/diversions-new rw, /var/lib/dpkg/diversions-old rwl -> /var/lib/dpkg/diversions, + #aa:lint ignore=too-wide /etc/** rw, include if exists diff --git a/apparmor.d/groups/apt/dpkg-genchanges b/apparmor.d/groups/apt/dpkg-genchanges index 7c7ad1681e..965ee9f6e3 100644 --- a/apparmor.d/groups/apt/dpkg-genchanges +++ b/apparmor.d/groups/apt/dpkg-genchanges @@ -25,6 +25,7 @@ profile dpkg-genchanges @{exec_path} flags=(complain) { # For package building owner @{user_build_dirs}/** rw, + owner @{user_pkg_dirs}/** rw, include if exists } diff --git a/apparmor.d/groups/apt/dpkg-maintscript-helper b/apparmor.d/groups/apt/dpkg-maintscript-helper new file mode 100644 index 0000000000..e004638c6d --- /dev/null +++ b/apparmor.d/groups/apt/dpkg-maintscript-helper @@ -0,0 +1,56 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/dpkg-maintscript-helper +profile dpkg-maintscript-helper @{exec_path} { + include + include + + @{exec_path} mrix, + + @{sh_path} rix, + @{bin}/basename ix, + @{bin}/dirname ix, + @{bin}/dpkg Cx -> dpkg, + @{bin}/dpkg-query Cx -> dpkg, + @{bin}/find ix, + @{bin}/ln ix, + @{bin}/mkdir ix, + @{bin}/mv ix, + @{bin}/realpath ix, + @{bin}/rm ix, + @{bin}/rmdir ix, + @{bin}/touch ix, + @{bin}/xargs ix, + + /usr/share/dpkg/sh/* r, + + /etc/**.dpkg-remove w, + + /tmp/tmp.@{rand10} rw, + + profile dpkg { + include + include + include + + capability dac_read_search, + + @{bin}/dpkg mr, + @{bin}/dpkg-query mrpx, + + /etc/dpkg/dpkg.cfg r, + /etc/dpkg/dpkg.cfg.d/{,*} r, + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/apt/dpkg-preconfigure b/apparmor.d/groups/apt/dpkg-preconfigure index c71d9749c2..d3736c4a95 100644 --- a/apparmor.d/groups/apt/dpkg-preconfigure +++ b/apparmor.d/groups/apt/dpkg-preconfigure @@ -7,39 +7,52 @@ abi , include -@{exec_path} = @{bin}/dpkg-preconfigure +@{exec_path} = @{sbin}/dpkg-preconfigure profile dpkg-preconfigure @{exec_path} { include include - include include + include + include - #capability sys_tty_config, + capability dac_read_search, + capability mknod, # optional: no audit @{exec_path} r, - @{sh_path} rix, - @{bin}/{,e}grep rix, - @{bin}/{,g,m}awk rix, - @{bin}/cat rix, - @{bin}/debconf-escape rix, - @{bin}/dialog rix, - @{bin}/expr rix, - @{bin}/locale rix, - @{bin}/readlink rix, - @{bin}/sed rix, - @{bin}/sort rix, - @{bin}/stty rix, - @{bin}/tr rix, - @{bin}/head rix, - @{bin}/readlink rix, - @{bin}/realpath rix, - - @{bin}/findmnt rPx, - @{bin}/dpkg rPx -> child-dpkg, - @{bin}/apt-extracttemplates rPx, - @{bin}/whiptail rPx, - @{lib}/apt/apt-extracttemplates rPx, + @{sh_path} rix, + @{bin}/{,e}grep ix, + @{bin}/{,g,m}awk ix, + @{bin}/cat ix, + @{bin}/cut ix, + @{bin}/debconf-escape Px, + @{bin}/dialog ix, + @{bin}/dirname ix, + @{bin}/expr ix, + @{bin}/find ix, + @{bin}/getent ix, + @{bin}/head ix, + @{bin}/host Px, + @{bin}/hostname ix, + @{bin}/infocmp ix, + @{bin}/locale ix, + @{bin}/readlink ix, + @{bin}/realpath ix, + @{bin}/sed ix, + @{bin}/sort ix, + @{bin}/stty ix, + @{bin}/tail ix, + @{bin}/touch ix, + @{bin}/tr ix, + @{bin}/uniq ix, + @{bin}/which{,.debianutils} rix, + + @{bin}/apt-extracttemplates Px, + @{bin}/dpkg Px -> child-dpkg, + @{bin}/findmnt Px, + @{bin}/lsb_release Px, + @{bin}/whiptail Px, + @{lib}/apt/apt-extracttemplates Px, /usr/share/debconf/confmodule r, /usr/share/dictionaries-common/{,*} r, @@ -59,13 +72,11 @@ profile dpkg-preconfigure @{exec_path} { /var/cache/debconf/tmp.ci/ w, - owner @{tmp}/*.template.* rw, - owner @{tmp}/*.config.* rwPUx, - + /var/cache/debconf/*.dat r, + /var/cache/debconf/tmp.ci/ r, /var/lib/dbus/machine-id r, owner /var/cache/debconf/ rw, owner /var/cache/debconf/{config,passwords,templates}.dat{,-old,-new} rwk, - owner /var/cache/debconf/tmp.ci/ r, owner /var/cache/debconf/tmp.ci/* rix, owner /var/cache/debconf/tmp.ci/*.config.@{rand6} w, owner /var/cache/debconf/tmp.ci/*.passwords.@{rand6} w, @@ -73,22 +84,14 @@ profile dpkg-preconfigure @{exec_path} { owner /var/cache/dictionaries-common/flag-wordlist-new w, owner /var/log/unattended-upgrades/unattended-upgrades-dpkg.log rw, + owner @{tmp}/*.template.* rw, + priority=1 owner @{tmp}/*.config.* rwPUx, + @{run}/user/@{uid}/.mutter-Xwaylandauth.@{rand6} r, @{run}/user/@{uid}/pk-debconf-socket rw, owner @{PROC}/@{pid}/fd/ r, - # The following is needed when dpkg-preconfigure uses debcconf GUI frontends. - include - include - include - include - capability dac_read_search, - @{bin}/lsb_release rPx -> lsb_release, - @{bin}/hostname rix, - @{HOME}/.Xauthority r, - owner @{PROC}/@{pid}/mounts r, - include if exists } diff --git a/apparmor.d/groups/apt/dpkg-query b/apparmor.d/groups/apt/dpkg-query index e0f4dbcdf9..a75ecc8dd9 100644 --- a/apparmor.d/groups/apt/dpkg-query +++ b/apparmor.d/groups/apt/dpkg-query @@ -22,7 +22,7 @@ profile dpkg-query @{exec_path} { # file_inherit /tmp/#@{int} rw, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/apt/dpkg-scripts b/apparmor.d/groups/apt/dpkg-scripts new file mode 100644 index 0000000000..28c4bfc612 --- /dev/null +++ b/apparmor.d/groups/apt/dpkg-scripts @@ -0,0 +1,222 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = /var/lib/dpkg/** +profile dpkg-scripts @{exec_path} { + include + include + include + include + + capability chown, + capability dac_override, + capability dac_read_search, + capability fowner, + capability fsetid, + capability setgid, + capability setuid, + capability sys_admin, # optional: no audit + + @{exec_path} mrix, + + # Common program found in maintainer scripts + @{sh_path} rix, + @{coreutils_path} rix, + @{python_path} rix, + @{bin}/run-parts rix, + + @{bin}/envsubst ix, + @{bin}/file ix, + @{bin}/getent ix, + @{bin}/gzip ix, + @{bin}/helpztags ix, + @{bin}/setpriv ix, + @{bin}/tput ix, + @{bin}/zcat ix, + @{lib}/ubuntu-advantage/cloud-id-shim.sh ix, + @{lib}/ubuntu-advantage/postinst-migrations.sh ix, + + @{bin}/dbus-send Cx -> bus, + @{bin}/kmod Cx -> kmod, + @{bin}/dpkg Px -> child-dpkg, + @{bin}/systemctl Cx -> systemctl, + @{sbin}/invoke-rc.d Cx -> rc, + @{sbin}/ldconfig Cx -> ldconfig, + @{sbin}/ldconfig.real Cx -> ldconfig, + @{sbin}/update-rc.d Cx -> rc, + + #aa:lint ignore=too-wide + # Maintainer scripts can legitimately start/restart anything + # PU is only used as a safety fallback. + @{bin}/** mrPUx, + @{sbin}/** mrPUx, + @{lib}/** mrPUx, + /etc/** PUx, + /usr/share/** PUx, + + #aa:lint ignore=too-wide + # Maintainer's scripts can update a lot of files + / r, + /*/ r, + @{bin}/ r, + @{bin}/* w, + @{sbin}/ r, + @{sbin}/* w, + @{lib}/ rw, + @{lib}/** wl -> @{lib}/**, + /opt/*/** rw, + + #aa:lint ignore=too-wide + /etc/ r, + /etc/** rw, + /usr/share/*/{,**} rw, + /usr/local/share/*/{,**} rw, + /var/** rw, + @{run}/** rwk, + @{efi}/grub/* rw, + + @{HOME}/.profile r, + + /tmp/*.@{rand10} rw, + /tmp/*.@{rand6} rw, + /tmp/*.@{word8} rw, + /tmp/dbconfig-*.@{rand6}/{,**} rw, + /tmp/sed@{rand6} rw, + /tmp/tmp.@{rand10}/{,**} rw, + + @{sys}/kernel/security/apparmor/features/policy/unconfined_restrictions/userns r, + + @{PROC}/@{pid}/fd/ r, + @{PROC}/@{pid}/mountinfo r, + + profile bus { + include + include + include + + capability dac_read_search, + + dbus send bus=system path=/ + interface=org.freedesktop.DBus + member=ReloadConfig + peer=(name=org.freedesktop.DBus, label="@{p_dbus_system}"), + + dbus send bus=system path=/org/freedesktop/PackageKit + interface=org.freedesktop.PackageKit + member=SuggestDaemonQuit + peer=(name=org.freedesktop.PackageKit), + + include if exists + } + + profile kmod { + include + include + + @{efi}/System.map-* r, + + /var/lib/dpkg/triggers/* r, + + @{lib}/modules/*/modules.* w, + + @{sys}/module/** r, + + include if exists + } + + profile systemctl { + include + include + include + + capability net_admin, + capability sys_ptrace, + capability sys_resource, + + signal send set=(cont term) peer=systemd-tty-ask-password-agent, + signal send set=cont peer=child-pager, + + ptrace read peer=@{p_systemd}, + + @{bin}/systemd-tty-ask-password-agent Px, + @{lib}/systemd/systemd-sysv-install PUx, + @{pager_path} Px -> child-pager, + + /etc/machine-id r, + + /etc/systemd/system/{,*/} r, + + /var/lib/systemd/catalog/database r, + + /{run,var}/log/journal/ r, + /{run,var}/log/journal/@{hex32}/ r, + /{run,var}/log/journal/@{hex32}/system.journal* r, + /{run,var}/log/journal/@{hex32}/system@@{hex}-@{hex}.journal* r, + /{run,var}/log/journal/@{hex32}/system@@{hex32}-@{hex16}-@{hex16}.journal* r, + /{run,var}/log/journal/@{hex32}/user-@{hex}.journal* r, + /{run,var}/log/journal/@{hex32}/user-@{uid}@@{hex}-@{hex}.journal* r, + /{run,var}/log/journal/@{hex32}/user-@{uid}@@{hex32}-@{hex16}-@{hex16}.journal* r, + + /tmp/tmp.@{rand10} rw, + + @{run}/utmp rk, + + include if exists + } + + profile rc { + include + include + include + + @{sbin}/update-rc.d mr, + @{sbin}/invoke-rc.d mr, + + @{coreutils_path} rix, + @{sh_path} rix, + @{bin}/systemctl rPx -> dpkg-scripts//systemctl, + + /etc/ r, + /etc/init.d/* r, + /etc/rc@{c}.d/ r, + /etc/rc@{c}.d/* rw, + /etc/rc@{int}.d/ r, + /etc/rc@{int}.d/* rw, + + /tmp/tmp.@{rand10} rw, + + include if exists + } + + profile ldconfig { + include + include + + @{sh_path} rix, + @{sbin}/ldconfig mrix, + @{sbin}/ldconfig.real rix, + + @{bin}/dpkg-trigger rPx, + + @{lib}/ r, + /usr/local/ r, + /usr/local/lib/ r, + + /etc/ld.so.cache rw, + /etc/ld.so.cache~ rw, + + /var/cache/ldconfig/ rw, + owner /var/cache/ldconfig/aux-cache* rw, + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/apt/dpkg-split b/apparmor.d/groups/apt/dpkg-split index e307e9867b..494b80fa62 100644 --- a/apparmor.d/groups/apt/dpkg-split +++ b/apparmor.d/groups/apt/dpkg-split @@ -29,6 +29,9 @@ profile dpkg-split @{exec_path} { @{user_pkg_dirs}/** r, owner @{user_build_dirs}/** rwkl -> @{user_build_dirs}/**, + #aa:only test + /tmp/@{rand10}/{,**} rw, + include if exists } diff --git a/apparmor.d/groups/apt/dpkg-statoverride b/apparmor.d/groups/apt/dpkg-statoverride new file mode 100644 index 0000000000..5bb0aa3acb --- /dev/null +++ b/apparmor.d/groups/apt/dpkg-statoverride @@ -0,0 +1,35 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/dpkg-statoverride +profile dpkg-statoverride @{exec_path} flags=(complain) { + include + include + include + + capability chown, + capability fowner, + capability fsetid, + + @{exec_path} mr, + + @{bin}/* w, + @{sbin}/* w, + @{lib}/** w, + + /var/lib/** w, + + /var/lib/dpkg/ r, + /var/lib/dpkg/statoverride rw, + /var/lib/dpkg/statoverride-new rw, + /var/lib/dpkg/statoverride-old wl, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/apt/dpkg-vendor b/apparmor.d/groups/apt/dpkg-vendor index aee717257d..800332d818 100644 --- a/apparmor.d/groups/apt/dpkg-vendor +++ b/apparmor.d/groups/apt/dpkg-vendor @@ -10,10 +10,10 @@ include @{exec_path} = @{bin}/dpkg-vendor profile dpkg-vendor @{exec_path} { include + include include @{exec_path} r, - /usr/bin/perl r, /etc/dpkg/origins/* r, diff --git a/apparmor.d/groups/apt/querybts b/apparmor.d/groups/apt/querybts index 85bd2e6c39..219d285316 100644 --- a/apparmor.d/groups/apt/querybts +++ b/apparmor.d/groups/apt/querybts @@ -10,14 +10,11 @@ include @{exec_path} = @{bin}/querybts profile querybts @{exec_path} { include - include - include - include - include + include + include include include include - include network inet dgram, network inet6 dgram, @@ -31,16 +28,14 @@ profile querybts @{exec_path} { @{bin}/ r, @{sh_path} rix, @{bin}/stty rix, - @{bin}/ldconfig rix, + @{sbin}/ldconfig rix, @{open_path} rPx -> child-open-browsers, @{bin}/dpkg rPx -> child-dpkg, /etc/reportbug.conf r, - owner @{HOME}/.reportbugrc r, - /etc/mime.types r, /etc/inputrc r, /etc/dpkg/origins/ r, @@ -48,8 +43,7 @@ profile querybts @{exec_path} { /etc/fstab r, - /var/lib/dbus/machine-id r, - /etc/machine-id r, + owner @{HOME}/.reportbugrc r, owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/mounts r, diff --git a/apparmor.d/groups/apt/reportbug b/apparmor.d/groups/apt/reportbug index ae2e64e5d1..e31c9c69c0 100644 --- a/apparmor.d/groups/apt/reportbug +++ b/apparmor.d/groups/apt/reportbug @@ -10,7 +10,7 @@ include @{exec_path} = @{bin}/reportbug profile reportbug @{exec_path} { include - include + include include include include @@ -30,7 +30,7 @@ profile reportbug @{exec_path} { @{bin}/ r, @{python_path} r, - @{bin}/ldconfig rix, + @{sbin}/ldconfig rix, @{bin}/selinuxenabled rix, @{sh_path} rix, @{bin}/aa-enabled rix, @@ -39,15 +39,16 @@ profile reportbug @{exec_path} { @{bin}/readlink rix, @{bin}/stty rix, /usr/share/reportbug/handle_bugscript rix, + /usr/share/bug/reportbug/script rix, - @{bin}/exim4 rPx, + @{sbin}/exim4 rPx, @{bin}/apt-cache rPx, @{bin}/debconf-show rPx, @{bin}/debsums rPx, @{bin}/dlocate rPx, @{bin}/dpkg rPx -> child-dpkg, @{bin}/dpkg-query rpx, - @{bin}/lsb_release rPx -> lsb_release, + @{bin}/lsb_release rPx, @{pager_path} rPx -> child-pager, @{bin}/systemctl rCx -> systemctl, @{lib}/firefox/firefox rPUx, # App allowed to open @@ -61,8 +62,8 @@ profile reportbug @{exec_path} { /usr/share/bug/*/{control,presubj} r, + #aa:lint ignore=too-wide /etc/** r, - /etc/reportbug.conf r, owner @{HOME}/ r, # For shell pwd owner @{HOME}/.reportbugrc{,~} rw, diff --git a/apparmor.d/groups/apt/synaptic b/apparmor.d/groups/apt/synaptic index 58224dd45d..29d056a0c7 100644 --- a/apparmor.d/groups/apt/synaptic +++ b/apparmor.d/groups/apt/synaptic @@ -10,7 +10,7 @@ include @{exec_path} = @{bin}/synaptic @{bin}/synaptic-pkexec profile synaptic @{exec_path} { include - include + include include include include @@ -45,9 +45,9 @@ profile synaptic @{exec_path} { @{bin}/deborphan rPx, @{bin}/debtags rPx, @{bin}/dpkg rPx, - @{bin}/dpkg-preconfigure rPx, + @{sbin}/dpkg-preconfigure rPx, @{bin}/localepurge rPx, - @{bin}/lsb_release rPx -> lsb_release, + @{bin}/lsb_release rPx, @{bin}/pkexec rCx -> pkexec, @{bin}/ps rPx, @{bin}/software-properties-gtk rPx, @@ -103,7 +103,7 @@ profile synaptic @{exec_path} { owner @{PROC}/@{pid}/mountinfo r, /dev/ptmx rw, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, deny @{bin}/dbus-launch x, deny @{bin}/dbus-send x, diff --git a/apparmor.d/groups/apt/unattended-upgrade b/apparmor.d/groups/apt/unattended-upgrade index 8a7c9755f3..357e452aca 100644 --- a/apparmor.d/groups/apt/unattended-upgrade +++ b/apparmor.d/groups/apt/unattended-upgrade @@ -10,13 +10,14 @@ include @{exec_path} = @{bin}/unattended-upgrade profile unattended-upgrade @{exec_path} flags=(attach_disconnected) { include - include + include include - include - include - include + include + include include include + include + include include capability chown, @@ -29,66 +30,57 @@ profile unattended-upgrade @{exec_path} flags=(attach_disconnected) { capability setuid, capability sys_nice, + network inet dgram, + network inet6 dgram, network netlink raw, - signal (send) peer=apt-methods-http, + signal send peer=apt-methods-http, unix type=stream addr=@@{udbus}/bus/unattended-upgr/system, + #aa:dbus own bus=system name=com.ubuntu.UnattendedUpgrade + @{exec_path} mr, @{bin}/ r, @{sh_path} rix, - @{bin}/echo rix, - @{bin}/gdbus rix, - @{bin}/ischroot rix, @{python_path} rix, - @{bin}/test rix, - @{bin}/touch rix, - @{bin}/uname rix, - - @{bin}/apt-listchanges rPx, - @{bin}/dpkg rPx, - @{bin}/dpkg-preconfigure rPx, - @{bin}/etckeeper rPx, - @{bin}/lsb_release rPx -> lsb_release, - @{bin}/on_ac_power rPx, - @{bin}/sendmail rPUx, - @{lib}/apt/methods/http{,s} rPx, - @{lib}/needrestart/apt-pinvoke rPx, - @{lib}/update-notifier/update-motd-updates-available rPx, - @{lib}/zsys-system-autosnapshot rPx, + @{bin}/echo ix, + @{bin}/gdbus ix, + @{bin}/md5sum ix, + @{bin}/tar ix, + @{bin}/test ix, + @{bin}/touch ix, + @{bin}/uname ix, + + @{bin}/apt-listchanges Px, + @{bin}/df Px, + @{bin}/dmesg Px, + @{bin}/dpkg Px, + @{bin}/dpkg-deb px, + @{bin}/dpkg-divert Px, + @{bin}/etckeeper Px, + @{bin}/ischroot Px, + @{bin}/lsb_release Px, + @{sbin}/dpkg-preconfigure Px, + @{sbin}/on_ac_power Px, + @{sbin}/sendmail Px, + @{lib}/apt/methods/http{,s} Px, + @{lib}/needrestart/apt-pinvoke Px, + @{lib}/update-notifier/update-motd-updates-available Px, + @{lib}/zsys-system-autosnapshot Px, /usr/share/distro-info/* r, + /usr/share/dbus-1/interfaces/*UnattendedUpgrade*.xml r, - @{etc_ro}/login.defs r, - @{etc_ro}/security/capability.conf r, - /etc/apt/*.list r, - /etc/apt/apt.conf.d/{,**} r, - /etc/debian_version r, - /etc/default/apport r, - /etc/default/grub.d/* r, - /etc/dpkg/origins/{,debian,ubuntu} r, - /etc/fwupd/{,**} r, - /etc/grub.d/* r, - /etc/init.d/* r, - /etc/issue{.net,} r, - /etc/kernel/*.d/*grub* r, - /etc/legal r, - /etc/lsb-release r, - /etc/machine-id r, - /etc/pam.d/* r, - /etc/pki/fwupd-metadata/{,**} r, - /etc/pki/fwupd/{,**} r, - /etc/profile.d/* r, - /etc/update-manager/{,**} r, - /etc/update-motd.d/* r, - /etc/vmware-tools/* r, + @{etc_ro}/** r, /var/log/unattended-upgrades/{,**} rw, + /var/crash/*.crash rw, /var/lib/apt/periodic/unattended-upgrades-stamp w, + /var/lib/dpkg/info/{,*} r, /var/lib/dpkg/lock rwk, /var/lib/dpkg/lock-frontend rwk, /var/lib/dpkg/updates/ r, @@ -99,10 +91,9 @@ profile unattended-upgrade @{exec_path} flags=(attach_disconnected) { /var/lib/apt/lists/ rw, /var/lib/apt/lists/partial/ rw, /var/lib/apt/periodic/ w, - /var/log/apt/{term,history}.log w, - /var/log/apt/eipp.log.xz w, + /var/log/apt/*.log* rw, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, owner @{run}/unattended-upgrades.lock rwk, owner @{run}/unattended-upgrades.pid rw, owner @{run}/unattended-upgrades.progress rw, @@ -112,6 +103,7 @@ profile unattended-upgrade @{exec_path} flags=(attach_disconnected) { @{PROC}/@{pid}/attr/current r, @{PROC}/@{pid}/cmdline r, @{PROC}/@{pid}/environ r, + @{PROC}/@{pid}/mounts r, @{PROC}/@{pids}/mountinfo r, @{PROC}/@{pids}/stat r, owner @{PROC}/@{pids}/fd/ r, diff --git a/apparmor.d/groups/apt/unattended-upgrade-shutdown b/apparmor.d/groups/apt/unattended-upgrade-shutdown index cd35bb5ae6..ef5aecc8ae 100644 --- a/apparmor.d/groups/apt/unattended-upgrade-shutdown +++ b/apparmor.d/groups/apt/unattended-upgrade-shutdown @@ -9,22 +9,26 @@ include @{exec_path} = /usr/share/unattended-upgrades/unattended-upgrade-shutdown profile unattended-upgrade-shutdown @{exec_path} flags=(attach_disconnected) { include + include include - include - include + include include + include include @{exec_path} mr, - @{bin}/ischroot rix, + @{bin}/ischroot Px, + + @{lib}/@{python_name}/**/__pycache__/ w, + @{lib}/@{python_name}/**/__pycache__/**.pyc w, + @{lib}/@{python_name}/**/__pycache__/**.pyc.@{u64} w, /usr/share/unattended-upgrades/{,*} r, - /etc/apt/apt.conf.d/{,*} r, owner /var/log/unattended-upgrades/*.log* rw, - owner @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + owner @{att}@{run}/systemd/inhibit/@{int}.ref rw, owner @{run}/unattended-upgrades.lock rwk, owner @{PROC}/@{pid}/mounts r, diff --git a/apparmor.d/groups/apt/update-apt-xapian-index b/apparmor.d/groups/apt/update-apt-xapian-index index 5da82090ff..6ea4f19fb2 100644 --- a/apparmor.d/groups/apt/update-apt-xapian-index +++ b/apparmor.d/groups/apt/update-apt-xapian-index @@ -10,17 +10,21 @@ include @{exec_path} = @{bin}/update-apt-xapian-index profile update-apt-xapian-index @{exec_path} { include - include + include + include include @{exec_path} r, @{python_path} r, @{bin}/ r, - @{bin}/dpkg rPx -> child-dpkg, + @{bin}/dpkg Px -> child-dpkg, /usr/share/apt-xapian-index/{,**} r, + /var/lib/dbus/machine-id r, + /etc/machine-id r, + /var/cache/apt-xapian-index/ rw, /var/cache/apt-xapian-index/** rwk, @@ -30,15 +34,9 @@ profile update-apt-xapian-index @{exec_path} { /var/cache/apt/ r, /var/cache/apt/** rwk, - owner @{PROC}/@{pid}/fd/ r, - /var/lib/debtags/package-tags r, - /var/lib/dbus/machine-id r, - /etc/machine-id r, - - # file_inherit - owner /dev/tty@{int} rw, + owner @{PROC}/@{pid}/fd/ r, include if exists } diff --git a/apparmor.d/groups/avahi/avahi-browse b/apparmor.d/groups/avahi/avahi-browse index 47c22d72d9..805d54b2ba 100644 --- a/apparmor.d/groups/avahi/avahi-browse +++ b/apparmor.d/groups/avahi/avahi-browse @@ -11,14 +11,10 @@ include profile avahi-browse @{exec_path} { include include - include + include + include include - dbus receive bus=system path=/Client@{int}/ServiceTypeBrowser@{int} - interface=org.freedesktop.Avahi.ServiceTypeBrowser - member={ItemNew,AllForNow,CacheExhausted} - peer=(name=:*, label=avahi-daemon), - @{exec_path} mr, @{lib}/@{multiarch}/avahi/service-types.db rwk, diff --git a/apparmor.d/groups/avahi/avahi-resolve b/apparmor.d/groups/avahi/avahi-resolve index ff2cae183e..d45cffca39 100644 --- a/apparmor.d/groups/avahi/avahi-resolve +++ b/apparmor.d/groups/avahi/avahi-resolve @@ -11,19 +11,11 @@ include profile avahi-resolve @{exec_path} { include include - include + include + include + include include - dbus send bus=system path=/Client@{int}/AddressResolver@{int} - interface=org.freedesktop.Avahi.AddressResolver - member={Free,HostNameResolverNew} - peer=(name=:*, label=avahi-daemon), - - dbus receive bus=system path=/Client@{int}/AddressResolver@{int} - interface=org.freedesktop.Avahi.AddressResolver - member={Failure,Found} - peer=(name=:*, label=avahi-daemon), - @{exec_path} mr, include if exists diff --git a/apparmor.d/groups/avahi/avahi-set-host-name b/apparmor.d/groups/avahi/avahi-set-host-name index dd9eaba6c6..45df7ce939 100644 --- a/apparmor.d/groups/avahi/avahi-set-host-name +++ b/apparmor.d/groups/avahi/avahi-set-host-name @@ -1,5 +1,6 @@ # apparmor.d - Full set of apparmor profiles # Copyright (C) 2022 Jeroen Rijken +# Copyright (C) 2025 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only abi , @@ -9,6 +10,8 @@ include @{exec_path} = @{bin}/avahi-set-host-name profile avahi-set-host-name @{exec_path} { include + include + include include @{exec_path} mr, diff --git a/apparmor.d/groups/bluetooth/blueman b/apparmor.d/groups/bluetooth/blueman index 469fb24a0e..6653030f08 100644 --- a/apparmor.d/groups/bluetooth/blueman +++ b/apparmor.d/groups/bluetooth/blueman @@ -11,11 +11,13 @@ include profile blueman @{exec_path} flags=(attach_disconnected) { include include - include - include + include + include + include include include include + include include include include @@ -26,11 +28,18 @@ profile blueman @{exec_path} flags=(attach_disconnected) { network netlink raw, network bluetooth raw, - ptrace (read) peer=gjs-console, + ptrace read peer=gjs, #aa:dbus own bus=session name=org.blueman.Applet #aa:dbus own bus=session name=org.blueman.Manager + #aa:dbus talk bus=system name=org.blueman.{m,M}echanism label=blueman-mechanism + + dbus receive bus=system path=/org/bluez/agent/blueman + interface=org.bluez.Agent1 + member=Release + peer=(name=@{busname}, label=bluetoothd), + @{exec_path} mrix, @{sh_path} rix, @@ -54,6 +63,7 @@ profile blueman @{exec_path} flags=(attach_disconnected) { owner @{user_cache_dirs}/obexd/* rw, @{PROC}/@{pids}/cmdline r, + owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/mounts r, @@ -62,8 +72,6 @@ profile blueman @{exec_path} flags=(attach_disconnected) { /dev/shm/ r, /dev/tty rw, - deny owner @{user_share_dirs}/gvfs-metadata/{,*} r, - include if exists } diff --git a/apparmor.d/groups/bluetooth/blueman-mechanism b/apparmor.d/groups/bluetooth/blueman-mechanism index bb6c6cdf7f..112a86a8b0 100644 --- a/apparmor.d/groups/bluetooth/blueman-mechanism +++ b/apparmor.d/groups/bluetooth/blueman-mechanism @@ -11,6 +11,7 @@ include profile blueman-mechanism @{exec_path} flags=(attach_disconnected) { include include + include include include @@ -22,7 +23,7 @@ profile blueman-mechanism @{exec_path} flags=(attach_disconnected) { network inet6 stream, network netlink raw, - #aa:dbus own bus=system name=org.blueman.Mechanism + #aa:dbus own bus=system name=org.blueman.{m,M}echanism @{exec_path} mr, @@ -36,9 +37,9 @@ profile blueman-mechanism @{exec_path} flags=(attach_disconnected) { /dev/rfkill rw, # For network AP - #@{bin}/ip rix, - #@{bin}/xtables-nft-multi rix, - #@{bin}/dnsmasq rPx, + #@{sbin}/ip rix, + #@{sbin}/xtables-nft-multi rix, + #@{sbin}/dnsmasq rPx, #@{bin}/dhclient rPx, # @{PROC}/sys/net/ipv4/ip_forward w, # @{PROC}/sys/net/ipv4/conf/ r, diff --git a/apparmor.d/groups/bluetooth/bluetoothctl b/apparmor.d/groups/bluetooth/bluetoothctl index e408b94b92..3c0c78ce8f 100644 --- a/apparmor.d/groups/bluetooth/bluetoothctl +++ b/apparmor.d/groups/bluetooth/bluetoothctl @@ -15,7 +15,11 @@ profile bluetoothctl @{exec_path} { network bluetooth raw, - #aa:dbus talk bus=system name=org.bluez label=bluetoothd + #aa:dbus talk bus=system name=org.bluez label="@{p_bluetoothd}" + dbus send bus=system path=/ + interface=org.freedesktop.DBus.ObjectManager + member=GetManagedObjects + peer=(name=org.bluez, label=bluetoothd), @{exec_path} mr, diff --git a/apparmor.d/groups/bluetooth/bluetoothd b/apparmor.d/groups/bluetooth/bluetoothd index 8ca699aaf0..a9dcb32d73 100644 --- a/apparmor.d/groups/bluetooth/bluetoothd +++ b/apparmor.d/groups/bluetooth/bluetoothd @@ -11,7 +11,8 @@ include profile bluetoothd @{exec_path} flags=(attach_disconnected) { include include - include + include + include # Needed for configuring HCI interfaces capability net_admin, @@ -20,20 +21,22 @@ profile bluetoothd @{exec_path} flags=(attach_disconnected) { network bluetooth raw, network bluetooth seqpacket, network bluetooth stream, - network alg seqpacket, + network alg seqpacket, # kernel crypto API network netlink raw, - #aa:dbus own bus=system name=org.bluez + #aa:dbus own bus=system name=org.bluez path=/{,**} + #aa:dbus talk bus=system name=org.mpris.MediaPlayer2.Player path=/{,**} label=mpris-proxy - dbus send bus=system path=/{,MediaEndpoint} + # Missing rules from the directive above as these one are not standard + # Part of abstractions/bus/system/org.bluez + dbus send bus=system interface=org.freedesktop.DBus.ObjectManager member=GetManagedObjects peer=(name=@{busname}), - - dbus send bus=system path=/ + dbus receive bus=system path=/ interface=org.freedesktop.DBus.ObjectManager - member=InterfacesRemoved - peer=(name=org.freedesktop.DBus), + member={InterfacesAdded,InterfacesRemoved} + peer=(name=@{busname}, label="@{p_bluetoothd}"), @{exec_path} mr, @@ -41,22 +44,26 @@ profile bluetoothd @{exec_path} flags=(attach_disconnected) { /etc/bluetooth/{,*.conf} r, + / r, + /var/lib/bluetooth/{,**} rw, - @{run}/sdp rw, - owner @{run}/systemd/notify w, - @{run}/udev/data/+hid:* r, # for HID-Compliant Keyboard + / r, + + @{run}/sdp rw, + + @{run}/udev/data/+hid:* r, # For Human Interface Device (mice, controllers, drawing tablets, scanners) @{sys}/devices/@{pci}/rfkill@{int}/name r, @{sys}/devices/@{pci}/**/{uevent,name} r, @{sys}/devices/platform/**/rfkill/**/name r, @{sys}/devices/virtual/dmi/id/chassis_type r, @{sys}/devices/virtual/misc/uhid/**/uevent r, + @{sys}/devices/virtual/vc/*/uevent r, @{PROC}/sys/kernel/hostname r, /dev/uhid rw, - /dev/uinput rw, /dev/rfkill rw, /dev/hidraw@{int} rw, diff --git a/apparmor.d/groups/bluetooth/obexautofs b/apparmor.d/groups/bluetooth/obexautofs index 9803490861..a7f991a0fb 100644 --- a/apparmor.d/groups/bluetooth/obexautofs +++ b/apparmor.d/groups/bluetooth/obexautofs @@ -27,11 +27,6 @@ profile obexautofs @{exec_path} { owner @{HOME}/*/ r, owner @{HOME}/*/*/ r, - @{sys}/devices/@{pci}/usb@{int}/bConfigurationValue r, - @{sys}/devices/@{pci}/usb@{int}/**/bConfigurationValue r, - @{sys}/devices/@{pci}/usb@{int}/{uevent,busnum,devnum,speed,descriptors} r, - @{sys}/devices/@{pci}/usb@{int}/**/{uevent,busnum,devnum,speed,descriptors} r, - /dev/fuse rw, profile fusermount { diff --git a/apparmor.d/groups/bluetooth/obexd b/apparmor.d/groups/bluetooth/obexd index 3da9b4f5de..eae4842386 100644 --- a/apparmor.d/groups/bluetooth/obexd +++ b/apparmor.d/groups/bluetooth/obexd @@ -8,10 +8,14 @@ abi , include @{exec_path} = @{lib}/bluetooth/obexd -profile obexd @{exec_path} { +profile obexd @{exec_path} flags=(attach_disconnected) { include - include include + include + include + include + include + include include network bluetooth stream, @@ -19,17 +23,24 @@ profile obexd @{exec_path} { #aa:dbus own bus=session name=org.bluez.obex + #aa:dbus talk bus=session name=org.gnome.evolution.dataserver.{Source,Sources@{int}} path=/org/gnome/evolution/dataserver/SourceManager{,/**} label=evolution-source-registry + dbus receive bus=system path=/org/bluez/obex/@{uuid} interface=org.bluez.Profile1 member=Release - peer=(name=:*, label=bluetoothd), + peer=(name=@{busname}, label="@{p_bluetoothd}"), + + dbus receive bus=session + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, owner @{user_cache_dirs}/ rw, owner @{user_cache_dirs}/obexd/{,**} rw, - owner @{HOME}/bluetooth/* rw, + @{run}/systemd/users/@{uid} r, include if exists } diff --git a/apparmor.d/groups/browsers/brave b/apparmor.d/groups/browsers/brave index cc3d18b58e..e9e8fc33c2 100644 --- a/apparmor.d/groups/browsers/brave +++ b/apparmor.d/groups/browsers/brave @@ -10,33 +10,30 @@ include @{name} = brave{,-beta,-dev,-bin} @{domain} = com.brave.Brave org.chromium.Chromium @{lib_dirs} = /opt/brave{-bin,.com}{,/@{name}} -@{config_dirs} = @{user_config_dirs}/BraveSoftware/Brave-Browser{,-Beta,-Dev} -@{cache_dirs} = @{user_cache_dirs}/BraveSoftware/Brave-Browser{,-Beta,-Dev} +@{config_dirs} = @{user_config_dirs}/BraveSoftware/ +@{cache_dirs} = @{user_cache_dirs}/BraveSoftware/ @{exec_path} = @{lib_dirs}/@{name} -profile brave @{exec_path} { +profile brave @{exec_path} flags=(attach_disconnected) { include include - unix (send, receive) type=stream peer=(label=brave-crashpad-handler), - #aa:dbus own bus=session name=org.mpris.MediaPlayer2.brave path=/org/mpris/MediaPlayer2 + ptrace trace peer=brave, + @{exec_path} mrix, @{bin}/man rPUx, # For "brave --help" - @{lib_dirs}/chrome_crashpad_handler rPx -> brave//&brave-crashpad-handler, + @{lib_dirs}/chrome_crashpad_handler Px -> brave//&brave//crashpad_handler, /usr/share/chromium/extensions/ r, /etc/opt/chrome/ r, /etc/opt/chrome/native-messaging-hosts/* r, - owner @{user_config_dirs}/BraveSoftware/ rw, - owner @{config_dirs}/WidevineCdm/libwidevinecdm.so mrw, - owner @{cache_dirs}/BraveSoftware/ rw, owner @{tmp}/net-export/ rw, # For brave://net-export/ diff --git a/apparmor.d/groups/browsers/brave-crashpad-handler b/apparmor.d/groups/browsers/brave-crashpad-handler deleted file mode 100644 index ae90c734e5..0000000000 --- a/apparmor.d/groups/browsers/brave-crashpad-handler +++ /dev/null @@ -1,42 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2021-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - -abi , - -include - -@{name} = brave{,-beta,-dev,-bin} -@{lib_dirs} = /opt/brave{-bin,.com}{,/@{name}} -@{config_dirs} = @{user_config_dirs}/BraveSoftware/Brave-Browser{,-Beta,-Dev} - -@{exec_path} = @{lib_dirs}/chrome_crashpad_handler -profile brave-crashpad-handler @{exec_path} { - include - - capability sys_ptrace, - - unix (send, receive) type=stream peer=(label=brave), - - ptrace peer=brave, - signal (send) peer=brave, - - @{exec_path} mrix, - - owner "@{config_dirs}/Crash Reports/**" rwk, - owner @{config_dirs}/CrashpadMetrics-active.pma rw, - owner @{config_dirs}/CrashpadMetrics.pma rw, - - @{PROC}/sys/kernel/yama/ptrace_scope r, - owner @{PROC}/@{pid}/fd/ r, - owner @{PROC}/@{pids}/mem r, - owner @{PROC}/@{pids}/stat r, - owner @{PROC}/@{pids}/task/ r, - - @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_cur_freq r, - @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_max_freq r, - - include if exists -} - -# vim:syntax=apparmor diff --git a/apparmor.d/groups/browsers/chrome b/apparmor.d/groups/browsers/chrome index 9c11f0a4a2..0121097f36 100644 --- a/apparmor.d/groups/browsers/chrome +++ b/apparmor.d/groups/browsers/chrome @@ -24,17 +24,8 @@ profile chrome @{exec_path} flags=(attach_disconnected) { @{bin}/man rPUx, # For "chrome --help" - @{lib_dirs}/chrome_crashpad_handler rPx -> chrome//&chrome-crashpad-handler, - @{lib_dirs}/google-@{name} rPx, - - @{lib_dirs}/nacl_helper rix, - @{lib_dirs}/xdg-mime rix, #-> xdg-mime, - @{lib_dirs}/xdg-settings rix, #-> xdg-settings, - - @{lib_dirs}/*.so* mr, - @{lib_dirs}/libwidevinecdm.so mr, - @{lib_dirs}/libwidevinecdmadapter.so mr, - @{lib_dirs}/WidevineCdm/_platform_specific/linux_*/libwidevinecdm.so mr, + @{lib_dirs}/chrome_crashpad_handler Px -> chrome//&chrome//crashpad_handler, + @{lib_dirs}/google-@{name} Px, include if exists } diff --git a/apparmor.d/groups/browsers/chrome-crashpad-handler b/apparmor.d/groups/browsers/chrome-crashpad-handler deleted file mode 100644 index ea3d7d64aa..0000000000 --- a/apparmor.d/groups/browsers/chrome-crashpad-handler +++ /dev/null @@ -1,38 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2018-2022 Mikhail Morfikov -# Copyright (C) 2022-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - -abi , - -include - -@{lib_dirs} = /opt/google/chrome{,-beta,-unstable} -@{config_dirs} = @{user_config_dirs}/google-chrome{,-beta,-unstable} - -@{exec_path} = @{lib_dirs}/chrome_crashpad_handler -profile chrome-crashpad-handler @{exec_path} { - include - - capability sys_ptrace, - - ptrace peer=chrome, - signal (send) peer=chrome, - - @{exec_path} mrix, - - owner "@{config_dirs}/Crash Reports/**" rwk, - - @{PROC}/sys/kernel/yama/ptrace_scope r, - owner @{PROC}/@{pid}/fd/ r, - owner @{PROC}/@{pids}/mem r, - owner @{PROC}/@{pids}/stat r, - owner @{PROC}/@{pids}/task/ r, - - @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_cur_freq r, - @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_max_freq r, - - include if exists -} - -# vim:syntax=apparmor diff --git a/apparmor.d/groups/browsers/chrome-wrapper b/apparmor.d/groups/browsers/chrome-wrapper index 709eb79a13..5a367f7d56 100644 --- a/apparmor.d/groups/browsers/chrome-wrapper +++ b/apparmor.d/groups/browsers/chrome-wrapper @@ -28,7 +28,7 @@ profile chrome-wrapper @{exec_path} flags=(attach_disconnected) { owner @{user_config_dirs}/chrome-flags.conf r, - owner @{PROC}/@{pid}/fd/* rw, + owner @{PROC}/@{pid}/fd/@{int} rw, # File Inherit owner @{HOME}/.xsession-errors w, diff --git a/apparmor.d/groups/browsers/chromium b/apparmor.d/groups/browsers/chromium index 658dee3987..a9e9bd7bc4 100644 --- a/apparmor.d/groups/browsers/chromium +++ b/apparmor.d/groups/browsers/chromium @@ -22,7 +22,7 @@ profile chromium @{exec_path} flags=(attach_disconnected) { @{exec_path} mrix, - @{lib_dirs}/chrome_crashpad_handler rPx -> chromium//&chromium-crashpad-handler, + @{lib_dirs}/chrome_crashpad_handler Px -> chromium//&chromium//crashpad_handler, include if exists } diff --git a/apparmor.d/groups/browsers/chromium-crashpad-handler b/apparmor.d/groups/browsers/chromium-crashpad-handler deleted file mode 100644 index 8d6ab24617..0000000000 --- a/apparmor.d/groups/browsers/chromium-crashpad-handler +++ /dev/null @@ -1,37 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2018-2022 Mikhail Morfikov -# Copyright (C) 2022-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - -abi , - -include - -@{config_dirs} = @{user_config_dirs}/chromium - -@{exec_path} = @{lib}/chromium/chrome_crashpad_handler -profile chromium-crashpad-handler @{exec_path} { - include - - capability sys_ptrace, - - ptrace peer=chromium, - signal (send) peer=chromium, - - @{exec_path} mrix, - - owner "@{config_dirs}/Crash Reports/**" rwk, - - @{PROC}/sys/kernel/yama/ptrace_scope r, - owner @{PROC}/@{pid}/fd/ r, - owner @{PROC}/@{pids}/mem r, - owner @{PROC}/@{pids}/stat r, - owner @{PROC}/@{pids}/task/ r, - - @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_cur_freq r, - @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_max_freq r, - - include if exists -} - -# vim:syntax=apparmor diff --git a/apparmor.d/groups/browsers/chromium-wrapper b/apparmor.d/groups/browsers/chromium-wrapper index dea35ae1a8..43482b7acf 100644 --- a/apparmor.d/groups/browsers/chromium-wrapper +++ b/apparmor.d/groups/browsers/chromium-wrapper @@ -41,10 +41,11 @@ profile chromium-wrapper @{exec_path} flags=(attach_disconnected) { owner @{tmp}/chromiumargs.@{rand6} rw, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, # Silencer deny @{user_share_dirs}/gvfs-metadata/* r, + deny @{user_share_dirs}/gnome-shell/session.gvdb rw, include if exists } diff --git a/apparmor.d/groups/browsers/ephy-profile-migrator b/apparmor.d/groups/browsers/ephy-profile-migrator index e6f8902dd0..6fb172504b 100644 --- a/apparmor.d/groups/browsers/ephy-profile-migrator +++ b/apparmor.d/groups/browsers/ephy-profile-migrator @@ -18,6 +18,8 @@ profile ephy-profile-migrator @{exec_path} { owner @{user_config_dirs}/epiphany/{,**} rw, owner @{user_share_dirs}/epiphany/.migrated{,.@{rand6}} rw, + owner @{user_share_dirs}/xdg-desktop-portal/{,**/} rw, + include if exists } diff --git a/apparmor.d/groups/browsers/epiphany b/apparmor.d/groups/browsers/epiphany index 636bbf9d3d..6628e42159 100644 --- a/apparmor.d/groups/browsers/epiphany +++ b/apparmor.d/groups/browsers/epiphany @@ -10,11 +10,12 @@ include profile epiphany @{exec_path} flags=(attach_disconnected) { include include - include - include - include + include + include + include include include + include include include include @@ -34,6 +35,13 @@ profile epiphany @{exec_path} flags=(attach_disconnected) { @{open_path} rPx -> child-open, @{bin}/bwrap rix, + @{lib}/epiphany/ephy-profile-migrator PUx, + + #aa:only apparmor<5.0 + @{lib}/glycin-loaders/@{d}+/glycin-* Px -> epiphany//&glycin//loaders, + + #aa:only apparmor>=5.0 + @{lib}/glycin-loaders/@{d}+/glycin-* Px -> epiphany//&:glycin:loaders, /usr/share/enchant*/{,**} r, @@ -45,13 +53,14 @@ profile epiphany @{exec_path} flags=(attach_disconnected) { owner @{user_share_dirs}/org.gnome.Epiphany.WebApp_@{hex}/{,**} rw, + owner @{tmp}/ContentRuleList-@{rand6} rw, owner @{tmp}/ContentRuleList@{rand6} rw, owner @{tmp}/epiphany-*-@{rand6}/{,**} rw, owner @{tmp}/Serialized@{rand9} rw, + owner @{tmp}/SerializedNFA-@{rand6} rw, owner @{tmp}/WebKit-Media-@{rand6} rw, @{sys}/devices/virtual/dmi/id/chassis_type r, - @{sys}/firmware/acpi/pm_profile r, @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/app-gnome-org.gnome.Epiphany-@{int}.scope/memory.* r, @{PROC}/@{pid}/cgroup r, @@ -62,8 +71,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/browsers/firefox b/apparmor.d/groups/browsers/firefox index a561954a31..80a7f5de58 100644 --- a/apparmor.d/groups/browsers/firefox +++ b/apparmor.d/groups/browsers/firefox @@ -10,24 +10,45 @@ include @{name} = firefox{,-esr,-bin} @{lib_dirs} = @{lib}/firefox{,-esr,-beta,-devedition,-nightly} /opt/@{name} @{config_dirs} = @{HOME}/.mozilla/ +@{config_dirs} += @{user_config_dirs}/mozilla/ @{cache_dirs} = @{user_cache_dirs}/mozilla/ @{exec_path} = @{bin}/@{name} @{lib_dirs}/@{name} profile firefox @{exec_path} flags=(attach_disconnected) { include + include #aa:only apparmor<5.0 include include include signal send set=(term, kill) peer=firefox//&keepassxc-proxy, + unix type=seqpacket addr=@gecko-crash-helper-pipe.@{int}, + unix type=seqpacket peer=(label=firefox-crashhelper), + unix type=seqpacket peer=(label=firefox-glxtest), + + unix type=seqpacket, + unix type=seqpacket peer=(label=firefox-crashreporter), + unix type=stream, + #aa:dbus own bus=session name=org.mozilla.firefox - #aa:dbus own bus=session name=org.mpris.MediaPlayer2.firefox path=/org/mpris/MediaPlayer2 + + dbus send bus=session path=/org/freedesktop/portal/desktop + interface=org.freedesktop.host.portal.Registry + member=Register + peer=(name=@{busname}, label=xdg-desktop-portal), @{exec_path} mrix, - @{lib_dirs}/glxtest rPx -> firefox//&firefox-glxtest, - @{lib_dirs}/vaapitest rPx -> firefox//&firefox-vaapitest, + @{lib_dirs}/crashhelper rPx -> firefox//&firefox-crashhelper, + @{lib_dirs}/glxtest rPx -> firefox//&firefox-glxtest, + @{lib_dirs}/vaapitest rPx -> firefox//&firefox-vaapitest, + + #aa:only apparmor<5.0 + # glycin-loaders sandboxed profile stack + include + @{bin}/bwrap Px -> firefox//&glycin, + @{lib}/glycin-loaders/@{d}+/glycin-* Px -> firefox//&glycin//&glycin//loaders, @{lib}/@{multiarch}/qt5/plugins/kf5/org.kde.kwindowsystem.platforms/KF5WindowSystemKWaylandPlugin.so mr, @{lib}/@{multiarch}/qt5/plugins/kf5/org.kde.kwindowsystem.platforms/KF5WindowSystemX11Plugin.so mr, @@ -42,18 +63,21 @@ profile firefox @{exec_path} flags=(attach_disconnected) { @{bin}/update-mime-database rPx, @{lib}/gvfsd-metadata rPx, @{lib}/mozilla/kmozillahelper rPUx, - @{open_path} rPx -> child-open, + @{open_path} rPx -> child-open-any, # Common extensions + @{bin}/browserpass rPx, + @{bin}/keepassxc-proxy rPx -> firefox//&keepassxc-proxy, + @{lib}/browserpass/browserpass-native rPx, + /opt/1Password/1Password-BrowserSupport rPUx, /opt/net.downloadhelper.coapp/bin/net.downloadhelper.coapp* rPx, - @{bin}/browserpass rPx, - @{bin}/keepassxc-proxy rPx -> firefox//&keepassxc-proxy, owner @{user_config_dirs}/gtk-{3,4}.0/assets/*.svg r, owner @{user_config_dirs}/ibus/bus/ r, owner @{user_config_dirs}/ibus/bus/@{hex32}-unix-{,wayland-}@{int} r, owner @{user_config_dirs}/kioslaverc r, - owner @{user_config_dirs}/mimeapps.list{,.@{rand6}} rw, + owner @{user_config_dirs}/mimeapps.list w, + owner @{user_config_dirs}/mimeapps.list.@{rand6} rw, owner @{user_share_dirs}/applications/userapp-Firefox-@{rand6}.desktop{,.@{rand6}} rw, owner @{user_share_dirs}/mime/packages/user-extension-{htm,html,xht,xhtml,shtml}.xml rw, @@ -62,13 +86,11 @@ profile firefox @{exec_path} flags=(attach_disconnected) { owner @{tmp}/.xfsm-ICE-@{rand6} rw, owner @{tmp}/@{rand8}.* rw, # file downloads (to anywhere) owner @{tmp}/@{uuid}.zip{,.tmp} rw, + owner @{tmp}/crashreporter@{int}-request@{int}.json r, owner @{tmp}/Mozilla@{uuid}-cachePurge-{@{hex15},@{hex16}} rwk, - owner @{tmp}/mozilla* rw, - owner @{tmp}/mozilla*/ rw, - owner @{tmp}/mozilla*/* rwk, owner @{tmp}/Mozilla\{@{uuid}\}-cachePurge-{@{hex15},@{hex16}} rwk, - owner @{tmp}/MozillaBackgroundTask-{@{hex15},@{hex16}}-removeDirectory/.parentlock k, - owner @{tmp}/MozillaBackgroundTask-{@{hex15},@{hex16}}-removeDirectory/{**,} rw, + owner @{tmp}/MozillaBackgroundTask-*/.parentlock k, + owner @{tmp}/MozillaBackgroundTask-*/{**,} rw, owner @{tmp}/Mozillato-be-removed-cachePurge-{@{hex15},@{hex16}} rwk, owner @{run}/user/@{uid}/org.keepassxc.KeePassXC.BrowsrServer w, diff --git a/apparmor.d/groups/browsers/firefox-crashhelper b/apparmor.d/groups/browsers/firefox-crashhelper new file mode 100644 index 0000000000..a60d37c07e --- /dev/null +++ b/apparmor.d/groups/browsers/firefox-crashhelper @@ -0,0 +1,35 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{name} = firefox{,.sh,-esr,-bin} +@{lib_dirs} = @{lib}/@{name} /opt/@{name} +@{config_dirs} = @{HOME}/.mozilla/ +@{cache_dirs} = @{user_cache_dirs}/mozilla/ + +@{exec_path} = @{lib_dirs}/crashhelper +profile firefox-crashhelper @{exec_path} flags=(attach_disconnected) { + include + + unix type=seqpacket peer=(label=firefox-crashreporter), + unix type=seqpacket peer=(label=firefox-glxtest), + unix type=seqpacket peer=(label=firefox-vaapitest), + unix type=seqpacket peer=(label=firefox), + + @{exec_path} mr, + + owner "@{config_dirs}/firefox{,-esr}/" rw, + owner "@{config_dirs}/firefox{,-esr}/Crash Reports/" rw, + owner "@{config_dirs}/firefox{,-esr}/Crash Reports/crash_helper_server.log" rw, + + # file_inherit + deny owner @{user_share_dirs}/gnome-shell/session.gvdb rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/browsers/firefox-crashreporter b/apparmor.d/groups/browsers/firefox-crashreporter index 1c418eef4b..9c53fb8a14 100644 --- a/apparmor.d/groups/browsers/firefox-crashreporter +++ b/apparmor.d/groups/browsers/firefox-crashreporter @@ -20,44 +20,55 @@ profile firefox-crashreporter @{exec_path} flags=(attach_disconnected) { include include - signal (receive) set=(term, kill) peer=firefox, - network inet dgram, network inet6 dgram, network inet stream, network inet6 stream, network netlink raw, - @{exec_path} mr, + unix type=seqpacket peer=(label=firefox), + unix type=seqpacket peer=(label=firefox-crashhelper), + + signal receive peer=firefox, + + @{exec_path} mrix, @{bin}/curl rix, @{bin}/mv rix, + @{firefox_path} rPx, @{lib_dirs}/minidump-analyzer rPx, - @{bin}/mv rix, - - owner "@{config_dirs}/firefox/Crash Reports/{,**}" rw, owner @{config_dirs}/firefox/*.*/crashes/{,**} rw, owner @{config_dirs}/firefox/*.*/crashes/events/@{uuid} rw, owner @{config_dirs}/firefox/*.*/extensions/*.xpi r, owner @{config_dirs}/firefox/*.*/minidumps/{,**} rw, owner @{config_dirs}/firefox/*.*/minidumps//@{uuid}.{dmp,extra} r, + owner @{config_dirs}/firefox/*.*/prefs.js r, + owner @{config_dirs}/firefox/*.*/storage-sync-v2.sqlite-shm r, owner @{config_dirs}/firefox/*.*/storage/default/* r, + owner @{config_dirs}/firefox/Crash?Reports/{,**} rwk, + owner @{config_dirs}/firefox/Pending?Pings/@{uuid}.json w, + owner @{config_dirs}/firefox/Profile*/*.sqlite-shm r, owner @{cache_dirs}/firefox/*.*/** r, /tmp/ r, /var/tmp/ r, owner @{tmp}/@{hex}.{dmp,extra} rw, + owner @{tmp}/crashreporter@{int}-request@{int}.json rw, owner @{tmp}/firefox/.parentlock w, owner /dev/shm/org.mozilla.ipc.@{int}.@{int} r, + owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/cmdline r, + owner @{PROC}/@{pid}/mountinfo r, /dev/dri/card@{int} rw, /dev/dri/renderD128 rw, + /dev/nvidia@{int} r, + /dev/nvidiactl r, # Silencer deny owner @{user_share_dirs}/gvfs-metadata/{,*} r, diff --git a/apparmor.d/groups/browsers/firefox-glxtest b/apparmor.d/groups/browsers/firefox-glxtest index 97e5645b90..9e6245eeb9 100644 --- a/apparmor.d/groups/browsers/firefox-glxtest +++ b/apparmor.d/groups/browsers/firefox-glxtest @@ -14,13 +14,19 @@ include @{exec_path} = @{lib_dirs}/glxtest profile firefox-glxtest @{exec_path} flags=(attach_disconnected) { include + include include include + include include - include + + unix type=seqpacket peer=(label=firefox), + unix type=seqpacket peer=(label=firefox-crashhelper), @{exec_path} mr, + / r, + owner @{cache_dirs}/firefox/*/startupCache/scriptCache-* r, owner @{cache_dirs}/firefox/*/startupCache/startupCache* r, diff --git a/apparmor.d/groups/browsers/firefox-kmozillahelper b/apparmor.d/groups/browsers/firefox-kmozillahelper index efcad72f8f..ade169f253 100644 --- a/apparmor.d/groups/browsers/firefox-kmozillahelper +++ b/apparmor.d/groups/browsers/firefox-kmozillahelper @@ -27,16 +27,11 @@ profile firefox-kmozillahelper @{exec_path} { /usr/share/kservices{5,6}/{,**} r, - /etc/xdg/menus/ r, - /etc/xdg/menus/applications-merged/ r, - owner @{HOME}/@{XDG_DESKTOP_DIR}/ r, owner @{HOME}/@{XDG_DESKTOP_DIR}/*.desktop r, owner @{user_config_dirs}/kmozillahelperrc r, owner @{user_config_dirs}/kmozillahelperrc.@{rand6} rwl, - owner @{user_config_dirs}/menus/ r, - owner @{user_config_dirs}/menus/applications-merged/ r, owner @{user_share_dirs}/kservices5/ r, owner @{user_share_dirs}/kservices5/searchproviders/ r, @@ -44,7 +39,7 @@ profile firefox-kmozillahelper @{exec_path} { owner @{run}/user/@{uid}/kmozillahelper@{rand6}.@{int}.kioworker.socket wl, owner @{run}/user/@{uid}/xauth_@{rand6} rl, - @{run}/udev/data/+usb:* r, # For /dev/bus/usb/** + @{run}/udev/data/+usb:* r, # Identifies all USB devices @{run}/udev/data/c189:@{int} r, # for /dev/bus/usb/** diff --git a/apparmor.d/groups/browsers/firefox-minidump-analyzer b/apparmor.d/groups/browsers/firefox-minidump-analyzer index 6e13ee8726..02b8b459e3 100644 --- a/apparmor.d/groups/browsers/firefox-minidump-analyzer +++ b/apparmor.d/groups/browsers/firefox-minidump-analyzer @@ -24,13 +24,13 @@ profile firefox-minidump-analyzer @{exec_path} flags=(attach_disconnected) { owner @{HOME}/.xsession-errors w, - owner "@{config_dirs}/firefox/Crash Reports/" rw, - owner "@{config_dirs}/firefox/Crash Reports/pending/" rw, - owner "@{config_dirs}/firefox/Crash Reports/pending/@{hex}.{dmp,extra}" rw, - owner @{config_dirs}/{,firefox/}*.*/extensions/*.xpi r, - owner @{config_dirs}/{,firefox/}*.*/minidumps/ rw, - owner @{config_dirs}/{,firefox/}*.*/minidumps/@{uuid}.{dmp,extra} rw, - owner @{config_dirs}/{,firefox/}*.*/storage/default/* r, + owner "@{config_dirs}/firefox{,-esr}/Crash Reports/" rw, + owner "@{config_dirs}/firefox{,-esr}/Crash Reports/pending/" rw, + owner "@{config_dirs}/firefox{,-esr}/Crash Reports/pending/@{hex}.{dmp,extra}" rw, + owner @{config_dirs}/{,firefox{,-esr}/}*.*/extensions/*.xpi r, + owner @{config_dirs}/{,firefox{,-esr}/}*.*/minidumps/ rw, + owner @{config_dirs}/{,firefox{,-esr}/}*.*/minidumps/@{uuid}.{dmp,extra} rw, + owner @{config_dirs}/{,firefox{,-esr}/}*.*/storage/default/* r, owner @{cache_dirs}/firefox/*.*/startupCache/*Cache* r, diff --git a/apparmor.d/groups/browsers/firefox-pingsender b/apparmor.d/groups/browsers/firefox-pingsender index 4c86af87af..a0e9ee0b15 100644 --- a/apparmor.d/groups/browsers/firefox-pingsender +++ b/apparmor.d/groups/browsers/firefox-pingsender @@ -12,7 +12,7 @@ include @{config_dirs} = @{HOME}/.mozilla/ @{exec_path} = @{lib_dirs}/pingsender -profile firefox-pingsender @{exec_path} { +profile firefox-pingsender @{exec_path} flags=(attach_disconnected) { include include include @@ -31,7 +31,7 @@ profile firefox-pingsender @{exec_path} { owner @{PROC}/@{pid}/stat r, owner @{PROC}/@{pid}/task/@{tid}/stat r, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/browsers/firefox-vaapitest b/apparmor.d/groups/browsers/firefox-vaapitest index 36069d36fa..62d56e4693 100644 --- a/apparmor.d/groups/browsers/firefox-vaapitest +++ b/apparmor.d/groups/browsers/firefox-vaapitest @@ -18,6 +18,9 @@ profile firefox-vaapitest @{exec_path} flags=(attach_disconnected) { network netlink raw, + unix type=seqpacket peer=(label=firefox), + unix (send receive) type=seqpacket peer=(label=firefox-crashhelper), + @{exec_path} mr, owner @{tmp}/@{name}/.parentlock rw, diff --git a/apparmor.d/groups/browsers/msedge b/apparmor.d/groups/browsers/msedge index f616df6c69..159ceaee5f 100644 --- a/apparmor.d/groups/browsers/msedge +++ b/apparmor.d/groups/browsers/msedge @@ -10,11 +10,11 @@ include @{name} = msedge{,-beta,-dev} @{domain} = com.microsoft.Edge @{lib_dirs} = /opt/microsoft/@{name} -@{config_dirs} = @{user_config_dirs}/microsoft-edge{,-beta,-dev} -@{cache_dirs} = @{user_cache_dirs}/microsoft-edge{,-beta,-dev} +@{config_dirs} = @{user_config_dirs}/microsoft-edge{,-beta,-dev} @{user_config_dirs}/Microsoft/Edge +@{cache_dirs} = @{user_cache_dirs}/microsoft-edge{,-beta,-dev} @{user_cache_dirs}/Microsoft/Edge @{exec_path} = @{lib_dirs}/@{name} -profile msedge @{exec_path} { +profile msedge @{exec_path} flags=(attach_disconnected) { include include @@ -24,17 +24,12 @@ profile msedge @{exec_path} { @{bin}/man rPUx, # For "chrome --help" - @{lib_dirs}/xdg-mime rix, #-> xdg-mime, - @{lib_dirs}/xdg-settings rix, #-> xdg-settings, + @{lib_dirs}/msedge_crashpad_handler Px -> msedge//&msedge//crashpad_handler, + @{lib_dirs}/microsoft-edge{,beta,-dev} ix, - @{lib_dirs}/microsoft-edge{,beta,-dev} rPx, - @{lib_dirs}/chrome_crashpad_handler rPx -> msedge//&msedge-crashpad-handler, - - @{lib_dirs}/*.so* mr, @{lib_dirs}/WidevineCdm/_platform_specific/linux_*/libwidevinecdm.so mr, owner @{user_cache_dirs}/Microsoft/ rw, - owner @{user_cache_dirs}/Microsoft/** rwk, owner @{tmp}/.ses rw, owner @{tmp}/cv_debug.log rw, diff --git a/apparmor.d/groups/browsers/msedge-crashpad-handler b/apparmor.d/groups/browsers/msedge-crashpad-handler deleted file mode 100644 index 67e8212ff8..0000000000 --- a/apparmor.d/groups/browsers/msedge-crashpad-handler +++ /dev/null @@ -1,38 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2022-2024 Alexandre Pujol -# Copyright (C) 2022-2024 Jose Maldonado -# SPDX-License-Identifier: GPL-2.0-only - -abi , - -include - -@{lib_dirs} = /opt/microsoft/msedge{,-beta,-dev} -@{config_dirs} = @{user_config_dirs}/microsoft-edge{,-beta,-dev} - -@{exec_path} = @{lib_dirs}/msedge_crashpad_handler -profile msedge-crashpad-handler @{exec_path} { - include - - capability sys_ptrace, - - ptrace peer=msedge, - signal (send) peer=msedge, - - @{exec_path} mrix, - - owner "@{config_dirs}/Crash Reports/**" rwk, - - @{PROC}/sys/kernel/yama/ptrace_scope r, - owner @{PROC}/@{pid}/fd/ r, - owner @{PROC}/@{pids}/mem r, - owner @{PROC}/@{pids}/stat r, - owner @{PROC}/@{pids}/task/ r, - - @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_cur_freq r, - @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_max_freq r, - - include if exists -} - -# vim:syntax=apparmor diff --git a/apparmor.d/groups/browsers/opera b/apparmor.d/groups/browsers/opera index 54cc054817..4f17e2138d 100644 --- a/apparmor.d/groups/browsers/opera +++ b/apparmor.d/groups/browsers/opera @@ -14,7 +14,7 @@ include @{cache_dirs} = @{user_cache_dirs}/@{name} @{exec_path} = @{lib_dirs}/@{name} -profile opera @{exec_path} { +profile opera @{exec_path} flags=(attach_disconnected) { include include diff --git a/apparmor.d/groups/browsers/opera-crashreporter b/apparmor.d/groups/browsers/opera-crashreporter index 01661215a8..eb67ede59a 100644 --- a/apparmor.d/groups/browsers/opera-crashreporter +++ b/apparmor.d/groups/browsers/opera-crashreporter @@ -17,7 +17,7 @@ profile opera-crashreporter @{exec_path} { include include include - include + include include ptrace (trace, read) peer=opera, diff --git a/apparmor.d/groups/browsers/torbrowser b/apparmor.d/groups/browsers/torbrowser index 5068886c32..3817c6d40e 100644 --- a/apparmor.d/groups/browsers/torbrowser +++ b/apparmor.d/groups/browsers/torbrowser @@ -42,7 +42,7 @@ profile torbrowser @{exec_path} flags=(attach_disconnected) { owner "@{tmp}/Tor Project*" rwk, owner "@{tmp}/Tor Project*/" rw, owner "@{tmp}/Tor Project*/**" rwk, - owner @{tmp}/@{rand8}.* rw, + owner @{tmp}/@{word8} rw, owner @{tmp}/mozilla_pc@{int}/ rw, owner @{tmp}/mozilla_pc@{int}/* rwk, diff --git a/apparmor.d/groups/browsers/torbrowser-glxtest b/apparmor.d/groups/browsers/torbrowser-glxtest index 4939edfbf3..86d8e5471c 100644 --- a/apparmor.d/groups/browsers/torbrowser-glxtest +++ b/apparmor.d/groups/browsers/torbrowser-glxtest @@ -17,11 +17,13 @@ profile torbrowser-glxtest @{exec_path} flags=(attach_disconnected) { include include include + include include - include @{exec_path} mr, + / r, + owner @{PROC}/@{pid}/cmdline r, deny @{config_dirs}/.parentlock rw, diff --git a/apparmor.d/groups/browsers/torbrowser-launcher b/apparmor.d/groups/browsers/torbrowser-launcher index 0f6273107d..4969a14c3d 100644 --- a/apparmor.d/groups/browsers/torbrowser-launcher +++ b/apparmor.d/groups/browsers/torbrowser-launcher @@ -32,7 +32,7 @@ profile torbrowser-launcher @{exec_path} flags=(attach_disconnected) { @{bin}/gpg{,2} Cx -> gpg, @{bin}/gpgconf Cx -> gpg, @{bin}/gpgsm Cx -> gpg, - @{bin}/grep ix, + @{bin}/{,e}grep ix, @{bin}/sed ix, @{bin}/tail ix, diff --git a/apparmor.d/groups/browsers/torbrowser-start b/apparmor.d/groups/browsers/torbrowser-start index 58bb31ac80..ce6a3678c2 100644 --- a/apparmor.d/groups/browsers/torbrowser-start +++ b/apparmor.d/groups/browsers/torbrowser-start @@ -22,7 +22,7 @@ profile torbrowser-start @{exec_path} { @{bin}/expr ix, @{bin}/file ix, @{bin}/getconf ix, - @{bin}/grep ix, + @{bin}/{,e}grep ix, @{bin}/id ix, @{bin}/ln ix, @{bin}/mkdir ix, diff --git a/apparmor.d/groups/bus/at-spi2-registryd b/apparmor.d/groups/bus/at-spi2-registryd index 26311b5752..c7be2735fa 100644 --- a/apparmor.d/groups/bus/at-spi2-registryd +++ b/apparmor.d/groups/bus/at-spi2-registryd @@ -10,10 +10,10 @@ include @{exec_path} = @{lib}/{,at-spi2{,-core}/}at-spi2-registryd profile at-spi2-registryd @{exec_path} flags=(attach_disconnected) { include - include include include - include + include + include include signal receive set=term peer=gdm, @@ -25,7 +25,7 @@ profile at-spi2-registryd @{exec_path} flags=(attach_disconnected) { dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, diff --git a/apparmor.d/groups/bus/dbus-accessibility b/apparmor.d/groups/bus/dbus-accessibility index ee787e4e18..25fae387d4 100644 --- a/apparmor.d/groups/bus/dbus-accessibility +++ b/apparmor.d/groups/bus/dbus-accessibility @@ -9,13 +9,15 @@ include @{exec_path} = @{lib}/{,at-spi2{,-core}/}at-spi-bus-launcher profile dbus-accessibility @{exec_path} flags=(attach_disconnected) { include - include include include - include - include + include + include + include include + include include + include network inet dgram, network inet stream, @@ -23,12 +25,15 @@ profile dbus-accessibility @{exec_path} flags=(attach_disconnected) { network inet6 stream, network netlink raw, - signal (receive) set=(term hup kill) peer=dbus-session, - signal (receive) set=(term hup kill) peer=gdm{,-session-worker}, + ptrace read, - unix type=stream addr=none peer=(label=xorg, addr=@/tmp/.X11-unix/X0), + signal receive set=(term hup kill) peer=dbus-session, + signal receive set=(term hup kill) peer=gdm{,-session-worker}, + signal receive set=(term hup kill) peer=gnome-session-binary, - #aa:dbus own bus=accessibility name=org.freedesktop.DBus + unix bind type=stream addr=@@{udbus}/bus/dbus-broker-lau/user, + + #aa:dbus own bus=accessibility name=org.freedesktop.DBus path=/{,org/freedesktop/{dBus,DBus,dbus}} #aa:dbus own bus=session name=org.a11y.{B,b}us dbus receive bus=accessibility path=/org/freedesktop/DBus interface=org.freedesktop.DBus @@ -38,7 +43,7 @@ profile dbus-accessibility @{exec_path} flags=(attach_disconnected) { dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mrix, @@ -49,17 +54,11 @@ profile dbus-accessibility @{exec_path} flags=(attach_disconnected) { @{lib}/at-spi2{,-core}/at-spi2-registryd rPx, /usr/share/dbus-1/accessibility-services/{,**} r, - /usr/share/dconf/profile/gdm r, /usr/share/defaults/at-spi2/{,**} r, - /usr/share/gdm/greeter-dconf-defaults r, - /usr/share/glib-2.0/schemas/gschemas.compiled r, /etc/machine-id r, /var/lib/dbus/machine-id r, - owner @{DESKTOP_HOME}/greeter-dconf-defaults r, - owner @{desktop_config_dirs}/dconf/user r, - owner @{HOME}/.Xauthority r, owner @{tmp}/xauth_@{rand6} r, @@ -71,10 +70,10 @@ profile dbus-accessibility @{exec_path} flags=(attach_disconnected) { @{sys}/kernel/security/apparmor/features/dbus/mask r, @{sys}/module/apparmor/parameters/enabled r, + @{PROC}/@{pid}/cmdline r, @{PROC}/1/cgroup r, owner @{PROC}/@{pid}/attr/apparmor/current r, owner @{PROC}/@{pid}/cgroup r, - owner @{PROC}/@{pid}/cmdline r, owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/fdinfo/@{int} r, owner @{PROC}/@{pid}/mounts r, diff --git a/apparmor.d/groups/bus/dbus-session b/apparmor.d/groups/bus/dbus-session index cc6b33f61c..7041bed8c0 100644 --- a/apparmor.d/groups/bus/dbus-session +++ b/apparmor.d/groups/bus/dbus-session @@ -21,20 +21,32 @@ profile dbus-session flags=(attach_disconnected) { include include - network unix stream, + signal receive set=(term hup) peer=gdm{,-*}, - unix (send receive) type=stream addr=none peer=(label=gnome-shell, addr=none), + ptrace read, - signal (receive) set=(term hup) peer=gdm{,-*}, - signal (send) set=(term hup kill) peer=dbus-accessibility, - signal (send) set=(term hup kill) peer=dconf-service, - signal (send) set=(term hup kill) peer=xdg-*, + # Internal stack dbus-session//&unconfined + signal (send receive) set=kill peer=dbus-system//&unconfined, + unix type=stream peer=(label=unconfined), + + # Dbus socket + unix bind type=stream addr=@@{udbus}/bus/dbus-broker-lau/user, + + unix type=stream peer=(label=snap.*), + unix (send receive) type=seqpacket peer=(label=fapp), + unix (send receive) type=seqpacket peer=(label=fbwrap), + unix (send receive) type=stream peer=(label=gnome-shell), #aa:dbus own bus=session name=org.freedesktop.DBus path=/{,org/freedesktop/{dBus,DBus,dbus}} - dbus receive bus=session path=/org/freedesktop/DBus - interface=org.freedesktop.DBus - member=Hello - peer=(name=@{busname}), + + # Larger than what is allowed in the directive above, needed due to complex + # setup with stack and peer names. + dbus receive bus=session interface=org.freedesktop.DBus, + + dbus receive bus=session path=/org/freedesktop/systemd1 + interface=org.freedesktop.systemd1.Activator + member=ActivationFailure + peer=(name=@{busname}, label="@{p_systemd_user}"), @{exec_path} mrix, @@ -42,6 +54,7 @@ profile dbus-session flags=(attach_disconnected) { @{lib}/{,at-spi2{,-core}/}at-spi-bus-launcher rPx -> dbus-accessibility, @{bin}/** PUx, + @{sbin}/** PUx, @{lib}/** PUx, @{user_share_dirs}/*/** PUx, /usr/share/*/** PUx, @@ -56,15 +69,21 @@ profile dbus-session flags=(attach_disconnected) { # Dbus can receive any user files owner @{HOME}/** r, + owner @{att}/@{HOME}/** rk, owner @{HOME}/.var/app/*/**/.ref rw, owner @{HOME}/.var/app/*/**/logs/* rw, + owner @{att}@{HOME}/.var/app/*/**/.ref rw, + owner @{att}@{HOME}/.var/app/*/**/logs/* rw, owner @{user_share_dirs}/dbus-1/services/{,**} r, + owner @{tmp}/gtkprint@{rand6} r, + @{run}/systemd/users/@{uid} r, owner @{run}/user/@{uid}/dbus-1/ rw, owner @{run}/user/@{uid}/dbus-1/services/ rw, + owner @{run}/user/@{uid}/pipewire-@{int} rw, owner @{run}/user/@{uid}/systemd/notify w, @{sys}/kernel/security/apparmor/.access rw, @@ -79,7 +98,7 @@ profile dbus-session flags=(attach_disconnected) { owner @{PROC}/@{pid}/oom_score_adj r, /dev/ptmx rw, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/bus/dbus-system b/apparmor.d/groups/bus/dbus-system index ee64c6497a..fa654f72b4 100644 --- a/apparmor.d/groups/bus/dbus-system +++ b/apparmor.d/groups/bus/dbus-system @@ -16,6 +16,7 @@ include profile dbus-system flags=(attach_disconnected) { include include + include include include include @@ -33,23 +34,42 @@ profile dbus-system flags=(attach_disconnected) { ptrace read peer=@{p_systemd}, - #aa:dbus own bus=system name=org.freedesktop.DBus path=/{,org/freedesktop/DBus} - dbus receive bus=system path=/org/freedesktop/DBus - interface=org.freedesktop.DBus - member=Hello - peer=(name=@{busname}), + # Internal stack dbus-system//&unconfined + signal (send receive) set=kill peer=dbus-system//&unconfined, + unix type=stream peer=(label=unconfined), + + # Dbus socket + unix bind type=stream addr=@@{udbus}/bus/dbus-broker-lau/system, + + unix (send receive ) type=seqpacket peer=(label=flatpak-system-helper), + + unix type=stream peer=(label=deb-systemd-invoke), + + #aa:dbus own bus=system name=org.freedesktop.DBus path=/{,org/freedesktop/{dBus,DBus,dbus}} + + # Larger than what is allowed in the directive above, needed due to complex + # setup with stack and peer names. + dbus receive bus=system interface=org.freedesktop.DBus, dbus receive bus=system path=/org/freedesktop/systemd1 interface=org.freedesktop.systemd1.Activator member=ActivationFailure - peer=(name=@{busname}, label="@{p_systemd}"), + peer=(label="@{p_systemd}"), + + dbus send bus=system path=/org/freedesktop/systemd1 + interface=org.freedesktop.systemd1.Manager + member=Subscribe + peer=(label="@{p_systemd}"), @{exec_path} mrix, @{bin}/** PUx, + @{sbin}/** PUx, @{lib}/** PUx, /usr/share/*/** PUx, + @{bin}/dbus-send r, + /etc/dbus-1/{,**} r, /usr/share/dbus-1/{,**} r, /var/lib/snapd/dbus-1/{,**} r, @@ -58,29 +78,29 @@ profile dbus-system flags=(attach_disconnected) { /etc/machine-id r, /var/lib/dbus/machine-id r, - @{att}/@{desktop_share_dirs}/icc/ r, - @{att}/@{desktop_share_dirs}/icc/edid-@{hex32}.icc r, - @{att}/@{user_share_dirs}/icc/ r, - @{att}/@{user_share_dirs}/icc/edid-@{hex32}.icc r, + @{att}@{desktop_share_dirs}/icc/ r, + @{att}@{desktop_share_dirs}/icc/edid-@{hex32}.icc r, + @{att}@{user_share_dirs}/icc/ r, + @{att}@{user_share_dirs}/icc/edid-@{hex32}.icc r, # Dbus can receive any user files @{HOME}/** r, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, - @{att}/@{run}/systemd/sessions/{,@{l}}@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/sessions/{,@{l}}@{int}.ref rw, - @{run}/systemd/notify w, @{run}/systemd/users/@{int} r, @{sys}/kernel/security/apparmor/.access rw, @{sys}/kernel/security/apparmor/features/dbus/mask r, @{sys}/module/apparmor/parameters/enabled r, - @{PROC}/@{pid}/attr/apparmor/current r, - @{PROC}/@{pid}/cmdline r, - @{PROC}/@{pid}/environ r, - @{PROC}/@{pid}/mounts r, - @{PROC}/@{pid}/oom_score_adj r, + @{PROC}/@{pids}/attr/apparmor/current r, + @{PROC}/@{pids}/cmdline r, + @{PROC}/@{pids}/environ r, + @{PROC}/@{pids}/mounts r, + @{PROC}/@{pids}/oom_score_adj r, + @{PROC}/@{pids}/status r, @{PROC}/cmdline r, @{PROC}/sys/kernel/osrelease r, owner @{PROC}/@{pid}/fd/ r, @@ -90,6 +110,7 @@ profile dbus-system flags=(attach_disconnected) { @{att}/dev/dri/card@{int} rw, @{att}/dev/input/event@{int} rw, + @{att}/dev/pts/ptmx rw, include if exists } diff --git a/apparmor.d/groups/bus/ibus-daemon b/apparmor.d/groups/bus/ibus-daemon index 3fdab031bf..b037cfaf6d 100644 --- a/apparmor.d/groups/bus/ibus-daemon +++ b/apparmor.d/groups/bus/ibus-daemon @@ -10,8 +10,8 @@ include profile ibus-daemon @{exec_path} flags=(attach_disconnected) { include include - include - include + include + include include signal (receive) set=(usr1) peer=gnome-shell, @@ -36,7 +36,7 @@ profile ibus-daemon @{exec_path} flags=(attach_disconnected) { dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mrix, @@ -55,8 +55,8 @@ profile ibus-daemon @{exec_path} flags=(attach_disconnected) { owner @{PROC}/@{pids}/fd/ r, - owner @{att}/dev/tty@{int} rw, - owner /dev/tty@{int} rw, + owner @{att}/dev/tty@{u8} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/bus/ibus-dconf b/apparmor.d/groups/bus/ibus-dconf index 6f66ec9b20..4deaacb75f 100644 --- a/apparmor.d/groups/bus/ibus-dconf +++ b/apparmor.d/groups/bus/ibus-dconf @@ -11,21 +11,25 @@ profile ibus-dconf @{exec_path} flags=(attach_disconnected) { include include include - include + include + include include include + signal receive set=kill peer=@{p_systemd_user}, signal receive set=term peer=ibus-daemon, dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), - @{exec_path} mr, + dbus receive bus=system path=/ca/desrt/dconf/Writer/ibus + interface=ca.desrt.dconf.Writer + member=WritabilityNotify + peer=(name=@{busname}, label=dconf), - /usr/share/gdm/greeter-dconf-defaults r, - /usr/share/dconf/profile/gdm r, + @{exec_path} mr, /etc/dconf/db/ibus r, /etc/dconf/profile/ibus r, @@ -37,15 +41,12 @@ profile ibus-dconf @{exec_path} flags=(attach_disconnected) { owner @{desktop_config_dirs}/dconf/user rw, owner @{desktop_config_dirs}/ibus/bus/ r, owner @{desktop_config_dirs}/ibus/bus/@{hex32}-unix-{,wayland-}@{int} r, - owner @{DESKTOP_HOME}/greeter-dconf-defaults r, owner @{user_cache_dirs}/ibus/dbus-@{rand8} rw, owner @{user_config_dirs}/ibus/bus/ r, owner @{user_config_dirs}/ibus/bus/@{hex32}-unix-{,wayland-}@{int} r, - owner /dev/tty@{int} rw, - include if exists } diff --git a/apparmor.d/groups/bus/ibus-engine-simple b/apparmor.d/groups/bus/ibus-engine-simple index e900fc3f5a..b021e7d57d 100644 --- a/apparmor.d/groups/bus/ibus-engine-simple +++ b/apparmor.d/groups/bus/ibus-engine-simple @@ -11,8 +11,8 @@ profile ibus-engine-simple @{exec_path} flags=(attach_disconnected) { include include include - include - include + include + include signal (receive) set=term peer=ibus-daemon, @@ -21,7 +21,7 @@ profile ibus-engine-simple @{exec_path} flags=(attach_disconnected) { dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, diff --git a/apparmor.d/groups/bus/ibus-extension-gtk3 b/apparmor.d/groups/bus/ibus-extension-gtk3 index 34d881a8a1..24f1142ac3 100644 --- a/apparmor.d/groups/bus/ibus-extension-gtk3 +++ b/apparmor.d/groups/bus/ibus-extension-gtk3 @@ -9,14 +9,11 @@ include @{exec_path} = @{lib}/{,ibus/}ibus-extension-gtk3 profile ibus-extension-gtk3 @{exec_path} flags=(attach_disconnected) { include - include - include - include - include + include include include include - include + include include signal (receive) set=term peer=ibus-daemon, @@ -29,28 +26,18 @@ profile ibus-extension-gtk3 @{exec_path} flags=(attach_disconnected) { #aa:dbus own bus=session name=org.freedesktop.IBus.Panel.Extension.Gtk3 - dbus receive bus=session path=/org/gtk/Settings - interface=org.freedesktop.DBus.Properties - member=PropertiesChanged - peer=(name=:*, label=gsd-xsettings), - dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, - /usr/share/dconf/profile/gdm r, /usr/share/ibus/{,**} r, - owner @{GDM_HOME}/greeter-dconf-defaults r, - owner @{desktop_config_dirs}/dconf/user r, owner @{desktop_config_dirs}/ibus/bus/ r, owner @{desktop_config_dirs}/ibus/bus/@{hex32}-unix-{,wayland-}@{int} r, - /dev/tty@{int} rw, - include if exists } diff --git a/apparmor.d/groups/bus/ibus-memconf b/apparmor.d/groups/bus/ibus-memconf index 803f28a4a9..f07f8126eb 100644 --- a/apparmor.d/groups/bus/ibus-memconf +++ b/apparmor.d/groups/bus/ibus-memconf @@ -10,8 +10,9 @@ include profile ibus-memconf @{exec_path} flags=(attach_disconnected) { include include - include - include + include + include + include include signal (receive) set=(term) peer=ibus-daemon, @@ -19,7 +20,7 @@ profile ibus-memconf @{exec_path} flags=(attach_disconnected) { dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, @@ -27,8 +28,6 @@ profile ibus-memconf @{exec_path} flags=(attach_disconnected) { owner @{desktop_config_dirs}/ibus/bus/ r, owner @{desktop_config_dirs}/ibus/bus/@{hex32}-unix-{,wayland-}@{int} r, - owner /dev/tty@{int} rw, - include if exists } diff --git a/apparmor.d/groups/bus/ibus-portal b/apparmor.d/groups/bus/ibus-portal index 53edb4b00b..e79c0e933f 100644 --- a/apparmor.d/groups/bus/ibus-portal +++ b/apparmor.d/groups/bus/ibus-portal @@ -10,16 +10,22 @@ include profile ibus-portal @{exec_path} flags=(attach_disconnected) { include include - include + include signal (receive) set=(term, hup) peer=gdm*, #aa:dbus own bus=session name=org.freedesktop.portal.IBus + #aa:dbus own bus=session name=org.freedesktop.IBus + + dbus receive bus=session path=/org/freedesktop/IBus + interface=org.freedesktop.DBus.Peer + member=Ping + peer=(name=@{busname}, label=ibus-daemon), dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, @@ -27,8 +33,8 @@ profile ibus-portal @{exec_path} flags=(attach_disconnected) { owner @{desktop_config_dirs}/ibus/bus/ r, owner @{desktop_config_dirs}/ibus/bus/@{hex32}-unix-{,wayland-}@{int} r, - owner @{att}/dev/tty@{int} rw, - owner /dev/tty@{int} rw, + owner @{att}/dev/tty@{u8} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/bus/ibus-x11 b/apparmor.d/groups/bus/ibus-x11 index 698eeedb67..d456021281 100644 --- a/apparmor.d/groups/bus/ibus-x11 +++ b/apparmor.d/groups/bus/ibus-x11 @@ -10,10 +10,6 @@ include profile ibus-x11 @{exec_path} flags=(attach_disconnected) { include include - include - include - include - include include include include @@ -30,7 +26,7 @@ profile ibus-x11 @{exec_path} flags=(attach_disconnected) { dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, @@ -43,6 +39,8 @@ profile ibus-x11 @{exec_path} flags=(attach_disconnected) { owner @{user_config_dirs}/ibus/bus/ r, owner @{user_config_dirs}/ibus/bus/@{hex32}-unix-{,wayland-}@{int} r, + owner @{PROC}/@{pids}/stat r, + include if exists } diff --git a/apparmor.d/groups/children/child-modprobe-nvidia b/apparmor.d/groups/children/child-modprobe-nvidia index 9b331a8ce3..b16bfb007c 100644 --- a/apparmor.d/groups/children/child-modprobe-nvidia +++ b/apparmor.d/groups/children/child-modprobe-nvidia @@ -19,12 +19,10 @@ include @{exec_path} = @{bin}/nvidia-modprobe profile child-modprobe-nvidia flags=(attach_disconnected) { include - include - include + include capability chown, capability fsetid, - capability mknod, capability sys_admin, capability syslog, @@ -35,22 +33,13 @@ profile child-modprobe-nvidia flags=(attach_disconnected) { @{sys}/bus/pci/devices/ r, @{sys}/devices/@{pci}/config r, - @{PROC}/sys/kernel/modprobe r, - - @{PROC}/devices r, @{PROC}/driver/nvidia/capabilities/mig/config r, @{PROC}/driver/nvidia/capabilities/mig/monitor r, @{PROC}/driver/nvidia/params r, - @{PROC}/modules r, owner /dev/char/@{dynamic}:@{int} w, # For dynamic assignment range 234 to 254, 384 to 511 - owner /dev/char/195:@{int} w, # Nvidia graphics devices + owner /dev/char/195:@{u8} w, # Nvidia graphics devices - /dev/nvidia-modeset w, - /dev/nvidia-uvm w, - /dev/nvidia-uvm-tools w, - /dev/nvidia@{int} rw, - /dev/nvidiactl rw, owner /dev/nvidia-caps/ w, owner /dev/nvidia-caps/nvidia-cap@{int} w, diff --git a/apparmor.d/groups/children/child-open-any b/apparmor.d/groups/children/child-open-any index 1259d7708e..446627e854 100644 --- a/apparmor.d/groups/children/child-open-any +++ b/apparmor.d/groups/children/child-open-any @@ -14,6 +14,7 @@ include profile child-open-any flags=(attach_disconnected,mediate_deleted) { include include + include @{bin}/** PUx, @{lib}/** PUx, @@ -22,12 +23,6 @@ profile child-open-any flags=(attach_disconnected,mediate_deleted) { /usr/local/bin/** PUx, /usr/share/** PUx, - @{bin}/ r, - @{user_bin_dirs}/ r, - / r, - /usr/ r, - /usr/local/bin/ r, - include if exists include if exists } diff --git a/apparmor.d/groups/children/child-open-browsers b/apparmor.d/groups/children/child-open-browsers index 473276bff6..2a65321a39 100644 --- a/apparmor.d/groups/children/child-open-browsers +++ b/apparmor.d/groups/children/child-open-browsers @@ -19,7 +19,9 @@ profile child-open-browsers flags=(attach_disconnected,mediate_deleted) { include include - @{browsers_path} rPx, + @{browsers_path} Px, + @{bin}/flatpak Px, + @{bin}/snap Px, include if exists include if exists diff --git a/apparmor.d/groups/children/child-open-editor b/apparmor.d/groups/children/child-open-editor index 16d3dc868b..45c22fde58 100644 --- a/apparmor.d/groups/children/child-open-editor +++ b/apparmor.d/groups/children/child-open-editor @@ -19,7 +19,9 @@ profile child-open-editor flags=(attach_disconnected,mediate_deleted) { include include - @{editor_ui_path} PUx, + @{editor_ui_path} PUx, + @{bin}/flatpak Px, + @{bin}/snap Px, include if exists include if exists diff --git a/apparmor.d/groups/children/child-open-help b/apparmor.d/groups/children/child-open-help index 1150d16d3a..0b80bca63f 100644 --- a/apparmor.d/groups/children/child-open-help +++ b/apparmor.d/groups/children/child-open-help @@ -10,8 +10,10 @@ profile child-open-help flags=(attach_disconnected,mediate_deleted) { include include - @{browsers_path} rPx, - @{help_path} rPx, + @{browsers_path} Px, + @{help_path} Px, + @{bin}/flatpak Px, + @{bin}/snap Px, include if exists include if exists diff --git a/apparmor.d/groups/children/child-open-strict b/apparmor.d/groups/children/child-open-strict index 7faf52185e..46e3569db1 100644 --- a/apparmor.d/groups/children/child-open-strict +++ b/apparmor.d/groups/children/child-open-strict @@ -15,8 +15,12 @@ profile child-open-strict flags=(attach_disconnected,mediate_deleted) { include include - @{browsers_path} Px, - @{file_explorers_path} Px, + @{browsers_path} Px, + @{file_explorers_path} Px, + @{bin}/snap Px, + @{bin}/flatpak Px, + + @{lib}/@{multiarch}/glib-@{version}/gio-launch-desktop mrix, include if exists include if exists diff --git a/apparmor.d/groups/children/child-pager b/apparmor.d/groups/children/child-pager index e904f96dd6..8e60bce47a 100644 --- a/apparmor.d/groups/children/child-pager +++ b/apparmor.d/groups/children/child-pager @@ -15,30 +15,7 @@ include profile child-pager flags=(attach_disconnected) { include - include - - capability dac_override, - capability dac_read_search, - - signal (receive) set=(stop, cont, term, kill), - - @{bin}/ r, - @{pager_path} mr, - - @{system_share_dirs}/terminfo/{,**} r, - /usr/share/file/misc/** r, - /usr/share/nvim/{,**} r, - - @{HOME}/.lesshst r, - - owner @{HOME}/ r, - owner @{HOME}/.lesshs* rw, - owner @{HOME}/.terminfo/@{int}/* r, - owner @{user_cache_dirs}/lesshs* rw, - owner @{user_state_dirs}/ r, - owner @{user_state_dirs}/lesshs* rw, - - /dev/tty@{int} rw, + include include if exists } diff --git a/apparmor.d/groups/children/child-systemctl b/apparmor.d/groups/children/child-systemctl index 6dd9afd4a1..ee97d9f13c 100644 --- a/apparmor.d/groups/children/child-systemctl +++ b/apparmor.d/groups/children/child-systemctl @@ -38,11 +38,16 @@ profile child-systemctl flags=(attach_disconnected) { /etc/machine-id r, /etc/systemd/user/{,**} rwl, + /var/lib/systemd/catalog/database r, + /{run,var}/log/journal/ r, /{run,var}/log/journal/@{hex32}/ r, - /{run,var}/log/journal/@{hex32}/user-@{hex}.journal* r, /{run,var}/log/journal/@{hex32}/system.journal* r, - /{run,var}/log/journal/@{hex32}/system@@{hex}.journal* r, + /{run,var}/log/journal/@{hex32}/system@@{hex}-@{hex}.journal* r, + /{run,var}/log/journal/@{hex32}/system@@{hex32}-@{hex16}-@{hex16}.journal* r, + /{run,var}/log/journal/@{hex32}/user-@{hex}.journal* r, + /{run,var}/log/journal/@{hex32}/user-@{uid}@@{hex}-@{hex}.journal* r, + /{run,var}/log/journal/@{hex32}/user-@{uid}@@{hex32}-@{hex16}-@{hex16}.journal* r, @{run}/systemd/private rw, diff --git a/apparmor.d/groups/children/glycin b/apparmor.d/groups/children/glycin new file mode 100644 index 0000000000..1c1ebea733 --- /dev/null +++ b/apparmor.d/groups/children/glycin @@ -0,0 +1,62 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Confine glycin-loaders sandboxed with bwrap. It also confines bwrap itself. +# for this use case. + +# Note: This profile does not specify an attachment path because it is +# intended to be used only via "Px -> glycin" exec transitions from other profiles. + +abi , + +include + +profile glycin flags=(attach_disconnected) { + include + include + + signal receive set=kill, + signal send set=kill peer=*//&glycin, + + ptrace read peer=*//&glycin, + + @{lib}/glycin-loaders/@{d}+/glycin-* Cx -> &glycin//loaders, + + #aa:lint ignore=too-wide + # Safe deny of inherited files from parent process. + deny network inet dgram, + deny network inet6 dgram, + deny network inet stream, + deny network inet6 stream, + deny /usr/share/nvidia/** r, + deny owner @{HOME}/.*/** rw, + deny owner /tmp/*/** w, + deny /opt/*/** rw, + deny @{sys}/devices/system/** r, + deny /dev/shm/** rw, + deny /dev/dri/* rw, + deny @{att}/dev/tty@{u8} rw, + + profile loaders flags=(attach_disconnected) { + include + include + + unix type=stream, + + @{lib}/glycin-loaders/@{d}+/glycin-* mr, + + @{att}/usr/share/glycin-loaders/{,**} r, + + @{att}/usr/share/gtksourceview-2.0/{,**} r, + @{att}/usr/share/gtksourceview-3.0/{,**} r, + @{att}/usr/share/gtksourceview-4/{,**} r, + @{att}/usr/share/gtksourceview-5/{,**} r, + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/code/code b/apparmor.d/groups/code/code new file mode 100644 index 0000000000..2c0a7320a8 --- /dev/null +++ b/apparmor.d/groups/code/code @@ -0,0 +1,209 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# !!! warning +# +# This profile is **not** installed by default as it breaks the POLA principle +# in the way to **will** cause some extension to not work: all extension +# that require privilege access to the system, like docker, kubernetes, +# remote ssh, VM, etc... will not work with this profile. +# +# **Architecture** +# +# The `code` profile stack define a "world" with generic rules of what should be +# allowed in an IDE and what is not: +# +# - **Allowed:** compilation, running code, debugging, git, ssh, network access, etc... +# in `@{user_projects_dirs}` +# - **Not allowed:** access to hardware, access to other users data, etc... +# +# We also ensure vscode can start a shell and we **confine** this shell to limit +# it to the same development related tasks. **Therefore, tasks such as installing +# system dependencies will not work.** +# + +abi , + +include + +@{name} = code{,-oss} vscode{,-oss} +@{config} = Code Code?-?OSS Code?-?Insiders +@{domain} = org.chromium.Chromium +@{lib_dirs} = @{lib}/@{name} /usr/share/@{name} +@{config_dirs} = @{HOME}/.@{name} @{user_config_dirs}/@{config} +@{ext_dirs} = @{config_dirs}/extensions +@{cache_dirs} = @{user_cache_dirs}/@{name} + +@{exec_path} = @{bin}/@{name} @{lib_dirs}/@{name} +profile code @{exec_path} flags=(attach_disconnected,mediate_deleted) { + include + include + include + include + include + include + include + include + include + include + include + include + include + + network inet dgram, + network inet6 dgram, + network inet stream, + network inet6 stream, + network netlink raw, + + ptrace read, + + unix (send receive) type=stream peer=(label=code-*), + unix (send receive) type=stream peer=(label=git), + unix (send receive) type=stream peer=(label=gitstatusd), + unix (send receive) type=stream peer=(label=nproc), + unix (send receive) type=stream peer=(label=ps), + unix type=seqpacket peer=(label=code-shells), + + signal send peer=claude, + signal send peer=code-*, + signal send peer=git, + signal send peer=gitstatusd, + + @{exec_path} mrix, + @{PROC}/self/exe mrix, + + @{bin}/rg rix, + @{bin}/env mr, + @{ldd_path} mrix, + @{lib_dirs}/** mr, + @{sh_path} r, + + #aa:lint ignore=too-wide + # Extensions + priority=-10 /** Px -> code-extensions, + + @{bin}/git Px, + @{open_path} Cx -> open, + + @{lib_dirs}/{,resources/}app/node_modules/** ix, + priority=1 @{lib_dirs}/{,resources/}app/node_modules/**/vsce-sign rCx -> sign, + + owner @{ext_dirs}/*/** mr, + owner @{ext_dirs}/anthropic.claude-code-*/** Px -> claude, + owner @{ext_dirs}/valentjn.vscode-ltex-*/** Px -> code-extension-ltex, + + # Terminal + # Some extension may need to run shells command directly. These command would also + # run trhough this shell profile, and may be limited by it. It is a feature. + @{shells_path} Px -> code-shells, + + /opt/ r, + + /etc/shells r, + /etc/lsb-release r, + + owner @{HOME}/ r, + owner @{HOME}/.claude/{,**} rw, + owner @{HOME}/.copilot/{,**} rw, + owner @{HOME}/@{XDG_SSH_DIR}/config r, + + owner @{user_config_dirs}/git/config r, + owner @{user_config_dirs}/git/ignore r, + + owner @{user_projects_dirs}/ r, + owner @{user_projects_dirs}/** rwkl, + + owner @{user_cache_dirs}/Microsoft/ rw, + owner @{user_cache_dirs}/Microsoft/** rwlk, + owner @{user_cache_dirs}/typescript/ rw, + owner @{user_cache_dirs}/typescript/** rwlk, + + owner @{run}/user/@{uid}/@{name}-*.sock rw, + owner @{run}/user/@{uid}/git-graph-askpass-@{rand32}.sock w, + + /var/tmp/ r, + + owner @{tmp}/@{name}-*/ rw, + owner @{tmp}/@{name}-*/** rwlk, + owner @{tmp}/@{user}-@{name}-*/{,**} rw, + owner @{tmp}/exthost-@{hex6}.cpuprofile w, + owner @{tmp}/mcp-@{rand6}/{,**} rw, + owner @{tmp}/node-compile-cache/{,**} rw, + owner @{tmp}/ovsx-@{rand6}/{,**} rw, + owner @{tmp}/tmp-@{int}-@{rand12}/ w, + + @{PROC}/loadavg r, + @{PROC}/sys/kernel/osrelease r, + owner @{PROC}/@{pid}/clear_refs w, + owner @{PROC}/@{pid}/comm w, + + /dev/ptmx rw, + + deny dbus send bus=system path=/ + interface=org.freedesktop.DBus.ObjectManager + member=GetManagedObjects + peer=(label=bluetoothd), + + profile sign { + include + include + include + include + + network inet dgram, + network inet6 dgram, + network inet stream, + network inet6 stream, + network netlink raw, + + unix type=stream peer=(label=code), + + @{lib_dirs}/** mr, + + owner @{HOME}/.dotnet/corefx/cryptography/{,**} rw, + + owner @{config_dirs}/CachedExtensionVSIXs/* rk, + + owner /dev/shm/.org.chromium.Chromium.@{rand6} rw, # file_inherit + + owner @{tmp}/.@{domain}.@{rand6} rw, + owner @{tmp}/{,c}dotnet-diagnostic-*-socket rw, + owner @{tmp}/clr-debug-pipe-* rw, + + @{sys}/devices/system/cpu/cpu@{int}/cache/index@{int}/level r, + @{sys}/devices/system/cpu/cpu@{int}/cache/index@{int}/size r, + @{sys}/devices/system/node/ r, + + owner @{PROC}/@{pid}/mountinfo r, + owner @{PROC}/@{pid}/stat r, + owner @{PROC}/@{pid}/task/@{tid}/comm rw, + + include if exists + } + + profile open { + include + include + include + + @{browsers_path} Px, + @{file_explorers_path} Px, + @{bin}/snap Px, + @{bin}/flatpak Px, + + @{lib}/@{multiarch}/glib-@{version}/gio-launch-desktop mrix, + + owner @{user_projects_dirs}/** rw, + + include + owner @{user_share_dirs}/gvfs-metadata/* r, + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-a-f/code-extension-git-askpass b/apparmor.d/groups/code/code-extension-git-askpass similarity index 61% rename from apparmor.d/profiles-a-f/code-extension-git-askpass rename to apparmor.d/groups/code/code-extension-git-askpass index 5a31889b9d..a590fe0156 100644 --- a/apparmor.d/profiles-a-f/code-extension-git-askpass +++ b/apparmor.d/groups/code/code-extension-git-askpass @@ -6,9 +6,16 @@ abi , include -@{exec_path} = @{lib}/code/extensions/git/dist/askpass.sh +@{name} = code{,-oss} vscode{,-oss} +@{config} = Code Code?-?OSS Code?-?Insiders +@{config_dirs} = @{HOME}/.@{name} @{user_config_dirs}/@{config} +@{ext_dirs} = @{config_dirs}/extensions +@{lib_dirs} = @{lib}/code/extensions/git + +@{exec_path} = @{lib}/code/extensions/git/dist/askpass.sh @{lib}/code/extensions/git/dist/ssh-askpass.sh profile code-extension-git-askpass @{exec_path} { include + include network inet dgram, network inet6 dgram, @@ -23,7 +30,7 @@ profile code-extension-git-askpass @{exec_path} { /usr/share/terminfo/** r, - owner @{tmp}/tmp.* rw, + owner @{tmp}/tmp.@{rand10} rw, /dev/tty rw, diff --git a/apparmor.d/profiles-a-f/code-extension-git-editor b/apparmor.d/groups/code/code-extension-git-editor similarity index 57% rename from apparmor.d/profiles-a-f/code-extension-git-editor rename to apparmor.d/groups/code/code-extension-git-editor index 8e56ac3aa5..2fb50b2f6f 100644 --- a/apparmor.d/profiles-a-f/code-extension-git-editor +++ b/apparmor.d/groups/code/code-extension-git-editor @@ -6,15 +6,24 @@ abi , include +@{name} = code{,-oss} vscode{,-oss} +@{config} = Code Code?-?OSS Code?-?Insiders +@{config_dirs} = @{HOME}/.@{name} @{user_config_dirs}/@{config} +@{ext_dirs} = @{config_dirs}/extensions +@{lib_dirs} = @{lib}/code/extensions/git + @{exec_path} = @{lib}/code/extensions/git/dist/git-editor.sh -profile code-extension-git-editor @{exec_path} { +profile code-extension-git-editor @{exec_path} flags=(attach_disconnected) { include + include @{exec_path} mr, @{sh_path} rix, @{lib}/electron@{int}/electron rix, + owner @{run}/user/@{uid}/vscode-git-@{hex}.sock rw, + @{sys}/devices/system/cpu/cpufreq/policy@{int}/cpuinfo_max_freq r, /dev/tty rw, diff --git a/apparmor.d/groups/code/code-extension-ltex b/apparmor.d/groups/code/code-extension-ltex new file mode 100644 index 0000000000..06616e3dc0 --- /dev/null +++ b/apparmor.d/groups/code/code-extension-ltex @@ -0,0 +1,54 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{name} = code{,-oss} vscode{,-oss} +@{config} = Code Code?-?OSS Code?-?Insiders +@{config_dirs} = @{HOME}/.@{name} @{user_config_dirs}/@{config} +@{ext_dirs} = @{config_dirs}/extensions +@{lib_dirs} = @{ext_dirs}/valentjn.vscode-ltex-*/ + +@{exec_path} = @{lib_dirs}/** +profile code-extension-ltex @{exec_path} flags=(attach_disconnected) { + include + include + include + + network inet stream, + network inet6 stream, + + @{exec_path} mix, + + @{sh_path} ix, + @{bin}/dirname ix, + @{bin}/env r, + @{bin}/uname ix, + + owner @{HOME}/ r, + owner @{HOME}/.languagetool/{,**} r, + + owner @{user_projects_dirs}/ r, + owner @{user_projects_dirs}/**/ r, + + /tmp/ r, + owner @{tmp}/hsperfdata_@{user}/ rw, + owner @{tmp}/hsperfdata_@{user}/@{int} rwk, + owner @{tmp}/jansi-*-libjansi.so rwm, + owner @{tmp}/jansi-*-libjansi.so.lck rw, + + @{PROC}/cgroups r, + @{PROC}/@{pid}/net/if_inet6 r, + @{PROC}/@{pid}/net/ipv6_route r, + owner @{PROC}/@{pid}/coredump_filter rw, + owner @{PROC}/@{pid}/mountinfo r, + + /dev/tty rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/code/code-extensions b/apparmor.d/groups/code/code-extensions new file mode 100644 index 0000000000..27e960e637 --- /dev/null +++ b/apparmor.d/groups/code/code-extensions @@ -0,0 +1,71 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{devtools} += rust-analyzer harper-ls proc-macro-srv + +@{name} = code{,-oss} vscode{,-oss} +@{config} = Code Code?-?OSS Code?-?Insiders +@{config_dirs} = @{HOME}/.@{name} @{user_config_dirs}/@{config} +@{ext_dirs} = @{config_dirs}/extensions +@{lib_dirs} = @{ext_dirs}/ + +@{exec_path} = @{lib_dirs}/** +profile code-extensions @{exec_path} flags=(attach_disconnected) { + include + include + include + include + include + include + include + + network inet dgram, + network inet stream, + network inet6 dgram, + network inet6 stream, + + ptrace trace peer=code-extensions, + + unix type=stream peer=(label=code-shells), + unix type=stream peer=(label=git), + + dbus send bus=session path=/org/freedesktop/systemd1 + interface=org.freedesktop.systemd1.Manager + member=GetUnitFileState + peer=(name=org.freedesktop.systemd1, label=unconfined), + + @{exec_path} mrix, + @{sh_path} rix, + + owner @{lib_dirs}/{,**/}__pycache__/ w, + owner @{lib_dirs}/{,**/}__pycache__/**.pyc{,*} w, + + owner @{user_config_dirs}/git/* r, + + owner @{user_projects_dirs}/ r, + owner @{user_projects_dirs}/** rwkl -> @{user_projects_dirs}/**, + + /tmp/ r, + owner @{tmp}/hsperfdata_@{user}/ rw, + owner @{tmp}/hsperfdata_@{user}/@{int} rwk, + owner @{tmp}/jansi-*-libjansi.so rwm, + owner @{tmp}/jansi-*-libjansi.so.lck rw, + owner @{tmp}/proc-macro-*/ w, + + @{sys}/devices/system/node/ r, + + @{PROC}/@{pid}/net/if_inet6 r, + @{PROC}/@{pid}/net/ipv6_route r, + @{PROC}/@{pid}/net/tcp r, + @{PROC}/sys/net/core/somaxconn r, + owner @{PROC}/@{pid}/coredump_filter rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/code/code-shells b/apparmor.d/groups/code/code-shells new file mode 100644 index 0000000000..28c9ada6e9 --- /dev/null +++ b/apparmor.d/groups/code/code-shells @@ -0,0 +1,73 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{devtools} += rust-analyzer harper-ls proc-macro-srv + +@{name} = code{,-oss} vscode{,-oss} +@{config} = Code Code?-?OSS Code?-?Insiders +@{config_dirs} = @{HOME}/.@{name} @{user_config_dirs}/@{config} +@{ext_dirs} = @{config_dirs}/extensions +@{lib_dirs} = @{ext_dirs}/ + +profile code-shells flags=(attach_disconnected) { + include + include + include + include + include + include + include + include + include + include + include + + network inet dgram, + network inet stream, + network inet6 dgram, + network inet6 stream, + network netlink raw, + + signal send peer=gitstatusd, + signal send peer=git, + + ptrace read peer=git, + ptrace read peer=child-pager, + + unix type=seqpacket peer=(label=git), + + @{shells_path} mrix, + + # Give glycin higher priority than `@{bin}/bwrap ix` got in the development abs + priority=10 @{bin}/bwrap Px -> :glycin:bwrap, + + # Well known programs used in shells, when we also have specific profiles for + # them and want to allow them, event if they need more/different permissions + # than what is allowed in this profile. + /opt/claude-code/bin/claude Px, + + owner @{config_dirs}/User/globalStorage/**/ r, + + owner @{user_projects_dirs}/ r, + owner @{user_projects_dirs}/** rwkl -> @{user_projects_dirs}/**, + + owner @{user_config_dirs}/git/*config r, + owner @{user_config_dirs}/git/ignore r, + + #aa:lint ignore=too-wide + owner @{tmp}/** rwlk, + + /dev/ptmx rw, + + # file_inherit + priority=-1 deny owner @{user_config_dirs}/Code/** rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/cron/anacron b/apparmor.d/groups/cron/anacron index 57c2ed4b8f..3acfc14fd2 100644 --- a/apparmor.d/groups/cron/anacron +++ b/apparmor.d/groups/cron/anacron @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/anacron +@{exec_path} = @{sbin}/anacron profile anacron @{exec_path} { include include @@ -17,7 +17,7 @@ profile anacron @{exec_path} { @{sh_path} rix, @{bin}/run-parts rCx -> run-parts, - @{bin}/exim4 rPx, + @{sbin}/exim4 rPx, / r, /etc/anacrontab r, @@ -28,6 +28,7 @@ profile anacron @{exec_path} { @{tmp}/file@{rand6} rw, /tmp/anacron-@{rand6} rw, + /tmp/anacron-@{rand6}@{c} rw, profile run-parts { include @@ -39,7 +40,9 @@ profile anacron @{exec_path} { owner @{tmp}/#@{int} rw, owner @{tmp}/file@{rand6} rw, + /tmp/anacron-@{rand6} rw, + /tmp/anacron-@{rand6}@{c} rw, include if exists } diff --git a/apparmor.d/groups/cron/cron b/apparmor.d/groups/cron/cron index 25549a39c8..efc1008c19 100644 --- a/apparmor.d/groups/cron/cron +++ b/apparmor.d/groups/cron/cron @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/cron +@{exec_path} = @{sbin}/cron profile cron @{exec_path} flags=(attach_disconnected) { include include @@ -25,28 +25,19 @@ profile cron @{exec_path} flags=(attach_disconnected) { network netlink raw, - ptrace (read) peer=unconfined, - - unix bind type=stream addr=@@{udbus}/bus/cron/system, - @{exec_path} mr, - @{sh_path} rix, - @{bin}/nice rix, - @{bin}/ionice rix, - @{bin}/exim4 rPx, - @{bin}/run-parts rCx -> run-parts, # could even be rix, as long as we are not - # using the run-parts profile we are good - - @{lib}/@{multiarch}/e2fsprogs/e2scrub_all_cron rPUx, - @{lib}/sysstat/debian-sa1 rPUx, - /usr/share/rsync/scripts/rrsync rPUx, + @{sh_path} rix, + @{sbin}/exim4 rPx, + @{bin}/ionice rix, + @{bin}/nice rix, + @{bin}/run-parts rCx -> run-parts, + @{lib}/sysstat/debian-sa1 rPx, + @{sbin}/sendmail rPUx, /etc/cron.d/{,*} r, /etc/crontab r, /etc/default/locale r, - @{etc_ro}/environment r, - @{etc_ro}/security/limits.d/{,**} r, /var/spool/cron/crontabs/{,*} r, /var/spool/cron/tabs/{,*} r, diff --git a/apparmor.d/groups/cron/cron-anacron b/apparmor.d/groups/cron/cron-anacron index 15d1b97378..91c531618b 100644 --- a/apparmor.d/groups/cron/cron-anacron +++ b/apparmor.d/groups/cron/cron-anacron @@ -12,7 +12,7 @@ profile cron-anacron @{exec_path} { @{exec_path} r, - @{bin}/anacron rPx, + @{sbin}/anacron rPx, @{sh_path} rix, @{bin}/cat rix, @{bin}/date rix, diff --git a/apparmor.d/groups/cron/cron-apt b/apparmor.d/groups/cron/cron-apt index 29294fa537..0d5d5a0818 100644 --- a/apparmor.d/groups/cron/cron-apt +++ b/apparmor.d/groups/cron/cron-apt @@ -46,7 +46,7 @@ profile cron-apt @{exec_path} { @{bin}/apt-get rPx, @{bin}/apt-file rPx, @{bin}/aptitude{,-curses} rPx, - @{bin}/exim4 rPx, + @{sbin}/exim4 rPx, /usr/share/cron-apt/{,*} r, diff --git a/apparmor.d/groups/cron/cron-apt-compat b/apparmor.d/groups/cron/cron-apt-compat index 2aaa6b142b..fcf5e44309 100644 --- a/apparmor.d/groups/cron/cron-apt-compat +++ b/apparmor.d/groups/cron/cron-apt-compat @@ -14,7 +14,7 @@ profile cron-apt-compat @{exec_path} { @{exec_path} r, @{sh_path} rix, - @{bin}/on_ac_power rPx, + @{sbin}/on_ac_power rPx, @{bin}/apt-config rPx, @{lib}/apt/apt.systemd.daily rPx, diff --git a/apparmor.d/groups/cron/cron-apt-xapian-index b/apparmor.d/groups/cron/cron-apt-xapian-index index 2c3f90a9aa..15f93efecc 100644 --- a/apparmor.d/groups/cron/cron-apt-xapian-index +++ b/apparmor.d/groups/cron/cron-apt-xapian-index @@ -14,15 +14,14 @@ profile cron-apt-xapian-index @{exec_path} { @{exec_path} r, @{sh_path} rix, - @{bin}/which{,.debianutils} rix, + @{bin}/which{,.debianutils} rix, @{bin}/{,e}grep rix, - @{bin}/nice rix, @{bin}/ionice rix, @{bin}/ r, @{bin}/update-apt-xapian-index rPx, - @{bin}/on_ac_power rPx, + @{sbin}/on_ac_power rPx, # For shell pwd / r, diff --git a/apparmor.d/groups/cron/cron-aptitude b/apparmor.d/groups/cron/cron-aptitude index 76657dc94d..82b33e8ab6 100644 --- a/apparmor.d/groups/cron/cron-aptitude +++ b/apparmor.d/groups/cron/cron-aptitude @@ -17,7 +17,7 @@ profile cron-aptitude @{exec_path} { @{bin}/cp rix, @{bin}/date rix, @{bin}/basename rix, - @{bin}/which{,.debianutils} rix, + @{bin}/which{,.debianutils} rix, @{bin}/dirname rix, @{bin}/rm rix, @{bin}/mv rix, diff --git a/apparmor.d/groups/cron/cron-cracklib b/apparmor.d/groups/cron/cron-cracklib index ede030682e..9399b6ed46 100644 --- a/apparmor.d/groups/cron/cron-cracklib +++ b/apparmor.d/groups/cron/cron-cracklib @@ -15,7 +15,7 @@ profile cron-cracklib @{exec_path} { @{sh_path} rix, @{bin}/logger rix, - @{bin}/update-cracklib rPx, + @{sbin}/update-cracklib rPx, /etc/cracklib/cracklib.conf r, diff --git a/apparmor.d/groups/cron/cron-debtags b/apparmor.d/groups/cron/cron-debtags index 3e6c182a7a..ea90869487 100644 --- a/apparmor.d/groups/cron/cron-debtags +++ b/apparmor.d/groups/cron/cron-debtags @@ -12,9 +12,9 @@ profile cron-debtags @{exec_path} { include @{exec_path} r, - @{sh_path} rix, - /usr/bin/debtags rPx, + @{sh_path} rix, + @{bin}/debtags rPx, include if exists } diff --git a/apparmor.d/groups/cron/cron-exim4-base b/apparmor.d/groups/cron/cron-exim4-base index 42f2f0823a..1d13585a59 100644 --- a/apparmor.d/groups/cron/cron-exim4-base +++ b/apparmor.d/groups/cron/cron-exim4-base @@ -34,13 +34,13 @@ profile cron-exim4-base @{exec_path} { @{bin}/hostname rix, @{bin}/xargs rix, @{bin}/find rix, - @{bin}/eximstats rix, + @{sbin}/eximstats rix, - @{bin}/exim4 rPx, - @{bin}/exim_tidydb rix, + @{sbin}/exim4 rPx, + @{sbin}/exim_tidydb rix, - @{bin}/start-stop-daemon rix, - @{bin}/runuser rix, + @{sbin}/start-stop-daemon rix, + @{sbin}/runuser rix, /etc/default/exim4 r, @@ -51,8 +51,6 @@ profile cron-exim4-base @{exec_path} { owner @{PROC}/@{pid}/fd/ r, @{PROC}/1/limits r, - @{etc_ro}/security/limits.d/ r, - include if exists } diff --git a/apparmor.d/groups/cron/cron-ipset-autoban-save b/apparmor.d/groups/cron/cron-ipset-autoban-save index 6013684462..8b5891eed1 100644 --- a/apparmor.d/groups/cron/cron-ipset-autoban-save +++ b/apparmor.d/groups/cron/cron-ipset-autoban-save @@ -15,7 +15,7 @@ profile cron-ipset-autoban-save @{exec_path} { @{exec_path} r, @{sh_path} rix, - @{bin}/ipset rix, + @{sbin}/ipset rix, /etc/peerblock/autoban rw, diff --git a/apparmor.d/groups/cron/cron-logrotate b/apparmor.d/groups/cron/cron-logrotate index abe3542f6c..36044b2f34 100644 --- a/apparmor.d/groups/cron/cron-logrotate +++ b/apparmor.d/groups/cron/cron-logrotate @@ -14,7 +14,7 @@ profile cron-logrotate @{exec_path} { @{exec_path} r, @{sh_path} rix, - @{bin}/logrotate rPx, + @{sbin}/logrotate rPx, @{bin}/logger rix, diff --git a/apparmor.d/groups/cron/cron-man-db b/apparmor.d/groups/cron/cron-man-db index 8629f7be23..709f843e80 100644 --- a/apparmor.d/groups/cron/cron-man-db +++ b/apparmor.d/groups/cron/cron-man-db @@ -20,7 +20,7 @@ profile cron-man-db @{exec_path} { @{sh_path} rix, @{bin}/{,e}grep rix, - @{bin}/start-stop-daemon rix, + @{sbin}/start-stop-daemon rix, @{bin}/xargs rix, @{bin}/find rix, diff --git a/apparmor.d/groups/cron/cron-mlocate b/apparmor.d/groups/cron/cron-mlocate index 852e85141b..f91956bcd0 100644 --- a/apparmor.d/groups/cron/cron-mlocate +++ b/apparmor.d/groups/cron/cron-mlocate @@ -15,7 +15,7 @@ profile cron-mlocate @{exec_path} { @{exec_path} r, @{sh_path} rix, - @{bin}/which{,.debianutils} rix, + @{bin}/which{,.debianutils} rix, @{bin}/true rix, @{bin}/flock rix, @{bin}/nocache rix, @@ -23,7 +23,7 @@ profile cron-mlocate @{exec_path} { @{bin}/nice rix, @{bin}/updatedb.mlocate rPx, - @{bin}/on_ac_power rPx, + @{sbin}/on_ac_power rPx, @{run}/mlocate.daily.lock rwk, diff --git a/apparmor.d/groups/cron/cron-ntp b/apparmor.d/groups/cron/cron-ntp index 17ab7f7457..7221cc6e1b 100644 --- a/apparmor.d/groups/cron/cron-ntp +++ b/apparmor.d/groups/cron/cron-ntp @@ -14,7 +14,7 @@ profile cron-ntp @{exec_path} { @{sh_path} rix, @{bin}/cat rix, - @{bin}/grep rix, + @{bin}/{,e}grep rix, @{bin}/sed rix, include if exists diff --git a/apparmor.d/groups/cron/cron-plocate b/apparmor.d/groups/cron/cron-plocate index 7080658c3f..7f52d1a14a 100644 --- a/apparmor.d/groups/cron/cron-plocate +++ b/apparmor.d/groups/cron/cron-plocate @@ -15,7 +15,7 @@ profile cron-plocate @{exec_path} { @{exec_path} r, @{sh_path} rix, - @{bin}/which{,.debianutils} rix, + @{bin}/which{,.debianutils} rix, @{bin}/true rix, @{bin}/flock rix, @{bin}/nocache rix, @@ -23,7 +23,7 @@ profile cron-plocate @{exec_path} { @{bin}/nice rix, @{bin}/updatedb.plocate rPx, - @{bin}/on_ac_power rPx, + @{sbin}/on_ac_power rPx, @{run}/plocate.daily.lock rwk, diff --git a/apparmor.d/groups/cron/cron-popularity-contest b/apparmor.d/groups/cron/cron-popularity-contest index 21455fb7d3..9434489578 100644 --- a/apparmor.d/groups/cron/cron-popularity-contest +++ b/apparmor.d/groups/cron/cron-popularity-contest @@ -18,7 +18,7 @@ profile cron-popularity-contest @{exec_path} { @{bin}/cat rix, @{bin}/date rix, - @{bin}/grep rix, + @{bin}/{,e}grep rix, @{bin}/logger rix, @{bin}/mkdir rix, @{bin}/mktemp rix, @@ -29,11 +29,11 @@ profile cron-popularity-contest @{exec_path} { # To send reports via TOR @{bin}/torify rix, @{bin}/torsocks rix, - @{bin}/getcap rix, + @{sbin}/getcap rix, /usr/share/popularity-contest/popcon-upload rCx -> popcon-upload, @{bin}/gpg{,2} rCx -> gpg, - @{bin}/runuser rCx -> runuser, + @{sbin}/runuser rCx -> runuser, @{bin}/savelog rCx -> savelog, /usr/share/popularity-contest/ r, @@ -74,7 +74,7 @@ profile cron-popularity-contest @{exec_path} { @{bin}/mv rix, @{bin}/rm rix, @{bin}/touch rix, - @{bin}/which{,.debianutils} rix, + @{bin}/which{,.debianutils} rix, @{sh_path} rix, /var/log/ r, @@ -93,13 +93,11 @@ profile cron-popularity-contest @{exec_path} { include include - @{bin}/runuser mr, + @{sbin}/runuser mr, @{sh_path} rix, @{bin}/popularity-contest rPx, - @{etc_ro}/security/limits.d/ r, - /var/log/popularity-contest.new w, @{PROC}/1/limits r, diff --git a/apparmor.d/groups/cron/crontab b/apparmor.d/groups/cron/crontab index d240454f5b..7b04be54ca 100644 --- a/apparmor.d/groups/cron/crontab +++ b/apparmor.d/groups/cron/crontab @@ -16,7 +16,9 @@ profile crontab @{exec_path} { capability audit_write, capability chown, + capability dac_override, capability dac_read_search, + capability fsetid, capability net_admin, capability setgid, capability setuid, @@ -28,8 +30,10 @@ profile crontab @{exec_path} { @{sh_path} rix, @{editor_path} rCx -> editor, + @{lib}/systemd-cron/crontab_setgid PUx, + @{lib}/systemd/system-generators/systemd-crontab-generator PUx, + @{etc_ro}/environment r, - @{etc_ro}/security/*.conf r, /etc/cron.{allow,deny} r, /etc/pam.d/* r, @@ -38,6 +42,9 @@ profile crontab @{exec_path} { owner @{user_cache_dirs}/crontab/crontab.bak rw, + @{run}/crond.reboot w, + + @{tmp}/#@{int} rw, @{tmp}/crontab.@{rand6} rw, @{tmp}/crontab.@{rand6}/ rw, @{tmp}/crontab.@{rand6}/crontab rwl, diff --git a/apparmor.d/groups/cups/cups-backend-beh b/apparmor.d/groups/cups/cups-backend-beh index e2dbc1b51a..1e9fe5b781 100644 --- a/apparmor.d/groups/cups/cups-backend-beh +++ b/apparmor.d/groups/cups/cups-backend-beh @@ -13,6 +13,7 @@ profile cups-backend-beh @{exec_path} { @{exec_path} mr, /etc/papersize r, + /etc/paperspecs r, include if exists } diff --git a/apparmor.d/groups/cups/cups-backend-bluetooth b/apparmor.d/groups/cups/cups-backend-bluetooth index ada4926ce6..fff48e91a3 100644 --- a/apparmor.d/groups/cups/cups-backend-bluetooth +++ b/apparmor.d/groups/cups/cups-backend-bluetooth @@ -9,10 +9,17 @@ include @{exec_path} = @{lib}/cups/backend/bluetooth profile cups-backend-bluetooth @{exec_path} { include + include + + dbus send bus=system path=/ + interface=org.bluez.Manager + member=DefaultAdapter + peer=(name=org.bluez, label=bluetoothd), @{exec_path} mr, /etc/papersize r, + /etc/paperspecs r, include if exists } diff --git a/apparmor.d/groups/cups/cups-backend-brf b/apparmor.d/groups/cups/cups-backend-brf index 27e98efc31..6d50b284f4 100644 --- a/apparmor.d/groups/cups/cups-backend-brf +++ b/apparmor.d/groups/cups/cups-backend-brf @@ -15,6 +15,7 @@ profile cups-backend-brf @{exec_path} { @{exec_path} mr, /etc/papersize r, + /etc/paperspecs r, include if exists } diff --git a/apparmor.d/groups/cups/cups-backend-dnssd b/apparmor.d/groups/cups/cups-backend-dnssd index f45b99216b..b508388fe4 100644 --- a/apparmor.d/groups/cups/cups-backend-dnssd +++ b/apparmor.d/groups/cups/cups-backend-dnssd @@ -9,11 +9,13 @@ include @{exec_path} = @{lib}/cups/backend/dnssd profile cups-backend-dnssd @{exec_path} { include - include + include + include @{exec_path} mr, /etc/papersize r, + /etc/paperspecs r, include if exists } diff --git a/apparmor.d/groups/cups/cups-backend-hp b/apparmor.d/groups/cups/cups-backend-hp index 6361215534..86083b31d7 100644 --- a/apparmor.d/groups/cups/cups-backend-hp +++ b/apparmor.d/groups/cups/cups-backend-hp @@ -9,10 +9,22 @@ include @{exec_path} = @{lib}/cups/backend/hp{,fax} profile cups-backend-hp @{exec_path} { include + include + include + include + + network netlink raw, @{exec_path} mr, + /usr/share/hplip/{,**} r, + /etc/papersize r, + /etc/paperspecs r, + /etc/hp/** r, + + owner /var/spool/cups/tmp/.hplip/ w, + owner /var/spool/cups/tmp/.hplip/hplip.conf rw, include if exists } diff --git a/apparmor.d/groups/cups/cups-backend-implicitclass b/apparmor.d/groups/cups/cups-backend-implicitclass index ba85c62fae..28d0128335 100644 --- a/apparmor.d/groups/cups/cups-backend-implicitclass +++ b/apparmor.d/groups/cups/cups-backend-implicitclass @@ -9,10 +9,32 @@ include @{exec_path} = @{lib}/cups/backend/implicitclass profile cups-backend-implicitclass @{exec_path} { include + include + include + include + + network inet dgram, + network inet6 dgram, + network inet stream, + network inet6 stream, + + # TODO: + # network (receive,send,setopt) inet dgram peer=(port=53), + # network (receive,send,setopt) inet stream peer=(port=631), + + signal receive set=term peer=cupsd, + signal send set=term peer=cups-backend-ipp, + + unix type=stream peer=(label=cups-backend-ipp), + unix type=stream peer=(label=cupsd), @{exec_path} mr, + @{bin}/ippfind Px, + @{lib}/cups/backend/ipp Px, + /etc/papersize r, + /etc/paperspecs r, include if exists } diff --git a/apparmor.d/groups/cups/cups-backend-ipp b/apparmor.d/groups/cups/cups-backend-ipp index b473ecaa34..05eeb35f03 100644 --- a/apparmor.d/groups/cups/cups-backend-ipp +++ b/apparmor.d/groups/cups/cups-backend-ipp @@ -9,10 +9,32 @@ include @{exec_path} = @{lib}/cups/backend/ipp profile cups-backend-ipp @{exec_path} { include + include + include + include + include + + network inet dgram, + network inet6 dgram, + network inet stream, + network inet6 stream, + + # TODO: + # network (receive,send,setopt) inet dgram peer=(port=53), + # network (receive,send,setopt) inet stream peer=(port=631), + + signal receive set=term peer=cups-backend-implicitclass, + signal receive set=term peer=cupsd, + + unix type=stream peer=(label=cups-backend-implicitclass), @{exec_path} mr, + /etc/cups/ppd/*.ppd r, + /etc/cups/snmp.conf r, + /etc/cups/ssl/* r, /etc/papersize r, + /etc/paperspecs r, include if exists } diff --git a/apparmor.d/groups/cups/cups-backend-lpd b/apparmor.d/groups/cups/cups-backend-lpd index af2901be08..89b62b5692 100644 --- a/apparmor.d/groups/cups/cups-backend-lpd +++ b/apparmor.d/groups/cups/cups-backend-lpd @@ -13,6 +13,7 @@ profile cups-backend-lpd @{exec_path} { @{exec_path} mr, /etc/papersize r, + /etc/paperspecs r, include if exists } diff --git a/apparmor.d/groups/cups/cups-backend-mdns b/apparmor.d/groups/cups/cups-backend-mdns index 0b9cce0dac..9e5dfbe0f9 100644 --- a/apparmor.d/groups/cups/cups-backend-mdns +++ b/apparmor.d/groups/cups/cups-backend-mdns @@ -13,6 +13,7 @@ profile cups-backend-mdns @{exec_path} { @{exec_path} mr, /etc/papersize r, + /etc/paperspecs r, include if exists } diff --git a/apparmor.d/groups/cups/cups-backend-parallel b/apparmor.d/groups/cups/cups-backend-parallel index a985e50427..b4340b2ed6 100644 --- a/apparmor.d/groups/cups/cups-backend-parallel +++ b/apparmor.d/groups/cups/cups-backend-parallel @@ -13,6 +13,7 @@ profile cups-backend-parallel @{exec_path} { @{exec_path} mr, /etc/papersize r, + /etc/paperspecs r, include if exists } diff --git a/apparmor.d/groups/cups/cups-backend-pdf b/apparmor.d/groups/cups/cups-backend-pdf index 7782ecb111..e8f9571966 100644 --- a/apparmor.d/groups/cups/cups-backend-pdf +++ b/apparmor.d/groups/cups/cups-backend-pdf @@ -14,9 +14,10 @@ profile cups-backend-pdf @{exec_path} { include capability chown, + capability dac_override, + capability dac_read_search, capability setgid, capability setuid, - capability dac_override, unix peer=(label=cupsd), @@ -24,16 +25,16 @@ profile cups-backend-pdf @{exec_path} { @{sh_path} rix, @{bin}/cp rix, - @{bin}/gs rix, + @{bin}/gs{,.bin} rCx -> gs, @{bin}/gsc rix, - @{lib}/ghostscript/** mr, /usr/share/ghostscript/{,**} r, - /etc/papersize r, /etc/cups/ r, /etc/cups/cups-pdf.conf r, /etc/cups/ppd/*.ppd r, + /etc/papersize r, + /etc/paperspecs r, /var/log/cups/cups-pdf*_log w, /var/spool/cups-pdf/{,**} rw, @@ -42,6 +43,20 @@ profile cups-backend-pdf @{exec_path} { /dev/tty rw, + profile gs { + include + + @{bin}/gs{,.bin} mr, + @{lib}/ghostscript/** mr, + + /usr/share/ghostscript/{,**} r, + /usr/share/color/icc/ghostscript/{,**} r, + + owner /tmp/gs_@{rand6} rw, + + include if exists + } + include if exists } diff --git a/apparmor.d/groups/cups/cups-backend-serial b/apparmor.d/groups/cups/cups-backend-serial index 3959a091d3..26811ab59f 100644 --- a/apparmor.d/groups/cups/cups-backend-serial +++ b/apparmor.d/groups/cups/cups-backend-serial @@ -13,6 +13,7 @@ profile cups-backend-serial @{exec_path} { @{exec_path} mr, /etc/papersize r, + /etc/paperspecs r, /dev/ttyS@{int} w, diff --git a/apparmor.d/groups/cups/cups-backend-snmp b/apparmor.d/groups/cups/cups-backend-snmp index 5badd529ac..816f6c25bb 100644 --- a/apparmor.d/groups/cups/cups-backend-snmp +++ b/apparmor.d/groups/cups/cups-backend-snmp @@ -19,6 +19,7 @@ profile cups-backend-snmp @{exec_path} { /etc/cups/snmp.conf r, /etc/papersize r, + /etc/paperspecs r, include if exists } diff --git a/apparmor.d/groups/cups/cups-backend-socket b/apparmor.d/groups/cups/cups-backend-socket index 3efcf183bc..f8f36a0563 100644 --- a/apparmor.d/groups/cups/cups-backend-socket +++ b/apparmor.d/groups/cups/cups-backend-socket @@ -13,6 +13,7 @@ profile cups-backend-socket @{exec_path} { @{exec_path} mr, /etc/papersize r, + /etc/paperspecs r, include if exists } diff --git a/apparmor.d/groups/cups/cups-backend-usb b/apparmor.d/groups/cups/cups-backend-usb index fa21e02044..e15475393c 100644 --- a/apparmor.d/groups/cups/cups-backend-usb +++ b/apparmor.d/groups/cups/cups-backend-usb @@ -12,6 +12,7 @@ profile cups-backend-usb @{exec_path} { include capability net_admin, + capability sys_admin, network netlink raw, @@ -21,6 +22,7 @@ profile cups-backend-usb @{exec_path} { /etc/cups/ppd/*.ppd r, /etc/papersize r, + /etc/paperspecs r, include if exists } diff --git a/apparmor.d/groups/cups/cups-browsed b/apparmor.d/groups/cups/cups-browsed index 41d22ed9bd..976ffa6cb7 100644 --- a/apparmor.d/groups/cups/cups-browsed +++ b/apparmor.d/groups/cups/cups-browsed @@ -6,19 +6,22 @@ abi , include -@{exec_path} = @{bin}/cups-browsed -profile cups-browsed @{exec_path} { +@{exec_path} = @{sbin}/cups-browsed +profile cups-browsed @{exec_path} flags=(attach_disconnected) { include + include include - include - include + include + include + include + include include include + include include capability net_admin, capability net_bind_service, - capability sys_nice, network inet dgram, network inet6 dgram, @@ -26,25 +29,28 @@ profile cups-browsed @{exec_path} { network inet6 stream, network netlink raw, - dbus receive bus=system path=/ - interface=org.freedesktop.Avahi.Server - member=StateChanged - peer=(name=:*, label=avahi-daemon), + #aa:dbus talk bus=system name=org.cups.cupsd.Notifier label=cups-notifier-dbus dbus receive bus=system path=/org/freedesktop/NetworkManager interface=org.freedesktop.NetworkManager member=CheckPermissions - peer=(name=:*, label=NetworkManager), + peer=(name=@{busname}, label=NetworkManager), @{exec_path} mr, + @{bin}/ippfind rPx, + /usr/share/cups/locale/{,**} r, /etc/cups/{,**} r, - /var/cache/cups/{,**} rw, /var/log/cups/{,**} rw, + /var/cache/cups/{,**} rw, + owner /var/cache/cups-browsed/{,**} rw, + + owner @{tmp}/@{hex} rw, + @{run}/cups/certs/* r, @{PROC}/sys/net/ipv6/conf/all/disable_ipv6 r, diff --git a/apparmor.d/groups/cups/cups-notifier-dbus b/apparmor.d/groups/cups/cups-notifier-dbus index 6e3b384905..4755c61ed0 100644 --- a/apparmor.d/groups/cups/cups-notifier-dbus +++ b/apparmor.d/groups/cups/cups-notifier-dbus @@ -7,7 +7,7 @@ abi , include @{exec_path} = @{lib}/cups/notifier/dbus -profile cups-notifier-dbus @{exec_path} { +profile cups-notifier-dbus @{exec_path} flags=(attach_disconnected) { include include include @@ -16,6 +16,8 @@ profile cups-notifier-dbus @{exec_path} { signal (receive) set=(term) peer=cupsd, + #aa:dbus own bus=system name=org.cups.cupsd.Notifier + @{exec_path} mr, owner /var/spool/cups/tmp/cups-dbus-notifier-lockfile rw, diff --git a/apparmor.d/groups/cups/cups-pk-helper-mechanism b/apparmor.d/groups/cups/cups-pk-helper-mechanism index 89d55c2f1d..d8ad4a67e0 100644 --- a/apparmor.d/groups/cups/cups-pk-helper-mechanism +++ b/apparmor.d/groups/cups/cups-pk-helper-mechanism @@ -11,7 +11,7 @@ include profile cups-pk-helper-mechanism @{exec_path} { include include - include + include include capability dac_read_search, @@ -22,11 +22,16 @@ profile cups-pk-helper-mechanism @{exec_path} { #aa:dbus own bus=system name=org.opensuse.CupsPkHelper.Mechanism path=/ + dbus send bus=system path=/org/freedesktop/DBus + interface=org.freedesktop.DBus.Properties + member=GetAll + peer=(name=org.freedesktop.DBus, label=dbus-system//&unconfined), + @{exec_path} mr, /etc/cups/ppd/*.ppd r, - owner @{tmp}/[a-z0-9]* rw, + owner @{tmp}/@{int} rw, @{run}/cups/cups.sock rw, diff --git a/apparmor.d/groups/cups/cupsd b/apparmor.d/groups/cups/cupsd index 697a307f9e..529ac8c17a 100644 --- a/apparmor.d/groups/cups/cupsd +++ b/apparmor.d/groups/cups/cupsd @@ -6,13 +6,15 @@ abi , include -@{exec_path} = @{bin}/cupsd +@{exec_path} = @{sbin}/cupsd profile cupsd @{exec_path} flags=(attach_disconnected) { include include + include include - include - include + include + include + include include include @@ -29,7 +31,9 @@ profile cupsd @{exec_path} flags=(attach_disconnected) { capability setuid, capability wake_alarm, + network inet dgram, network inet stream, + network inet6 dgram, network inet6 stream, network appletalk dgram, @@ -42,19 +46,24 @@ profile cupsd @{exec_path} flags=(attach_disconnected) { network rose dgram, network x25 seqpacket, - signal (send) set=(term) peer=cups-notifier-dbus, + signal send set=term peer=cups-backend-*, + signal send set=term peer=cups-notifier-dbus, + + unix type=stream peer=(label=cups-backend-*), + unix type=stream peer=(label=ippfind), @{exec_path} mr, @{sh_path} rix, @{bin}/cat rix, + @{bin}/echo ix, @{bin}/chmod rix, @{bin}/cp rix, - @{bin}/grep rix, - @{bin}/gs rix, + @{bin}/{,e}grep rix, + @{bin}/gs{,.bin} rCx -> gs, @{bin}/gsc rix, @{bin}/hostname rix, - @{bin}/ippfind rix, + @{bin}/ippfind rPx, @{bin}/mktemp rix, @{bin}/printenv rix, @{python_path} rix, @@ -71,8 +80,9 @@ profile cupsd @{exec_path} flags=(attach_disconnected) { @{lib}/cups/monitor/* rix, @{lib}/cups/notifier/* rPx, + /usr/share/brother/Printers/*/cupswrapper/lpdwrapper rPUx, + /usr/share/cups/{,**} r, - /usr/share/ghostscript/{,**} r, /usr/share/poppler/{,**} r, /usr/share/ppd/{,**} r, @@ -89,7 +99,6 @@ profile cupsd @{exec_path} flags=(attach_disconnected) { /var/spool/cups/{,**} rw, @{run}/cups/{,**} rw, - @{run}/systemd/notify w, @{sys}/module/apparmor/parameters/enabled r, @@ -100,6 +109,26 @@ profile cupsd @{exec_path} flags=(attach_disconnected) { /dev/tty rw, + profile gs { + include + include + + @{bin}/gs{,.bin} mr, + + /usr/share/ghostscript/{,**} r, + /usr/share/color/icc/ghostscript/{,**} r, + + /etc/papersize r, + /etc/paperspecs r, + + /var/lib/ghostscript/{,**} r, + owner /var/spool/cups/tmp/gs_@{rand6} rw, + + owner /tmp/gs_@{rand6} rw, + + include if exists + } + include if exists } diff --git a/apparmor.d/groups/cups/ippfind b/apparmor.d/groups/cups/ippfind new file mode 100644 index 0000000000..1ad6e870ea --- /dev/null +++ b/apparmor.d/groups/cups/ippfind @@ -0,0 +1,26 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/ippfind +profile ippfind @{exec_path} flags=(attach_disconnected) { + include + include + include + include + include + + unix type=stream peer=(label=cupsd), + + @{exec_path} mr, + + @{bin}/echo rix, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/cups/print-backends-cups b/apparmor.d/groups/cups/print-backends-cups new file mode 100644 index 0000000000..fe61e7b06e --- /dev/null +++ b/apparmor.d/groups/cups/print-backends-cups @@ -0,0 +1,43 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/@{multiarch}/print-backends/cups +profile print-backends-cups @{exec_path} { + include + include + include + include + include + include + include + + network inet stream, + network inet6 stream, + + #aa:dbus own bus=session name=org.openprinting.Backend.CUPS + #aa:dbus own bus=session name=org.openprinting.PrintBackend path=/{,**} + + @{exec_path} mr, + + @{sh_path} rix, + @{bin}/mkdir ix, + + /usr/share/cups/locale/{,**} r, + + /home/ r, + owner @{HOME}/ r, + owner @{HOME}/cpdb/ rw, + owner @{HOME}/cpdb/sockets/ rw, + owner @{HOME}/cpdb/sockets/cups-@{int}.sock rw, + + owner /tmp/@{rand} rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/display-manager/lightdm b/apparmor.d/groups/display-manager/lightdm index e0e0bd794d..b526017198 100644 --- a/apparmor.d/groups/display-manager/lightdm +++ b/apparmor.d/groups/display-manager/lightdm @@ -10,7 +10,6 @@ include @{exec_path} = @{bin}/lightdm profile lightdm @{exec_path} flags=(attach_disconnected) { include - include include include include @@ -63,8 +62,6 @@ profile lightdm @{exec_path} flags=(attach_disconnected) { /usr/share/wayland-sessions/{,*.desktop} r, /usr/share/xgreeters/{,**} r, - @{etc_ro}/environment r, - @{etc_ro}/security/limits.d/{,*} r, /etc/default/locale r, /etc/lightdm/{,**} r, /etc/machine-id r, @@ -90,7 +87,7 @@ profile lightdm @{exec_path} flags=(attach_disconnected) { owner @{PROC}/@{pid}/uid_map r, owner @{PROC}/@{pid}/mountinfo r, - /dev/tty@{int} r, + /dev/tty@{u8} r, include if exists } diff --git a/apparmor.d/groups/display-manager/x11-xsession b/apparmor.d/groups/display-manager/x11-xsession index 4455316910..361a30b268 100644 --- a/apparmor.d/groups/display-manager/x11-xsession +++ b/apparmor.d/groups/display-manager/x11-xsession @@ -34,7 +34,7 @@ profile x11-xsession @{exec_path} { @{bin}/tail rix, @{bin}/tempfile rix, @{bin}/touch rix, - @{bin}/which{,.debianutils} rix, + @{bin}/which{,.debianutils} rix, @{bin}/dbus-update-activation-environment rCx -> dbus, diff --git a/apparmor.d/groups/display-manager/xdm-xsession b/apparmor.d/groups/display-manager/xdm-xsession index cfdaeed3f7..2d220d0a43 100644 --- a/apparmor.d/groups/display-manager/xdm-xsession +++ b/apparmor.d/groups/display-manager/xdm-xsession @@ -10,6 +10,7 @@ include profile xdm-xsession @{exec_path} { include include + include include include include @@ -20,12 +21,12 @@ profile xdm-xsession @{exec_path} { @{bin}/basename rix, @{bin}/cat rix, - @{bin}/checkproc rix, + @{sbin}/checkproc rix, @{bin}/dirname rix, @{bin}/fortune rPUx, @{bin}/gpg-agent rPx, @{bin}/gpg-connect-agent rPx, - @{bin}/grep rix, + @{bin}/{,e}grep rix, @{bin}/locale rix, @{bin}/manpath rix, @{bin}/readlink rix, @@ -55,10 +56,12 @@ profile xdm-xsession @{exec_path} { @{etc_ro}/X11/xdm/sys.xsession rix, @{etc_ro}/X11/xinit/xinitrc.d/50-systemd-user.sh rix, @{etc_ro}/X11/xinit/xinitrc.d/xdg-user-dirs.sh rix, - @{HOME}/.xinitrc rPix, # TODO: rCx @{lib}/xinit/xinitrc rix, - /usr/share/glib-2.0/schemas/gschemas.compiled r, + #aa:lint ignore=transition + # FIXME: Pix is a bad idea here, it **will** lead to breakage. + @{HOME}/.xinitrc rPix, + /usr/share/mc/mc.sh r, /usr/share/terminfo/{,**} r, @@ -90,7 +93,7 @@ profile xdm-xsession @{exec_path} { owner @{PROC}/@{pid}/fd/ r, /dev/tty rw, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, profile dbus { include diff --git a/apparmor.d/groups/filesystem/btrfs b/apparmor.d/groups/filesystem/btrfs index 82742fd4a7..51b9dbd197 100644 --- a/apparmor.d/groups/filesystem/btrfs +++ b/apparmor.d/groups/filesystem/btrfs @@ -25,14 +25,17 @@ profile btrfs @{exec_path} flags=(attach_disconnected) { / r, /.snapshots/ r, - /boot/ r, - /boot/**/ r, + @{efi}/ r, + @{efi}/**/ r, /home/ r, /opt/ r, /root/ r, /srv/ r, /usr/local/ r, /var/ r, + /var/log/ r, + /var/tmp/ r, + /var/cache/ r, @{MOUNTS}/ r, @{MOUNTS}/ext2_saved/ rw, @{MOUNTS}/ext2_saved/image rw, @@ -50,6 +53,7 @@ profile btrfs @{exec_path} flags=(attach_disconnected) { @{run}/blkid/blkid.tab.old rwl -> @{run}/blkid/blkid.tab, @{run}/snapper-tools-*/ r, @{run}/snapper-tools-@{rand6}/@/.snapshots/@{int}/snapshot r, + @{run}/BtrfsAssistant/@{uuid}/ r, @{sys}/fs/btrfs/@{uuid}/** r, @@ -57,8 +61,8 @@ profile btrfs @{exec_path} flags=(attach_disconnected) { owner @{PROC}/@{pid}/mounts r, /dev/btrfs-control rw, - /dev/pts/@{int} rw, - /dev/tty@{int} rw, + /dev/pts/@{u16} rw, + /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/filesystem/btrfs-convert b/apparmor.d/groups/filesystem/btrfs-convert index 2dccbf1fd2..22715c8576 100644 --- a/apparmor.d/groups/filesystem/btrfs-convert +++ b/apparmor.d/groups/filesystem/btrfs-convert @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/btrfs-convert +@{exec_path} = @{sbin}/btrfs-convert profile btrfs-convert @{exec_path} { include include diff --git a/apparmor.d/groups/filesystem/btrfs-find-root b/apparmor.d/groups/filesystem/btrfs-find-root index eef4b68236..cec2bbb619 100644 --- a/apparmor.d/groups/filesystem/btrfs-find-root +++ b/apparmor.d/groups/filesystem/btrfs-find-root @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/btrfs-find-root +@{exec_path} = @{sbin}/btrfs-find-root profile btrfs-find-root @{exec_path} { include include diff --git a/apparmor.d/groups/filesystem/btrfs-image b/apparmor.d/groups/filesystem/btrfs-image index 6f18ac0959..48be7c3815 100644 --- a/apparmor.d/groups/filesystem/btrfs-image +++ b/apparmor.d/groups/filesystem/btrfs-image @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/btrfs-image +@{exec_path} = @{sbin}/btrfs-image profile btrfs-image @{exec_path} { include include diff --git a/apparmor.d/groups/filesystem/btrfstune b/apparmor.d/groups/filesystem/btrfstune index f8fa4a0476..24a8ef46e2 100644 --- a/apparmor.d/groups/filesystem/btrfstune +++ b/apparmor.d/groups/filesystem/btrfstune @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/btrfstune +@{exec_path} = @{sbin}/btrfstune profile btrfstune @{exec_path} { include include diff --git a/apparmor.d/groups/filesystem/fsck.btrfs b/apparmor.d/groups/filesystem/fsck.btrfs index f8ac9419d6..52109e7bc2 100644 --- a/apparmor.d/groups/filesystem/fsck.btrfs +++ b/apparmor.d/groups/filesystem/fsck.btrfs @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/fsck.btrfs +@{exec_path} = @{sbin}/fsck.btrfs profile fsck.btrfs @{exec_path} { include @@ -16,6 +16,10 @@ profile fsck.btrfs @{exec_path} { @{sh_path} rix, /etc/fstab r, + /etc/nsswitch.conf r, + /etc/passwd r, + + /dev/tty rw, include if exists } diff --git a/apparmor.d/groups/filesystem/fsck.fat b/apparmor.d/groups/filesystem/fsck.fat index fd944532fc..0e7df947d7 100644 --- a/apparmor.d/groups/filesystem/fsck.fat +++ b/apparmor.d/groups/filesystem/fsck.fat @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/fsck.fat @{bin}/fsck.msdos @{bin}/fsck.vfat @{bin}/dosfsck +@{exec_path} = @{sbin}/fsck.fat @{sbin}/fsck.msdos @{sbin}/fsck.vfat @{sbin}/dosfsck profile fsck.fat @{exec_path} { include include diff --git a/apparmor.d/groups/filesystem/lvm b/apparmor.d/groups/filesystem/lvm index 4fb66d92c6..ad4645bff0 100644 --- a/apparmor.d/groups/filesystem/lvm +++ b/apparmor.d/groups/filesystem/lvm @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/lvm +@{exec_path} = @{sbin}/lvm profile lvm @{exec_path} flags=(attach_disconnected) { include include diff --git a/apparmor.d/groups/filesystem/lvmconfig b/apparmor.d/groups/filesystem/lvmconfig index 5e5a0d1dda..39224c22f0 100644 --- a/apparmor.d/groups/filesystem/lvmconfig +++ b/apparmor.d/groups/filesystem/lvmconfig @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/lvmconfig +@{exec_path} = @{sbin}/lvmconfig profile lvmconfig @{exec_path} { include include diff --git a/apparmor.d/groups/filesystem/lvmdump b/apparmor.d/groups/filesystem/lvmdump index 6a443fc570..5e90ffeee3 100644 --- a/apparmor.d/groups/filesystem/lvmdump +++ b/apparmor.d/groups/filesystem/lvmdump @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/lvmdump +@{exec_path} = @{sbin}/lvmdump profile lvmdump @{exec_path} { include include diff --git a/apparmor.d/groups/filesystem/lvmpolld b/apparmor.d/groups/filesystem/lvmpolld index fdc3bad3f1..cce01b0d03 100644 --- a/apparmor.d/groups/filesystem/lvmpolld +++ b/apparmor.d/groups/filesystem/lvmpolld @@ -6,14 +6,14 @@ abi , include -@{exec_path} = @{bin}/lvmpolld +@{exec_path} = @{sbin}/lvmpolld profile lvmpolld @{exec_path} { include include include @{exec_path} rm, - @{bin}/grep rix, + @{bin}/{,e}grep rix, @{bin}/umount rPx, @{run}/lvmpolld.pid rwk, diff --git a/apparmor.d/groups/filesystem/mke2fs b/apparmor.d/groups/filesystem/mke2fs index 56a223bddf..90df8ecb1b 100644 --- a/apparmor.d/groups/filesystem/mke2fs +++ b/apparmor.d/groups/filesystem/mke2fs @@ -7,9 +7,10 @@ abi , include -@{exec_path} = @{bin}/mke2fs @{bin}/mkfs.ext2 @{bin}/mkfs.ext3 @{bin}/mkfs.ext4 +@{exec_path} = @{sbin}/mke2fs @{sbin}/mkfs.ext2 @{sbin}/mkfs.ext3 @{sbin}/mkfs.ext4 profile mke2fs @{exec_path} { include + include include include @@ -19,7 +20,7 @@ profile mke2fs @{exec_path} { # To check for badblocks @{sh_path} rix, - @{bin}/badblocks rPx, + @{sbin}/badblocks rPx, /usr/share/file/misc/magic.mgc r, diff --git a/apparmor.d/groups/filesystem/mkfs-btrfs b/apparmor.d/groups/filesystem/mkfs-btrfs index 1e6c958385..fc619228b5 100644 --- a/apparmor.d/groups/filesystem/mkfs-btrfs +++ b/apparmor.d/groups/filesystem/mkfs-btrfs @@ -7,12 +7,13 @@ abi , include -@{exec_path} = @{bin}/mkfs.btrfs +@{exec_path} = @{sbin}/mkfs.btrfs profile mkfs-btrfs @{exec_path} { include include capability sys_admin, + capability sys_rawio, @{exec_path} mr, diff --git a/apparmor.d/groups/filesystem/mkswap b/apparmor.d/groups/filesystem/mkswap index 4a818cd58c..92d0624013 100644 --- a/apparmor.d/groups/filesystem/mkswap +++ b/apparmor.d/groups/filesystem/mkswap @@ -7,9 +7,10 @@ abi , include -@{exec_path} = @{bin}/mkswap +@{exec_path} = @{sbin}/mkswap profile mkswap @{exec_path} { include + include include capability mknod, @@ -18,6 +19,7 @@ profile mkswap @{exec_path} { owner /swapfile rw, owner /swap/swapfile rw, + owner /var/swapfile rw, @{PROC}/swaps r, owner @{PROC}/@{pid}/mounts r, diff --git a/apparmor.d/groups/filesystem/mount b/apparmor.d/groups/filesystem/mount index f8616cd88a..a6f3a1ab38 100644 --- a/apparmor.d/groups/filesystem/mount +++ b/apparmor.d/groups/filesystem/mount @@ -37,6 +37,7 @@ profile mount @{exec_path} flags=(attach_disconnected) { @{bin}/mount.* rPx, @{bin}/ntfs-3g rPx, @{bin}/sshfs rPx, + @{sbin}/mount.* rPx, /etc/fstab r, diff --git a/apparmor.d/groups/filesystem/mount-cifs b/apparmor.d/groups/filesystem/mount-cifs index cf1ceefb35..a6c8d01e30 100644 --- a/apparmor.d/groups/filesystem/mount-cifs +++ b/apparmor.d/groups/filesystem/mount-cifs @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/mount.cifs +@{exec_path} = @{sbin}/mount.cifs profile mount-cifs @{exec_path} flags=(complain) { include include diff --git a/apparmor.d/groups/filesystem/mount-nfs b/apparmor.d/groups/filesystem/mount-nfs index 26f3e2d570..f670b62d78 100644 --- a/apparmor.d/groups/filesystem/mount-nfs +++ b/apparmor.d/groups/filesystem/mount-nfs @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/mount.nfs +@{exec_path} = @{sbin}/mount.nfs profile mount-nfs @{exec_path} flags=(complain) { include include @@ -42,7 +42,7 @@ profile mount-nfs @{exec_path} flags=(complain) { @{sh_path} rix, @{bin}/flock rix, - @{bin}/start-statd rix, + @{sbin}/start-statd rix, @{bin}/systemctl rCx -> systemctl, /etc/fstab r, diff --git a/apparmor.d/groups/filesystem/mount-zfs b/apparmor.d/groups/filesystem/mount-zfs index 552f96b056..8c1848a791 100644 --- a/apparmor.d/groups/filesystem/mount-zfs +++ b/apparmor.d/groups/filesystem/mount-zfs @@ -16,7 +16,7 @@ profile mount-zfs @{exec_path} flags=(complain) { @{exec_path} mr, - /dev/pts/@{int} rw, + /dev/pts/@{u16} rw, @{MOUNTDIRS}/ r, @{MOUNTS}/ r, diff --git a/apparmor.d/groups/filesystem/nfsdcld b/apparmor.d/groups/filesystem/nfsdcld index be122a3cb3..297ee16839 100644 --- a/apparmor.d/groups/filesystem/nfsdcld +++ b/apparmor.d/groups/filesystem/nfsdcld @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/nfsdcld +@{exec_path} = @{sbin}/nfsdcld profile nfsdcld @{exec_path} { include @@ -17,10 +17,14 @@ profile nfsdcld @{exec_path} { /etc/nfs.conf r, /etc/nfs.conf rk, + /etc/nfs.conf.d/{,*} r, /var/lib/nfs/nfsdcld/{,**} rw, + /var/lib/nfs/nfsdcld/main.sqlite rk, /var/lib/nfs/rpc_pipefs/nfsd/* rw, + @{run}/rpc_pipefs/nfsd/cld rw, + include if exists } diff --git a/apparmor.d/groups/filesystem/ntfs-3g b/apparmor.d/groups/filesystem/ntfs-3g index d94d7a0f22..896f676c22 100644 --- a/apparmor.d/groups/filesystem/ntfs-3g +++ b/apparmor.d/groups/filesystem/ntfs-3g @@ -34,6 +34,8 @@ profile ntfs-3g @{exec_path} flags=(attach_disconnected) { mount fstype=fuseblk /dev/dm-[0-9]* -> @{MOUNTS}/, mount fstype=fuseblk /dev/dm-[0-9]* -> @{MOUNTS}/*/, + mount fstype=fuseblk /dev/{s,v}d[a-z]*[0-9]* -> /tmp/fsa/*/, # fsarchiver + umount @{MOUNTDIRS}/, umount @{MOUNTS}/, umount @{MOUNTS}/*/, @@ -53,7 +55,7 @@ profile ntfs-3g @{exec_path} flags=(attach_disconnected) { owner @{PROC}/@{pid}/mounts r, /dev/fuse rw, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/filesystem/ntfsclone b/apparmor.d/groups/filesystem/ntfsclone index c239e81af8..c6443bf7a3 100644 --- a/apparmor.d/groups/filesystem/ntfsclone +++ b/apparmor.d/groups/filesystem/ntfsclone @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/ntfsclone +@{exec_path} = @{sbin}/ntfsclone profile ntfsclone @{exec_path} { include include diff --git a/apparmor.d/groups/filesystem/ntfscp b/apparmor.d/groups/filesystem/ntfscp index 2e36046ba7..f3bc38b6a8 100644 --- a/apparmor.d/groups/filesystem/ntfscp +++ b/apparmor.d/groups/filesystem/ntfscp @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/ntfscp +@{exec_path} = @{sbin}/ntfscp profile ntfscp @{exec_path} { include include diff --git a/apparmor.d/groups/filesystem/ntfsfix b/apparmor.d/groups/filesystem/ntfsfix index e840ed6c53..a4cc93569d 100644 --- a/apparmor.d/groups/filesystem/ntfsfix +++ b/apparmor.d/groups/filesystem/ntfsfix @@ -8,10 +8,13 @@ abi , include @{exec_path} = @{bin}/ntfsfix -profile ntfsfix @{exec_path} { +profile ntfsfix @{exec_path} flags=(attach_disconnected) { include + include include + capability dac_override, + capability dac_read_search, capability sys_admin, @{exec_path} mr, diff --git a/apparmor.d/groups/filesystem/ntfslabel b/apparmor.d/groups/filesystem/ntfslabel index 471aefaa16..5d4089a44d 100644 --- a/apparmor.d/groups/filesystem/ntfslabel +++ b/apparmor.d/groups/filesystem/ntfslabel @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/ntfslabel +@{exec_path} = @{sbin}/ntfslabel profile ntfslabel @{exec_path} { include include diff --git a/apparmor.d/groups/filesystem/ntfsresize b/apparmor.d/groups/filesystem/ntfsresize index 5c7d5c8350..3eac37d70f 100644 --- a/apparmor.d/groups/filesystem/ntfsresize +++ b/apparmor.d/groups/filesystem/ntfsresize @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/ntfsresize +@{exec_path} = @{sbin}/ntfsresize profile ntfsresize @{exec_path} { include include diff --git a/apparmor.d/groups/filesystem/ntfsundelete b/apparmor.d/groups/filesystem/ntfsundelete index 4d96d1dbdd..9f68cba7a5 100644 --- a/apparmor.d/groups/filesystem/ntfsundelete +++ b/apparmor.d/groups/filesystem/ntfsundelete @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/ntfsundelete +@{exec_path} = @{sbin}/ntfsundelete profile ntfsundelete @{exec_path} { include include diff --git a/apparmor.d/groups/filesystem/udiskie b/apparmor.d/groups/filesystem/udiskie index a6a2e2ad38..61e997efb6 100644 --- a/apparmor.d/groups/filesystem/udiskie +++ b/apparmor.d/groups/filesystem/udiskie @@ -8,19 +8,15 @@ abi , include @{exec_path} = @{bin}/udiskie -profile udiskie @{exec_path} { +profile udiskie @{exec_path} flags=(attach_disconnected) { include include - include - include + include include - include - include + include include - include include - include - include + include @{exec_path} r, @{python_path} r, @@ -33,9 +29,10 @@ profile udiskie @{exec_path} { owner @{user_config_dirs}/udiskie/ r, owner @{user_config_dirs}/udiskie/config.yml r, + owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/fd/ r, - owner @{PROC}/@{pid}/mounts r, owner @{PROC}/@{pid}/mountinfo r, + owner @{PROC}/@{pid}/mounts r, # Silencer deny @{lib}/** w, diff --git a/apparmor.d/groups/filesystem/udiskie-info b/apparmor.d/groups/filesystem/udiskie-info index 0b39fd3dcf..b59b914722 100644 --- a/apparmor.d/groups/filesystem/udiskie-info +++ b/apparmor.d/groups/filesystem/udiskie-info @@ -15,7 +15,8 @@ profile udiskie-info @{exec_path} { @{exec_path} r, @{python_path} r, - /usr/bin/ r, + @{bin}/ r, + @{sbin}/ r, owner @{user_config_dirs}/udiskie/ r, owner @{user_config_dirs}/udiskie/config.yml r, diff --git a/apparmor.d/groups/filesystem/udiskie-mount b/apparmor.d/groups/filesystem/udiskie-mount index 0513a8c359..3ec9e422a0 100644 --- a/apparmor.d/groups/filesystem/udiskie-mount +++ b/apparmor.d/groups/filesystem/udiskie-mount @@ -15,7 +15,8 @@ profile udiskie-mount @{exec_path} { @{exec_path} r, @{python_path} r, - /usr/bin/ r, + @{bin}/ r, + @{sbin}/ r, owner @{user_config_dirs}/udiskie/ r, owner @{user_config_dirs}/udiskie/config.yml r, diff --git a/apparmor.d/groups/filesystem/udiskie-umount b/apparmor.d/groups/filesystem/udiskie-umount index cf147b875c..01271bdc65 100644 --- a/apparmor.d/groups/filesystem/udiskie-umount +++ b/apparmor.d/groups/filesystem/udiskie-umount @@ -15,7 +15,8 @@ profile udiskie-umount @{exec_path} { @{exec_path} r, @{python_path} r, - /usr/bin/ r, + @{bin}/ r, + @{sbin}/ r, owner @{user_config_dirs}/udiskie/ r, owner @{user_config_dirs}/udiskie/config.yml r, diff --git a/apparmor.d/groups/filesystem/udisksd b/apparmor.d/groups/filesystem/udisksd index f661ccd121..091ad1ea46 100644 --- a/apparmor.d/groups/filesystem/udisksd +++ b/apparmor.d/groups/filesystem/udisksd @@ -30,26 +30,26 @@ profile udisksd @{exec_path} flags=(attach_disconnected) { network netlink raw, # Allow mounting of removable devices - mount fstype={btrfs,ext*,vfat,exfat,iso9660,udf,ntfs3} /dev/{s,v}d[a-z]* -> @{MOUNTS}/*/, - mount fstype={btrfs,ext*,vfat,exfat,iso9660,udf,ntfs3} /dev/{s,v}d[a-z]*[0-9]* -> @{MOUNTS}/*/, - mount fstype={btrfs,ext*,vfat,exfat,iso9660,udf,ntfs3} /dev/dm-[0-9]* -> @{MOUNTS}/*/, + mount fstype={btrfs,ext*,vfat,exfat,f2fs,iso9660,udf,ntfs3,hfsplus} /dev/{s,v}d[a-z]* -> @{MOUNTS}/*/, + mount fstype={btrfs,ext*,vfat,exfat,f2fs,iso9660,udf,ntfs3,hfsplus} /dev/{s,v}d[a-z]*[0-9]* -> @{MOUNTS}/*/, + mount fstype={btrfs,ext*,vfat,exfat,f2fs,iso9660,udf,ntfs3,hfsplus} /dev/dm-[0-9]* -> @{MOUNTS}/*/, # Allow mounting of loop devices (ISO files) - mount fstype={btrfs,ext*,vfat,exfat,iso9660,udf,ntfs3} /dev/loop[0-9]* -> @{MOUNTS}/*/, - mount fstype={btrfs,ext*,vfat,exfat,iso9660,udf,ntfs3} /dev/loop[0-9]*p[0-9]* -> @{MOUNTS}/*/, + mount fstype={btrfs,ext*,vfat,exfat,iso9660,udf,ntfs3,squashfs} /dev/loop[0-9]* -> @{MOUNTS}/*/, + mount fstype={btrfs,ext*,vfat,exfat,iso9660,udf,ntfs3,squashfs} /dev/loop[0-9]*p[0-9]* -> @{MOUNTS}/*/, # Allow mounting of cdrom mount fstype={btrfs,ext*,vfat,exfat,iso9660,udf,ntfs3} /dev/loop[0-9]* -> @{MOUNTS}/*/, mount fstype={iso9660,udf,ntfs3} /dev/sr[0-9]* -> @{MOUNTS}/*/, # Allow mounting od sd cards - mount fstype={btrfs,ext*,vfat,exfat,iso9660,udf,ntfs3} /dev/mmcblk[0-9] -> @{MOUNTS}/*/, - mount fstype={btrfs,ext*,vfat,exfat,iso9660,udf,ntfs3} /dev/mmcblk[0-9]*p[0-9]* -> @{MOUNTS}/*/, + mount fstype={btrfs,ext*,vfat,exfat,f2fs,iso9660,udf,ntfs3} /dev/mmcblk[0-9] -> @{MOUNTS}/*/, + mount fstype={btrfs,ext*,vfat,exfat,f2fs,iso9660,udf,ntfs3} /dev/mmcblk[0-9]*p[0-9]* -> @{MOUNTS}/*/, mount options=(rw move) -> @{MOUNTS}/, mount options=(rw move) -> @{MOUNTS}/*/, - mount fstype=vfat -> /boot/efi/, + mount fstype=vfat -> @{efi}/, # Allow mounting on temporary mount point mount -> @{run}/udisks2/temp-mount-*/, @@ -59,51 +59,56 @@ profile udisksd @{exec_path} flags=(attach_disconnected) { umount @{MOUNTS}/, umount @{MOUNTS}/*/, umount @{run}/udisks2/temp-mount-*/, - umount /boot/efi/, + umount @{efi}/, umount /media/cdrom@{int}/, signal receive set=int peer=@{p_systemd}, #aa:dbus own bus=system name=org.freedesktop.UDisks2 - #aa:dbus talk bus=system name=org.freedesktop.login1 label=systemd-logind - #aa:dbus talk bus=system name=org.freedesktop.PolicyKit1 label=polkitd + #aa:dbus talk bus=system name=org.freedesktop.login1 label="@{p_systemd_logind}" + #aa:dbus talk bus=system name=org.freedesktop.PolicyKit1 label="@{p_polkitd}" @{exec_path} mr, @{sh_path} rix, @{bin}/umount rix, - @{bin}/dmidecode rPx, - @{bin}/dumpe2fs rPx, + @{sbin}/dmidecode rPx, + @{sbin}/dumpe2fs rPx, @{bin}/eject rPx, - @{bin}/fsck.fat rPx, - @{bin}/lvm rPUx, - @{bin}/mke2fs rPx, - @{bin}/mkfs.* rPx, + @{sbin}/fsck.fat rPx, + @{sbin}/lvm rPUx, + @{sbin}/mke2fs rPx, + @{sbin}/mkfs.* rPx, @{bin}/mount.exfat-fuse rPUx, @{bin}/ntfs-3g rPx, @{bin}/ntfsfix rPx, - @{bin}/sfdisk rPx, - @{bin}/sgdisk rPx, + @{sbin}/sfdisk rPx, + @{sbin}/sgdisk rPx, @{bin}/systemctl rCx -> systemctl, @{bin}/systemd-escape rPx, @{bin}/xfs_* rPUx, + /usr/share/gvfs/remote-volume-monitors/{,**} r, + + @{etc_ro}/udisks2/{,**} r, /etc/crypttab r, /etc/fstab r, /etc/libblockdev/{,**} r, /etc/nvme/* r, - /etc/udisks2/{,**} r, + /var/lib/udisks2/ w, /var/lib/udisks2/{,**} r, /var/lib/udisks2/mounted-fs{,*} rw, + / r, + # Be able to create/delete dirs for removable media @{MOUNTDIRS}/ rw, @{MOUNTS}/ rw, @{MOUNTS}/*/ rw, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, @{run}/ r, @{run}/mount/utab{,.*} rwk, @@ -112,15 +117,16 @@ profile udisksd @{exec_path} flags=(attach_disconnected) { @{run}/cryptsetup/ r, @{run}/cryptsetup/L* rwk, - @{run}/udev/data/+acpi:* r, # for acpi + @{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/+platform:* r, - @{run}/udev/data/+scsi:* r, - @{run}/udev/data/+vmbus:* r, + @{run}/udev/data/+platform:* r, # Identifies onboard devices (laptop/board model, power controllers, thermal sensors) + @{run}/udev/data/+scsi:* r, # For SCSI devices. Block-storage for SATA, SAS, USB, iSCSI + @{run}/udev/data/+vmbus:* r, # For Hyper-V devices, (network adapters, storage controllers, and other virtual devices) @{run}/udev/data/c@{dynamic}:@{int} r, # For dynamic assignment range 234 to 254, 384 to 511 @{sys}/bus/ r, @{sys}/bus/pci/slots/ r, + @{sys}/bus/pci/slots/@{int}-@{int}/address r, @{sys}/bus/pci/slots/@{int}/address r, @{sys}/bus/scsi/devices/ r, @{sys}/class/ r, @@ -136,6 +142,9 @@ profile udisksd @{exec_path} flags=(attach_disconnected) { @{sys}/devices/virtual/block/loop@{int}/uevent rw, @{sys}/devices/virtual/dmi/id/product_uuid r, @{sys}/devices/virtual/nvme-subsystem/{,**} r, + @{sys}/firmware/dmi/entries/ r, + @{sys}/firmware/dmi/entries/*/raw r, + @{sys}/firmware/dmi/entries/*/type r, @{sys}/fs/ r, @{PROC}/cmdline r, diff --git a/apparmor.d/groups/filesystem/umount.udisks2 b/apparmor.d/groups/filesystem/umount.udisks2 index 4e842c7fb9..752a1d5d38 100644 --- a/apparmor.d/groups/filesystem/umount.udisks2 +++ b/apparmor.d/groups/filesystem/umount.udisks2 @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/umount.udisks2 +@{exec_path} = @{sbin}/umount.udisks2 profile umount.udisks2 @{exec_path} flags=(complain) { include diff --git a/apparmor.d/groups/firewall/firewall-applet b/apparmor.d/groups/firewall/firewall-applet index 280bd9d049..7685a67d2a 100644 --- a/apparmor.d/groups/firewall/firewall-applet +++ b/apparmor.d/groups/firewall/firewall-applet @@ -12,8 +12,11 @@ profile firewall-applet @{exec_path} flags=(attach_disconnected) { include include include + include include + #aa:dbus talk bus=system name=org.fedoraproject.FirewallD1 label=firewalld + @{exec_path} mr, @{bin}/ r, @@ -21,6 +24,9 @@ profile firewall-applet @{exec_path} flags=(attach_disconnected) { owner @{PROC}/@{pid}/cmdline r, owner @{PROC}/@{pid}/mounts r, + owner @{PROC}/@{pid}/cgroup r, + + owner @{user_config_dirs}/firewall/applet.conf rwkl, include if exists } diff --git a/apparmor.d/groups/firewall/firewalld b/apparmor.d/groups/firewall/firewalld index 003089ca4b..509296f47f 100644 --- a/apparmor.d/groups/firewall/firewalld +++ b/apparmor.d/groups/firewall/firewalld @@ -6,22 +6,20 @@ abi , include -@{exec_path} = @{bin}/firewalld +@{exec_path} = @{sbin}/firewalld profile firewalld @{exec_path} flags=(attach_disconnected) { include - include include include - include - include + include include + include capability dac_read_search, capability mknod, capability net_admin, capability net_raw, capability setpcap, - capability sys_module, network inet raw, network inet6 raw, @@ -33,15 +31,14 @@ profile firewalld @{exec_path} flags=(attach_disconnected) { @{python_path} r, @{bin}/ r, - @{bin}/alts rix, - @{bin}/ebtables-legacy rix, - @{bin}/ebtables-legacy-restore rix, - @{bin}/false rix, - @{bin}/ipset rix, - @{bin}/kmod rix, - @{bin}/modprobe rix, - @{bin}/xtables-legacy-multi rix, - @{bin}/xtables-nft-multi rmix, + @{sbin}/ r, + @{bin}/alts ix, + @{bin}/false ix, + @{bin}/kmod Cx -> kmod, + @{sbin}/ebtables-legacy ix, + @{sbin}/ebtables-legacy-restore ix, + @{sbin}/ipset ix, + @{sbin}/xtables-{nft,legacy}-multi rmix, /usr/local/lib/@{python_name}/dist-packages/ r, @@ -57,18 +54,29 @@ profile firewalld @{exec_path} flags=(attach_disconnected) { /var/log/firewalld rw, @{run}/firewalld/{,*} rw, - @{run}/modprobe.d/{,*.conf} r, @{run}/xtables.lock rwk, - @{sys}/module/compression r, - @{sys}/module/*/initstate r, - @{PROC}/sys/kernel/modprobe r, @{PROC}/sys/net/ipv{4,6}/ip_forward rw, owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/mounts r, owner @{PROC}/@{pids}/net/ip_tables_names r, + profile kmod flags=(attach_disconnected) { + include + include + + capability sys_module, + + @{run}/xtables.lock r, + + @{sys}/module/compression r, + @{sys}/module/nf_*/initstate r, + @{sys}/module/x_tables/initstate r, + + include if exists + } + include if exists } diff --git a/apparmor.d/groups/firewall/nft b/apparmor.d/groups/firewall/nft index 292b220430..97b149bb6a 100644 --- a/apparmor.d/groups/firewall/nft +++ b/apparmor.d/groups/firewall/nft @@ -7,8 +7,8 @@ abi , include -@{exec_path} = @{bin}/nft -profile nft @{exec_path} { +@{exec_path} = @{sbin}/nft +profile nft @{exec_path} flags=(attach_disconnected) { include include @@ -18,6 +18,8 @@ profile nft @{exec_path} { ptrace (read), + signal receive set=(cont term) peer=unshare, + @{exec_path} mr, /usr/share/iproute2/{,**} r, @@ -26,6 +28,9 @@ profile nft @{exec_path} { /etc/nftables.conf r, /etc/nftables/{,**} r, + @{PROC}/@{pid}/fd/ r, + @{PROC}/@{pid}/net/netlink r, + @{PROC}/@{pid}/stat r, @{PROC}/1/environ r, @{PROC}/cmdline r, @{PROC}/sys/kernel/osrelease r, diff --git a/apparmor.d/groups/firewall/ufw b/apparmor.d/groups/firewall/ufw index d16675235f..1635d88126 100644 --- a/apparmor.d/groups/firewall/ufw +++ b/apparmor.d/groups/firewall/ufw @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/ufw +@{exec_path} = @{sbin}/ufw profile ufw @{exec_path} flags=(attach_disconnected) { include include @@ -30,13 +30,15 @@ profile ufw @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, @{python_path} rix, - @{bin}/ r, + @{sbin}/ r, @{bin}/cat rix, @{bin}/env r, - @{bin}/sysctl rix, - @{bin}/xtables-legacy-multi rix, - @{bin}/xtables-nft-multi rix, - @{lib}/ufw/ufw-init rix, + @{bin}/kmod rCx -> kmod, + @{lib}/ufw/ufw-init rPx, + @{sbin}/sysctl rCx -> sysctl, + @{sbin}/xtables-{nft,legacy}-multi rix, + + /usr/share/ufw/{,**} r, /etc/default/ufw rw, /etc/ufw/ rw, @@ -53,9 +55,36 @@ profile ufw @{exec_path} flags=(attach_disconnected) { @{PROC}/@{pid}/fd/ r, @{PROC}/@{pid}/net/ip_tables_names r, @{PROC}/@{pid}/stat r, - @{PROC}/sys/net/ipv{4,6}/** rw, + @{PROC}/sys/net/ipv{4,6}/** r, @{PROC}/sys/kernel/modprobe r, + profile kmod flags=(attach_disconnected) { + include + include + + capability sys_module, + + @{sys}/module/compression r, + @{sys}/module/*/initstate r, + + include if exists + } + + profile sysctl { + include + include + + capability net_admin, + + @{sbin}/sysctl mr, + + /etc/ufw/sysctl.conf r, + + @{PROC}/sys/net/ipv{4,6}/** rw, + + include if exists + } + include if exists } diff --git a/apparmor.d/groups/firewall/ufw-init b/apparmor.d/groups/firewall/ufw-init index 78483a399a..422bebb025 100644 --- a/apparmor.d/groups/firewall/ufw-init +++ b/apparmor.d/groups/firewall/ufw-init @@ -9,9 +9,13 @@ include @{exec_path} = @{lib}/ufw/ufw-init profile ufw-init @{exec_path} { include + include include + capability dac_override, + capability dac_read_search, capability net_admin, + capability net_raw, network inet dgram, network inet raw, @@ -22,15 +26,47 @@ profile ufw-init @{exec_path} { @{exec_path} mr, @{sh_path} rix, - @{bin}/sysctl rix, - @{bin}/xtables-legacy-multi rix, - @{bin}/xtables-nft-multi rix, + @{bin}/echo rix, + @{sbin}/sysctl rCx -> sysctl, + @{sbin}/xtables-{nft,legacy}-multi rix, + @{bin}/kmod rCx -> kmod, /etc/default/ufw r, /etc/ufw/* r, - @{PROC}/@{pid}/net/ip_tables_names r, - @{PROC}/sys/net/ipv{4,6}/** rw, + @{run}/xtables.lock rwk, + + @{PROC}/@{pid}/net/{ip,ip6}_tables_names r, + @{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 + include + + capability net_admin, + + @{sbin}/sysctl mr, + + /etc/ufw/sysctl.conf r, + + @{PROC}/sys/net/ipv{4,6}/** rw, + + include if exists + } include if exists } diff --git a/apparmor.d/groups/flatpak/fapp b/apparmor.d/groups/flatpak/fapp new file mode 100644 index 0000000000..4f66fc3a78 --- /dev/null +++ b/apparmor.d/groups/flatpak/fapp @@ -0,0 +1,27 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Default profile for all flatpak applications. Ideally, this profile should be +# generated by flatpak itself with settings from the flatpak manifest. + +# See abstractions/app/flatpak for more details about the security objectives. + +abi , + +include + +@{appid} = @{word}.@{word}.@{word}{,.@{word}} +@{profile_dbus} = xdg-dbus-proxy + +profile fapp flags=(attach_disconnected,mediate_deleted) { + include + include + + deny @{att}/ r, + deny @{att}@{run}/.userns r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/flatpak/fbwrap b/apparmor.d/groups/flatpak/fbwrap new file mode 100644 index 0000000000..b72ad1a559 --- /dev/null +++ b/apparmor.d/groups/flatpak/fbwrap @@ -0,0 +1,108 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{appid} = @{word}.@{word}.@{word}{,.@{word}} +@{profile_dbus} = xdg-dbus-proxy + +@{exec_path} = @{bin}/bwrap +profile fbwrap flags=(attach_disconnected,mediate_deleted) { + include + include + include + + capability sys_resource, + + unix type=seqpacket peer=(label=fapp), + unix type=stream peer=(label=fapp), + unix type=stream peer=(label=gnome-software), + + signal receive peer=gnome-software, + signal receive peer=flatpak, + + # Required by the xdg-dbus-proxy stack + # By design xdg-dbus-proxy proxies and filters dbus communication from flatpak + # apps to the system. Thus, it can manage the full system and session buses. + dbus bus=session, + dbus bus=system, + + dbus send bus=accessibility path=/ + interface=org.freedesktop.DBus + member=ListNames + peer=(name=org.freedesktop.DBus, label=dbus-accessibility), + + @{exec_path} mr, + + @{bin}/true ix, # Required by glycin, harmless + + @{sbin}/ldconfig Cx -> &fbwrap//ldconfig, + @{bin}/xdg-dbus-proxy Px -> fbwrap//&xdg-dbus-proxy, + + #aa:only apparmor>=4.1 + #aa:only apparmor<5.0 + priority=2 @{lib}/glycin-loaders/@{d}+/glycin-* Px -> fbwrap//&glycin//loaders, + + #aa:only apparmor>=5.0 + priority=2 @{lib}/glycin-loaders/@{d}+/glycin-* Px -> fbwrap//&:glycin:loaders, + + priority=1 /app/bin/** Px -> fbwrap//&fapp, + priority=1 @{lib}/** Px -> fbwrap//&fapp, + priority=1 @{HOME}/.var/app/@{appid}/** Px -> fbwrap//&fapp, + + /usr/share/flatpak/triggers/desktop-database.trigger Px -> flatpak-system-helper//bwrap, + /usr/share/flatpak/triggers/gtk-icon-cache.trigger Px -> flatpak-system-helper//bwrap, + /usr/share/flatpak/triggers/mime-database.trigger Px -> flatpak-system-helper//bwrap, + + /app/.ref rk, + /usr/.ref rk, + + /bindfile@{rand6} rw, + + owner @{run}/flatpak/.flatpak/@{int}/.ref rk, + owner @{run}/flatpak/ld.so.conf.d/ r, + owner @{run}/flatpak/ld.so.conf.d/*.conf r, + owner @{run}/flatpak/per-app-dirs-ref rk, + owner @{run}/ld-so-cache-dir/@{hex64}.@{rand6}{,~} rw, + + owner @{run}/user/@{uid}/.dbus-proxy/a11y-bus-proxy-@{rand6} w, + owner @{run}/user/@{uid}/.dbus-proxy/session-bus-proxy-@{rand6} w, + owner @{run}/user/@{uid}/.dbus-proxy/system-bus-proxy-@{rand6} w, + owner @{run}/user/@{uid}/.flatpak/@{int}/bwrapinfo.json rw, + owner @{run}/user/@{uid}/.flatpak/@{int}/info r, + + owner @{att}@{run}/user/@{uid}/at-spi/bus rw, + owner @{att}@{run}/user/@{uid}/bus rw, + + @{PROC}/cgroups r, + owner @{PROC}/@{pid}/coredump_filter rw, + + profile ldconfig flags=(attach_disconnected,mediate_deleted) { + include + include + + @{sbin}/ldconfig mr, + @{lib}/ r, + + /usr/share/runtime/lib/plugins/QGnomePlatform/lib/{,*} r, + + /app/lib/{,**} r, + /app/lib{32,64}/{,**} r, + + owner /var/cache/ldconfig/aux-cache r, + + owner @{run}/flatpak/ld.so.conf.d/ r, + owner @{run}/flatpak/ld.so.conf.d/*.conf r, + owner @{run}/ld-so-cache-dir/@{hex64}.@{rand6} w, + owner @{run}/ld-so-cache-dir/@{hex64}.@{rand6}~ rw, + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/flatpak/flatpak b/apparmor.d/groups/flatpak/flatpak index 42d9fd9c37..10465c6735 100644 --- a/apparmor.d/groups/flatpak/flatpak +++ b/apparmor.d/groups/flatpak/flatpak @@ -6,27 +6,38 @@ abi , include +@{appid} = @{word}.@{word}.@{word}{,.@{word}} + @{exec_path} = @{bin}/flatpak -profile flatpak @{exec_path} flags=(attach_disconnected,mediate_deleted,complain) { +profile flatpak @{exec_path} flags=(attach_disconnected,mediate_deleted) { include - include + include + include include include - include - include - include + include + include + include include include - include + include + include + include include include - - userns, + include capability dac_override, capability dac_read_search, capability net_admin, capability sys_ptrace, + capability syslog, # optional: no audit + + # Manage the sandbox + capability setgid, + capability setuid, + capability sys_admin, + capability sys_chroot, network inet dgram, network inet6 dgram, @@ -36,27 +47,48 @@ profile flatpak @{exec_path} flags=(attach_disconnected,mediate_deleted,complain mount fstype=fuse.revokefs-fuse options=(rw, nosuid, nodev) -> /var/tmp/flatpak-cache-*/*/, - ptrace (read) peer=flatpak-app, + ptrace read peer=bwrap.*, # bwrap for experimental per app generated profile + ptrace read peer=fbwrap, # Generic bwrap for flatpak app + ptrace read peer=flatpak-app, # Deprecated generic profile + ptrace read peer=flatpak.*, signal send peer=flatpak-app, + signal send peer=polkit-agent-helper, + + unix type=seqpacket peer=(label=flatpak-system-helper), + unix type=stream peer=(label=flatpak//fusermount), + unix (send receive) type=seqpacket peer=(label=fapp), + unix (send receive) type=seqpacket peer=(label=fbwrap), + + #aa:dbus talk bus=system name=org.freedesktop.Flatpak.SystemHelper label=flatpak-system-helper + #aa:dbus talk bus=system name=org.freedesktop.PolicyKit1 label="@{p_polkitd}" #aa:dbus talk bus=session name=org.freedesktop.Flatpak.SessionHelper label=flatpak-session-helper - #aa:dbus talk bus=system name=org.freedesktop.Accounts label=accounts-daemon - #aa:dbus talk bus=system name=org.freedesktop.PolicyKit1 label=polkitd + #aa:dbus talk bus=session name=org.freedesktop.portal.Documents path=/org/freedesktop/portal/documents label=xdg-document-portal + + dbus send bus=system path=/org/freedesktop/Flatpak/SystemHelper + interface=org.freedesktop.Flatpak.SystemHelper + member=GetRevokefsFd + peer=(name=org.freedesktop.Flatpak.SystemHelper), - dbus send bus=session path=/org/freedesktop/portal/documents - interface=org.freedesktop.portal.Documents - member=GetMountPoint - peer=(name=org.freedesktop.portal.Documents, label="{xdg-document-portal,unconfined}"), + dbus send bus=session path=/org/freedesktop/DBus + interface=org.freedesktop.DBus + member=ReloadConfig + peer=(name=org.freedesktop.DBus, label="@{p_systemd_user}"), @{exec_path} mr, - @{bin}/bwrap rPx -> flatpak-app, + @{bin}/bwrap rPx -> flatpak-app, #aa:only apparmor<4.1 + @{bin}/bwrap rPx -> fbwrap, #aa:only apparmor>=4.1 @{bin}/fusermount{,3} rCx -> fusermount, @{bin}/gpg rCx -> gpg, @{bin}/gpgconf rCx -> gpg, @{bin}/gpgsm rCx -> gpg, @{lib}/revokefs-fuse rix, + @{lib}/flatpak-validate-icon rPx, + + # For flatpack enter, the shell is not confined on purpose. + @{bin}/@{shells} rUx, @{lib}/polkit-[0-9]/polkit-agent-helper-[0-9] rPx, @{lib}/polkit-agent-helper-[0-9] rPx, @@ -66,7 +98,8 @@ profile flatpak @{exec_path} flags=(attach_disconnected,mediate_deleted,complain /etc/flatpak/{,**} r, /etc/pulse/client.conf r, - / r, + / r, + @{att}/ r, /var/lib/flatpak/{,**} rwlk, @@ -77,6 +110,8 @@ profile flatpak @{exec_path} flags=(attach_disconnected,mediate_deleted,complain owner @{HOME}/.var/ w, owner @{HOME}/.var/app/{,**} rw, + owner @{att}@{HOME}/.var/app/@{appid}/.local/share/*/logs/* rw, + owner @{att}@{HOME}/.var/app/@{appid}/.local/share/*/**/usr/.ref rw, # Can create dotfile directories for any app owner @{user_cache_dirs}/*/ w, @@ -85,6 +120,7 @@ profile flatpak @{exec_path} flags=(attach_disconnected,mediate_deleted,complain owner @{user_games_dirs}/{,**/} w, owner @{user_documents_dirs}/ w, + @{user_config_dirs}/dconf/user r, owner @{user_cache_dirs}/flatpak/{,**} rw, owner @{user_config_dirs}/pulse/client.conf r, owner @{user_config_dirs}/user-dirs.dirs r, @@ -96,30 +132,39 @@ profile flatpak @{exec_path} flags=(attach_disconnected,mediate_deleted,complain owner @{tmp}/#@{int} rw, owner @{tmp}/ostree-gpg-@{rand6}/{,**} rw, + owner @{tmp}/remote-summary-sig.@{rand6} rw, + owner @{tmp}/remote-summary.@{rand6} rw, owner /dev/shm/flatpak*/{,**} rw, - @{run}/.userns r, + @{att}@{run}/.userns r, + @{run}/polkit/agent-helper.socket rw, + @{run}/user/@{uid}/.dbus-proxy/ w, @{run}/user/@{uid}/dconf/user rw, owner @{run}/user/@{uid}/.dbus-proxy/* rw, owner @{run}/user/@{uid}/.flatpak-cache rw, owner @{run}/user/@{uid}/.flatpak/ rw, owner @{run}/user/@{uid}/.flatpak/** rwlk -> @{run}/user/@{uid}/.flatpak/**, + owner @{run}/user/@{uid}/.mutter-Xwaylandauth.@{rand6} r, owner @{run}/user/@{uid}/app/ w, owner @{run}/user/@{uid}/app/*/ w, owner @{run}/user/@{uid}/systemd/private rw, + owner @{run}/user/@{uid}/wayland-@{int} rw, @{sys}/module/nvidia/version r, + @{PROC}/modules r, @{PROC}/sys/fs/pipe-max-size r, + owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/fdinfo/@{int} r, owner @{PROC}/@{pid}/stat r, /dev/fuse rw, /dev/tty rw, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, - deny owner @{user_share_dirs}/gvfs-metadata/* r, + #aa:only test + mount fstype=fuse.revokefs-fuse options=(rw, nosuid, nodev) revokefs-fuse -> /tmp/test-flatpak-*/**, profile gpg { include @@ -131,6 +176,7 @@ profile flatpak @{exec_path} flags=(attach_disconnected,mediate_deleted,complain @{bin}/gpgconf mr, @{bin}/gpgsm mr, @{bin}/gpg-agent rix, + @{lib}/gnupg/scdaemon rix, @{HOME}/@{XDG_GPG_DIR}/*.conf r, @@ -146,9 +192,18 @@ profile flatpak @{exec_path} flags=(attach_disconnected,mediate_deleted,complain include include - mount fstype=fuse.revokefs-fuse options=(rw, nosuid, nodev) -> /var/tmp/flatpak-cache-*/*/, + capability setuid, + + unix type=seqpacket peer=(label=flatpak-system-helper), + unix type=stream peer=(label=flatpak), + + mount fstype=fuse.revokefs-fuse options=(rw, nosuid, nodev) revokefs-fuse -> /var/tmp/flatpak-cache-*/*/, umount /var/tmp/flatpak-cache-*/*/, + #aa:only test + mount fstype=fuse.revokefs-fuse options=(rw, nosuid, nodev) revokefs-fuse -> /tmp/test-flatpak.*/**, + umount /tmp/test-flatpak-@{rand6}/**, + include if exists } diff --git a/apparmor.d/groups/flatpak/flatpak-app b/apparmor.d/groups/flatpak/flatpak-app index e332f50cad..1bc77ff616 100644 --- a/apparmor.d/groups/flatpak/flatpak-app +++ b/apparmor.d/groups/flatpak/flatpak-app @@ -2,6 +2,10 @@ # Copyright (C) 2023-2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only +# Note: This profile is **deprecated** and will be removed in future releases. +# It is only used when using apparmor < 4.1 +# See fapp and fbwrap profiles instead. + # Default profile for all flatpak applications. Ideally, this profile should be # generated by flatpak itself with settings from the flatpak manifest and # fully separated from bwrap. @@ -22,31 +26,26 @@ abi , include +@{appid} = @{word}.@{word}.@{word}{,.@{word}} +@{profile_dbus} = xdg-dbus-proxy + +@{exec_path} = @{bin}/bwrap profile flatpak-app flags=(attach_disconnected,mediate_deleted) { include - include - include - include + include + include - capability dac_override, - capability dac_read_search, - capability setuid, # Needed when bwrap is setup with setuid privileges. capability sys_resource, - - network inet dgram, - network inet6 dgram, - network inet stream, - network inet6 stream, - network netlink dgram, - network netlink raw, - network unix stream, - - ptrace (read), - ptrace trace peer=flatpak-app, + capability setuid, # Needed when bwrap is setup with setuid privileges. signal receive peer=flatpak, signal receive set=(int term) peer=flatpak-portal, - signal receive set=(int) peer=flatpak-session-helper, + signal receive set=(int term) peer=flatpak-session-helper, + + unix type=seqpacket peer=(label=dbus-session), + unix type=seqpacket peer=(label=xdg-dbus-proxy), + + @{exec_path} mr, @{bin}/** rmix, @{lib}/** rmix, @@ -54,44 +53,25 @@ profile flatpak-app flags=(attach_disconnected,mediate_deleted) { /usr/plugins/** rmix, /usr/share/flatpak/triggers/* rix, /usr/share/runtime/** rmix, - /var/lib/flatpak/app/*/**/@{bin}/** rmix, - /var/lib/flatpak/app/*/**/@{lib}/** rmix, - @{run}/flatpak/app/*/**so* rm, @{run}/parent/@{bin}/** rmix, @{run}/parent/@{lib}/** rmix, @{run}/parent/app/** rmix, - @{bin}/gtk{,4}-update-icon-cache rPx -> flatpak-app//>k-update-icon-cache, - @{bin}/update-desktop-database rPx -> flatpak-app//&update-desktop-database, - @{bin}/update-mime-database rPx -> flatpak-app//&update-mime-database, - @{bin}/xdg-dbus-proxy rPx -> flatpak-app//&xdg-dbus-proxy, - @{lib}/kf5/kioslave5 rPx, @{lib}/kf6/kioworker rPx, /etc/**/ rw, /etc/shells rw, - /app/.ref rk, /app/extra/** rw, - /app/lib/** rk, - /bindfile@{rand6} rw, + /app/.ref rk, /usr/.ref rk, + /bindfile@{rand6} rw, + /var/lib/flatpak/app/{,**} r, /var/lib/flatpak/exports/** rw, - /var/tmp/etilqs_@{hex16} rw, - - @{run}/.userns r, - @{run}/parent/** r, - @{run}/parent/app/.ref rk, - @{run}/parent/usr/.ref rk, - owner @{run}/flatpak/{,**} rk, - owner @{run}/flatpak/app/** rw, - owner @{run}/flatpak/doc/** rw, - owner @{run}/ld-so-cache-dir/* rw, - owner @{run}/user/ r, include if exists include if exists diff --git a/apparmor.d/groups/flatpak/flatpak-portal b/apparmor.d/groups/flatpak/flatpak-portal index 8a8d2b9011..04f60cdaae 100644 --- a/apparmor.d/groups/flatpak/flatpak-portal +++ b/apparmor.d/groups/flatpak/flatpak-portal @@ -10,35 +10,44 @@ include profile flatpak-portal @{exec_path} flags=(attach_disconnected) { include include + include + include + include include + include capability sys_ptrace, network netlink raw, + unix (send receive) type=seqpacket peer=(label=fapp), + unix (send receive) type=seqpacket peer=(label=fbwrap), + ptrace read, signal send, #aa:dbus own bus=session name=org.freedesktop.portal.Flatpak + dbus receive bus=session + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), + @{exec_path} mr, @{bin}/flatpak rPx, - /usr/share/mime/mime.cache r, /usr/share/xdg-desktop-portal/portals/{,*.portal} r, - /var/lib/flatpak/exports/share/mime/mime.cache r, - - owner @{att}/ r, + / r, + owner /att/**/ r, owner @{att}/.flatpak-info r, - owner @{HOME}/.var/app/*/**/.ref rw, - owner @{HOME}/.var/app/*/**/logs/* rw, + owner @{att}@{HOME}/.var/app/*/.local/share/*/logs/* rw, + owner @{att}@{HOME}/.var/app/*/.local/share/*/**/usr/.ref rw, owner @{user_config_dirs}/user-dirs.dirs r, - owner @{user_share_dirs}/mime/mime.cache r, owner @{run}/user/@{uid}/.flatpak/@{int}/* r, owner @{run}/user/@{uid}/.flatpak/@{int}-private/* r, diff --git a/apparmor.d/groups/flatpak/flatpak-session-helper b/apparmor.d/groups/flatpak/flatpak-session-helper index 162e3b4481..df4acc1e90 100644 --- a/apparmor.d/groups/flatpak/flatpak-session-helper +++ b/apparmor.d/groups/flatpak/flatpak-session-helper @@ -6,55 +6,77 @@ abi , include +@{appid} = @{word}.@{word}.@{word}{,.@{word}} + @{exec_path} = @{lib}/flatpak-session-helper -profile flatpak-session-helper @{exec_path} flags=(attach_disconnected) { +profile flatpak-session-helper @{exec_path} flags=(attach_disconnected,mediate_deleted) { include include include include include - include signal send set=(hup int) peer=user_unconfined, - signal send set=(int) peer=@{p_systemd}, - signal send set=(int) peer=flatpak-app, + signal send set=int peer=@{p_systemd}, + signal send set=int peer=flatpak-session-helper-app, #aa:dbus own bus=session name=org.freedesktop.Flatpak + dbus receive bus=session + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), + @{exec_path} mr, - @{shells_path} rUx -> user_unconfined, + @{shells_path} rUx, + @{coreutils_path} rix, @{bin}/dbus-monitor rPUx, - @{bin}/env rix, @{bin}/flatpak rPx, @{bin}/getent rix, - @{bin}/p11-kit rix, + @{bin}/p11-kit rCx -> p11-kit, @{bin}/pkexec rCx -> pkexec, @{bin}/printenv rix, @{bin}/ps rPx, - @{bin}/test rix, - @{bin}/touch rix, - @{lib}/p11-kit/p11-kit-remote rix, - @{lib}/p11-kit/p11-kit-server rix, - /var/lib/flatpak/app/*/**/@{bin}/** rPx -> flatpak-app, - /var/lib/flatpak/app/*/**/@{lib}/** rPx -> flatpak-app, + + /var/lib/flatpak/app/@{appid}/**/@{bin}/** rPx -> flatpak-session-helper-app, + /var/lib/flatpak/app/@{appid}/**/@{lib}/** rPx -> flatpak-session-helper-app, + + owner @{user_cache_dirs}/.flatpak-helper/{,**} rw, owner @{user_config_dirs}/mimeapps.list w, owner @{run}/user/@{uid}/.flatpak-helper/{,**} rw, - owner @{run}/user/@{uid}/.flatpak-helper/pkcs11-flatpak-@{int} rw, - - owner @{PROC}/@{pids}/fd/ r, /dev/ptmx rw, - profile pkexec { + profile pkexec flags=(attach_disconnected,mediate_deleted) { include include include if exists } + profile p11-kit flags=(attach_disconnected,mediate_deleted) { + include + include + + signal receive set=term peer=flatpak-session-helper, + + @{bin}/p11-kit mr, + + @{lib}/p11-kit/p11-kit-remote ix, + @{lib}/p11-kit/p11-kit-server ix, + + owner @{user_cache_dirs}/.flatpak-helper/pkcs11-flatpak-@{int} rw, + + owner @{run}/user/@{uid}/.flatpak-helper/pkcs11-flatpak-@{int} rw, + + owner @{PROC}/@{pids}/fd/ r, + + include if exists + } + include if exists } diff --git a/apparmor.d/groups/flatpak/flatpak-session-helper-app b/apparmor.d/groups/flatpak/flatpak-session-helper-app new file mode 100644 index 0000000000..c752452429 --- /dev/null +++ b/apparmor.d/groups/flatpak/flatpak-session-helper-app @@ -0,0 +1,108 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{appid} = @{word}.@{word}.@{word}{,.@{word}} + +@{exec_path} = /var/lib/flatpak/app/@{appid}/**/@{bin}/** +@{exec_path} += /var/lib/flatpak/app/@{appid}/**/@{lib}/** +profile flatpak-session-helper-app flags=(attach_disconnected) { + include + include + include + include + + capability sys_ptrace, + + network netlink raw, + + signal receive set=int peer=flatpak-session-helper, + + ptrace read, + + @{exec_path} mrk, + + @{bin}/@{shells} Ux, #aa:exclude RBAC + @{bin}/udevadm Cx -> udevadm, + + @{sys}/block/ r, + @{sys}/devices/@{pci}/ r, + @{sys}/devices/@{pci}/stat r, + @{sys}/devices/**/speed r, + @{sys}/devices/**/statistics/rx_bytes r, + @{sys}/devices/**/statistics/tx_bytes r, + @{sys}/devices/virtual/tty/tty@{int}/active r, + + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/ r, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/*.slice/ r, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/*.slice/*.service/ r, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/*.slice/{,**/}cgroup.procs r, + + @{PROC}/ r, + @{PROC}/@{pids}/ r, + @{PROC}/@{pids}/cgroup r, + @{PROC}/@{pids}/cmdline r, + @{PROC}/@{pids}/cpuset r, + @{PROC}/@{pids}/io r, + @{PROC}/@{pids}/maps r, + @{PROC}/@{pids}/smaps r, + @{PROC}/@{pids}/stat r, + @{PROC}/@{pids}/statm r, + @{PROC}/@{pids}/status r, + @{PROC}/@{pids}/task/ r, + @{PROC}/@{pids}/task/@{tid}/status r, + @{PROC}/modules r, + @{PROC}/sys/fs/file-max r, + @{PROC}/sys/fs/file-nr r, + @{PROC}/sys/fs/inotify/max_queued_events r, + @{PROC}/sys/fs/inotify/max_user_instances r, + @{PROC}/sys/fs/inotify/max_user_watches r, + @{PROC}/sys/fs/nr_open r, + @{PROC}/sys/fs/pipe-max-size r, + @{PROC}/sys/kernel/hostname r, + @{PROC}/sys/kernel/osrelease r, + @{PROC}/sys/kernel/ostype r, + @{PROC}/sys/kernel/pid_max r, + @{PROC}/sys/kernel/random/boot_id r, + @{PROC}/sys/kernel/random/entropy_avail r, + @{PROC}/sys/kernel/random/uuid r, + @{PROC}/sys/kernel/shmmax r, + @{PROC}/sys/kernel/yama/ptrace_scope r, + @{PROC}/version r, + @{PROC}/version_signature r, + owner @{PROC}/@{pid}/cgroup r, + owner @{PROC}/@{pid}/clear_refs w, + owner @{PROC}/@{pid}/cmdline r, + owner @{PROC}/@{pid}/comm r, + owner @{PROC}/@{pid}/environ r, + owner @{PROC}/@{pid}/fd/ r, + owner @{PROC}/@{pid}/fdinfo/ r, + owner @{PROC}/@{pid}/fdinfo/@{int} r, + owner @{PROC}/@{pid}/limits r, + owner @{PROC}/@{pid}/loginuid r, + owner @{PROC}/@{pid}/mountinfo r, + owner @{PROC}/@{pid}/oom_adj r, + owner @{PROC}/@{pid}/oom_score_adj r, + owner @{PROC}/@{pid}/sessionid r, + owner @{PROC}/@{pid}/smaps_rollup r, + owner @{PROC}/@{pid}/task/ r, + owner @{PROC}/@{pid}/task/@{tid}/comm rw, + owner @{PROC}/@{pid}/task/@{tid}/smaps r, + owner @{PROC}/@{pid}/task/@{tid}/stat r, + owner @{PROC}/@{pid}/task/@{tid}/statm r, + + profile udevadm { + include + include + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/flatpak/flatpak-system-helper b/apparmor.d/groups/flatpak/flatpak-system-helper index dfaa920aca..5ec1e51a35 100644 --- a/apparmor.d/groups/flatpak/flatpak-system-helper +++ b/apparmor.d/groups/flatpak/flatpak-system-helper @@ -6,11 +6,15 @@ abi , include +@{appid} = @{word}.@{word}.@{word}{,.@{word}} + @{exec_path} = @{lib}/flatpak-system-helper -profile flatpak-system-helper @{exec_path} { +profile flatpak-system-helper @{exec_path} flags=(attach_disconnected,mediate_deleted) { include + include include - include + include + include include include include @@ -25,13 +29,24 @@ profile flatpak-system-helper @{exec_path} { capability sys_nice, capability sys_ptrace, + network inet6 dgram, + ptrace read, + unix type=seqpacket peer=(label=dbus-system), + unix type=seqpacket peer=(label=flatpak), + unix type=seqpacket peer=(label=flatpak//fusermount), + unix type=seqpacket peer=(label=gnome-software), + unix type=seqpacket peer=(label=gnome-software//fusermount), + unix type=seqpacket peer=(label=unconfined), + unix type=seqpacket peer=(label=bazaar), + unix type=seqpacket peer=(label=bazaar//fusermount), + #aa:dbus own bus=system name=org.freedesktop.Flatpak.SystemHelper @{exec_path} mr, - @{bin}/bwrap rPUx, + @{bin}/bwrap rCx -> bwrap, @{bin}/gpg{,2} rCx -> gpg, @{bin}/gpgconf rCx -> gpg, @{bin}/gpgsm rCx -> gpg, @@ -40,9 +55,8 @@ profile flatpak-system-helper @{exec_path} { /etc/flatpak/{,**} r, /etc/machine-id r, - /usr/share/flatpak/remotes.d/ r, + /usr/share/flatpak/remotes.d/{,**} r, /usr/share/flatpak/triggers/ r, - /usr/share/mime/mime.cache r, /var/lib/flatpak/{,**} rwkl, /var/tmp/flatpak-cache-*/{,**} rw, @@ -51,13 +65,75 @@ profile flatpak-system-helper @{exec_path} { owner /{var/,}tmp/ostree-gpg-@{rand6}/ rw, owner @{tmp}/ostree-gpg-@{rand6}/** rwkl -> /tmp/ostree-gpg-@{rand6}/**, - /tmp/remote-summary-sig.@{rand6} r, - /tmp/remote-summary.@{rand6} r, + @{tmp}/remote-summary-sig.@{rand6} r, + @{tmp}/remote-summary.@{rand6} r, - @{PROC}/@{pid}/stat r, + @{PROC}/@{pids}/cgroup r, + @{PROC}/@{pids}/stat r, + @{PROC}/@{pids}/status r, owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/fdinfo/@{int} r, + profile bwrap flags=(attach_disconnected) { + include + include + include + + capability dac_override, + capability dac_read_search, + capability sys_resource, + + @{bin}/bwrap mr, + + /app/bin/* rix, + + @{bin}/bsdtar ix, + @{bin}/cp ix, + @{bin}/install ix, + @{bin}/mv ix, + @{bin}/rm ix, + @{bin}/sed ix, + @{bin}/tar ix, + @{bin}/xz ix, + + @{bin}/gtk{,4}-update-icon-cache Px -> flatpak-system-helper//bwrap//>k-update-icon-cache, + @{bin}/update-desktop-database Px -> flatpak-system-helper//bwrap//&update-desktop-database, + @{bin}/update-mime-database Px -> flatpak-system-helper//bwrap//&update-mime-database, + + /usr/share/flatpak/triggers/desktop-database.trigger ix, + /usr/share/flatpak/triggers/gtk-icon-cache.trigger ix, + /usr/share/flatpak/triggers/mime-database.trigger ix, + + @{system_share_dirs}/** r, + @{system_share_dirs}/*ubuntu/applications/.mimeinfo.cache.* rw, + @{system_share_dirs}/*ubuntu/applications/mimeinfo.cache w, + @{system_share_dirs}/applications/.mimeinfo.cache.* w, + @{system_share_dirs}/applications/mimeinfo.cache w, + @{system_share_dirs}/icons/**/.icon-theme.cache rw, + @{system_share_dirs}/icons/**/icon-theme.cache w, + @{system_share_dirs}/icons/hicolor/index.theme w, + @{system_share_dirs}/mime/{,**} w, + + @{user_share_dirs}/** r, + @{user_share_dirs}/.mimeinfo.cache.* w, + @{user_share_dirs}/**/.icon-theme.cache w, + @{user_share_dirs}/**/icon-theme.cache w, + @{user_share_dirs}/applications/.mimeinfo.cache.* w, + @{user_share_dirs}/applications/mimeinfo.cache w, + @{user_share_dirs}/mime/{,**} w, + @{user_share_dirs}/mimeinfo.cache w, + + /app/extra/** rw, + /bindfile@{rand6} rw, + /usr/.ref rk, + + /tmp/#@{int} rw, + + /dev/tty rw, + + include if exists + } + profile gpg { include include @@ -72,6 +148,12 @@ profile flatpak-system-helper @{exec_path} { owner @{tmp}/ostree-gpg-@{rand6}/ r, owner @{tmp}/ostree-gpg-@{rand6}/** rwkl -> /tmp/ostree-gpg-@{rand6}/**, + @{run}/user/@{uid}/gnupg/ r, + @{run}/user/@{uid}/gnupg/d.@{rand}/ rw, + @{run}/user/@{uid}/gnupg/d.@{rand}/S.gpg-agent{,.ssh,.browser,.extra} rw, + @{run}/user/@{uid}/gnupg/d.@{rand}/S.scdaemon rw, + @{run}/user/@{uid}/gnupg/S.scdaemon rw, + owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/task/@{tid}/comm rw, diff --git a/apparmor.d/groups/freedesktop/accounts-daemon b/apparmor.d/groups/freedesktop/accounts-daemon index d3aaa753fa..e3f63b98a7 100644 --- a/apparmor.d/groups/freedesktop/accounts-daemon +++ b/apparmor.d/groups/freedesktop/accounts-daemon @@ -11,7 +11,7 @@ include profile accounts-daemon @{exec_path} flags=(attach_disconnected) { include include - include + include include include @@ -24,16 +24,17 @@ profile accounts-daemon @{exec_path} flags=(attach_disconnected) { ptrace read peer=unconfined, #aa:dbus own bus=system name=org.freedesktop.Accounts + #aa:dbus talk bus=system name=org.freedesktop.home1 label=systemd-homed @{exec_path} mr, - @{bin}/adduser rPx, + @{sbin}/adduser rPx, @{bin}/cat rix, @{bin}/chage rPx, @{bin}/passwd rPx, - @{bin}/chpasswd rPx, - @{bin}/userdel rPx, - @{bin}/usermod rPx, + @{sbin}/chpasswd rPx, + @{sbin}/userdel rPx, + @{sbin}/usermod rPx, @{bin}/locale rPUx, /usr/share/language-tools/language-validate rPx, @@ -43,6 +44,7 @@ profile accounts-daemon @{exec_path} flags=(attach_disconnected) { /usr/share/accountsservice/{,**} r, /usr/share/dbus-1/interfaces/*.xml r, + @{etc_rw}/tcb/{,**} r, /etc/default/locale r, /etc/gdm{3,}/ r, /etc/gdm{3,}/custom.conf{,.@{rand6}} rw, @@ -63,6 +65,8 @@ profile accounts-daemon @{exec_path} flags=(attach_disconnected) { owner @{tmp}/gnome-control-center-user-icon-@{rand6} rw, + @{att}@{run}/systemd/userdb/io.systemd.Machine rw, + @{PROC}/@{pid}/cmdline r, @{PROC}/@{pid}/loginuid r, @{PROC}/1/environ r, diff --git a/apparmor.d/groups/freedesktop/boltd b/apparmor.d/groups/freedesktop/boltd index 8f55bb3758..f5e2f93386 100644 --- a/apparmor.d/groups/freedesktop/boltd +++ b/apparmor.d/groups/freedesktop/boltd @@ -10,43 +10,54 @@ include profile boltd @{exec_path} flags=(attach_disconnected) { include include - include + include include + include capability net_admin, network netlink raw, + #aa:dbus own bus=system name=org.freedesktop.bolt1 path=/org/freedesktop/bolt #aa:dbus own bus=system name=org.freedesktop.bolt @{exec_path} mr, + / r, + /var/lib/boltd/{,**} rw, owner @{run}/boltd/{,**} rw, - @{att}/@{run}/systemd/notify w, - - @{run}/udev/data/+thunderbolt:* r, + @{run}/udev/data/+thunderbolt:* r, # For Thunderbolt devices, such as docks, external GPUs, and storage devices. @{sys}/bus/ r, @{sys}/bus/thunderbolt/devices/ r, @{sys}/bus/wmi/devices/ r, @{sys}/class/ r, - @{sys}/devices/@{pci}/@{uuid}/uevent r, + @{sys}/devices/**/uevent r, @{sys}/devices/@{pci}/device r, @{sys}/devices/@{pci}/domain@{int}/ r, - @{sys}/devices/@{pci}/domain@{int}/{security,uevent} r, @{sys}/devices/@{pci}/domain@{int}/**/ r, - @{sys}/devices/@{pci}/domain@{int}/**/{authorized,generation} r, - @{sys}/devices/@{pci}/domain@{int}/**/{boot,rx_lanes,rx_speed,tx_lanes,tx_speed} r, - @{sys}/devices/@{pci}/domain@{int}/**/{uevent,unique_id} r, - @{sys}/devices/@{pci}/domain@{int}/**/{vendor,device}_name r, + @{sys}/devices/@{pci}/domain@{int}/**/authorized r, + @{sys}/devices/@{pci}/domain@{int}/**/boot r, + @{sys}/devices/@{pci}/domain@{int}/**/device_name r, + @{sys}/devices/@{pci}/domain@{int}/**/generation r, + @{sys}/devices/@{pci}/domain@{int}/**/rx_lanes r, + @{sys}/devices/@{pci}/domain@{int}/**/rx_speed r, + @{sys}/devices/@{pci}/domain@{int}/**/tx_lanes r, + @{sys}/devices/@{pci}/domain@{int}/**/tx_speed r, + @{sys}/devices/@{pci}/domain@{int}/**/unique_id r, + @{sys}/devices/@{pci}/domain@{int}/**/vendor_name r, @{sys}/devices/@{pci}/domain@{int}/boot_acl rw, @{sys}/devices/@{pci}/domain@{int}/iommu_dma_protection r, + @{sys}/devices/@{pci}/domain@{int}/security r, @{sys}/devices/platform/**/uevent r, @{sys}/devices/platform/*/wmi_bus/wmi_bus-*/@{uuid}/force_power rw, - @{sys}/devices/virtual/dmi/id/{sys_vendor,product_version,product_name} r, + + #aa:only test + owner /tmp/tmp@{rand8}/{,**} rw, + owner /tmp/umockdev.@{rand6}/{,**} rw, include if exists } diff --git a/apparmor.d/groups/freedesktop/colord b/apparmor.d/groups/freedesktop/colord index 031ba06051..a782e4e0e4 100644 --- a/apparmor.d/groups/freedesktop/colord +++ b/apparmor.d/groups/freedesktop/colord @@ -11,10 +11,14 @@ include profile colord @{exec_path} flags=(attach_disconnected) { include include - include - include + include + include + include + include include + include include + include network inet dgram, network inet6 dgram, @@ -23,6 +27,9 @@ profile colord @{exec_path} flags=(attach_disconnected) { #aa:dbus own bus=system name=org.freedesktop.ColorManager @{exec_path} mrix, + @{lib}/colord-sane ix, + + /opt/brother/scanner/** r, /etc/machine-id r, /etc/sane.d/{,**} r, @@ -30,10 +37,10 @@ profile colord @{exec_path} flags=(attach_disconnected) { /etc/udev/hwdb.bin r, /usr/share/color/icc/{,**} r, - /usr/share/mime/mime.cache r, + /usr/share/gvfs/remote-volume-monitors/{,**} r, /usr/share/snmp/mibs/{,*} r, - @{system_share_dirs}/mime/mime.cache r, + / r, owner /var/lib/colord/.cache/ rw, owner /var/lib/colord/.cache/** rw, @@ -44,8 +51,10 @@ profile colord @{exec_path} flags=(attach_disconnected) { owner /var/lib/snmp/mibs/{iana,ietf}/ r, owner /var/lib/snmp/mibs/{iana,ietf}/[A-Z]* r, - @{att}/@{desktop_share_dirs}/icc/edid-*.icc r, - @{att}/@{user_share_dirs}/icc/edid-*.icc r, + @{att}@{desktop_share_dirs}/icc/edid-@{hex32}.icc r, + @{att}@{user_share_dirs}/icc/edid-@{hex32}.icc r, + + @{att}@{run}/systemd/userdb/io.systemd.Machine rw, @{run}/systemd/sessions/* r, @@ -55,10 +64,12 @@ profile colord @{exec_path} flags=(attach_disconnected) { @{sys}/bus/scsi/devices/ r, @{sys}/class/drm/ r, @{sys}/class/video4linux/ r, - @{sys}/devices/@{pci}/{vendor,model,type} r, - @{sys}/devices/@{pci}/drm/card@{int}/**/{enabled,edid} r, - @{sys}/devices/@{pci}/uevent r, - @{sys}/devices/virtual/dmi/id/{sys_vendor,product_version,product_name} r, + @{sys}/devices/**/uevent r, + @{sys}/devices/@{pci}/drm/card@{int}/**/edid r, + @{sys}/devices/@{pci}/drm/card@{int}/**/enabled r, + @{sys}/devices/@{pci}/model r, + @{sys}/devices/@{pci}/type r, + @{sys}/devices/@{pci}/vendor r, @{PROC}/sys/dev/parport/ r, @{PROC}/sys/dev/parport/parport@{int}/base-addr r, diff --git a/apparmor.d/groups/freedesktop/cpupower b/apparmor.d/groups/freedesktop/cpupower index 2d58faffe4..9ea1890566 100644 --- a/apparmor.d/groups/freedesktop/cpupower +++ b/apparmor.d/groups/freedesktop/cpupower @@ -10,28 +10,28 @@ include @{exec_path} = @{bin}/cpupower profile cpupower @{exec_path} { include + include - # Needed to read the /dev/cpu/@{int}/msr device, and hence remove the following error: - # Could not read perf-bias value[-1] - capability sys_rawio, - - # Needed to operate on CPU IDLE states capability sys_admin, + capability sys_rawio, @{exec_path} mr, @{sh_path} rix, + @{bin}/basename rix, @{bin}/kmod rCx -> kmod, @{bin}/man rPx, + @{bin}/uname rix, + + @{lib}/linux-*/cpupower rix, - @{sys}/devices/system/cpu/{cpufreq,cpuidle}/ r, - @{sys}/devices/system/cpu/{cpufreq,cpuidle}/** r, - @{sys}/devices/system/cpu/cpu@{int}/{cpufreq,cpuidle}/ r, - @{sys}/devices/system/cpu/cpu@{int}/{cpufreq,cpuidle}/** r, @{sys}/devices/system/cpu/cpu@{int}/cpuidle/state@{int}/disable rw, @{sys}/devices/system/cpu/cpu@{int}/online r, - @{sys}/devices/system/cpu/cpu@{int}/topology/{physical_package_id,core_id} r, + @{sys}/devices/system/cpu/cpu@{int}/topology/{,**} r, + @{sys}/devices/system/cpu/cpufreq/{,**} r, @{sys}/devices/system/cpu/cpufreq/policy@{int}/* rw, + @{sys}/devices/system/cpu/cpuidle/{,**} r, + @{sys}/devices/virtual/powercap/{,**} r, /dev/cpu/@{int}/msr r, diff --git a/apparmor.d/groups/freedesktop/dconf b/apparmor.d/groups/freedesktop/dconf index be4972f042..db2c58782b 100644 --- a/apparmor.d/groups/freedesktop/dconf +++ b/apparmor.d/groups/freedesktop/dconf @@ -9,11 +9,18 @@ include @{exec_path} = @{bin}/dconf profile dconf @{exec_path} flags=(attach_disconnected) { include + include + include include capability sys_nice, capability dac_override, + dbus send bus=system path=/ca/desrt/dconf/Writer/ibus + interface=ca.desrt.dconf.Writer + member=WritabilityNotify + peer=(label=ibus-dconf), + @{exec_path} mr, /etc/dconf/db/** rw, diff --git a/apparmor.d/groups/freedesktop/dconf-service b/apparmor.d/groups/freedesktop/dconf-service index da950506a8..d9fd8cec45 100644 --- a/apparmor.d/groups/freedesktop/dconf-service +++ b/apparmor.d/groups/freedesktop/dconf-service @@ -22,7 +22,7 @@ profile dconf-service @{exec_path} flags=(attach_disconnected) { dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, diff --git a/apparmor.d/groups/freedesktop/fc-cache b/apparmor.d/groups/freedesktop/fc-cache index 128a4708b8..3720b369a2 100644 --- a/apparmor.d/groups/freedesktop/fc-cache +++ b/apparmor.d/groups/freedesktop/fc-cache @@ -24,6 +24,8 @@ profile fc-cache @{exec_path} { /var/cache/fontconfig/*.cache-@{int}.LCK rwl, /var/cache/fontconfig/CACHEDIR.TAG.LCK rwl, + /var/log/fontconfig.log w, + /var/tmp/mkinitramfs_*/{**,} rwl, owner @{user_cache_dirs}/ w, diff --git a/apparmor.d/groups/freedesktop/geoclue b/apparmor.d/groups/freedesktop/geoclue index 6332f49e23..b0319d2095 100644 --- a/apparmor.d/groups/freedesktop/geoclue +++ b/apparmor.d/groups/freedesktop/geoclue @@ -9,13 +9,15 @@ include @{exec_path} = @{lib}/geoclue @{lib}/geoclue-2.0/demos/agent profile geoclue @{exec_path} flags=(attach_disconnected) { include - include include - include - include - include - include + include + include + include + include + include + include include + include include include @@ -29,13 +31,13 @@ profile geoclue @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, - /usr/share/glib-2.0/schemas/gschemas.compiled r, - /etc/geoclue/{,**} r, /etc/sysconfig/proxy r, /var/lib/nscd/services r, - /var/lib/dbus/machine-id r, + + @{run}/systemd/resolve/io.systemd.Resolve rw, + @{att}@{run}/systemd/resolve/io.systemd.Resolve rw, @{PROC}/@{pids}/cgroup r, @{PROC}/sys/net/ipv{4,6}/conf/all/disable_ipv{4,6} r, diff --git a/apparmor.d/groups/freedesktop/iio-sensor-proxy b/apparmor.d/groups/freedesktop/iio-sensor-proxy index d7122bdbbc..2f88aef125 100644 --- a/apparmor.d/groups/freedesktop/iio-sensor-proxy +++ b/apparmor.d/groups/freedesktop/iio-sensor-proxy @@ -7,10 +7,13 @@ abi , include @{exec_path} = @{lib}/iio-sensor-proxy -profile iio-sensor-proxy @{exec_path} { +profile iio-sensor-proxy @{exec_path} flags=(attach_disconnected) { include + include + include capability net_admin, + capability sys_admin, network netlink raw, @@ -18,8 +21,10 @@ profile iio-sensor-proxy @{exec_path} { @{exec_path} mr, - @{run}/udev/data/+platform:* r, + @{run}/udev/data/+acpi:* r, # Exposes ACPI objects (power buttons, batteries, thermal) @{run}/udev/data/+input:input@{int} r, # for mouse, keyboard, touchpad + @{run}/udev/data/+platform:* r, # Identifies onboard devices (laptop/board model, power controllers, thermal sensors) + @{run}/udev/data/+sound:card@{int} r, # For sound card @{run}/udev/data/c13:@{int} r, # For /dev/input/* @{run}/udev/data/c@{dynamic}:@{int} r, # For dynamic assignment range 234 to 254, 384 to 511 @@ -28,10 +33,11 @@ profile iio-sensor-proxy @{exec_path} { @{sys}/bus/platform/devices/ r, @{sys}/class/ r, @{sys}/class/input/ r, - @{sys}/devices/**/uevent r, @{sys}/devices/@{pci}/ r, @{sys}/devices/@{pci}/iio:*/** rw, @{sys}/devices/@{pci}/name r, + @{sys}/devices/**/input@{int}/capabilities/sw r, + @{sys}/devices/**/uevent r, /dev/iio:* r, diff --git a/apparmor.d/groups/freedesktop/pipewire b/apparmor.d/groups/freedesktop/pipewire index f4c9367cd2..9f9ffcbd6a 100644 --- a/apparmor.d/groups/freedesktop/pipewire +++ b/apparmor.d/groups/freedesktop/pipewire @@ -13,22 +13,24 @@ profile pipewire @{exec_path} flags=(attach_disconnected) { include include include - include + include + include + include include - include + include capability sys_ptrace, network netlink raw, - ptrace (read), + ptrace read, #aa:dbus own bus=session name=org.pulseaudio.Server dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mrix, @@ -40,18 +42,20 @@ profile pipewire @{exec_path} flags=(attach_disconnected) { /etc/pipewire/{,**} r, / r, - @{att}/ r, - owner @{att}// r, + /att/**/ r, owner @{att}/.flatpak-info r, owner @{user_config_dirs}/pipewire/{,**} r, owner @{tmp}/librnnoise-@{int}.so rm, + @{run}/snapd.socket rw, owner @{run}/user/@{uid}/pipewire-@{int} rw, + owner @{run}/user/@{uid}/pipewire-@{int}-manager rw, owner @{run}/user/@{uid}/pipewire-@{int}-manager.lock rwk, owner @{run}/user/@{uid}/pipewire-@{int}.lock rwk, owner @{run}/user/@{uid}/pulse/pid rw, + owner @{run}/user/@{uid}/xauth_@{rand6} r, @{run}/udev/data/c@{dynamic}:@{int} r, # For dynamic assignment range 234 to 254, 384 to 511 @@ -60,13 +64,11 @@ profile pipewire @{exec_path} flags=(attach_disconnected) { @{sys}/class/ r, @{sys}/devices/@{pci}/usb@{int}/**/{idVendor,idProduct,removable,uevent} r, @{sys}/devices/**/device:*/**/path r, - @{sys}/devices/virtual/dmi/id/{sys_vendor,product_version,product_name,bios_vendor,board_vendor} r, @{sys}/module/apparmor/parameters/enabled r, + 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 af6f30e9c9..5ccc912010 100644 --- a/apparmor.d/groups/freedesktop/pipewire-media-session +++ b/apparmor.d/groups/freedesktop/pipewire-media-session @@ -13,10 +13,10 @@ profile pipewire-media-session @{exec_path} { include include include - include + include + include include include - include network bluetooth raw, network bluetooth seqpacket, @@ -26,7 +26,7 @@ profile pipewire-media-session @{exec_path} { dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, diff --git a/apparmor.d/groups/freedesktop/pipewire-pulse b/apparmor.d/groups/freedesktop/pipewire-pulse index 530fa97dba..5dbc39af87 100644 --- a/apparmor.d/groups/freedesktop/pipewire-pulse +++ b/apparmor.d/groups/freedesktop/pipewire-pulse @@ -11,15 +11,22 @@ include profile pipewire-pulse @{exec_path} flags=(attach_disconnected) { include include + include + include + include include + include capability sys_ptrace, - ptrace (read), + ptrace read, + + #aa:dbus own bus=session name=org.pulseaudio.Server @{exec_path} mr, @{bin}/pactl rix, + @{bin}/pipewire mr, /usr/share/pipewire/{,**} r, @@ -34,10 +41,9 @@ profile pipewire-pulse @{exec_path} flags=(attach_disconnected) { owner @{run}/user/@{uid}/pulse/pid w, owner @{tmp}/librnnoise-@{int}.so rm, - @{sys}/devices/virtual/dmi/id/product_name r, - @{sys}/devices/virtual/dmi/id/sys_vendor r, - @{sys}/devices/virtual/dmi/id/board_vendor r, - @{sys}/devices/virtual/dmi/id/bios_vendor r, + @{sys}/module/apparmor/parameters/enabled r, + + owner @{PROC}/@{pid}/task/@{tid}/comm rw, include if exists } diff --git a/apparmor.d/groups/freedesktop/pkla-check-authorization b/apparmor.d/groups/freedesktop/pkla-check-authorization new file mode 100644 index 0000000000..ff5b72f719 --- /dev/null +++ b/apparmor.d/groups/freedesktop/pkla-check-authorization @@ -0,0 +1,18 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/pkla-check-authorization +profile pkla-check-authorization @{exec_path} { + include + + @{exec_path} mr, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/freedesktop/plymouth-set-default-theme b/apparmor.d/groups/freedesktop/plymouth-set-default-theme index bd5a34dcd9..da13572e53 100644 --- a/apparmor.d/groups/freedesktop/plymouth-set-default-theme +++ b/apparmor.d/groups/freedesktop/plymouth-set-default-theme @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/plymouth-set-default-theme +@{exec_path} = @{sbin}/plymouth-set-default-theme profile plymouth-set-default-theme @{exec_path} flags=(attach_disconnected) { include include @@ -15,7 +15,7 @@ profile plymouth-set-default-theme @{exec_path} flags=(attach_disconnected) { @{sh_path} rix, @{bin}/{m,g,}awk rix, - @{bin}/grep rix, + @{bin}/{,e}grep rix, @{bin}/plymouth rPx, /usr/share/plymouth/{,**} r, diff --git a/apparmor.d/groups/freedesktop/plymouthd b/apparmor.d/groups/freedesktop/plymouthd index 1b004021f9..4abefb8c9a 100644 --- a/apparmor.d/groups/freedesktop/plymouthd +++ b/apparmor.d/groups/freedesktop/plymouthd @@ -6,12 +6,13 @@ abi , include -@{exec_path} = @{bin}/plymouthd +@{exec_path} = @{sbin}/plymouthd profile plymouthd @{exec_path} { include include include include + include include capability checkpoint_restore, @@ -24,11 +25,11 @@ profile plymouthd @{exec_path} { network netlink raw, - signal (send) peer=unconfined, - signal (send) set=(rtmin+23) peer=@{p_systemd}, - signal (send) set=(rtmin+23) peer=systemd-shutdown, + signal send peer=unconfined, + signal send set=(rtmin+23) peer=@{p_systemd}, + signal send set=(rtmin+23) peer=systemd-shutdown, - ptrace (read) peer=plymouth, + ptrace read peer=plymouth, unix type=stream addr="@/org/freedesktop/plymouthd", unix type=stream peer=(addr="@/org/freedesktop/plymouthd"), @@ -42,33 +43,38 @@ profile plymouthd @{exec_path} { /etc/plymouth/plymouthd.conf r, /etc/vconsole.conf r, + / r, + /var/lib/plymouth/{,**} rw, + /var/log/boot.log w, /var/log/plymouth-*.log w, + @{run}/initramfs/usr/share/fonts/{,**} r, @{run}/plymouth/{,**} rw, + @{run}/systemd/fsck.progress w, @{run}/udev/data/+drm:card@{int}-* r, # For screen outputs - @{run}/udev/data/c226:@{int} r, # For /dev/dri/card[0-9]* @{run}/udev/data/c29:@{int} r, # For /dev/fb[0-9]* @{sys}/bus/ r, @{sys}/class/ r, @{sys}/class/drm/ r, @{sys}/class/graphics/ r, - @{sys}/devices/virtual/graphics/fbcon/uevent r, + @{sys}/devices/**/uevent r, @{sys}/devices/virtual/tty/console/active r, @{sys}/firmware/acpi/bgrt/{,*} r, @{sys}/firmware/efi/efivars/SecureBoot-@{uuid} r, @{PROC}/1/cmdline r, @{PROC}/cmdline r, + @{PROC}/consoles r, @{PROC}/sys/kernel/printk r, owner @{PROC}/@{pid}/cmdline r, owner @{PROC}/@{pid}/stat r, /dev/kmsg rw, /dev/ptmx rw, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, /dev/ttyS@{int} rw, include if exists diff --git a/apparmor.d/groups/freedesktop/polkit-gnome-authentication-agent b/apparmor.d/groups/freedesktop/polkit-gnome-authentication-agent index f1ca0fd31e..37cd951d8a 100644 --- a/apparmor.d/groups/freedesktop/polkit-gnome-authentication-agent +++ b/apparmor.d/groups/freedesktop/polkit-gnome-authentication-agent @@ -12,8 +12,6 @@ include @{exec_path} += @{lib}/polkit-gnome/polkit-gnome-authentication-agent-1 profile polkit-gnome-authentication-agent @{exec_path} { include - include - include include include include diff --git a/apparmor.d/groups/freedesktop/polkit-kde-authentication-agent b/apparmor.d/groups/freedesktop/polkit-kde-authentication-agent index f53f4d1643..da8e5bff4a 100644 --- a/apparmor.d/groups/freedesktop/polkit-kde-authentication-agent +++ b/apparmor.d/groups/freedesktop/polkit-kde-authentication-agent @@ -11,9 +11,11 @@ include @{exec_path} += @{lib}/polkit-kde-authentication-agent-[0-9] profile polkit-kde-authentication-agent @{exec_path} flags=(attach_disconnected,mediate_deleted) { include + include include include include + include include include include @@ -26,6 +28,9 @@ profile polkit-kde-authentication-agent @{exec_path} flags=(attach_disconnected, signal (send) set=(term, kill) peer=polkit-agent-helper, + #aa:dbus own bus=session name=org.kde.polkit-kde-authentication-agent-@{int} + #aa:dbus talk bus=system name=org.freedesktop.PolicyKit1 label=polkitd + @{exec_path} mr, @{lib}/polkit-[0-9]/polkit-agent-helper-[0-9] rPx, @@ -36,6 +41,7 @@ profile polkit-kde-authentication-agent @{exec_path} flags=(attach_disconnected, owner @{user_config_dirs}/breezerc r, owner @{user_config_dirs}/kdedefaults/plasmarc r, + owner @{user_config_dirs}/Kvantum/{,**} r, owner @{user_cache_dirs}/polkit-kde-authentication-agent-@{int}/ rw, owner @{user_cache_dirs}/polkit-kde-authentication-agent-@{int}/** rwk, diff --git a/apparmor.d/groups/freedesktop/polkit-mate-authentication-agent b/apparmor.d/groups/freedesktop/polkit-mate-authentication-agent index 0dfea75251..8445e857ba 100644 --- a/apparmor.d/groups/freedesktop/polkit-mate-authentication-agent +++ b/apparmor.d/groups/freedesktop/polkit-mate-authentication-agent @@ -29,7 +29,7 @@ profile polkit-mate-authentication-agent @{exec_path} { owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/fd/ r, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/freedesktop/pulseaudio b/apparmor.d/groups/freedesktop/pulseaudio index 804020b7bd..f21bc07bdc 100644 --- a/apparmor.d/groups/freedesktop/pulseaudio +++ b/apparmor.d/groups/freedesktop/pulseaudio @@ -12,24 +12,27 @@ include profile pulseaudio @{exec_path} { include include - include - include - include - include - include - include + include + include + include + include + include + include + include include include + include include include - include include include + include include + include - ptrace (trace) peer=@{profile_name}, + ptrace trace peer=@{profile_name}, - signal (receive) peer=pacmd, + signal receive peer=pacmd, network inet stream, network inet6 stream, @@ -45,28 +48,13 @@ profile pulseaudio @{exec_path} { dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), - - dbus receive bus=system path=/Client@{int}/ServiceResolver@{int} - interface=org.freedesktop.Avahi.ServiceResolver - member=Found - peer=(name=:*, label=avahi-daemon), - - dbus receive bus=system path=/Client@{int}/ServiceBrowser@{int} - interface=org.freedesktop.Avahi.ServiceBrowser - member=ItemRemove - peer=(name=:*, label=avahi-daemon), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), dbus send bus=system path=/ interface=org.freedesktop.DBus.ObjectManager member=GetManagedObjects peer=(name=org.bluez), - dbus send bus=system path=/Client@{int}/ServiceResolver@{int} - interface=org.freedesktop.Avahi.ServiceResolver - member={Found,Free} - peer=(name=org.freedesktop.Avahi, label=avahi-daemon), - @{exec_path} mrix, @{lib}/pulse/gsettings-helper rix, @@ -80,18 +68,13 @@ profile pulseaudio @{exec_path} { / r, - owner @{desktop_cache_dirs}/gstreamer-1.0/ rw, - owner @{desktop_cache_dirs}/gstreamer-1.0/registry.*.bin{,.tmp@{rand6}} rw, - owner @{desktop_config_dirs}/dconf/user r, - owner @{desktop_config_dirs}/pulse/{,**} rw, - owner @{desktop_config_dirs}/pulse/cookie k, + owner @{desktop_config_dirs}/pulse/{,**} rw, + owner @{desktop_config_dirs}/pulse/cookie k, owner @{HOME}/.pulse/{,**} rw, owner @{user_config_dirs}/ w, owner @{user_config_dirs}/pulse/{,**} rw, - owner @{user_cache_dirs}/gstreamer-1.0/registry.*.bin r, - owner @{run}/user/@{uid}/ rw, owner @{run}/user/@{uid}/pulse/ rw, owner @{run}/user/@{uid}/pulse/** rwk, @@ -104,8 +87,6 @@ profile pulseaudio @{exec_path} { @{run}/udev/data/c@{dynamic}:@{int} r, # For dynamic assignment range 234 to 254, 384 to 511 @{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,11 +94,8 @@ 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, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/freedesktop/update-desktop-database b/apparmor.d/groups/freedesktop/update-desktop-database index 90be74ecf4..0313606b65 100644 --- a/apparmor.d/groups/freedesktop/update-desktop-database +++ b/apparmor.d/groups/freedesktop/update-desktop-database @@ -11,8 +11,7 @@ include profile update-desktop-database @{exec_path} flags=(attach_disconnected) { include include - include - include + include capability dac_override, capability dac_read_search, diff --git a/apparmor.d/groups/freedesktop/update-mime-database b/apparmor.d/groups/freedesktop/update-mime-database index 9efd9cccc4..1c7cf6010c 100644 --- a/apparmor.d/groups/freedesktop/update-mime-database +++ b/apparmor.d/groups/freedesktop/update-mime-database @@ -23,8 +23,8 @@ profile update-mime-database @{exec_path} flags=(attach_disconnected) { owner @{user_share_dirs}/mime/{,**} rw, - /dev/tty@{int} rw, - owner /dev/pts/@{int} rw, + /dev/tty@{u8} rw, + owner /dev/pts/@{u16} rw, # Inherit silencer deny network inet6 stream, diff --git a/apparmor.d/groups/freedesktop/upower b/apparmor.d/groups/freedesktop/upower index 931b47509e..83652914f6 100644 --- a/apparmor.d/groups/freedesktop/upower +++ b/apparmor.d/groups/freedesktop/upower @@ -13,7 +13,7 @@ profile upower @{exec_path} { include include - #aa:dbus own bus=system name=org.freedesktop.UPower label=upowerd + #aa:dbus talk bus=system name=org.freedesktop.UPower label="@{p_upowerd}" @{exec_path} mr, diff --git a/apparmor.d/groups/freedesktop/upowerd b/apparmor.d/groups/freedesktop/upowerd index f832d285e9..39fd3803c6 100644 --- a/apparmor.d/groups/freedesktop/upowerd +++ b/apparmor.d/groups/freedesktop/upowerd @@ -10,10 +10,17 @@ include @{exec_path} = @{lib}/{,upower/}upowerd profile upowerd @{exec_path} flags=(attach_disconnected) { include + include + include include - include - include + include + include include + include + include + + capability net_admin, + capability sys_admin, network netlink raw, @@ -21,43 +28,39 @@ profile upowerd @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, - /etc/UPower/ r, - /etc/UPower/UPower.conf r, + /etc/UPower/{,**} r, /var/lib/upower/ r, /var/lib/upower/history-*.dat{,.*} rw, - @{run}/udev/data/ r, - @{run}/udev/data/+acpi:* r, # for acpi - @{run}/udev/data/+hid:* r, # for HID-Compliant Keyboard - @{run}/udev/data/+i2c:* r, - @{run}/udev/data/+input:input@{int} r, # for mouse, keyboard, touchpad + / r, + + owner /tmp/tmp@{rand8} r, + owner /tmp/umockdev.@{rand6}/{,**} rw, + owner /tmp/upower-cfg-@{word8} rw, + owner /tmp/upower-history-@{word8}/{,**} rw, + + @{run}/udev/data/ r, # Lists all udev data files + @{run}/udev/data/+acpi:* r, # Exposes ACPI objects (power buttons, batteries, thermal) + @{run}/udev/data/+hid:* r, # For Human Interface Device (mice, controllers, drawing tablets, scanners) + @{run}/udev/data/+i2c:* r, # For Inter-Integrated Circuit, low-speed peripherals (sensors, EEPROMs, etc.) @{run}/udev/data/+pci:* r, # Identifies all PCI devices (CPU, GPU, Network, Disks, USB, etc.) - @{run}/udev/data/+platform:* r, + @{run}/udev/data/+platform:* r, # Identifies onboard devices (laptop/board model, power controllers, thermal sensors) + @{run}/udev/data/+power_supply:* r, # For power supply devices (batteries, AC adapters, USB chargers) @{run}/udev/data/+serio:* r, # for serial mice - @{run}/udev/data/+power_supply* r, @{run}/udev/data/+sound:card@{int} r, # for sound card @{run}/udev/data/c10:@{int} r, # for non-serial mice, misc features - @{run}/udev/data/c13:@{int} r, # for /dev/input/* + @{run}/udev/data/c14:@{int} r, # Open Sound System (OSS) @{run}/udev/data/c116:@{int} r, # for ALSA - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, @{sys}/bus/hid/devices/ r, - @{sys}/class/input/ r, - @{sys}/class/leds/ r, @{sys}/class/power_supply/ r, @{sys}/class/sound/ r, @{sys}/devices/ r, - @{sys}/devices/**/capabilities/* r, - @{sys}/devices/**/leds/**/brightness rw, - @{sys}/devices/**/leds/**/brightness_hw_changed r, - @{sys}/devices/**/leds/**/max_brightness r, @{sys}/devices/**/power_supply/**/* r, @{sys}/devices/**/uevent r, - @{sys}/devices/virtual/dmi/id/product_name r, - - /dev/input/event* r, include if exists } diff --git a/apparmor.d/groups/freedesktop/wireplumber b/apparmor.d/groups/freedesktop/wireplumber index 7d0836f7ac..8363c282c7 100644 --- a/apparmor.d/groups/freedesktop/wireplumber +++ b/apparmor.d/groups/freedesktop/wireplumber @@ -7,29 +7,42 @@ abi , include @{exec_path} = @{bin}/wireplumber -profile wireplumber @{exec_path} { +profile wireplumber @{exec_path} flags=(attach_disconnected) { include - include include + include include include - include - include + include + include + include include + include include - include + include + include + + capability sys_ptrace, network bluetooth raw, network bluetooth seqpacket, network bluetooth stream, network netlink raw, + ptrace read, + #aa:dbus own bus=session name=org.freedesktop.ReserveDevice1.Audio@{int} + #aa:dbus own bus=session name=org.pipewire.Telephony dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), + + dbus receive bus=system path=/midi{,server@{int}} + interface=org.freedesktop.DBus.ObjectManager + member=GetManagedObjects + peer=(name=@{busname}, label="@{p_bluetoothd}"), @{exec_path} mr, @@ -40,9 +53,13 @@ profile wireplumber @{exec_path} { /usr/share/spa-*/bluez@{int}/{,*} r, /usr/share/wireplumber/{,**} r, + / r, + /att/**/ r, + owner @{att}/.flatpak-info r, + owner @{desktop_local_dirs}/ w, - owner @{desktop_local_dirs}/state/ w, - owner @{desktop_local_dirs}/state/wireplumber/{,**} rw, + owner @{desktop_state_dirs}/ w, + owner @{desktop_state_dirs}/wireplumber/{,**} rw, owner @{HOME}/.local/ w, owner @{user_state_dirs}/ w, @@ -50,33 +67,32 @@ profile wireplumber @{exec_path} { owner @{user_config_dirs}/wireplumber/{,**} r, owner @{run}/user/@{uid}/pipewire-@{int} rw, + owner @{run}/user/@{uid}/pipewire-@{int}-manager rw, - /dev/shm/lttng-ust-wait-@{int} r, - owner /dev/shm/lttng-ust-wait-@{int}-@{uid} rw, - owner /dev/shm/lttng-ust-wait-@{int}-@{int} rw, + @{run}/snapd.socket rw, @{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, + @{sys}/devices/**/uevent r, @{sys}/devices/system/node/ r, @{sys}/devices/system/node/node@{int}/meminfo r, - @{sys}/devices/virtual/dmi/id/bios_vendor r, - @{sys}/devices/virtual/dmi/id/product_name r, - @{sys}/devices/virtual/dmi/id/sys_vendor r, + @{PROC}/@{pids}/ r, + @{PROC}/@{pids}/cgroup r, + @{PROC}/@{pids}/cmdline r, + @{PROC}/@{pids}/status r, + owner @{PROC}/@{pid}/stat 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/wmname b/apparmor.d/groups/freedesktop/wmname new file mode 100644 index 0000000000..1d2c7aa23d --- /dev/null +++ b/apparmor.d/groups/freedesktop/wmname @@ -0,0 +1,20 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2024 Roman Beslik +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/wmname +profile wmname @{exec_path} { + include + include + + @{exec_path} mr, + owner @{HOME}/.Xauthority r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/freedesktop/xdg-dbus-proxy b/apparmor.d/groups/freedesktop/xdg-dbus-proxy index c6efaf3602..5400a7946c 100644 --- a/apparmor.d/groups/freedesktop/xdg-dbus-proxy +++ b/apparmor.d/groups/freedesktop/xdg-dbus-proxy @@ -9,30 +9,37 @@ include @{exec_path} = @{bin}/xdg-dbus-proxy profile xdg-dbus-proxy @{exec_path} flags=(attach_disconnected) { include - include - include + include include include - include - include - include - include + include + include + include + include include network unix stream, - dbus send bus=session path=/org/freedesktop/portal/desktop - interface=org.freedesktop.portal.Realtime - member=MakeThread* - peer=(name=org.freedesktop.portal.Desktop, label=xdg-desktop-portal), + unix (send receive) type=seqpacket peer=(label=fapp), + unix (send receive) type=seqpacket peer=(label=fbwrap), + + signal receive peer=flatpak-portal, + + # By design xdg-dbus-proxy proxies and filters dbus communication from flatpak + # apps to the system. Thus, it can manage the full system and session buses. + dbus bus=session, + dbus bus=system, @{exec_path} mr, - owner @{att}/@{HOME}/.var/app/** r, - owner @{HOME}/.var/app/*/.local/share/*/logs/* rw, - owner @{HOME}/.var/app/*/.local/share/*/**/usr/.ref rw, + owner @{att}@{HOME}/.var/app/** r, + owner @{att}@{HOME}/.var/app/*/.local/share/*/logs/* rw, + owner @{att}@{HOME}/.var/app/*/.local/share/*/**/usr/.ref rw, + + @{att}@{run}/systemd/inhibit/@{int}.ref rw, + owner @{att}@{run}/user/@{uid}/at-spi/bus rw, + owner @{att}@{run}/user/@{uid}/bus rw, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, owner @{run}/firejail/dbus/@{int}/@{int}-{system,user} rw, owner @{run}/flatpak/doc/** r, owner @{run}/user/@{uid}/.dbus-proxy/{system,session,a11y}-bus-proxy-@{rand6} rw, @@ -40,12 +47,8 @@ profile xdg-dbus-proxy @{exec_path} flags=(attach_disconnected) { owner @{run}/user/@{uid}/webkitgtk/bus-proxy-@{rand6} rw, owner @{run}/user/@{uid}/webkitgtk/dbus-proxy-@{rand6} rw, - @{sys}/devices/virtual/thermal/thermal_zone@{int}/hwmon@{int}/temp* r, - /dev/dri/card@{int} rw, - deny owner @{user_share_dirs}/gvfs-metadata/{,*} r, - include if exists } diff --git a/apparmor.d/groups/freedesktop/xdg-desktop-icon b/apparmor.d/groups/freedesktop/xdg-desktop-icon index a6200a2b22..485c86f2e3 100644 --- a/apparmor.d/groups/freedesktop/xdg-desktop-icon +++ b/apparmor.d/groups/freedesktop/xdg-desktop-icon @@ -9,29 +9,10 @@ include @{exec_path} = @{bin}/xdg-desktop-icon profile xdg-desktop-icon @{exec_path} { include - include + include @{exec_path} r, - @{sh_path} rix, - @{bin}/{,e}grep ix, - @{bin}/basename ix, - @{bin}/cat ix, - @{bin}/chmod ix, - @{bin}/cp ix, - @{bin}/cut ix, - @{bin}/mkdir ix, - @{bin}/readlink ix, - @{bin}/realpath ix, - @{bin}/rm ix, - @{bin}/sed ix, - @{bin}/tr ix, - @{bin}/umask ix, - @{bin}/uname ix, - - # To get DE information - @{bin}/kde{,4}-config ix, - @{bin}/dbus-send Cx -> bus, @{bin}/xprop Px, @@ -39,6 +20,7 @@ profile xdg-desktop-icon @{exec_path} { include include include + include include if exists } diff --git a/apparmor.d/groups/freedesktop/xdg-desktop-menu b/apparmor.d/groups/freedesktop/xdg-desktop-menu index f86fbedc8e..c28f224ee3 100644 --- a/apparmor.d/groups/freedesktop/xdg-desktop-menu +++ b/apparmor.d/groups/freedesktop/xdg-desktop-menu @@ -10,36 +10,14 @@ include @{exec_path} = @{bin}/xdg-desktop-menu profile xdg-desktop-menu @{exec_path} flags=(complain) { include - include - include + include include @{exec_path} r, @{sh_path} rix, - @{bin}/{,e}grep ix, - @{bin}/{m,g,}awk ix, - @{bin}/basename ix, - @{bin}/cat ix, - @{bin}/chmod ix, - @{bin}/cp ix, - @{bin}/cut ix, - @{bin}/dirname ix, - @{bin}/ln ix, - @{bin}/mkdir ix, - @{bin}/mktemp ix, - @{bin}/mv ix, - @{bin}/readlink ix, - @{bin}/realpath ix, - @{bin}/rm ix, - @{bin}/sed ix, - @{bin}/touch ix, - @{bin}/tr ix, - @{bin}/umask ix, - @{bin}/uname ix, - - # To get DE information - @{bin}/kde{,4}-config ix, + @{bin}/chmod rix, + @{bin}/id rPx, @{bin}/dbus-send Cx -> bus, @{bin}/update-desktop-database Px, @@ -49,6 +27,8 @@ profile xdg-desktop-menu @{exec_path} flags=(complain) { include include include + include + include if exists } diff --git a/apparmor.d/groups/freedesktop/xdg-desktop-portal b/apparmor.d/groups/freedesktop/xdg-desktop-portal index ae20e37514..991d6cbd45 100644 --- a/apparmor.d/groups/freedesktop/xdg-desktop-portal +++ b/apparmor.d/groups/freedesktop/xdg-desktop-portal @@ -10,18 +10,22 @@ include profile xdg-desktop-portal @{exec_path} flags=(attach_disconnected) { include include - include include include include - include - include - include - include + include + include + include include + include + include include - include + include + include include + include + include + include include include include @@ -29,64 +33,104 @@ profile xdg-desktop-portal @{exec_path} flags=(attach_disconnected) { capability sys_ptrace, network netlink raw, + network inet dgram, + network inet6 dgram, + network inet dgram, ptrace read, signal receive set=term peer=gdm, signal receive set=hup peer=gdm-session-worker, - #aa:dbus own bus=session name=org.freedesktop.portal.Desktop path=/org/freedesktop/portal/desktop interface={org.freedesktop.DBus.Properties,org.freedesktop{,.impl}.portal.{Settings,Background}} + unix (send receive) type=stream peer=(label=fapp), + unix (send receive) type=stream peer=(label=fbwrap), + unix (send receive) type=stream peer=(label=flatpak.*), + unix (send receive) type=stream peer=(label=snap.*), + + #aa:dbus own bus=session name=org.freedesktop.portal interface+=org.freedesktop.impl.portal + dbus receive bus=session path=/org/freedesktop/portal/desktop - interface=org.freedesktop.portal.Realtime - member=MakeThread* - peer=(name=:*), + interface=org.freedesktop.impl.portal.Settings + member=SettingChanged + peer=(name=@{busname}), + + # Receive registertration of from anyone + dbus receive bus=session path=/org/freedesktop/portal/desktop + interface=org.freedesktop.host.portal.Registry + member=Register + peer=(name=@{busname}), #aa:dbus own bus=session name=org.freedesktop.background.Monitor path=/org/freedesktop/background/monitor + #aa:dbus own bus=session name=org.freedesktop.impl.portal path=/org/freedesktop/portal/desktop{,/**} + #aa:dbus talk bus=session name=org.freedesktop.FileManager1 label=nautilus #aa:dbus talk bus=session name=org.freedesktop.portal.Documents path=/org/freedesktop/portal/documents label=xdg-document-portal + dbus send bus=session path=/org/freedesktop/portal/desktop + interface=org.freedesktop.impl.portal.Secret + member=RetrieveSecret + peer=(name=@{busname}, label=gnome-keyring-daemon), + dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), + + # FIXME: This should have been included in the talk directive + dbus send bus=session path=/org/freedesktop/FileManager1 + interface=org.freedesktop.FileManager1 + member=ShowItems + peer=(name=org.freedesktop.FileManager1), + + dbus send bus=session path=/org/gnome/Nautilus + interface=org.freedesktop.Application + member=Open + peer=(name=org.gnome.Nautilus), @{exec_path} mr, @{sh_path} rix, @{bin}/nautilus rPx, - @{bin}/kreadconfig{,5} rPx, + @{bin}/browserpass rPx, + @{bin}/kreadconfig{,5,6} rPx, + @{lib}/browserpass/browserpass-native rPx, @{lib}/xdg-desktop-portal-validate-icon rPx, - @{open_path} rPx -> child-open, - - / r, - @{att}/.flatpak-info r, - owner @{att}/ r, + @{open_path} mrPx -> child-open-any, - /usr/share/dconf/profile/gdm r, /usr/share/xdg-desktop-portal/** r, - /usr/share/gdm/greeter-dconf-defaults r, /etc/sysconfig/proxy r, + / r, + /att/**/ r, + @{att}/ r, + @{att}/.flatpak-info r, + + owner /var/lib/gdm/seat@{int}/config/evolution/sources/ r, + owner /var/lib/gdm/seat@{int}/config/evolution/sources/system-proxy.source r, + @{GDM_HOME}/greeter-dconf-defaults r, - owner @{gdm_config_dirs}/dconf/user r, owner @{gdm_config_dirs}/user-dirs.dirs r, + # The portal can receive any user file as it is a file chooser for UI app. + owner @{HOME}/** r, + owner @{HOME}/.var/app/*/{,**} rw, + @{user_config_dirs}/kioslaverc r, owner @{user_config_dirs}/xdg-desktop-portal/* r, owner @{user_share_dirs}/xdg-desktop-portal/{,**} rw, + owner @{tmp}/gtkprint@{rand6} r, owner @{tmp}/icon@{rand6} rw, + owner @{att}@{run}/flatpak/doc/** r, owner @{run}/user/@{uid}/.flatpak/{,*/*} r, - @{sys}/devices/virtual/dmi/id/bios_vendor r, - @{sys}/devices/virtual/dmi/id/board_vendor r, - @{sys}/devices/virtual/dmi/id/product_name r, - @{sys}/devices/virtual/dmi/id/sys_vendor r, + @{sys}/devices/**/uevent r, @{PROC}/ r, + @{PROC}/@{pids}/status r, @{PROC}/*/ r, @{PROC}/1/cgroup r, @{PROC}/cmdline r, diff --git a/apparmor.d/groups/freedesktop/xdg-desktop-portal-gnome b/apparmor.d/groups/freedesktop/xdg-desktop-portal-gnome index ac321fd07b..7762f7d27d 100644 --- a/apparmor.d/groups/freedesktop/xdg-desktop-portal-gnome +++ b/apparmor.d/groups/freedesktop/xdg-desktop-portal-gnome @@ -9,14 +9,10 @@ include @{exec_path} = @{lib}/xdg-desktop-portal-gnome profile xdg-desktop-portal-gnome @{exec_path} flags=(attach_disconnected) { include + include + include + include include - include - include - include - include - include - include - include include include include @@ -27,52 +23,100 @@ profile xdg-desktop-portal-gnome @{exec_path} flags=(attach_disconnected) { network unix stream, - signal (receive) set=term peer=gdm, - signal (receive) set=(hup term) peer=gdm-session-worker, + signal receive set=term peer=gdm, + signal receive set=(hup term) peer=gdm-session-worker, #aa:dbus own bus=session name=org.freedesktop.impl.portal.desktop.gnome - #aa:dbus talk bus=session name=org.freedesktop.impl.portal path=/org/freedesktop/portal/desktop label=xdg-desktop-portal + #aa:dbus own bus=session name=org.freedesktop.impl.portal.FileChooser path=/org/freedesktop/portal/desktop + + #aa:dbus talk bus=session name=org.freedesktop.impl.portal.* path=/org/freedesktop/portal/desktop label=xdg-desktop-portal #aa:dbus talk bus=session name=org.gnome.Mutter label=gnome-shell + #aa:dbus talk bus=session name=org.gnome.Settings.GlobalShortcutsProvider label=gnome-control-center-global-shortcuts-provider + #aa:dbus talk bus=session name=org.gnome.Shell label=gnome-shell #aa:dbus talk bus=session name=org.gnome.Shell.Screenshot label=gnome-shell + #aa:dbus talk bus=session name=org.gtk.Private.RemoteVolumeMonitor label="gvfs-*-volume-monitor" dbus send bus=session path=/org/freedesktop/portal/desktop - interface=org.freedesktop.impl.portal.Background - member=RunningApplicationsChanged - peer=(name=org.freedesktop.DBus, label=xdg-desktop-portal), + interface=org.freedesktop.impl.portal.FileChooser, + + dbus send bus=session path=/org/gnome/Shell + interface=org.freedesktop.DBus.Properties + member=GetAll + peer=(name=@{busname}, label=gnome-shell), + dbus receive bus=session path=/org/gnome/Shell + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name=@{busname}, label=gnome-shell), @{exec_path} mr, / r, @{bin}/ r, @{bin}/* r, + @{bin}/flatpak rCx -> flatpak, /opt/** r, - /usr/share/dconf/profile/gdm r, - /usr/share/gdm/greeter-dconf-defaults r, + @{open_path} rPx -> child-open-any, + + /usr/share/gdm/greeter/applications/{,**} r, /usr/share/thumbnailers/{,**} r, - owner @{desktop_cache_dirs}/dconf/user r, + /snap/*/@{uid}/**.@{icon_ext} r, + /var/lib/flatpak/app/*/@{arch}/ r, + /var/lib/flatpak/repo/config r, + /var/lib/flatpak/runtime/*/@{arch}/ r, + owner @{desktop_cache_dirs}/fontconfig/[a-f0-9]*.cache-?{,.NEW,.LCK,.TMP-*} rw, - owner @{desktop_config_dirs}/dconf/user r, - owner @{DESKTOP_HOME}/greeter-dconf-defaults r, + owner @{desktop_share_dirs}/applications/{,**} r, owner @{HOME}/ r, owner @{HOME}/* r, owner @{HOME}/*/{,**} rw, owner @{MOUNTS}/ r, + owner @{tmp}/.@{rand6} rw, owner @{tmp}/.goutputstream-@{rand6} rw, owner @{tmp}/@{rand6} rw, + owner @{tmp}/gtkprint_ppd_@{rand6} rw, + owner @{tmp}/gtkprint@{rand6} r, + owner @{tmp}/settings@{rand6}.ini rw, + owner @{tmp}/settings@{rand6}.ini.@{rand6} rw, + owner @{tmp}/xdg-desktop-portal-gnome@{rand6} rw, + + owner @{run}/user/@{uid}/gvfsd/socket-@{rand8} rw, @{run}/mount/utab r, + @{sys}/devices/**/uevent r, + owner @{PROC}/@{pid}/ r, owner @{PROC}/@{pid}/cmdline r, owner @{PROC}/@{pid}/mountinfo r, + owner @{PROC}/@{pid}/stat r, owner @{PROC}/@{pid}/task/@{tid}/ r, owner @{PROC}/@{pid}/task/@{tid}/comm rw, owner @{PROC}/@{pid}/task/@{tid}/status r, + profile flatpak { + include + include + include + + @{bin}/flatpak mr, + + /var/lib/flatpak/app/{,*/} r, + /var/lib/flatpak/app/*/@{arch}/ r, + /var/lib/flatpak/repo/{,*/} r, + /var/lib/flatpak/repo/config r, + /var/lib/flatpak/runtime/{,*/} r, + /var/lib/flatpak/runtime/*/@{arch}/ r, + + owner @{user_cache_dirs}/flatpak/system-cache/ r, + owner @{user_share_dirs}/flatpak/repo/{,**} r, + + include if exists + } + include if exists } diff --git a/apparmor.d/groups/freedesktop/xdg-desktop-portal-gtk b/apparmor.d/groups/freedesktop/xdg-desktop-portal-gtk index cff06d8671..eb096a5aee 100644 --- a/apparmor.d/groups/freedesktop/xdg-desktop-portal-gtk +++ b/apparmor.d/groups/freedesktop/xdg-desktop-portal-gtk @@ -9,71 +9,58 @@ include @{exec_path} = @{lib}/xdg-desktop-portal-gtk profile xdg-desktop-portal-gtk @{exec_path} flags=(attach_disconnected) { include + include + include include - include - include - include - include - include - include - include - include - include - include - include include + include include include include include + include + include + include + include + include include - include + + network inet stream, signal receive set=term peer=gdm, signal receive set=hup peer=gdm-session-worker, - unix (send, receive, connect) type=stream peer=(addr="@/tmp/.X11-unix/*", label=gnome-shell), - #aa:dbus own bus=session name=org.freedesktop.impl.portal.desktop.gtk - dbus receive bus=session path=/org/freedesktop/portal/desktop - interface=org.freedesktop.impl.portal.Settings - peer=(name=:*), - dbus send bus=session path=/org/freedesktop/portal/desktop - interface=org.freedesktop.impl.portal.Settings - member=SettingChanged - peer=(name=org.freedesktop.DBus, label=xdg-desktop-portal), + #aa:dbus talk bus=session name=org.gnome.ScreenSaver label=gjs + #aa:dbus talk bus=session name=org.freedesktop.impl.portal{,.*} path=/org/freedesktop/portal/desktop label=xdg-desktop-portal - dbus send bus=session path=/org/gtk/Notifications - interface=org.freedesktop.DBus.Properties - member=GetAll - peer=(name=:*, label=gnome-shell), - - dbus receive bus=session - interface=org.freedesktop.DBus.Introspectable - member=Introspect - peer=(name=:*, label=gnome-shell), + dbus receive bus=session path=/org/freedesktop/portal/desktop/request/** + interface=org.freedesktop.impl.portal.Request + member=Close + peer=(name=@{busname}, label=xdg-desktop-portal), @{exec_path} mr, - /usr/share/gdm/greeter-dconf-defaults r, + / r, + owner /att/**/ r, - / r, + owner @{HOME}/{,**} r, owner /var/lib/xkb/server-@{int}.xkm rw, - owner @{gdm_config_dirs}/dconf/user r, + owner @{gdm_cache_dirs}/fontconfig/@{hex32}-le{32,64}{,d4}.cache-@{d} r, + + owner @{user_config_dirs}/autostart/ w, owner @{tmp}/runtime-*/xauth_@{rand6} r, @{run}/mount/utab r, - @{sys}/devices/virtual/dmi/id/bios_vendor r, - @{sys}/devices/virtual/dmi/id/board_vendor r, - @{sys}/devices/virtual/dmi/id/product_name r, - @{sys}/devices/virtual/dmi/id/sys_vendor r, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/xdg-desktop-portal-gtk.service/cpu.max r, owner @{PROC}/@{pid}/mountinfo r, + owner @{PROC}/@{pid}/cgroup r, include if exists } diff --git a/apparmor.d/groups/freedesktop/xdg-desktop-portal-hyprland b/apparmor.d/groups/freedesktop/xdg-desktop-portal-hyprland index 876825ee4a..82470cb372 100644 --- a/apparmor.d/groups/freedesktop/xdg-desktop-portal-hyprland +++ b/apparmor.d/groups/freedesktop/xdg-desktop-portal-hyprland @@ -15,6 +15,7 @@ profile xdg-desktop-portal-hyprland @{exec_path} { include include include + include @{exec_path} mr, @@ -23,16 +24,14 @@ profile xdg-desktop-portal-hyprland @{exec_path} { @{bin}/sleep rix, @{bin}/slurp rix, + owner @{user_config_dirs}/hypr/xdph.conf r, + owner /tmp/hypr/ rw, owner /tmp/hypr/\#@{int} rwkl, owner /tmp/hypr/hyprland-share-picker.conf* rwkl, - @{sys}/devices/virtual/dmi/id/bios_vendor r, - @{sys}/devices/virtual/dmi/id/board_vendor r, - @{sys}/devices/virtual/dmi/id/product_name r, - @{sys}/devices/virtual/dmi/id/sys_vendor r, - owner @{PROC}/@{pid}/cmdline r, + owner @{PROC}/@{pid}/task/@{tid}/comm rw, include if exists } diff --git a/apparmor.d/groups/freedesktop/xdg-desktop-portal-kde b/apparmor.d/groups/freedesktop/xdg-desktop-portal-kde index 3b02d2b169..1e38713686 100644 --- a/apparmor.d/groups/freedesktop/xdg-desktop-portal-kde +++ b/apparmor.d/groups/freedesktop/xdg-desktop-portal-kde @@ -8,12 +8,15 @@ include @{exec_path} = @{lib}/xdg-desktop-portal-kde @{exec_path} += @{lib}/@{multiarch}/{,libexec/}xdg-desktop-portal-kde -profile xdg-desktop-portal-kde @{exec_path} { +profile xdg-desktop-portal-kde @{exec_path} flags=(attach_disconnected,mediate_deleted) { include + include include include include include + include + include network inet dgram, network inet6 dgram, @@ -27,16 +30,44 @@ profile xdg-desktop-portal-kde @{exec_path} { #aa:exec kioworker + /usr/share/plasma/look-and-feel/** r, + /usr/share/thumbnailers/{,**} r, + + /etc/fstab r, + /etc/xdg/dolphinrc r, + + / r, + + owner @{HOME}/ r, + owner @{desktop_config_dirs}/user-dirs.dirs r, + owner @{user_cache_dirs}/xdg-desktop-portal-kde/{,**} rwl, + + owner @{user_config_dirs}/#@{int8} rw, owner @{user_config_dirs}/autostart/org.kde.*.desktop r, owner @{user_config_dirs}/breezerc r, + owner @{user_config_dirs}/kbookmarkrc r, + owner @{user_config_dirs}/kioslaverc r, + owner @{user_config_dirs}/kservicemenurc r, owner @{user_config_dirs}/xdg-desktop-portal-kderc{,.*} rwlk, + owner @{user_config_dirs}/kdeglobals.@{rand6} rwl, + owner @{user_config_dirs}/Kvantum/{,**} r, + + owner @{user_share_dirs}/user-places.xbel r, + + owner @{user_state_dirs}/#@{int} rw, + owner @{user_state_dirs}/xdg-desktop-portal-kdestaterc rw, + owner @{user_state_dirs}/xdg-desktop-portal-kdestaterc.@{rand6} rwlk, + owner @{user_state_dirs}/xdg-desktop-portal-kdestaterc.lock rwk, - owner @{run}/user/@{uid}/xdg-desktop-portal-kde@{rand6}.*.socket rw, + owner @{run}/user/@{uid}/#@{int} rw, + owner @{run}/user/@{uid}/xdg-desktop-portal-kde@{rand6}.@{int}.socket rwl, + owner @{run}/user/@{uid}/xdg-desktop-portal-kde@{rand6}.@{int}.kioworker.socket rwl, owner @{PROC}/@{pid}/mountinfo r, + /dev/shm/ r, /dev/tty r, include if exists diff --git a/apparmor.d/groups/freedesktop/xdg-desktop-portal-rewrite-launchers b/apparmor.d/groups/freedesktop/xdg-desktop-portal-rewrite-launchers index 62adb343ba..2fa8cc01fa 100644 --- a/apparmor.d/groups/freedesktop/xdg-desktop-portal-rewrite-launchers +++ b/apparmor.d/groups/freedesktop/xdg-desktop-portal-rewrite-launchers @@ -10,7 +10,7 @@ include profile xdg-desktop-portal-rewrite-launchers @{exec_path} { include include - include + include @{exec_path} mr, diff --git a/apparmor.d/groups/freedesktop/xdg-desktop-portal-validate-icon b/apparmor.d/groups/freedesktop/xdg-desktop-portal-validate-icon index 2c6c37538c..766673d8b7 100644 --- a/apparmor.d/groups/freedesktop/xdg-desktop-portal-validate-icon +++ b/apparmor.d/groups/freedesktop/xdg-desktop-portal-validate-icon @@ -9,7 +9,7 @@ include @{exec_path} = @{lib}/xdg-desktop-portal-validate-icon profile xdg-desktop-portal-validate-icon @{exec_path} flags=(attach_disconnected) { include - include + include include capability dac_override, @@ -18,6 +18,12 @@ profile xdg-desktop-portal-validate-icon @{exec_path} flags=(attach_disconnected @{bin}/bwrap ix, + #aa:only apparmor<5.0 + @{lib}/glycin-loaders/@{d}+/glycin-* Cx -> foliate//&glycin//loaders, + + #aa:only apparmor>=5.0 + @{lib}/glycin-loaders/@{d}+/glycin-* Px -> xdg-desktop-portal-validate-icon//&:glycin:loaders, + owner @{tmp}/icon@{rand6} r, include if exists diff --git a/apparmor.d/groups/freedesktop/xdg-document-portal b/apparmor.d/groups/freedesktop/xdg-document-portal index de362990a8..c3d49c498e 100644 --- a/apparmor.d/groups/freedesktop/xdg-document-portal +++ b/apparmor.d/groups/freedesktop/xdg-document-portal @@ -9,10 +9,12 @@ include @{exec_path} = @{lib}/xdg-document-portal profile xdg-document-portal @{exec_path} flags=(attach_disconnected) { include - include include - include + include + include include + include + include include capability sys_admin, @@ -29,33 +31,39 @@ profile xdg-document-portal @{exec_path} flags=(attach_disconnected) { unix (send receive) type=stream peer=(label=xdg-document-portal//fusermount), - #aa:dbus own bus=session name=org.freedesktop.portal.Documents path=/org/freedesktop/portal/documents + #aa:dbus own bus=session name=org.freedesktop.portal.{Documents,FileTransfer} path=/org/freedesktop/portal/documents + #aa:dbus talk bus=session name=org.freedesktop.impl.portal.PermissionStore label=xdg-permission-store dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, - @{bin}/flatpak rPUx, + @{bin}/flatpak rPx, @{bin}/fusermount{,3} rCx -> fusermount, + @{bin}/snap rPx, / r, - owner @{att}/ r, + owner /att/**/ r, owner @{att}/.flatpak-info r, owner @{HOME}/ r, - owner @{HOME}/*/{,**} rw, + owner @{HOME}/** rw, owner @{MOUNTS}/ r, + owner @{MOUNTS}/** rw, owner @{user_share_dirs}/flatpak/db/documents r, owner @{user_share_dirs}/Trash/files/** r, + owner @{run}/user/@{uid}/.flatpak/@{int}/bwrapinfo.json r, owner @{run}/user/@{uid}/doc/ rw, + @{PROC}/ r, @{PROC}/1/cgroup r, @{PROC}/sys/fs/pipe-max-size r, + owner @{PROC}/@{pid}/ r, owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/fd/ r, @@ -63,13 +71,14 @@ profile xdg-document-portal @{exec_path} flags=(attach_disconnected) { profile fusermount flags=(attach_disconnected) { include + include include capability dac_read_search, capability dac_override, capability setuid, - mount options=(rw, rprivate) -> /, + mount options=(rw, make-rprivate) /, mount options=(rw, rbind) @{run}/user/@{uid}/ -> /, mount fstype=fuse.portal -> @{run}/user/@{uid}/doc/, @@ -77,14 +86,8 @@ profile xdg-document-portal @{exec_path} flags=(attach_disconnected) { unix (send receive) type=stream peer=(label=xdg-document-portal), - @{bin}/mount rix, - @{bin}/umount rix, - owner @{run}/user/@{uid}/doc/ rw, - @{run}/mount/utab r, - @{run}/mount/utab.* rwk, - include if exists } diff --git a/apparmor.d/groups/freedesktop/xdg-email b/apparmor.d/groups/freedesktop/xdg-email index cf580ceacb..2f468889e2 100644 --- a/apparmor.d/groups/freedesktop/xdg-email +++ b/apparmor.d/groups/freedesktop/xdg-email @@ -8,43 +8,27 @@ abi , include @{exec_path} = @{bin}/xdg-email -profile xdg-email @{exec_path} flags=(complain) { +profile xdg-email @{exec_path} flags=(attach_disconnected) { include - include - include + include + include @{exec_path} r, - @{sh_path} rix, - @{bin}/{,e}grep ix, - @{bin}/{m,g,}awk ix, - @{bin}/basename ix, - @{bin}/cat ix, - @{bin}/cut ix, - @{bin}/readlink ix, - @{bin}/realpath ix, - @{bin}/sed ix, - @{bin}/tail ix, - @{bin}/tr ix, - @{bin}/uname ix, - - # To get DE information - @{bin}/kde{,4}-config ix, - @{bin}/gconftool{,-2} ix, - @{bin}/qtxdg-mat ix, - @{bin}/dbus-send Cx -> bus, @{bin}/gdbus Cx -> bus, @{bin}/kreadconfig{,5} Px, @{bin}/xdg-mime Px, @{bin}/xprop Px, + @{open_path} Px -> child-open-email, @{thunderbird_path} Px, - profile bus flags=(complain) { + profile bus flags=(attach_disconnected) { include include include + include include if exists } diff --git a/apparmor.d/groups/freedesktop/xdg-icon-resource b/apparmor.d/groups/freedesktop/xdg-icon-resource index 4f29d38a0a..7c6e5a95f2 100644 --- a/apparmor.d/groups/freedesktop/xdg-icon-resource +++ b/apparmor.d/groups/freedesktop/xdg-icon-resource @@ -10,42 +10,26 @@ include @{exec_path} = @{bin}/xdg-icon-resource profile xdg-icon-resource @{exec_path} flags=(attach_disconnected) { include + include include - include + include + include @{exec_path} r, - - @{sh_path} rix, - @{bin}/{,e}grep ix, - @{bin}/{m,g,}awk ix, - @{bin}/basename ix, - @{bin}/cat ix, - @{bin}/cp ix, - @{bin}/cut ix, - @{bin}/dirname ix, - @{bin}/ln ix, - @{bin}/mkdir ix, - @{bin}/readlink ix, - @{bin}/realpath ix, - @{bin}/rm ix, - @{bin}/sed ix, - @{bin}/touch ix, - @{bin}/tr ix, - @{bin}/umask ix, - @{bin}/uname ix, - @{bin}/whoami ix, - - # To get DE information - @{bin}/kde{,4}-config ix, + @{sh_path} r, @{bin}/dbus-send Cx -> bus, @{bin}/gtk{,4}-update-icon-cache Px, @{bin}/xprop Px, + /usr/local/share/icons/** w, + profile bus flags=(complain) { include include include + include + include if exists } diff --git a/apparmor.d/groups/freedesktop/xdg-mime b/apparmor.d/groups/freedesktop/xdg-mime index 15b73a2d18..8d63342c43 100644 --- a/apparmor.d/groups/freedesktop/xdg-mime +++ b/apparmor.d/groups/freedesktop/xdg-mime @@ -10,56 +10,29 @@ include @{exec_path} = @{bin}/xdg-mime profile xdg-mime @{exec_path} flags=(attach_disconnected) { include - include - include + include @{exec_path} r, - @{sh_path} rix, - @{bin}/{,e}grep ix, - @{bin}/{m,g,}awk ix, - @{bin}/basename ix, - @{bin}/cat ix, - @{bin}/cut ix, - @{bin}/file ix, - @{bin}/head ix, - @{bin}/mkdir ix, - @{bin}/mv ix, - @{bin}/readlink ix, - @{bin}/realpath ix, - @{bin}/rm ix, - @{bin}/sed ix, - @{bin}/touch ix, - @{bin}/tr ix, - @{bin}/umask ix, - @{bin}/uname ix, - - # To query DE information - @{bin}/gio ix, - @{bin}/gnomevfs-info ix, - @{bin}/gvfs-info ix, - @{bin}/kde{,4}-config ix, - @{bin}/kfile ix, - @{bin}/kmimetypefinder{,5} ix, - @{bin}/ktraderclient{,5} ix, - @{bin}/qtpaths ix, - @{bin}/qtxdg-mat ix, - @{bin}/dbus-send Cx -> bus, @{bin}/kbuildsycoca{,5} Px, @{bin}/mimetype Px, @{bin}/vendor_perl/mimetype Px, @{bin}/xprop Px, + /usr/share/file/misc/magic.mgc r, + owner @{user_config_dirs}/mimeapps.list{,.new} rw, owner @{tmp}/wl-copy-buffer-@{rand6}/stdin r, - @{PROC}/version r, - - /dev/tty rw, + # file_inherit + deny /opt/*/** r, + deny owner @{user_config_dirs}/*/** rw, + deny owner @{tmp}/.org.chromium.Chromium.@{rand6} rw, + deny owner /dev/shm/.org.chromium.Chromium.@{rand6} rw, - profile bus flags=(complain) { + profile bus flags=(attach_disconnected) { include include include diff --git a/apparmor.d/groups/freedesktop/xdg-open b/apparmor.d/groups/freedesktop/xdg-open index 7893800d12..4e6dcb6762 100644 --- a/apparmor.d/groups/freedesktop/xdg-open +++ b/apparmor.d/groups/freedesktop/xdg-open @@ -3,39 +3,33 @@ # Copyright (C) 2021-2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only +# Generic profile for xdg-open utility. It is an equivalent of child-open-any. + abi , include @{exec_path} = @{bin}/xdg-open -profile xdg-open @{exec_path} flags=(attach_disconnected) { +profile xdg-open @{exec_path} flags=(attach_disconnected,mediate_deleted) { include - include - include - include + include + include + include @{exec_path} r, - @{sh_path} rix, - @{bin}/{,e}grep ix, - @{bin}/basename ix, - @{bin}/cat ix, - @{bin}/cut ix, - @{bin}/env ix, - @{bin}/readlink ix, - @{bin}/realpath ix, - @{bin}/sed ix, - @{bin}/tr ix, - @{bin}/uname ix, - - # To get DE information - @{bin}/kde{,4}-config ix, - @{bin}/dbus-send Cx -> bus, @{bin}/gdbus Cx -> bus, @{bin}/xprop Px, @{bin}/xdg-mime Px, - @{open_path} Px -> child-open-any, + + # Allow to open everything (equivalent to child-open-any) + @{bin}/** PUx, + @{lib}/** PUx, + @{user_bin_dirs}/** PUx, + /opt/*/** PUx, + /usr/local/bin/** PUx, + /usr/share/** PUx, @{PROC}/version r, @@ -43,6 +37,7 @@ profile xdg-open @{exec_path} flags=(attach_disconnected) { include include include + include include if exists } diff --git a/apparmor.d/groups/freedesktop/xdg-permission-store b/apparmor.d/groups/freedesktop/xdg-permission-store index 81c6fd1cb4..0840cf2850 100644 --- a/apparmor.d/groups/freedesktop/xdg-permission-store +++ b/apparmor.d/groups/freedesktop/xdg-permission-store @@ -24,7 +24,7 @@ profile xdg-permission-store @{exec_path} flags=(attach_disconnected) { dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, @@ -47,6 +47,8 @@ profile xdg-permission-store @{exec_path} flags=(attach_disconnected) { owner @{user_share_dirs}/flatpak/db/devices rw, owner @{user_share_dirs}/flatpak/db/documents rw, owner @{user_share_dirs}/flatpak/db/notifications rw, + owner @{user_share_dirs}/flatpak/db/screencast r, + owner @{user_share_dirs}/flatpak/db/webextensions rw, include if exists } diff --git a/apparmor.d/groups/freedesktop/xdg-screensaver b/apparmor.d/groups/freedesktop/xdg-screensaver index dd7d17118d..9f4e776d27 100644 --- a/apparmor.d/groups/freedesktop/xdg-screensaver +++ b/apparmor.d/groups/freedesktop/xdg-screensaver @@ -10,29 +10,12 @@ include @{exec_path} = @{bin}/xdg-screensaver profile xdg-screensaver @{exec_path} flags=(complain) { include - include - include + include include @{exec_path} r, - @{sh_path} rix, - @{bin}/{,e}grep ix, - @{bin}/{m,g,}awk ix, - @{bin}/basename ix, - @{bin}/cat ix, - @{bin}/cut ix, - @{bin}/dirname ix, - @{bin}/kill ix, - @{bin}/ln ix, @{bin}/lockfile ix, - @{bin}/mktemp ix, - @{bin}/mv ix, - @{bin}/readlink ix, - @{bin}/realpath ix, - @{bin}/rm ix, - @{bin}/sed ix, - @{bin}/uname ix, @{bin}/xautolock ix, @{bin}/dbus-send Cx -> bus, @@ -45,9 +28,10 @@ profile xdg-screensaver @{exec_path} flags=(complain) { include include include + include #aa:dbus talk bus=session name=org.freedesktop.ScreenSaver label=gsd-screensaver-proxy - #aa:dbus talk bus=session name=org.gnome.ScreenSaver label=gjs-console + #aa:dbus talk bus=session name=org.gnome.ScreenSaver label=gjs include if exists } diff --git a/apparmor.d/groups/freedesktop/xdg-settings b/apparmor.d/groups/freedesktop/xdg-settings index 870d4cfe4a..423c69b3f8 100644 --- a/apparmor.d/groups/freedesktop/xdg-settings +++ b/apparmor.d/groups/freedesktop/xdg-settings @@ -8,39 +8,12 @@ abi , include @{exec_path} = @{bin}/xdg-settings -profile xdg-settings @{exec_path} { +profile xdg-settings @{exec_path} flags=(attach_disconnected) { include - include - include + include @{exec_path} r, - @{sh_path} rix, - @{bin}/{,e}grep rix, - @{bin}/basename rix, - @{bin}/cat ix, - @{bin}/cut rix, - @{bin}/head ix, - @{bin}/mkdir ix, - @{bin}/mktemp ix, - @{bin}/mv ix, - @{bin}/readlink ix, - @{bin}/realpath rix, - @{bin}/rm ix, - @{bin}/sed ix, - @{bin}/sleep ix, - @{bin}/sort ix, - @{bin}/touch ix, - @{bin}/tr ix, - @{bin}/uname ix, - @{bin}/wc ix, - - # To set/get DE information - @{bin}/gconftool{,-2} ix, - @{bin}/kde{,4}-config ix, - @{bin}/kwriteconfig{,5,6} ix, - @{bin}/qtxdg-mat ix, - @{bin}/dbus-send Cx -> bus, @{bin}/kreadconfig{,5} Px, @{bin}/xdg-mime Px, @@ -49,14 +22,11 @@ profile xdg-settings @{exec_path} { owner @{user_config_dirs}/xfce4/helpers.rc{,.@{rand6}} rw, owner @{user_share_dirs}/applications/{,**} rw, - @{PROC}/version r, - - owner /dev/pts/@{int} rw, - - profile bus flags=(complain) { + profile bus flags=(attach_disconnected) { include include include + include include if exists } diff --git a/apparmor.d/groups/freedesktop/xdg-terminal-exec b/apparmor.d/groups/freedesktop/xdg-terminal-exec new file mode 100644 index 0000000000..016f9b17f0 --- /dev/null +++ b/apparmor.d/groups/freedesktop/xdg-terminal-exec @@ -0,0 +1,38 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/xdg-terminal-exec +profile xdg-terminal-exec @{exec_path} flags=(attach_disconnected) { + include + include + include + + @{exec_path} mr, + + @{sh_path} rix, + @{bin}/{m,g,}awk ix, + @{bin}/find ix, + @{bin}/ls ix, + @{bin}/md5sum ix, + @{bin}/tr ix, + + @{bin}/gnome-terminal Px, + @{bin}/ptyxis Px, + + /usr/share/xdg-terminal-exec/{,**} r, + + owner @{HOME}/ r, + + owner @{user_cache_dirs}/xdg-terminal-exec rw, + owner @{user_config_dirs}/*-xdg-terminals.list r, + owner @{user_config_dirs}/xdg-terminals.list r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/freedesktop/xdg-user-dirs-gtk-update b/apparmor.d/groups/freedesktop/xdg-user-dirs-gtk-update index 8892bd1ce2..12cf109bd9 100644 --- a/apparmor.d/groups/freedesktop/xdg-user-dirs-gtk-update +++ b/apparmor.d/groups/freedesktop/xdg-user-dirs-gtk-update @@ -7,16 +7,21 @@ abi , include @{exec_path} = @{bin}/xdg-user-dirs-gtk-update -profile xdg-user-dirs-gtk-update @{exec_path} { +profile xdg-user-dirs-gtk-update @{exec_path} flags=(attach_disconnected) { include - include + include + include + include @{exec_path} mr, + @{bin}/xdg-user-dirs-update Px, + owner @{user_config_dirs}/gtk-3.0/bookmarks* rw, - owner @{user_config_dirs}/user-dirs.dirs r, owner @{user_config_dirs}/user-dirs.locale r, + owner @{tmp}/dirs-@{rand6} rw, + include if exists } diff --git a/apparmor.d/groups/freedesktop/xdg-user-dirs-update b/apparmor.d/groups/freedesktop/xdg-user-dirs-update index 7177703a9b..70f6d27889 100644 --- a/apparmor.d/groups/freedesktop/xdg-user-dirs-update +++ b/apparmor.d/groups/freedesktop/xdg-user-dirs-update @@ -9,15 +9,14 @@ include @{exec_path} = @{bin}/xdg-user-dirs-update profile xdg-user-dirs-update @{exec_path} { include + include include @{exec_path} mr, - /etc/xdg/user-dirs.conf r, - /etc/xdg/user-dirs.defaults r, - owner @{desktop_config_dirs}/ rw, - owner @{desktop_config_dirs}/user-dirs.dirs{,*} rw, + owner @{desktop_config_dirs}/user-dirs.dirs rw, + owner @{desktop_config_dirs}/user-dirs.dirs@{rand6} rw, owner @{desktop_config_dirs}/user-dirs.locale rw, owner @{DESKTOP_HOME}/@{XDG_DESKTOP_DIR}/ rw, owner @{DESKTOP_HOME}/@{XDG_DOCUMENTS_DIR}/ rw, diff --git a/apparmor.d/groups/freedesktop/xhost b/apparmor.d/groups/freedesktop/xhost index 6032179e48..01107b2750 100644 --- a/apparmor.d/groups/freedesktop/xhost +++ b/apparmor.d/groups/freedesktop/xhost @@ -15,7 +15,7 @@ profile xhost @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, # Silencer deny @{user_share_dirs}/gvfs-metadata/* r, diff --git a/apparmor.d/groups/freedesktop/xkbcomp b/apparmor.d/groups/freedesktop/xkbcomp index 325d444f50..342bd66632 100644 --- a/apparmor.d/groups/freedesktop/xkbcomp +++ b/apparmor.d/groups/freedesktop/xkbcomp @@ -11,12 +11,12 @@ include profile xkbcomp @{exec_path} flags=(attach_disconnected) { include include - include include include unix (send,receive) type=stream addr=none peer=(label=gnome-shell), unix (send,receive) type=stream addr=none peer=(label=xwayland), + unix (send,receive) type=stream addr=none peer=(label=kwin_wayland), @{exec_path} mr, diff --git a/apparmor.d/groups/freedesktop/xorg b/apparmor.d/groups/freedesktop/xorg index 00e277f1f5..787324c35d 100644 --- a/apparmor.d/groups/freedesktop/xorg +++ b/apparmor.d/groups/freedesktop/xorg @@ -13,11 +13,12 @@ include @{exec_path} += @{lib}/xorg/Xorg{,.wrap} profile xorg @{exec_path} flags=(attach_disconnected) { include - include - include + include + include include include include + include include capability chown, @@ -31,6 +32,7 @@ profile xorg @{exec_path} flags=(attach_disconnected) { capability setuid, capability sys_admin, capability sys_rawio, + capability sys_nice, signal (send) set=(usr1), @@ -40,6 +42,8 @@ profile xorg @{exec_path} flags=(attach_disconnected) { signal (receive) set=hup peer=gdm-session-worker, signal (receive) set=term peer=gdm{,-session}, + ptrace read peer=xsetroot, + unix (bind, listen) type=stream addr=@/tmp/.X11-unix/*, unix (send, receive, accept) type=stream addr=@/tmp/.X11-unix/*, # all peers @@ -48,7 +52,7 @@ profile xorg @{exec_path} flags=(attach_disconnected) { dbus send bus=system path=/org/freedesktop/login1/session/* interface=org.freedesktop.login1.Session member=ReleaseControl - peer=(name=org.freedesktop.login1, label=systemd-logind), + peer=(name=org.freedesktop.login1, label="@{p_systemd_logind}"), @{exec_path} mrix, @@ -92,24 +96,21 @@ profile xorg @{exec_path} flags=(attach_disconnected) { owner @{tmp}/server-* rwk, owner @{tmp}/serverauth.* r, - @{run}/udev/data/+acpi:* r, # for acpi + @{run}/udev/data/+acpi:* r, # Exposes ACPI objects (power buttons, batteries, thermal) @{run}/udev/data/+dmi* r, # for motherboard info @{run}/udev/data/+drm:card@{int}-* r, # For screen outputs - @{run}/udev/data/+hid:* r, # for HID-Compliant Keyboard - @{run}/udev/data/+i2c:* r, - @{run}/udev/data/+input:input@{int} r, # for mouse, keyboard, touchpad + @{run}/udev/data/+hid:* r, # For Human Interface Device (mice, controllers, drawing tablets, scanners) + @{run}/udev/data/+i2c:* r, # For Inter-Integrated Circuit, low-speed peripherals (sensors, EEPROMs, etc.) @{run}/udev/data/+pci:* r, # Identifies all PCI devices (CPU, GPU, Network, Disks, USB, etc.) - @{run}/udev/data/+platform:* r, # for ? + @{run}/udev/data/+platform:* r, # Identifies onboard devices (laptop/board model, power controllers, thermal sensors) @{run}/udev/data/+serio:* r, # for touchpad? @{run}/udev/data/+sound:card@{int} r, # for sound card - @{run}/udev/data/+usb* r, # for USB mouse and keyboard + @{run}/udev/data/+usb:* r, # Identifies all USB devices @{run}/udev/data/c4:@{int} r, # for /dev/tty[0-9]* @{run}/udev/data/c5:@{int} r, # for /dev/tty, /dev/console, /dev/ptmx @{run}/udev/data/c10:@{int} r, # for non-serial mice, misc features - @{run}/udev/data/c13:@{int} r, # for /dev/input/* @{run}/udev/data/c189:@{int} r, # for /dev/bus/usb/** - @{run}/udev/data/c226:@{int} r, # for /dev/dri/card* @{sys}/bus/ r, @{sys}/bus/pci/devices/ r, @@ -117,15 +118,13 @@ profile xorg @{exec_path} flags=(attach_disconnected) { @{sys}/class/{tty,input,drm}/ r, @{sys}/class/power_supply/ r, @{sys}/devices/@{pci}/ r, - @{sys}/devices/@{pci}/backlight/**/{,max_,actual_}brightness r, - @{sys}/devices/@{pci}/backlight/**/{uevent,type,enabled} r, - @{sys}/devices/@{pci}/backlight/**/brightness rw, @{sys}/devices/@{pci}/boot_vga r, @{sys}/devices/@{pci}/resource@{int} rw, @{sys}/devices/**/{uevent,name,id,config} r, @{sys}/devices/**/hid r, @{sys}/devices/**/power_supply/**/{type,online} r, @{sys}/devices/platform/ r, + @{sys}/devices/platform/*/serio@{int}/id/ r, @{sys}/module/i915/{,**} r, @{PROC}/@{pids}/cmdline r, @@ -133,13 +132,13 @@ profile xorg @{exec_path} flags=(attach_disconnected) { @{PROC}/ioports r, @{PROC}/mtrr rw, + /dev/ r, /dev/fb@{int} rw, /dev/input/event@{int} rw, - /dev/input/mouse@{int} rw, /dev/shm/#@{int} rw, /dev/shm/shmfd-* rw, /dev/tty rw, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, /dev/udmabuf rw, /dev/vga_arbiter rw, # Graphic card modules diff --git a/apparmor.d/groups/freedesktop/xrandr b/apparmor.d/groups/freedesktop/xrandr index fc1935c4be..30e8293c8e 100644 --- a/apparmor.d/groups/freedesktop/xrandr +++ b/apparmor.d/groups/freedesktop/xrandr @@ -12,9 +12,13 @@ profile xrandr @{exec_path} { include include + capability dac_read_search, + @{exec_path} mr, - owner /dev/tty@{int} rw, + @{run}/sddm/xauth_@{rand6} r, + + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/freedesktop/xrdb b/apparmor.d/groups/freedesktop/xrdb index 55d0698150..53b5fb5bcd 100644 --- a/apparmor.d/groups/freedesktop/xrdb +++ b/apparmor.d/groups/freedesktop/xrdb @@ -8,7 +8,7 @@ abi , include @{exec_path} = @{bin}/xrdb -profile xrdb @{exec_path} { +profile xrdb @{exec_path} flags=(attach_disconnected) { include include @@ -48,11 +48,11 @@ profile xrdb @{exec_path} { @{run}/sddm/xauth_@{rand6} r, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, owner @{HOME}/.xsession-errors w, /dev/tty rw, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/freedesktop/xset b/apparmor.d/groups/freedesktop/xset index 20dc2b1fbd..6653d91a78 100644 --- a/apparmor.d/groups/freedesktop/xset +++ b/apparmor.d/groups/freedesktop/xset @@ -22,7 +22,7 @@ profile xset @{exec_path} { @{run}/sddm/xauth_@{rand6} r, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, owner @{HOME}/.xsession-errors w, deny /dev/dri/card@{int} rw, diff --git a/apparmor.d/groups/freedesktop/xsetroot b/apparmor.d/groups/freedesktop/xsetroot index bc1291ef42..c17d1f2166 100644 --- a/apparmor.d/groups/freedesktop/xsetroot +++ b/apparmor.d/groups/freedesktop/xsetroot @@ -10,6 +10,7 @@ include @{exec_path} = @{bin}/xsetroot profile xsetroot @{exec_path} { include + include include capability dac_read_search, @@ -18,10 +19,6 @@ profile xsetroot @{exec_path} { @{exec_path} mr, - /usr/share/icons/{,**} r, - - owner @{HOME}/.icons/** r, - owner @{user_share_dirs}/sddm/xorg-session.log w, owner @{user_share_dirs}/sddm/wayland-session.log w, @@ -29,7 +26,7 @@ profile xsetroot @{exec_path} { @{run}/user/@{uid}/xauth_@{rand6} rl, @{run}/sddm/xauth_@{rand6} r, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/freedesktop/xwayland b/apparmor.d/groups/freedesktop/xwayland index 03b418684e..b313ccf0ed 100644 --- a/apparmor.d/groups/freedesktop/xwayland +++ b/apparmor.d/groups/freedesktop/xwayland @@ -9,9 +9,11 @@ include @{exec_path} = @{bin}/Xwayland profile xwayland @{exec_path} flags=(attach_disconnected) { include + include + include include include - include + include include signal (receive) set=(term hup) peer=gdm*, @@ -19,7 +21,8 @@ profile xwayland @{exec_path} flags=(attach_disconnected) { signal (receive) set=(term hup) peer=kwin_wayland, signal (receive) set=(term hup) peer=login, - unix type=stream addr=none peer=(label=gnome-shell, addr=none), + unix type=stream peer=(label=gnome-shell), + unix type=stream peer=(label=kwin_wayland), @{exec_path} mrix, @@ -29,6 +32,12 @@ profile xwayland @{exec_path} flags=(attach_disconnected) { /usr/share/fonts/{,**} r, /usr/share/ghostscript/fonts/{,**} r, + / r, + + owner @{desktop_cache_dirs}/nvidia/ w, + owner @{desktop_cache_dirs}/nvidia/GLCache/ rw, + owner @{desktop_cache_dirs}/nvidia/GLCache/** rwk, + owner @{tmp}/server-@{int}.xkm rwk, owner @{run}/user/@{uid}/.mutter-Xwaylandauth.@{rand6} rw, owner @{run}/user/@{uid}/server-@{int}.xkm rw, @@ -36,9 +45,6 @@ profile xwayland @{exec_path} flags=(attach_disconnected) { @{PROC}/@{pids}/cmdline r, - @{att}/dev/tty@{int} rw, - /dev/tty rw, - include if exists } diff --git a/apparmor.d/groups/gnome/chrome-gnome-shell b/apparmor.d/groups/gnome/chrome-gnome-shell index 8c6372ba5c..944d5e1d53 100644 --- a/apparmor.d/groups/gnome/chrome-gnome-shell +++ b/apparmor.d/groups/gnome/chrome-gnome-shell @@ -10,6 +10,7 @@ include profile chrome-gnome-shell @{exec_path} { include include + include include include include @@ -23,8 +24,6 @@ profile chrome-gnome-shell @{exec_path} { @{exec_path} mr, @{bin}/ r, - /usr/share/glib-2.0/schemas/gschemas.compiled r, - owner @{PROC}/@{pid}/mounts r, deny @{HOME}/.* r, diff --git a/apparmor.d/groups/gnome/decibels b/apparmor.d/groups/gnome/decibels new file mode 100644 index 0000000000..ff8a244634 --- /dev/null +++ b/apparmor.d/groups/gnome/decibels @@ -0,0 +1,37 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/decibels @{bin}/org.gnome.Decibels +profile decibels @{exec_path} flags=(attach_disconnected) { + include + include + include + include + include + include + + @{exec_path} mr, + + @{bin}/gjs-console rix, + + @{open_path} rPx -> child-open-help, + + /usr/share/org.gnome.Decibels/{,**} r, + + owner @{user_music_dirs}/{,**} r, + owner @{user_pictures_dirs}/{,**} r, + owner @{user_torrents_dirs}/{,**} r, + owner @{user_videos_dirs}/{,**} r, + + owner @{PROC}/@{pid}/mounts r, + owner @{PROC}/@{pid}/task/@{tid}/stat r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/gnome/deja-dup-monitor b/apparmor.d/groups/gnome/deja-dup-monitor index 90a5b0f649..bd95fb553f 100644 --- a/apparmor.d/groups/gnome/deja-dup-monitor +++ b/apparmor.d/groups/gnome/deja-dup-monitor @@ -11,30 +11,48 @@ profile deja-dup-monitor @{exec_path} { include include include - include - include - include - include - include + include + include + include + include include + include + include + include + include + include + include network netlink raw, #aa:dbus own bus=session name=org.gnome.DejaDup.Monitor - #aa:dbus talk bus=session name=org.gnome.DejaDup interface+=org.gtk.Actions label=deja-dup + #aa:dbus talk bus=session name=org.gnome.DejaDup label=deja-dup - dbus send bus=system path=/org/freedesktop/NetworkManager - interface=org.freedesktop.DBus.Properties - member=GetAll - peer=(name=:*, label=NetworkManager), + dbus receive bus=session path=/org/gnome/DejaDup + interface=org.gtk.Actions + member=Changed + peer=(name=@{busname}, label=deja-dup), + + dbus receive bus=session + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, - /usr/share/glib-2.0/schemas/gschemas.compiled r, + @{bin}/chrt rix, + @{bin}/ionice rix, + @{bin}/deja-dup Px, + + /usr/share/gvfs/remote-volume-monitors/{,**} r, /var/tmp/ r, /tmp/ r, + @{run}/mount/utab r, + + owner @{PROC}/@{pid}/mountinfo r, + include if exists } diff --git a/apparmor.d/groups/gnome/epiphany-search-provider b/apparmor.d/groups/gnome/epiphany-search-provider index e66450d09c..04a7ec75a3 100644 --- a/apparmor.d/groups/gnome/epiphany-search-provider +++ b/apparmor.d/groups/gnome/epiphany-search-provider @@ -7,14 +7,17 @@ abi , include @{exec_path} = @{lib}/epiphany-search-provider -profile epiphany-search-provider @{exec_path} { +profile epiphany-search-provider @{exec_path} flags=(attach_disconnected) { include + include include include include include include + include include + include include network inet dgram, @@ -29,6 +32,7 @@ profile epiphany-search-provider @{exec_path} { @{lib}/{,@{multiarch}/}webkit{2,}gtk-*/WebKitWebProcess rix, owner @{user_cache_dirs}/epiphany/{,**} rwk, + owner @{user_config_dirs}/epiphany/{,**} rw, owner @{user_share_dirs}/epiphany/{,**} rwk, owner @{tmp}/ContentRuleList-@{rand6} rw, diff --git a/apparmor.d/groups/gnome/epiphany-webapp-provider b/apparmor.d/groups/gnome/epiphany-webapp-provider index c161a5a0cf..bfc8239678 100644 --- a/apparmor.d/groups/gnome/epiphany-webapp-provider +++ b/apparmor.d/groups/gnome/epiphany-webapp-provider @@ -9,6 +9,7 @@ include @{exec_path} = @{lib}/epiphany-webapp-provider profile epiphany-webapp-provider @{exec_path} { include + include @{exec_path} mr, diff --git a/apparmor.d/groups/gnome/evolution-addressbook-factory b/apparmor.d/groups/gnome/evolution-addressbook-factory index 9f18395f2f..f3e44aa224 100644 --- a/apparmor.d/groups/gnome/evolution-addressbook-factory +++ b/apparmor.d/groups/gnome/evolution-addressbook-factory @@ -11,11 +11,12 @@ profile evolution-addressbook-factory @{exec_path} { include include include - include - include - include + include + include include + include include + include include include @@ -25,43 +26,26 @@ profile evolution-addressbook-factory @{exec_path} { network inet6 dgram, network netlink raw, - #aa:dbus own bus=session name=org.gnome.evolution.dataserver.AddressBook@{int} + #aa:dbus own bus=session name=org.gnome.evolution.dataserver.AddressBook{,@{u8},Cursor,View,Factory} path=/org/gnome/evolution/dataserver/Subprocess{,/**} + #aa:dbus own bus=session name=org.gnome.evolution.dataserver.AddressBook{,@{u8},Cursor,View,Factory} - dbus (send, receive) bus=session path=/org/gnome/evolution/dataserver/** - interface=org.gnome.evolution.dataserver.* - peer=(name=:*), - - dbus send bus=session path=/org/gnome/evolution/dataserver/** - interface=org.gnome.evolution.dataserver.* - peer=(name=org.freedesktop.DBus, label=evolution-*), - - dbus (send, receive) bus=session path=/org/gnome/evolution/dataserver/** - interface=org.freedesktop.DBus.Properties - peer=(name=:*, label=evolution-*), - - dbus send bus=session path=/org/gnome/evolution/dataserver/SourceManager - interface=org.freedesktop.DBus.ObjectManager - member=GetManagedObjects - peer=(name=:*, label=evolution-source-registry), - - dbus send bus=session path=/org/gnome/evolution/dataserver/** - interface=org.freedesktop.DBus.Properties - member=PropertiesChanged - peer=(name=org.freedesktop.DBus, label=evolution-calendar-factory), + #aa:dbus talk bus=session name=org.gnome.evolution.dataserver.{Source,Sources@{int}} path=/org/gnome/evolution/dataserver/SourceManager{,/**} label=evolution-source-registry dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, @{exec_path}-subprocess rix, - /usr/share/glib-2.0/schemas/gschemas.compiled r, /usr/share/icu/@{int}.@{int}/*.dat r, - owner @{user_share_dirs}/evolution/{,**} rwk, + owner @{desktop_cache_dirs}/evolution/addressbook/{,**} rwk, + owner @{desktop_share_dirs}/evolution/{,**} rwk, + owner @{user_cache_dirs}/evolution/addressbook/{,**} rwk, + owner @{user_share_dirs}/evolution/{,**} rwk, @{PROC}/sys/kernel/osrelease r, @{PROC}/cmdline r, diff --git a/apparmor.d/groups/gnome/evolution-alarm-notify b/apparmor.d/groups/gnome/evolution-alarm-notify index ce8f799bbc..4d3713712d 100644 --- a/apparmor.d/groups/gnome/evolution-alarm-notify +++ b/apparmor.d/groups/gnome/evolution-alarm-notify @@ -7,12 +7,9 @@ abi , include @{exec_path} = @{lib}/evolution-data-server/{,evolution-data-server/}evolution-alarm-notify -profile evolution-alarm-notify @{exec_path} { +profile evolution-alarm-notify @{exec_path} flags=(attach_disconnected) { include - include - include - include - include + include include include include @@ -23,13 +20,9 @@ profile evolution-alarm-notify @{exec_path} { #aa:dbus own bus=session name=org.gnome.Evolution-alarm-notify - dbus (send, receive) bus=session path=/org/gnome/evolution/dataserver/** - interface=org.gnome.evolution.dataserver.Calendar* - peer=(name=:*, label=evolution-*), - - dbus (send, receive) bus=session path=/org/gnome/evolution/dataserver/** - interface=org.freedesktop.DBus.{ObjectManager,Properties} - peer=(name=:*, label=evolution-*), + #aa:dbus talk bus=session name=org.gnome.evolution.dataserver.{Source,Sources@{int}} path=/org/gnome/evolution/dataserver/SourceManager{,/**} label=evolution-source-registry + #aa:dbus talk bus=session name=org.gnome.evolution.dataserver.Calendar{,View,Factory} path=/org/gnome/evolution/dataserver/Subprocess{,**} label=evolution-calendar-factory + #aa:dbus talk bus=session name=org.gnome.evolution.dataserver.Calendar{,View,Factory} label=evolution-calendar-factory @{exec_path} mr, @@ -37,6 +30,8 @@ profile evolution-alarm-notify @{exec_path} { /etc/timezone r, + owner @{user_share_dirs}/evolution/datetime-formats.ini r, + include if exists } diff --git a/apparmor.d/groups/gnome/evolution-calendar-factory b/apparmor.d/groups/gnome/evolution-calendar-factory index f856a06d2d..43c969209d 100644 --- a/apparmor.d/groups/gnome/evolution-calendar-factory +++ b/apparmor.d/groups/gnome/evolution-calendar-factory @@ -11,10 +11,12 @@ profile evolution-calendar-factory @{exec_path} { include include include - include - include + include + include include + include include + include include include @@ -24,60 +26,29 @@ profile evolution-calendar-factory @{exec_path} { network inet6 dgram, network netlink raw, - #aa:dbus own bus=session name=org.gnome.evolution.dataserver.Calendar8 + #aa:dbus own bus=session name=org.gnome.evolution.dataserver.Calendar{,@{u8},View,Factory} path=/org/gnome/evolution/dataserver/Subprocess{,/**} + #aa:dbus own bus=session name=org.gnome.evolution.dataserver.Calendar{,@{u8},View,Factory} - dbus (send, receive) bus=session path=/org/gnome/evolution/dataserver/** - interface=org.gnome.evolution.dataserver.* - peer=(name=:*), - - dbus send bus=session path=/org/gnome/evolution/dataserver/** - interface=org.gnome.evolution.dataserver.* - peer=(name=org.freedesktop.DBus, label="{evolution-*,gnome-shell-*-server}"), - - dbus (send, receive) bus=session path=/org/gnome/evolution/dataserver/** - interface=org.freedesktop.DBus.Properties - peer=(name=:*), - - dbus send bus=session path=/org/gnome/evolution/dataserver/** - interface=org.freedesktop.DBus.Properties - peer=(name=org.freedesktop.DBus, label=evolution-*), - - dbus send bus=session path=/org/gnome/evolution/dataserver/SourceManager - interface=org.freedesktop.DBus.ObjectManager - member=GetManagedObjects - peer=(name=:*, label=evolution-source-registry), - - dbus send bus=session path=/org/gnome/evolution/dataserver/** - interface=org.freedesktop.DBus.Properties - member=PropertiesChanged - peer=(name=org.freedesktop.DBus, label=gnome-shell-calendar-server), - - dbus send bus=session path=/org/gnome/evolution/dataserver/CalendarView/** - interface=org.gnome.evolution.dataserver.CalendarView - member=Complete - peer=(name=org.freedesktop.DBus, label=gnome-calendar), - - dbus send bus=session path=/org/gtk/vfs/metadata - interface=org.gtk.vfs.Metadata - member=Move - peer=(name=:*, label=gvfsd-metadata), + #aa:dbus talk bus=session name=org.gnome.evolution.dataserver.{Source,Sources@{int}} path=/org/gnome/evolution/dataserver/SourceManager{,/**} label=evolution-source-registry + #aa:dbus talk bus=session name=org.gnome.evolution.dataserver.AddressBook{,Cursor,View,Factory} path=/org/gnome/evolution/dataserver/Subprocess{,**} label=evolution-addressbook-factory + #aa:dbus talk bus=session name=org.gnome.evolution.dataserver.AddressBook{,Cursor,View,Factory} label=evolution-addressbook-factory dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, @{exec_path}-subprocess rix, - /usr/share/glib-2.0/schemas/gschemas.compiled r, + owner @{desktop_share_dirs}/evolution/{,**} rwk, owner @{user_cache_dirs}/evolution/calendar/{,**} rwk, owner @{user_cache_dirs}/evolution/tasks/{,**} rwk, owner @{user_share_dirs}/evolution/calendar/{,**} rwk, - owner @{user_share_dirs}/evolution/tasks/system/ w, - owner @{user_share_dirs}/evolution/tasks/system/tasks.ics* rw, + owner @{user_share_dirs}/evolution/memos/system/{,**} rw, + owner @{user_share_dirs}/evolution/tasks/system/{,**} rw, owner @{user_share_dirs}/gvfs-metadata/{,*} r, @{PROC}/sys/kernel/osrelease r, diff --git a/apparmor.d/groups/gnome/evolution-source-registry b/apparmor.d/groups/gnome/evolution-source-registry index 379ea5befe..e7cba265ff 100644 --- a/apparmor.d/groups/gnome/evolution-source-registry +++ b/apparmor.d/groups/gnome/evolution-source-registry @@ -10,10 +10,15 @@ include profile evolution-source-registry @{exec_path} { include include - include + include + include + include include + include include + include include + include include network inet stream, @@ -22,39 +27,34 @@ profile evolution-source-registry @{exec_path} { network inet6 dgram, network netlink raw, - #aa:dbus own bus=session name=org.gnome.evolution.dataserver.Sources@{int} + #aa:dbus own bus=session name=org.gnome.evolution.dataserver.{Source,Sources@{int}} path=/org/gnome/evolution/dataserver/SourceManager{,/**} - dbus receive bus=session path=/org/gnome/evolution/dataserver/SourceManager{,/**} - interface={org.freedesktop.DBus.ObjectManager,org.freedesktop.DBus.Properties} - peer=(name=:*), - dbus receive bus=session path=/org/gnome/evolution/dataserver/SourceManager{,/**} - interface=org.gnome.evolution.dataserver.Source{,.*} - peer=(name=:*), - dbus send bus=session path=/org/gnome/evolution/dataserver/SourceManager{,/**} - interface=org.freedesktop.DBus.Properties - peer=(name=org.freedesktop.DBus), + #aa:dbus talk bus=session name=org.gnome.OnlineAccounts label=goa-daemon dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), dbus send bus=session path=/org/gnome/OnlineAccounts interface=org.freedesktop.DBus.ObjectManager member=GetManagedObjects - peer=(name=:*, label=goa-daemon), + peer=(name=@{busname}, label=goa-daemon), @{exec_path} mr, - /usr/share/glib-2.0/schemas/gschemas.compiled r, + owner /var/lib/gdm/seat@{int}/config/evolution/sources/ r, + owner /var/lib/gdm/seat@{int}/config/evolution/sources/system-proxy.source r, + + owner @{desktop_cache_dirs}/evolution/{,**} rwk, + owner @{desktop_share_dirs}/evolution/{,**} rwk, owner @{user_cache_dirs}/evolution/{,**} rwk, + owner @{user_config_dirs}/evolution/{,**/} w, owner @{user_config_dirs}/evolution/sources/{,*} rw, owner @{user_share_dirs}/evolution/{,**} r, - owner @{user_share_dirs}/gvfs-metadata/{,*} r, - - owner @{user_config_dirs}/evolution/{,**/} w, owner @{user_share_dirs}/evolution/{,**/} w, + owner @{user_share_dirs}/gvfs-metadata/{,*} r, @{PROC}/sys/kernel/osrelease r, @{PROC}/cmdline r, diff --git a/apparmor.d/groups/gnome/evolution-user-prompter b/apparmor.d/groups/gnome/evolution-user-prompter index d1c095abfd..d2b46f33a7 100644 --- a/apparmor.d/groups/gnome/evolution-user-prompter +++ b/apparmor.d/groups/gnome/evolution-user-prompter @@ -9,7 +9,6 @@ include @{exec_path} = @{lib}/{,evolution-data-server/}evolution-user-prompter profile evolution-user-prompter @{exec_path} { include - include include include diff --git a/apparmor.d/groups/gnome/gcr-prompter b/apparmor.d/groups/gnome/gcr-prompter index 6bcbd1cc00..109cb2e5bb 100644 --- a/apparmor.d/groups/gnome/gcr-prompter +++ b/apparmor.d/groups/gnome/gcr-prompter @@ -7,9 +7,11 @@ abi , include @{exec_path} = @{lib}/gcr-prompter -profile gcr-prompter @{exec_path} { +profile gcr-prompter @{exec_path} flags=(attach_disconnected) { include + include include + include @{exec_path} mr, diff --git a/apparmor.d/groups/gnome/gcr-ssh-agent b/apparmor.d/groups/gnome/gcr-ssh-agent index 24e94d9cbe..c69076b960 100644 --- a/apparmor.d/groups/gnome/gcr-ssh-agent +++ b/apparmor.d/groups/gnome/gcr-ssh-agent @@ -7,7 +7,7 @@ abi , include @{exec_path} = @{lib}/gcr-ssh-agent -profile gcr-ssh-agent @{exec_path} { +profile gcr-ssh-agent @{exec_path} flags=(attach_disconnected) { include @{exec_path} mr, @@ -17,6 +17,8 @@ profile gcr-ssh-agent @{exec_path} { owner @{HOME}/@{XDG_SSH_DIR}/{,*} r, + owner @{run}/user/@{uid}/gcr/.ssh rw, + owner @{run}/user/@{uid}/gcr/ssh rw, owner @{run}/user/@{uid}/ssh-askpass.@{rand6}/{,*} rw, include if exists diff --git a/apparmor.d/groups/gnome/gdm b/apparmor.d/groups/gnome/gdm index dca6cda160..2a567d9f15 100644 --- a/apparmor.d/groups/gnome/gdm +++ b/apparmor.d/groups/gnome/gdm @@ -6,9 +6,10 @@ abi , include -@{exec_path} = @{bin}/gdm{3,} +@{exec_path} = @{sbin}/gdm @{sbin}/gdm3 profile gdm @{exec_path} flags=(attach_disconnected) { include + include include include include @@ -17,9 +18,11 @@ profile gdm @{exec_path} flags=(attach_disconnected) { capability chown, capability dac_override, capability dac_read_search, + capability fowner, capability fsetid, capability kill, capability net_admin, + capability sys_admin, capability sys_nice, capability sys_tty_config, @@ -34,8 +37,12 @@ profile gdm @{exec_path} flags=(attach_disconnected) { #aa:dbus own bus=system name=org.gnome.DisplayManager - #aa:dbus talk bus=system name=org.freedesktop.login1 label=systemd-logind - #aa:dbus talk bus=system name=org.freedesktop.Accounts label=accounts-daemon + #aa:dbus talk bus=system name=org.freedesktop.login1 label="@{p_systemd_logind}" + + dbus send bus=system path=/org/freedesktop/Accounts + interface=org.freedesktop.Accounts + member=ListCachedUsers + peer=(name=org.freedesktop.Accounts), @{exec_path} mr, @@ -50,9 +57,12 @@ profile gdm @{exec_path} flags=(attach_disconnected) { /etc/gdm{3,}/PrimeOff/Default rix, /usr/share/gdm{3,}/gdm.schemas r, + /usr/share/gdm{3,}/greeter/wayland-sessions/*.desktop r, + /usr/share/gvfs/remote-volume-monitors/{,**} r, /usr/share/wayland-sessions/*.desktop r, /usr/share/xsessions/*.desktop r, + /etc/.pwd.lock rwk, /etc/default/locale r, /etc/gdm{3,}/custom.conf r, /etc/gdm{3,}/daemon.conf r, @@ -65,18 +75,22 @@ profile gdm @{exec_path} flags=(attach_disconnected) { /var/log/gdm{3,}/ rw, - owner @{GDM_HOME}/block-initial-setup rw, - - @{run}/gdm{3,}/greeter/ rw, - @{run}/systemd/seats/seat@{int} r, - @{run}/systemd/sessions/* r, - @{run}/systemd/users/@{uid} r, - owner @{run}/gdm{3,}.pid rw, - owner @{run}/gdm{3,}/ rw, - owner @{run}/gdm{3,}/custom.conf r, - owner @{run}/gdm{3,}/dbus/ w, - owner @{run}/gdm{3,}/dbus/dbus-@{rand8} w, - owner @{run}/gdm{3,}/gdm.pid rw, + / r, + + @{GDM_HOME}/ rw, + @{GDM_HOME}/** rw, + + @{run}/gdm{,3}/@{HOME}/ rw, + @{run}/gdm{,3}/home/ rw, + @{run}/gdm{,3}.pid rw, + @{run}/gdm{,3}/ rw, + @{run}/gdm{,3}/gdm.pid rw, + owner @{run}/gdm{,3}/dbus/ rw, + owner @{run}/gdm{,3}/dbus/dbus-@{rand8} rw, + + @{run}/systemd/seats/seat@{int} r, + @{run}/systemd/sessions/* r, + @{run}/systemd/users/@{uid} r, @{run}/udev/data/+drm:card@{int}-* r, # For screen outputs @{run}/udev/data/+pci:* r, # Identifies all PCI devices (CPU, GPU, Network, Disks, USB, etc.) diff --git a/apparmor.d/groups/gnome/gdm-generate-config b/apparmor.d/groups/gnome/gdm-generate-config index 6d621f18b4..1590ec4f03 100644 --- a/apparmor.d/groups/gnome/gdm-generate-config +++ b/apparmor.d/groups/gnome/gdm-generate-config @@ -18,20 +18,22 @@ profile gdm-generate-config @{exec_path} { capability setgid, capability setuid, + # ptrace read, + @{exec_path} mr, @{sh_path} rix, @{bin}/dconf rix, @{bin}/install rix, - @{bin}/pgrep rix, - @{bin}/pkill rix, + @{bin}/pgrep rCx -> &pgrep, + @{bin}/pkill rCx -> &pgrep, @{bin}/setpriv rix, @{bin}/setsid rix, /etc/gdm{3,}/* r, /usr/share/gdm{3,}/{,**} r, - /var/lib/ r, + /var/lib/ rw, @{GDM_HOME}/ rw, owner @{GDM_HOME}/greeter-dconf-defaults rw, owner @{GDM_HOME}/greeter-dconf-defaults.@{rand6} rw, @@ -40,12 +42,25 @@ profile gdm-generate-config @{exec_path} { @{sys}/devices/system/node/node@{int}/meminfo r, @{PROC}/ r, - @{PROC}/@{pid}/cgroup r, - @{PROC}/@{pid}/cmdline r, - @{PROC}/@{pid}/stat r, + @{PROC}/@{pid}/ r, + @{PROC}/@{pids}/cgroup r, + @{PROC}/@{pids}/cmdline r, + @{PROC}/@{pids}/stat r, + @{PROC}/@{pids}/status r, @{PROC}/tty/drivers r, @{PROC}/uptime r, + profile pgrep { + include + include + + @{bin}/pkill mr, + + @{PROC}/@{pid}/ r, + + include if exists + } + include if exists } diff --git a/apparmor.d/groups/gnome/gdm-session b/apparmor.d/groups/gnome/gdm-session index 4e3440656c..332dbc1c31 100644 --- a/apparmor.d/groups/gnome/gdm-session +++ b/apparmor.d/groups/gnome/gdm-session @@ -7,23 +7,25 @@ abi , include @{exec_path} = @{lib}/{,gdm/}gdm-{x,wayland}-session -profile gdm-session @{exec_path} { +profile gdm-session @{exec_path} flags=(attach_disconnected) { include include include - include - include + include + include - signal (receive) set=(hup term) peer=gdm-session-worker, - signal (receive) set=(term) peer=gdm, - signal (send) set=(term) peer=dbus-session, - signal (send) set=(term) peer=gnome-session-binary, - signal (send) set=(term) peer=xorg, + signal receive set=(hup term) peer=gdm-session-worker, + signal receive set=term peer=gdm, + signal send set=term peer=dbus-session, + signal send set=term peer=gnome-session-binary, + signal send set=term peer=gnome-session-init-worker, + signal send set=term peer=gnome-session, + signal send set=term peer=xorg, dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, @@ -46,13 +48,13 @@ profile gdm-session @{exec_path} { owner @{gdm_cache_dirs}/gdm/ rw, owner @{gdm_cache_dirs}/gdm/Xauthority rw, owner @{gdm_config_dirs}/dconf/user r, - owner @{GDM_HOME}/greeter-dconf-defaults r, + owner @{DESKTOP_HOME}/greeter-dconf-defaults r, @{run}/gdm{3,}/custom.conf r, owner @{run}/user/@{uid}/gdm/ w, owner @{run}/user/@{uid}/gdm/Xauthority rw, # only: xorg - /dev/tty@{int} rw, + /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/gnome/gdm-session-worker b/apparmor.d/groups/gnome/gdm-session-worker index d54ed16fcd..bf150567e6 100644 --- a/apparmor.d/groups/gnome/gdm-session-worker +++ b/apparmor.d/groups/gnome/gdm-session-worker @@ -37,7 +37,7 @@ profile gdm-session-worker @{exec_path} flags=(attach_disconnected) { signal send set=hup peer=dbus-accessibility, signal send set=hup peer=dbus-session, signal send set=hup peer=dconf-service, - signal send set=hup peer=gjs-console, + signal send set=hup peer=gjs, signal send set=hup peer=gnome-*, signal send set=hup peer=gsd-*, signal send set=hup peer=ibus-*, @@ -47,15 +47,20 @@ profile gdm-session-worker @{exec_path} flags=(attach_disconnected) { signal send set=hup peer=xorg, signal send set=hup peer=xwayland, - unix (bind) type=stream addr=@@{udbus}/bus/gdm-session-wor/system, + unix bind type=stream addr=@@{udbus}/bus/gdm-session-wor/system, - #aa:dbus talk bus=system name=org.freedesktop.Accounts label=accounts-daemon - #aa:dbus talk bus=system name=org.freedesktop.home1.Manager label=systemd-homed + #aa:dbus talk bus=system name=org.freedesktop.Accounts label="@{p_accounts_daemon}" + #aa:dbus talk bus=system name=org.freedesktop.home1 interface=org.freedesktop.home1.Manager label="@{p_systemd_homed}" dbus send bus=system path=/org/freedesktop/login1 interface=org.freedesktop.login1.Manager member={*Session,CreateSessionWithPIDFD} - peer=(name=org.freedesktop.login1, label=systemd-logind), + peer=(name=org.freedesktop.login1, label="@{p_systemd_logind}"), + + dbus send bus=system path=/org/freedesktop/home1 + interface=org.freedesktop.home1.Manager + member=GetUserRecordByName + peer=(name=org.freedesktop.home1, label="@{p_systemd_homed}"), @{exec_path} mrix, @@ -75,8 +80,6 @@ profile gdm-session-worker @{exec_path} flags=(attach_disconnected) { /etc/nshadow rw, /etc/shadow w, - @{etc_ro}/environment r, - @{etc_ro}/security/limits.d/{,*.conf} r, /etc/default/locale r, /etc/fscrypt.conf r, /etc/gdm{3,}/custom.conf r, @@ -99,6 +102,7 @@ profile gdm-session-worker @{exec_path} flags=(attach_disconnected) { /.fscrypt/protectors/ r, owner /.fscrypt/protectors/@{hex16} r, + #aa:lint ignore=tunables /home/ r, /home/.fscrypt/policies/ r, owner /home/.fscrypt/policies/@{hex32} r, @@ -108,6 +112,9 @@ profile gdm-session-worker @{exec_path} flags=(attach_disconnected) { owner @{user_cache_dirs}/ w, + @{run}/systemd/home/@{user}.dont-suspend w, + @{run}/systemd/io.systemd.Login rw, + @{run}/cockpit/active.issue r, @{run}/cockpit/inactive.motd r, owner @{run}/systemd/seats/seat@{int} r, @@ -118,12 +125,13 @@ profile gdm-session-worker @{exec_path} flags=(attach_disconnected) { owner @{run}/gdm{3,}/dbus/ w, owner @{run}/gdm{3,}/dbus/dbus-@{rand8} w, - @{att}/@{run}/systemd/sessions/{,@{l}}@{int}.ref rw, + @{att}@{run}/systemd/sessions/{,@{l}}@{int}.ref rw, @{run}/cockpit/active.motd r, @{run}/faillock/@{user} rwk, @{run}/fscrypt/ rw, @{run}/fscrypt/@{uid}.count rwk, @{run}/motd.d/{,*} r, + @{run}/systemd/io.systemd.Login rw, @{run}/systemd/sessions/* r, @{run}/systemd/users/@{uid} r, @{run}/utmp rwk, @@ -138,7 +146,7 @@ profile gdm-session-worker @{exec_path} flags=(attach_disconnected) { owner @{PROC}/@{pid}/uid_map r, /dev/tty rw, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/gnome/gdm-xsession b/apparmor.d/groups/gnome/gdm-xsession index 03e77816c0..885ace4461 100644 --- a/apparmor.d/groups/gnome/gdm-xsession +++ b/apparmor.d/groups/gnome/gdm-xsession @@ -11,6 +11,7 @@ profile gdm-xsession @{exec_path} { include include include + include include include @@ -51,7 +52,6 @@ profile gdm-xsession @{exec_path} { @{etc_ro}/X11/xdm/Xsession rPx, @{lib}/gnome-session-binary rPx, - /usr/share/glib-2.0/schemas/gschemas.compiled r, /usr/share/im-config/data/{,*} r, /usr/share/im-config/xinputrc.common r, @@ -61,7 +61,7 @@ profile gdm-xsession @{exec_path} { owner @{tmp}/gdm{3,}-config-err-@{rand6} rw, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, profile dbus { include @@ -77,7 +77,7 @@ profile gdm-xsession @{exec_path} { owner @{HOME}/.xsession-errors w, /dev/tty rw, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, include if exists } @@ -86,7 +86,7 @@ profile gdm-xsession @{exec_path} { include include - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/gnome/gio-launch-desktop b/apparmor.d/groups/gnome/gio-launch-desktop index 5e013012ed..d9a9ba8b1b 100644 --- a/apparmor.d/groups/gnome/gio-launch-desktop +++ b/apparmor.d/groups/gnome/gio-launch-desktop @@ -18,6 +18,7 @@ include profile gio-launch-desktop @{exec_path} flags=(attach_disconnected) { include include + include include include include @@ -30,6 +31,8 @@ profile gio-launch-desktop @{exec_path} flags=(attach_disconnected) { @{bin}/gnome-terminal rPUx, @{lib}/gio-launch-desktop rix, + @{lib}/*/** rPx, + @{lib}/* rPx, owner @{HOME}/{,**} rw, diff --git a/apparmor.d/groups/gnome/gjs b/apparmor.d/groups/gnome/gjs new file mode 100644 index 0000000000..c41b394874 --- /dev/null +++ b/apparmor.d/groups/gnome/gjs @@ -0,0 +1,142 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2021-2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# GNOME JavaScript interpreter. It is used to run some gnome internal app +# as well as third party extensions. +# +# Therefore, by default, some extension are confined under this profile. To fix +# this, the various programs using gjs must never run gjs as module, they need +# to run it as executable with a specific script. +# +# This currently concerns: +# +# - gnome-extension-ding (used to not be started as a module) +# - org.gnome.ScreenSaver (simple dbus service) +# - org.gnome.Shell.Extensions (full UI app, requires gnome-strict, graphics, ...) +# - org.gnome.Shell.Notifications (simple dbus service) +# - org.gnome.Shell.Screencast (simple dbus service) + +abi , + +include + +@{exec_path} = @{bin}/gjs-console +profile gjs @{exec_path} flags=(attach_disconnected) { + include + include + include + include + include + + # Only needed by org.gnome.Shell.Extensions + include + include + include + include + include + + # Only needed by gnome-extension-ding + include + include + include + include + include + include + include + + network netlink raw, + + unix type=stream peer=(label=gnome-shell), + + signal receive set=(term hup) peer=gdm, + + #aa:dbus own bus=session name=com.rastersoft.ding + #aa:dbus talk bus=session name=com.rastersoft.dingextension label=gnome-shell interface+=org.gtk.Actions + dbus send bus=session path=/org/freedesktop/DBus + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=org.freedesktop.DBus, label="@{p_dbus_session}"), + dbus send bus=session path=/org/freedesktop/DBus + interface=org.freedesktop.DBus* + peer=(name=org.freedesktop.DBus, label="@{p_dbus_session}"), + dbus send bus=system path=/org/freedesktop/DBus + interface=org.freedesktop.DBus* + peer=(name=org.freedesktop.DBus, label="@{p_dbus_system}"), + + #aa:dbus own bus=session name=org.freedesktop.Notifications + + #aa:dbus talk bus=session name=org.gnome.Mutter.ScreenCast label=gnome-shell + #aa:dbus talk bus=session name=org.gnome.ArchiveManager1 label=file-roller + + # Only needed by org.gnome.ScreenSaver + #aa:dbus own bus=session name=org.gnome.ScreenSaver + + # Only needed by org.gnome.Shell.Extensions + #aa:dbus own bus=session name=org.gnome.Shell.Extensions path=/org/gnome/Shell + + # Only needed by org.gnome.Shell.Notifications + #aa:dbus own bus=session name=org.gnome.Shell.Notifications + + # Only needed by org.gnome.Shell.Screencast + #aa:dbus own bus=session name=org.gnome.Shell.Screencast + + @{exec_path} mrix, + + # gnome-extension-ding + @{sh_path} rix, + @{bin}/env rix, + @{bin}/true rix, + @{bin}/gnome-control-center Px, + @{bin}/nautilus Px, + + /usr/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/{service/daemon.js,gsconnect-preferences} Px, + @{user_share_dirs}/gnome-shell/extensions/gsconnect@andyholmes.github.io/{service/daemon.js,gsconnect-preferences} Px, + + /usr/share/gnome-shell/{,**} r, + /usr/share/thumbnailers/{,**} r, + /usr/share/xkeyboard-config-2/{,**} r, + + owner @{desktop_cache_dirs}/nvidia/ w, + owner @{desktop_cache_dirs}/nvidia/GLCache/ rw, + owner @{desktop_cache_dirs}/nvidia/GLCache/** rwk, + + owner @{HOME}/ r, + owner @{user_videos_dirs}/{,**} r, # TODO: ScreenCast only + + owner @{user_cache_dirs}/gjs_repl_history rw, + owner @{user_cache_dirs}/gjs_repl_history-@{int}.tmp rw, + + owner @{user_share_dirs}/gnome-shell/extensions/{,**} r, + owner @{user_share_dirs}/nautilus/scripts/ r, + + # To register extensions + owner @{user_config_dirs}/**/NativeMessagingHosts/ r, + owner @{user_config_dirs}/**/NativeMessagingHosts/org.gnome.shell.extensions.*.json w, + owner @{user_config_dirs}/**/NativeMessagingHosts/org.gnome.shell.extensions.*.json.@{rand6} rw, + owner @{user_share_dirs}/applications/org.gnome.Shell.Extensions.*.desktop w, + owner @{user_share_dirs}/applications/org.gnome.Shell.Extensions.*.desktop.@{rand6} w, + owner @{user_share_dirs}/dbus-1/services/ r, + owner @{user_share_dirs}/dbus-1/services/org.gnome.Shell.Extensions.*.service w, + owner @{user_share_dirs}/dbus-1/services/org.gnome.Shell.Extensions.*.service.@{rand6} rw, + owner @{user_share_dirs}/icons/**/org.gnome.Shell.Extensions.*.svg w, + owner @{user_share_dirs}/icons/**/org.gnome.Shell.Extensions.*.svg.@{rand6} w, + owner @{user_share_dirs}/icons/**/org.gnome.Shell.Extensions.GSConnect.svg w, + owner @{user_share_dirs}/icons/**/org.gnome.Shell.Extensions.GSConnect.svg.@{rand6} w, + + owner @{user_desktop_dirs}/ r, + owner @{user_templates_dirs}/ r, + + @{sys}/devices/**/uevent r, + + owner @{PROC}/@{pid}/mounts r, + owner @{PROC}/@{pid}/stat r, + owner @{PROC}/@{pid}/statm r, + owner @{PROC}/@{pid}/task/ r, + owner @{PROC}/@{pid}/task/@{tid}/comm rw, + owner @{PROC}/@{pid}/task/@{tid}/stat r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/gnome/gjs-console b/apparmor.d/groups/gnome/gjs-console deleted file mode 100644 index 012ca7ee0a..0000000000 --- a/apparmor.d/groups/gnome/gjs-console +++ /dev/null @@ -1,94 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2021-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - -# TODO: GNOME JavaScript interpreter. It is used to run some gnome internal app -# as well as third party extensions. Therefore, by default, some extension are -# confined under this profile. The resulting profile is quite broad. -# This architecture needs to be rethinked. - -abi , - -include - -@{exec_path} = @{bin}/gjs-console -profile gjs-console @{exec_path} flags=(attach_disconnected) { - include - include - include - include - include - include - include - include - include - include - include - include - - network netlink raw, - - signal (receive) set=(term hup) peer=gdm*, - - #aa:dbus own bus=session name=org.freedesktop.Notifications - #aa:dbus own bus=session name=org.gnome.ScreenSaver - #aa:dbus own bus=session name=org.gnome.Shell.Extensions - #aa:dbus own bus=session name=org.gnome.Shell.Notifications - #aa:dbus own bus=session name=org.gnome.Shell.Screencast - - #aa:dbus talk bus=session name=org.gnome.Mutter.ScreenCast label=gnome-shell - - dbus send bus=session path=/org/gnome/Shell - interface=org.freedesktop.DBus.Properties - member=GetAll - peer=(name=:*, label=gnome-shell), - dbus send bus=session path=/org/gnome/Shell - interface=org.gnome.Shell.Extensions - member=ListExtensions - peer=(name=:*, label=gnome-shell), - - @{exec_path} mr, - - @{bin}/ r, - @{bin}/* PUx, - @{lib}/** PUx, - - /usr/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/{service/daemon.js,gsconnect-preferences} rPx, - @{user_share_dirs}/gnome-shell/extensions/gsconnect@andyholmes.github.io/{service/daemon.js,gsconnect-preferences} rPx, - - /etc/openni2/OpenNI.ini r, - - /usr/share/dconf/profile/gdm r, - /usr/share/gdm/greeter-dconf-defaults r, - /usr/share/gnome-shell/{,**} r, - - /tmp/ r, - /var/tmp/ r, - - owner @{gdm_cache_dirs}/fontconfig/[a-f0-9]*.cache-?{,.NEW,.LCK,.TMP-*} rwl, - owner @{gdm_cache_dirs}/gstreamer-1.0/ rw, - owner @{gdm_cache_dirs}/gstreamer-1.0/registry.*.bin{,.tmp@{rand6}} rw, - owner @{gdm_config_dirs}/dconf/user r, - owner @{GDM_HOME}/greeter-dconf-defaults r, - - owner @{HOME}/ r, - - owner @{user_share_dirs}/gnome-shell/extensions/{,**} r, - owner @{user_cache_dirs}/gstreamer-1.0/ rw, - owner @{user_cache_dirs}/gstreamer-1.0/registry.*.bin{,.tmp@{rand6}} rw, - - owner @{PROC}/@{pid}/cmdline r, - owner @{PROC}/@{pid}/fd/ r, - owner @{PROC}/@{pid}/mounts r, - owner @{PROC}/@{pid}/stat r, - owner @{PROC}/@{pid}/task/ r, - owner @{PROC}/@{pid}/task/@{tid}/comm rw, - owner @{PROC}/@{pid}/task/@{tid}/stat r, - - /dev/ r, - /dev/tty rw, - - include if exists -} - -# vim:syntax=apparmor diff --git a/apparmor.d/groups/gnome/gnome-boxes b/apparmor.d/groups/gnome/gnome-boxes index 2462c20713..beec39225f 100644 --- a/apparmor.d/groups/gnome/gnome-boxes +++ b/apparmor.d/groups/gnome/gnome-boxes @@ -7,17 +7,18 @@ abi , include @{exec_path} = @{bin}/gnome-boxes -profile gnome-boxes @{exec_path} { +profile gnome-boxes @{exec_path} flags=(attach_disconnected) { include include - include - include - include + include + include include include include include + include include + include include include include @@ -36,6 +37,7 @@ profile gnome-boxes @{exec_path} { @{bin}/virsh rCx -> virsh, @{bin}/virtqemud rPUx, + /usr/share/ladspa/rdf/{,*} r, /usr/share/osinfo/{,**} r, /usr/share/gnome-boxes/{,**} r, @@ -55,17 +57,23 @@ profile gnome-boxes @{exec_path} { owner @{user_config_dirs}/gnome-boxes/ rw, owner @{user_config_dirs}/gnome-boxes/** rwk, + owner @{user_share_dirs}/gnome-boxes/ rw, + owner @{user_share_dirs}/gnome-boxes/** rwk, + + owner /var/tmp/*.svg-@{rand6} rw, owner @{tmp}/.goutputstream-@{rand6} rw, owner @{tmp}/*.iso-@{rand6} rw, owner @{tmp}/*.svg-@{rand6} rw, owner @{run}/user/@{uid}/libvirt/ rw, owner @{run}/user/@{uid}/libvirt/virtqemud.lock rwk, + owner @{run}/user/@{uid}/libvirt/virtqemud-sock rw, @{run}/mount/utab r, @{run}/udev/data/c@{dynamic}:@{int} r, # For dynamic assignment range 234 to 254, 384 to 511 + @{sys}/devices/@{pci}/usb@{int}/** r, owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/app-dbus*org.gnome.Boxes.slice/*/memory.* r, @{PROC}/sys/net/ipv6/conf/all/disable_ipv6 r, @@ -75,9 +83,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-browser-connector-host b/apparmor.d/groups/gnome/gnome-browser-connector-host index 95af09ed66..e95762b6ad 100644 --- a/apparmor.d/groups/gnome/gnome-browser-connector-host +++ b/apparmor.d/groups/gnome/gnome-browser-connector-host @@ -11,6 +11,7 @@ profile gnome-browser-connector-host @{exec_path} { include include include + include @{exec_path} mr, @@ -19,8 +20,6 @@ profile gnome-browser-connector-host @{exec_path} { @{lib}/@{python_name}/site-packages/gnome_browser_connector/__pycache__/{,**} rw, - /usr/share/glib-2.0/schemas/gschemas.compiled r, - owner @{PROC}/@{pid}/mounts r, include if exists diff --git a/apparmor.d/groups/gnome/gnome-calculator b/apparmor.d/groups/gnome/gnome-calculator index 3f2290e6a8..cd1b082dbf 100644 --- a/apparmor.d/groups/gnome/gnome-calculator +++ b/apparmor.d/groups/gnome/gnome-calculator @@ -7,9 +7,11 @@ abi , include @{exec_path} = @{bin}/gnome-calculator -profile gnome-calculator @{exec_path} { +profile gnome-calculator @{exec_path} flags=(attach_disconnected) { include include + include + include include # Needed to get currency exchange rates @@ -19,11 +21,18 @@ profile gnome-calculator @{exec_path} { network inet6 stream, network netlink raw, + #aa:dbus own bus=session name=org.gnome.Calculator + + dbus send bus=system path=/org/freedesktop/NetworkManager + interface=org.freedesktop.DBus.Properties + member=GetAll + peer=(label=NetworkManager), + @{exec_path} mr, @{open_path} rPx -> child-open-help, - owner @{PROC}/@{pid}/stat r, + @{PROC}/sys/net/ipv6/conf/all/disable_ipv6 r, include if exists } diff --git a/apparmor.d/groups/gnome/gnome-calculator-search-provider b/apparmor.d/groups/gnome/gnome-calculator-search-provider index da03ed6653..2e79369c40 100644 --- a/apparmor.d/groups/gnome/gnome-calculator-search-provider +++ b/apparmor.d/groups/gnome/gnome-calculator-search-provider @@ -9,7 +9,6 @@ include @{exec_path} = @{lib}/gnome-calculator-search-provider profile gnome-calculator-search-provider @{exec_path} { include - include include include include @@ -23,6 +22,8 @@ profile gnome-calculator-search-provider @{exec_path} { @{bin}/* rPUx, + owner @{user_cache_dirs}/gnome-calculator/* r, + owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/cmdline r, diff --git a/apparmor.d/groups/gnome/gnome-calendar b/apparmor.d/groups/gnome/gnome-calendar index 97309c1a73..a96837d39e 100644 --- a/apparmor.d/groups/gnome/gnome-calendar +++ b/apparmor.d/groups/gnome/gnome-calendar @@ -7,35 +7,30 @@ abi , include @{exec_path} = @{bin}/gnome-calendar -profile gnome-calendar @{exec_path} { +profile gnome-calendar @{exec_path} flags=(attach_disconnected) { include - include - include - include - include - include + include + include include include + include include include + network inet stream, + network inet6 stream, + network inet dgram, + network inet6 dgram, network netlink raw, #aa:dbus own bus=session name=org.gnome.Calendar - #aa:dbus talk bus=session name=org.gnome.evolution.dataserver.AddressBook@{int} label=evolution-addressbook-factory - #aa:dbus talk bus=session name=org.gnome.evolution.dataserver.Calendar@{int} label=evolution-calendar-factory - #aa:dbus talk bus=session name=org.gnome.evolution.dataserver.CalendarView label=evolution-calendar-factory - #aa:dbus talk bus=session name=org.gnome.evolution.dataserver.Source label=evolution-source-registry - #aa:dbus talk bus=session name=org.gnome.evolution.dataserver.Sources@{int} label=evolution-source-registry + #aa:dbus talk bus=system name=org.freedesktop.GeoClue2 label="@{p_geoclue}" + + #aa:dbus talk bus=session name=org.gnome.evolution.dataserver label="{evolution-*-factory,evolution-source-registry}" #aa:dbus talk bus=session name=org.gnome.OnlineAccounts label=goa-daemon #aa:dbus talk bus=session name=org.gnome.SettingsDaemon.Color label=gsd-color - #aa:dbus talk bus=system name=org.freedesktop.GeoClue2 label=geoclue - - dbus send bus=session path=/org/gnome/evolution/dataserver/SourceManager{,/**} - interface=org.freedesktop.DBus.ObjectManager - member=GetManagedObjects - peer=(name=:*, label=evolution-source-registry), + #aa:dbus talk bus=session name=org.gnome.Shell.SearchProvider2 path=/org/gnome/Calendar/SearchProvider label=gnome-shell @{exec_path} mr, @{open_path} rPx -> child-open-help, diff --git a/apparmor.d/groups/gnome/gnome-characters b/apparmor.d/groups/gnome/gnome-characters index 9511e781fa..ecd24aa996 100644 --- a/apparmor.d/groups/gnome/gnome-characters +++ b/apparmor.d/groups/gnome/gnome-characters @@ -7,15 +7,18 @@ abi , include @{exec_path} = @{bin}/gnome-characters /usr/share/org.gnome.Characters/org.gnome.Characters -profile gnome-characters @{exec_path} { +profile gnome-characters @{exec_path} flags=(attach_disconnected) { include - include - include + include include include include - #aa:dbus own bus=session name=org.gnome.Characters interface+=org.gnome.Shell.SearchProvider2 + #aa:dbus own bus=session name=org.gnome.Characters + dbus send bus=system path=/org/freedesktop/DBus + interface=org.freedesktop.DBus + member=ListNames + peer=(label=dbus-system), @{exec_path} mr, @@ -27,8 +30,6 @@ profile gnome-characters @{exec_path} { /usr/share/xml/iso-codes/{,**} r, owner @{PROC}/@{pid}/mounts r, - owner @{PROC}/@{pid}/stat r, - owner @{PROC}/@{pid}/status r, owner @{PROC}/@{pid}/task/@{tid}/stat r, include if exists diff --git a/apparmor.d/groups/gnome/gnome-characters-backgroudservice b/apparmor.d/groups/gnome/gnome-characters-backgroudservice index 4b70cdfa60..57bd45a509 100644 --- a/apparmor.d/groups/gnome/gnome-characters-backgroudservice +++ b/apparmor.d/groups/gnome/gnome-characters-backgroudservice @@ -9,7 +9,6 @@ include @{exec_path} = /usr/share/org.gnome.Characters/org.gnome.Characters.BackgroundService profile gnome-characters-backgroudservice @{exec_path} { include - include include include diff --git a/apparmor.d/groups/gnome/gnome-clocks b/apparmor.d/groups/gnome/gnome-clocks index 13f161dfd8..6aad86f762 100644 --- a/apparmor.d/groups/gnome/gnome-clocks +++ b/apparmor.d/groups/gnome/gnome-clocks @@ -7,19 +7,18 @@ abi , include @{exec_path} = @{bin}/gnome-clocks -profile gnome-clocks @{exec_path} { +profile gnome-clocks @{exec_path} flags=(attach_disconnected) { include include - include - include - include include include + include include network netlink raw, - #aa:dbus own bus=session name=org.gnome.clocks interface+=org.gtk.Actions + #aa:dbus own bus=session name=org.gnome.clocks.SearchProvider interface+=org.gnome.Shell.SearchProvider2 + #aa:dbus own bus=session name=org.gnome.clocks @{exec_path} mr, @{open_path} rPx -> child-open-help, diff --git a/apparmor.d/groups/gnome/gnome-contacts b/apparmor.d/groups/gnome/gnome-contacts index b6474cf55b..eb194299e0 100644 --- a/apparmor.d/groups/gnome/gnome-contacts +++ b/apparmor.d/groups/gnome/gnome-contacts @@ -7,9 +7,8 @@ abi , include @{exec_path} = @{bin}/gnome-contacts -profile gnome-contacts @{exec_path} { +profile gnome-contacts @{exec_path} flags=(attach_disconnected) { include - include include include include @@ -24,7 +23,8 @@ profile gnome-contacts @{exec_path} { #aa:dbus talk bus=session name=org.gnome.OnlineAccounts label=goa-daemon @{exec_path} mr, - @{open_path} rPx -> child-open-help, + + @{open_path} Px -> child-open-help, owner @{user_cache_dirs}/evolution/addressbook/{,**} r, owner @{user_share_dirs}/folks/relationships.ini r, diff --git a/apparmor.d/groups/gnome/gnome-contacts-search-provider b/apparmor.d/groups/gnome/gnome-contacts-search-provider index 0abc39acd9..69bb8d915f 100644 --- a/apparmor.d/groups/gnome/gnome-contacts-search-provider +++ b/apparmor.d/groups/gnome/gnome-contacts-search-provider @@ -9,7 +9,7 @@ include @{exec_path} = @{lib}/gnome-contacts-search-provider profile gnome-contacts-search-provider @{exec_path} { include - include + include include include include diff --git a/apparmor.d/groups/gnome/gnome-control-center b/apparmor.d/groups/gnome/gnome-control-center index 195a72d39d..8264d00140 100644 --- a/apparmor.d/groups/gnome/gnome-control-center +++ b/apparmor.d/groups/gnome/gnome-control-center @@ -10,17 +10,17 @@ include profile gnome-control-center @{exec_path} flags=(attach_disconnected) { include include - include - include - include - include - include - include + include + include + include include include + include include include include + include + include include include include @@ -35,49 +35,86 @@ profile gnome-control-center @{exec_path} flags=(attach_disconnected) { signal send set=kill peer=unconfined, signal send set=kill peer=passwd, - unix (send, receive, connect) type=stream peer=(addr="@/home/*/.cache/ibus/dbus-????????", label=ibus-daemon), - #aa:dbus own bus=session name=org.gnome.Settings #aa:dbus own bus=session name=org.bluez.obex.Agent1 #aa:dbus talk bus=session name=org.bluez.obex label=obexd + #aa:dbus talk bus=session name=org.freedesktop.impl.portal.PermissionStore label=xdg-permission-store + #aa:dbus talk bus=session name=org.gnome.Identity label=goa-identity-service #aa:dbus talk bus=session name=org.gnome.Mutter label=gnome-shell - #aa:dbus talk bus=session name=org.gnome.SettingsDaemon.Color label=gsd-color + #aa:dbus talk bus=session name=org.gnome.OnlineAccounts label=goa-daemon + #aa:dbus talk bus=session name=org.gnome.SessionManager label="@{p_gnome_session}" + #aa:dbus talk bus=session name=org.gnome.SettingsDaemon.* label="gsd-*" #aa:dbus talk bus=session name=org.gnome.Shell label=gnome-shell - - #aa:dbus talk bus=system name=org.freedesktop.hostname1 label=systemd-hostnamed + #aa:dbus talk bus=session name=org.gnome.Shell.Extensions label=gjs + + #aa:dbus talk bus=system name=com.ubuntu.WhoopsiePreferences label=whoopsie-preferences + #aa:dbus talk bus=system name=net.hadess.SwitcherooControl label=switcheroo-control + #aa:dbus talk bus=system name=net.reactivated.Fprint.Manager label="@{p_fprintd}" + #aa:dbus talk bus=system name=org.bluez label=bluetoothd + #aa:dbus talk bus=system name=org.cups.cupsd.Notifier label=cups-notifier-dbus + #aa:dbus talk bus=system name=org.freedesktop.Accounts label="@{p_accounts_daemon}" + #aa:dbus talk bus=system name=org.freedesktop.bolt1 path=/org/freedesktop/bolt{,/**} label=boltd + #aa:dbus talk bus=system name=org.freedesktop.ColorManager label=colord + #aa:dbus talk bus=system name=org.freedesktop.fwupd path=/ label=fwupd + #aa:dbus talk bus=system name=org.freedesktop.hostname1 label="@{p_systemd_hostnamed}" + #aa:dbus talk bus=system name=org.freedesktop.locale1 label=label=systemd-localed + #aa:dbus talk bus=system name=org.freedesktop.login1 label="@{p_systemd_logind}" + #aa:dbus talk bus=system name=org.freedesktop.ModemManager1 label="@{p_ModemManager}" #aa:dbus talk bus=system name=org.freedesktop.NetworkManager label=NetworkManager - #aa:dbus talk bus=system name=org.freedesktop.UPower label=upowerd + #aa:dbus talk bus=system name=org.freedesktop.PolicyKit1 label="@{p_polkitd}" + #aa:dbus talk bus=system name=org.freedesktop.systemd1 label="@{p_systemd}" + #aa:dbus talk bus=system name=org.freedesktop.timedate1 label=systemd-timedated + #aa:dbus talk bus=system name=org.freedesktop.UDisks2 label=udisksd + #aa:dbus talk bus=system name=org.freedesktop.UPower label="@{p_upowerd}" + #aa:dbus talk bus=system name=org.freedesktop.UPower.PowerProfiles label=@{p_power_profiles_daemon} + #aa:dbus talk bus=system name=org.opensuse.CupsPkHelper.Mechanism label=cups-pk-helper-mechanism + + # Get new/old interfaces signals from any other services + dbus send bus=system path=/{,org/freedesktop} + interface=org.freedesktop.DBus.ObjectManager + member=GetManagedObjects + peer=(name=@{busname}), + dbus receive bus=system path=/{,org/freedesktop} + interface=org.freedesktop.DBus.ObjectManager + member={InterfacesAdded,InterfacesRemoved} + peer=(name=@{busname}), + + dbus receive bus=system path=/org/gnome/bluetooth/settings + interface=org.bluez.Agent1 + member=Release + peer=(name=@{busname}, label=bluetoothd), @{exec_path} mr, @{bin}/@{shells} rUx, @{bin}/gcm-viewer rix, - @{bin}/grep rix, + @{bin}/{,e}grep rix, @{bin}/locale rix, @{bin}/sed rix, @{bin}/tecla rPx, - @{bin}/bwrap rCx -> bwrap, + # glycin @{bin}/gkbd-keyboard-display rPx, @{bin}/gnome-software rPx, - @{bin}/openvpn rPx, + @{bin}/lscpu rPx, @{bin}/passwd rPx, @{bin}/pkexec rCx -> pkexec, @{bin}/software-properties-gtk rPx, - @{bin}/usermod rPx, + @{bin}/update-manager rPx, @{lib}/{,@{multiarch}/}webkit{2,}gtk-*/WebKitNetworkProcess rix, @{lib}/cups/backend/snmp rPx, @{lib}/gnome-control-center-goa-helper rPx, @{lib}/gnome-control-center-print-renderer rPx, + @{sbin}/openvpn rPx, + @{sbin}/usermod rPx, /usr/share/language-tools/language2locale rix, /usr/share/language-tools/language-options rPUx, @{open_path} rPx -> child-open-any, - /opt/**/share/icons/{,**} r, - /snap/*/@{int}/**.png r, + /snap/*/@{int}/**.@{icon_ext} r, /usr/share/backgrounds/{,**} r, /usr/share/cups/data/testprint r, /usr/share/firefox{,-esr}/browser/chrome/icons/{,**} r, @@ -88,6 +125,7 @@ profile gnome-control-center @{exec_path} flags=(attach_disconnected) { /usr/share/gnome-shell/search-providers/{,**} r, /usr/share/gnome/gnome-version.xml r, /usr/share/language-tools/main-countries r, + /usr/share/publicsuffix/{,**} r, /usr/share/thumbnailers/{,*} r, /usr/share/wallpapers/{,**} r, /usr/share/xml/iso-codes/{,**} r, @@ -96,15 +134,17 @@ profile gnome-control-center @{exec_path} flags=(attach_disconnected) { @{etc_ro}/security/pwquality.conf.d/{,**} r, /etc/machine-info r, /etc/rygel.conf r, + /etc/xdg/autostart/ r, + /etc/xdg/autostart/*.desktop r, /etc/fstab r, - /etc/machine-id r, - /var/lib/dbus/machine-id r, /var/cache/cracklib/cracklib_dict.* r, /var/cache/samba/ rw, /var/lib/AccountsService/icons/* r, + /usr/share/snapd/*.svg r, + / r, owner @{HOME}/.cat_installer/ca.pem r, @@ -119,14 +159,17 @@ profile gnome-control-center @{exec_path} flags=(attach_disconnected) { owner @{user_config_dirs}/gnome-control-center/{,**} rw, owner @{user_config_dirs}/ibus/bus/ r, owner @{user_config_dirs}/ibus/bus/@{hex32}-unix-{,wayland-}@{int} r, - owner @{user_config_dirs}/mimeapps.list{,.@{rand6}} rw, + owner @{user_config_dirs}/mimeapps.list w, + owner @{user_config_dirs}/mimeapps.list.@{rand6} rw, owner @{user_config_dirs}/rygel.conf{,.@{rand6}} rw, - owner @{user_games_dirs}/**.png r, + @{system_games_dirs}/**.@{icon_ext} r, + owner @{user_games_dirs}/**.@{icon_ext} r, owner @{user_share_dirs}/backgrounds/{,**} rw, owner @{user_share_dirs}/gnome-remote-desktop/ w, owner @{user_share_dirs}/gnome-remote-desktop/rdp-tls.{crt,key}{,.@{rand6}} rw, + owner @{user_share_dirs}/gnome-shell/session-active-history.json r, owner @{user_share_dirs}/icc/{,edid-*} r, owner @{tmp}/@{hex12}@{h} rw, @@ -146,7 +189,7 @@ profile gnome-control-center @{exec_path} flags=(attach_disconnected) { @{run}/udev/data/+pci:* r, # Identifies all PCI devices (CPU, GPU, Network, Disks, USB, etc.) @{run}/udev/data/c13:@{int} r, # for /dev/input/* @{run}/udev/data/c@{dynamic}:@{int} r, # For dynamic assignment range 234 to 254, 384 to 511 - @{run}/udev/data/n@{int} r, + @{run}/udev/data/n@{int} r, # For network interfaces @{sys}/bus/ r, @{sys}/class/ r, @@ -159,9 +202,6 @@ profile gnome-control-center @{exec_path} flags=(attach_disconnected) { @{sys}/devices/virtual/thermal/thermal_zone@{int}/hwmon@{int}/temp* r, @{sys}/firmware/acpi/pm_profile r, - @{sys}/fs/cgroup/user.slice/cpu.max r, - @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/cpu.max r, - @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/cpu.max r, owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/{,**} rw, @{PROC}/cmdline r, @@ -179,19 +219,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, - - profile bwrap flags=(attach_disconnected) { - include - include - - @{bin}/bwrap mr, - - include if exists - } profile pkexec { include diff --git a/apparmor.d/groups/gnome/gnome-control-center-global-shortcuts-provider b/apparmor.d/groups/gnome/gnome-control-center-global-shortcuts-provider new file mode 100644 index 0000000000..d5110ad61f --- /dev/null +++ b/apparmor.d/groups/gnome/gnome-control-center-global-shortcuts-provider @@ -0,0 +1,41 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/gnome-control-center-global-shortcuts-provider +profile gnome-control-center-global-shortcuts-provider @{exec_path} flags=(attach_disconnected) { + include + include + include + include + include + include + + signal receive set=term peer=gdm, + signal receive set=hup peer=gdm-session-worker, + + unix type=stream peer=(label=gnome-shell), + + #aa:dbus own bus=session name=org.gnome.Settings.GlobalShortcutsProvider + + dbus send bus=session path=/org/gnome/Mutter/ServiceChannel + interface=org.gnome.Mutter.ServiceChannel + member=OpenWaylandServiceConnection + peer=(name=@{busname}, label=gnome-shell), + + @{exec_path} mr, + + /usr/share/gnome-control-center/keybindings/{,**} r, + + owner @{gdm_cache_dirs}/fontconfig/* r, + + owner @{PROC}/@{pid}/task/@{tid}/comm w, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/gnome/gnome-control-center-goa-helper b/apparmor.d/groups/gnome/gnome-control-center-goa-helper index 1fa7d70503..e8428c930c 100644 --- a/apparmor.d/groups/gnome/gnome-control-center-goa-helper +++ b/apparmor.d/groups/gnome/gnome-control-center-goa-helper @@ -9,12 +9,7 @@ include @{exec_path} = @{lib}/gnome-control-center-goa-helper profile gnome-control-center-goa-helper @{exec_path} { include - include - include - include - include - include - include + include include include include @@ -35,7 +30,7 @@ profile gnome-control-center-goa-helper @{exec_path} { dbus send bus=session path=/org/gnome/OnlineAccounts interface=org.freedesktop.DBus.ObjectManager member=GetManagedObjects - peer=(name=:*, label=goa-daemon), + peer=(name=@{busname}, label=goa-daemon), @{exec_path} mr, @@ -67,7 +62,7 @@ profile gnome-control-center-goa-helper @{exec_path} { profile bwrap flags=(attach_disconnected,complain) { include - include + include @{bin}/bwrap mr, diff --git a/apparmor.d/groups/gnome/gnome-control-center-print-renderer b/apparmor.d/groups/gnome/gnome-control-center-print-renderer index 59679deb8c..24c9498820 100644 --- a/apparmor.d/groups/gnome/gnome-control-center-print-renderer +++ b/apparmor.d/groups/gnome/gnome-control-center-print-renderer @@ -7,11 +7,8 @@ abi , include @{exec_path} = @{lib}/gnome-control-center-print-renderer -profile gnome-control-center-print-renderer @{exec_path} { +profile gnome-control-center-print-renderer @{exec_path} flags=(attach_disconnected) { include - include - include - include include include include @@ -19,11 +16,16 @@ profile gnome-control-center-print-renderer @{exec_path} { @{exec_path} mr, + @{bin}/flatpak Px, + /usr/share/pixmaps/{,**} r, / r, + owner @{HOME}/.var/app/*/cache/{,**/} r, + owner @{PROC}/@{pid}/cmdline r, + owner @{PROC}/@{pid}/stat r, owner @{PROC}/@{pid}/task/@{tid}/comm rw, include if exists diff --git a/apparmor.d/groups/gnome/gnome-control-center-search-provider b/apparmor.d/groups/gnome/gnome-control-center-search-provider index 3dfd1bf031..a082b53289 100644 --- a/apparmor.d/groups/gnome/gnome-control-center-search-provider +++ b/apparmor.d/groups/gnome/gnome-control-center-search-provider @@ -9,12 +9,12 @@ include @{exec_path} = @{lib}/gnome-control-center-search-provider profile gnome-control-center-search-provider @{exec_path} { include - include include + include include include - #aa:dbus own bus=session name=org.gnome.Settings.SearchProvider + #aa:dbus own bus=session name=org.gnome.Settings.SearchProvider interface+=org.gnome.Shell.SearchProvider2 @{exec_path} mr, diff --git a/apparmor.d/groups/gnome/gnome-desktop-thumbnailers b/apparmor.d/groups/gnome/gnome-desktop-thumbnailers index 436d824431..de4193962f 100644 --- a/apparmor.d/groups/gnome/gnome-desktop-thumbnailers +++ b/apparmor.d/groups/gnome/gnome-desktop-thumbnailers @@ -8,25 +8,74 @@ include profile gnome-desktop-thumbnailers flags=(attach_disconnected) { include - include - include + include include + include capability dac_override, - @{bin}/bwrap mr, - @{bin}/*-thumbnailer rix, + unix (send receive) type=stream peer=(label=nautilus), + + signal receive set=kill peer=nautilus, + + @{bin}/*-thumbnailer Cx -> &gnome-desktop-thumbnailers//thumbnailer, + + #aa:only apparmor<5.0 + @{lib}/glycin-loaders/@{d}+/glycin-* Cx -> gnome-desktop-thumbnailers//&glycin//loaders, + + #aa:only apparmor>=5.0 + @{lib}/glycin-loaders/@{d}+/glycin-* Px -> gnome-desktop-thumbnailers//&:glycin:loaders, - /usr/share/ladspa/rdf/{,**} r, /usr/share/poppler/{,**} r, owner @{user_cache_dirs}/gnome-desktop-thumbnailer/{,**} rw, + owner @{tmp}/.goutputstream-@{rand6} rw, owner @{tmp}/flatpak-seccomp-@{rand6} rw, owner @{tmp}/gnome-desktop-file-to-thumbnail.* r, owner @{tmp}/gnome-desktop-thumbnailer.png w, owner @{tmp}/gsf-thumbnailer-@{rand6} rw, + owner @{PROC}/@{pid}/cgroup r, + owner @{PROC}/@{pid}/cmdline r, + owner @{PROC}/@{pid}/mountinfo r, + + profile thumbnailer flags=(attach_disconnected) { + include + include + include + include + + network (bind create getattr getopt setopt) netlink raw, + + unix type=stream peer=(label=gnome-desktop-thumbnailers), + + @{bin}/*-thumbnailer mr, + @{lib}/glycin-loaders/@{d}+/glycin-* ix, + + /usr/share/poppler/{,**} r, + + /usr/share/glycin-loaders/{,**} r, + @{att}/usr/share/glycin-loaders/{,**} r, + + @{att}/usr/share/gtksourceview-2.0/{,**} r, + @{att}/usr/share/gtksourceview-3.0/{,**} r, + @{att}/usr/share/gtksourceview-4/{,**} r, + @{att}/usr/share/gtksourceview-5/{,**} r, + + owner @{user_cache_dirs}/gnome-desktop-thumbnailer/{,**} rw, + + owner @{tmp}/gnome-desktop-file-to-thumbnail.* r, + owner @{tmp}/gnome-desktop-thumbnailer.png w, + owner @{tmp}/gsf-thumbnailer-@{rand6} rw, + + owner @{PROC}/@{pid}/cgroup r, + owner @{PROC}/@{pid}/cmdline r, + owner @{PROC}/@{pid}/mountinfo r, + + include if exists + } + include if exists } diff --git a/apparmor.d/groups/gnome/gnome-disk-image-mounter b/apparmor.d/groups/gnome/gnome-disk-image-mounter index 379a887b3e..c43b4fc2f1 100644 --- a/apparmor.d/groups/gnome/gnome-disk-image-mounter +++ b/apparmor.d/groups/gnome/gnome-disk-image-mounter @@ -7,12 +7,15 @@ abi , include @{exec_path} = @{bin}/gnome-disk-image-mounter -profile gnome-disk-image-mounter @{exec_path} { +profile gnome-disk-image-mounter @{exec_path} flags=(attach_disconnected) { include + include include include include + #aa:dbus talk bus=system name=org.freedesktop.UDisks2 label=udisksd + @{exec_path} mr, # Allow to mount user files diff --git a/apparmor.d/groups/gnome/gnome-disks b/apparmor.d/groups/gnome/gnome-disks index 4d5301262d..eaabd71102 100644 --- a/apparmor.d/groups/gnome/gnome-disks +++ b/apparmor.d/groups/gnome/gnome-disks @@ -7,15 +7,16 @@ abi , include @{exec_path} = @{bin}/gnome-disks -profile gnome-disks @{exec_path} { +profile gnome-disks @{exec_path} flags=(attach_disconnected) { include - include include include include + include include #aa:dbus own bus=session name=org.gnome.DiskUtility + #aa:dbus talk bus=system name=org.freedesktop.UDisks2 label=udisksd @{exec_path} mr, diff --git a/apparmor.d/groups/gnome/gnome-extension b/apparmor.d/groups/gnome/gnome-extension new file mode 100644 index 0000000000..af4365aad5 --- /dev/null +++ b/apparmor.d/groups/gnome/gnome-extension @@ -0,0 +1,54 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# gjs started from gnome-shell should (in theory) only run gnome extensions. + +abi , + +include + +@{share_dirs} = /usr/share/gnome-shell/extensions/ +@{share_dirs} += @{user_share_dirs}/gnome-shell/extensions/ + +@{exec_path} = @{bin}/gjs-console +profile gnome-extension { + include + include + include + include + include + include + include + include + + # Server side of abstractions/gnome-base: introspect everything + dbus send bus=session + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=@{busname}), + dbus send bus=session + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=org.freedesktop.DBus, label="@{p_dbus_session}"), + + @{exec_path} mr, + + # Used to track the extensions supported by this profile + @{share_dirs}/tilingshell@ferrarodomenico.com/*.js r, + @{share_dirs}/ubuntu-appindicators@ubuntu.com/*.js r, + @{share_dirs}/ubuntu-appindicators@ubuntu.com/tools/busAnalyzer.js r, + @{share_dirs}/ubuntu-dock@ubuntu.com/*.js r, + + /usr/share/xkeyboard-config-2/{,**} r, + + owner @{run}/user/@{uid}/gvfsd/socket-@{rand8} rw, + + owner @{PROC}/@{pid}/mounts r, + owner @{PROC}/@{pid}/stat r, + owner @{PROC}/@{pid}/task/@{tid}/stat r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/gnome/gnome-extension-ding b/apparmor.d/groups/gnome/gnome-extension-ding index 695be9f0d9..6cb2a84473 100644 --- a/apparmor.d/groups/gnome/gnome-extension-ding +++ b/apparmor.d/groups/gnome/gnome-extension-ding @@ -9,31 +9,24 @@ include @{share_dirs} = /usr/share/gnome-shell/extensions/ding@rastersoft.com @{share_dirs} += @{user_share_dirs}/gnome-shell/extensions/ding@rastersoft.com -@{exec_path} = @{share_dirs}/{,app/}ding.js +@{exec_path} = @{share_dirs}/app/{ding,createThumbnail}.js profile gnome-extension-ding @{exec_path} { include include - include - include - include - include - include - include - include - include - include - include - include - include - include + include + include + include + include + include include include include + include unix (send,receive) type=stream addr=none peer=(label=gnome-shell), - #aa:dbus own bus=session name=com.rastersoft.ding interface+=org.gtk.Actions - #aa:dbus talk bus=session name=com.rastersoft.dingextension label=gnome-shell interface+=org.gtk.Actions + #aa:dbus own bus=session name=com.rastersoft.ding + #aa:dbus talk bus=session name=com.rastersoft.dingextension label=gnome-shell dbus send bus=session path=/org/freedesktop/DBus interface=org.freedesktop.DBus.Introspectable @@ -58,10 +51,10 @@ profile gnome-extension-ding @{exec_path} { @{share_dirs}/{,**} r, /usr/share/thumbnailers/{,*.thumbnailer} r, - owner @{HOME}/@{XDG_TEMPLATES_DIR}/ r, - owner @{HOME}/@{XDG_DESKTOP_DIR}/ r, + owner @{user_desktop_dirs}/{,**} r, + owner @{user_templates_dirs}/{,**} r, - owner @{user_share_dirs}/nautilus/scripts/ r, + owner @{user_share_dirs}/nautilus/scripts/{,**} r, owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/mounts r, diff --git a/apparmor.d/groups/gnome/gnome-extension-gsconnect b/apparmor.d/groups/gnome/gnome-extension-gsconnect index c0f131dd11..bed0ff2491 100644 --- a/apparmor.d/groups/gnome/gnome-extension-gsconnect +++ b/apparmor.d/groups/gnome/gnome-extension-gsconnect @@ -10,17 +10,23 @@ include @{share_dirs} += @{user_share_dirs}/gnome-shell/extensions/gsconnect@andyholmes.github.io @{exec_path} = @{share_dirs}/service/daemon.js @{share_dirs}/gsconnect-preferences -profile gnome-extension-gsconnect @{exec_path} { +profile gnome-extension-gsconnect @{exec_path} flags=(attach_disconnected) { include include - include - include - include + include + include + include + include + include + include include include + include include + include include include + include network inet dgram, network inet6 dgram, @@ -28,6 +34,33 @@ profile gnome-extension-gsconnect @{exec_path} { network inet6 stream, network netlink raw, + unix type=stream addr=none peer=(label=gvfsd-*, addr=none), + + #aa:dbus own bus=session name=org.gnome.Shell.Extensions.GSConnect + + #aa:dbus own bus=session name=org.mpris.MediaPlayer2.GSConnect.* + + dbus send bus=session path=/org/freedesktop/DBus + interface=org.freedesktop.DBus.Monitoring + member=BecomeMonitor + peer=(name=org.freedesktop.DBus, label="@{p_dbus_session}"), + + dbus send bus=session path=/org/mpris/MediaPlayer2 + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name=@{busname}), + + dbus receive bus=session path=/org/mpris/MediaPlayer2 + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name=@{busname}), + dbus send bus=session path=/org/mpris/MediaPlayer2 + interface=org.mpris.MediaPlayer2.Player + member=PlayPause + peer=(name=@{busname}), + + dbus eavesdrop bus=session, + @{exec_path} mr, @{sh_path} rix, @@ -48,25 +81,38 @@ profile gnome-extension-gsconnect @{exec_path} { @{share_dirs}/{,**} r, @{share_dirs}/gsconnect-preferences rix, + /snap/*/@{uid}/**.@{icon_ext} r, + /usr/share/**.@{icon_ext} r, + /var/lib/flatpak/appstream/**/icons/{,**} r, + owner @{user_cache_dirs}/gsconnect/{,**} rw, + owner @{user_cache_dirs}/*/**.@{icon_ext} r, owner @{user_config_dirs}/gsconnect/{,**} rw, owner @{user_config_dirs}/mimeapps.list w, owner @{user_config_dirs}/mimeapps.list.@{rand6} rw, - owner @{HOME}/.mozilla/firefox/firefox-mpris/@{word}.png r, + owner @{HOME}/.mozilla/firefox{,-esr}/firefox-mpris/@{word}.@{icon_ext} r, + owner @{HOME}/.var/app/*/**.@{icon_ext} r, owner @{tmp}/.org.chromium.Chromium.@{rand6} r, + owner @{run}/user/@{uid}/app/*/.org.chromium.Chromium.@{rand6} r, + owner @{run}/user/@{uid}/gcr/ssh rw, owner @{run}/user/@{uid}/gsconnect/{,**} rw, + owner @{run}/user/@{uid}/gvfsd/socket-@{rand8} rw, + owner @{run}/user/@{uid}/keyring/ssh rw, @{sys}/devices/virtual/dmi/id/chassis_type r, + owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/mounts r, owner @{PROC}/@{pid}/stat r, - owner @{PROC}/@{pid}/status r, + owner @{PROC}/@{pid}/statm r, owner @{PROC}/@{pid}/task/@{tid}/stat r, + deny @{user_share_dirs}/gvfs-metadata/* r, + include if exists } diff --git a/apparmor.d/groups/gnome/gnome-extension-manager b/apparmor.d/groups/gnome/gnome-extension-manager index 3b23d4ffc4..a8155124f0 100644 --- a/apparmor.d/groups/gnome/gnome-extension-manager +++ b/apparmor.d/groups/gnome/gnome-extension-manager @@ -7,12 +7,13 @@ abi , include @{exec_path} = @{bin}/extension-manager -profile gnome-extension-manager @{exec_path} { +profile gnome-extension-manager @{exec_path} flags=(attach_disconnected) { include include include include include + include include include @@ -22,6 +23,9 @@ profile gnome-extension-manager @{exec_path} { network inet6 stream, network netlink raw, + #aa:dbus own bus=session name=com.mattjakeman.ExtensionManager + #aa:dbus talk bus=session name=org.gnome.Shell.Extensions label=gjs + @{exec_path} mr, @{bin}/gjs-console rix, diff --git a/apparmor.d/groups/gnome/gnome-extensions-app b/apparmor.d/groups/gnome/gnome-extensions-app index f1e229b591..0a65c95f2e 100644 --- a/apparmor.d/groups/gnome/gnome-extensions-app +++ b/apparmor.d/groups/gnome/gnome-extensions-app @@ -22,7 +22,6 @@ profile gnome-extensions-app @{exec_path} { /usr/share/terminfo/** r, owner @{PROC}/@{pid}/mounts r, - owner @{PROC}/@{pids}/stat r, owner @{PROC}/@{pids}/task/@{tid}/stat r, /dev/tty rw, diff --git a/apparmor.d/groups/gnome/gnome-firmware b/apparmor.d/groups/gnome/gnome-firmware index af44afbece..87b76cb80b 100644 --- a/apparmor.d/groups/gnome/gnome-firmware +++ b/apparmor.d/groups/gnome/gnome-firmware @@ -9,7 +9,6 @@ include @{exec_path} = @{bin}/gnome-firmware profile gnome-firmware @{exec_path} { include - include include include include @@ -20,8 +19,8 @@ profile gnome-firmware @{exec_path} { network inet6 stream, network netlink raw, - #aa:dbus talk bus=system name=org.freedesktop.fwupd label=fwupd path=/ - #aa:dbus talk bus=system name=org.freedesktop.login1 label=systemd-logind + #aa:dbus talk bus=system name=org.freedesktop.fwupd label="@{p_fwupd}" path=/ + #aa:dbus talk bus=system name=org.freedesktop.login1 label="@{p_systemd_logind}" @{exec_path} mr, @{open_path} rPx -> child-open-help, diff --git a/apparmor.d/groups/gnome/gnome-initial-setup b/apparmor.d/groups/gnome/gnome-initial-setup index 3f5cf61090..a372615bbd 100644 --- a/apparmor.d/groups/gnome/gnome-initial-setup +++ b/apparmor.d/groups/gnome/gnome-initial-setup @@ -9,19 +9,16 @@ include @{exec_path} = @{lib}/gnome-initial-setup profile gnome-initial-setup @{exec_path} { include - include - include - include - include - include - include - include + include include include include include include + include include + include + include network inet dgram, network inet6 dgram, @@ -29,22 +26,38 @@ profile gnome-initial-setup @{exec_path} { network inet6 stream, network netlink raw, - #aa:dbus own bus=session name=org.gnome.InitialSetup interface+=org.gtk.Actions + #aa:dbus own bus=session name=org.gnome.InitialSetup + + #aa:dbus talk bus=session name=org.gnome.Shell label=gnome-shell + + #aa:only ubuntu + #aa:dbus talk bus=system name=com.ubuntu.WhoopsiePreferences label=whoopsie-preferences + + #aa:only ubuntu + dbus send bus=system path=/com/canonical/UbuntuAdvantage/Manager + interface=org.freedesktop.DBus.Properties + member=Get + peer=(name=com.canonical.UbuntuAdvantage), @{exec_path} mr, - @{bin}/df rPx, - @{bin}/dpkg rPx -> child-dpkg, - @{bin}/locale rix, - @{bin}/lscpu rPx, - @{bin}/lspci rPx, - @{bin}/xrandr rPx, + @{bin}/df Px, + @{bin}/dpkg Px -> child-dpkg, #aa:only apt + @{bin}/locale rix, + @{bin}/lsb_release Px, + @{bin}/lsblk Px, + @{bin}/lscpu Px, + @{bin}/lspci Px, + @{bin}/systemd-detect-virt Px, + @{bin}/ubuntu-advantage Px, #aa:only ubuntu + @{bin}/xrandr Px, + @{open_path} Px -> child-open-browsers, @{lib}/gnome-initial-setup-goa-helper rix, - @{lib}/@{multiarch}/ld-linux-*.so* rix, + @{ldd_path} rix, - /usr/share/dconf/profile/gdm r, /usr/share/gnome-initial-setup/{,**} r, + /usr/share/thumbnailers/{,**} r, /usr/share/xml/iso-codes/{,**} r, @{etc_ro}/security/pwquality.conf r, @@ -55,14 +68,14 @@ profile gnome-initial-setup @{exec_path} { /var/log/installer/telemetry r, #aa:only ubuntu - owner @{GDM_HOME}/greeter-dconf-defaults r, - #aa:only ubuntu - owner @{user_cache_dirs}/ubuntu-report/ rw, - owner @{user_cache_dirs}/ubuntu-report/* rw, + owner @{user_cache_dirs}/ubuntu-report/{,**} rw, + owner @{user_cache_dirs}/ubuntu-insights/{,**} rw, owner @{user_config_dirs}/gnome-initial-setup-done w, owner @{user_config_dirs}/gnome-initial-setup-done.@{rand6} rw, + owner @{user_config_dirs}/gnome-initial-setup/{,**} rw, + owner @{user_config_dirs}/ubuntu-insights/{,**} rw, #aa:only ubuntu owner @{user_config_dirs}/ibus/bus/ r, owner @{user_config_dirs}/ibus/bus/@{hex32}-unix-{,wayland-}@{int} r, @@ -74,20 +87,11 @@ profile gnome-initial-setup @{exec_path} { @{run}/systemd/sessions/@{int} r, @{run}/systemd/users/@{uid} r, - @{sys}/fs/cgroup/user.slice/cpu.max r, - @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/cpu.max r, - @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/cpu.max r, - owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/cpu.max r, owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/gnome-initial-setup-first-login.service/memory.* r, - @{sys}/devices/virtual/dmi/id/bios_vendor r, - @{sys}/devices/virtual/dmi/id/bios_version r, - @{sys}/devices/virtual/dmi/id/product_family r, - @{sys}/devices/virtual/dmi/id/product_name r, - @{sys}/devices/virtual/dmi/id/sys_vendor r, - @{PROC}/zoneinfo r, owner @{PROC}/@{pid}/cgroup r, + owner @{PROC}/@{pid}/mountinfo r, include if exists } diff --git a/apparmor.d/groups/gnome/gnome-keyring-daemon b/apparmor.d/groups/gnome/gnome-keyring-daemon index c62175c853..9b42cc9311 100644 --- a/apparmor.d/groups/gnome/gnome-keyring-daemon +++ b/apparmor.d/groups/gnome/gnome-keyring-daemon @@ -10,30 +10,41 @@ include @{exec_path} = @{bin}/gnome-keyring-daemon profile gnome-keyring-daemon @{exec_path} flags=(attach_disconnected) { include - include include include - include - include - include + include + include + include capability ipc_lock, - signal (receive) set=(term) peer=gdm, - signal (send) set=(term) peer=ssh-agent, + signal receive set=(term) peer=gdm, + signal send set=(term) peer=ssh-agent, + + unix (send receive) type=stream peer=(label=snap.*), + unix (send receive) type=stream peer=(label=fapp), + unix (send receive) type=stream peer=(label=fbwrap), + unix (send receive) type=stream peer=(label=flatpak.*), #aa:dbus own bus=session name=org.gnome.keyring - #aa:dbus own bus=session name=org.freedesktop.{S,s}ecret{,s} + #aa:dbus own bus=session name=org.freedesktop.[sS]ecret{,s}{,.*} + #aa:dbus own bus=session name=org.freedesktop.impl.portal.Secret path=/org/freedesktop/portal/desktop + #aa:dbus talk bus=session name=org.freedesktop.impl.portal.Request path=/org/freedesktop/portal/desktop/ label=xdg-desktop-portal dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), dbus send bus=system path=/org/freedesktop/login1 interface=org.freedesktop.login1.Manager member=GetSession - peer=(name=org.freedesktop.login1, label=systemd-logind), + peer=(name=org.freedesktop.login1, label="@{p_systemd_logind}"), + + dbus send bus=session path=/org/gnome/SessionManager + interface=org.gnome.SessionManager + member=Setenv + peer=(name=org.gnome.SessionManager, label="@{p_gnome_session}"), @{exec_path} mr, diff --git a/apparmor.d/groups/gnome/gnome-logs b/apparmor.d/groups/gnome/gnome-logs index 06e66a43b2..5e3ab03bdd 100644 --- a/apparmor.d/groups/gnome/gnome-logs +++ b/apparmor.d/groups/gnome/gnome-logs @@ -27,8 +27,6 @@ profile gnome-logs @{exec_path} { /{run,var}/log/journal/@{hex32}/user-@{uid}@@{hex32}-@{hex16}-@{hex16}.journal r, /{run,var}/log/journal/remote/ r, - owner @{PROC}/@{pid}/stat r, - include if exists } diff --git a/apparmor.d/groups/gnome/gnome-maps b/apparmor.d/groups/gnome/gnome-maps index 294d6229a4..de1a53018c 100644 --- a/apparmor.d/groups/gnome/gnome-maps +++ b/apparmor.d/groups/gnome/gnome-maps @@ -7,7 +7,7 @@ abi , include @{exec_path} = @{bin}/gnome-maps /usr/share/gnome-maps/org.gnome.Maps -profile gnome-maps @{exec_path} { +profile gnome-maps @{exec_path} flags=(attach_disconnected) { include include include @@ -24,7 +24,7 @@ profile gnome-maps @{exec_path} { @{open_path} rPx -> child-open-help, - audit @{bin}/gjs-console rix, + @{bin}/gjs-console r, owner @{user_pictures_dirs}/** rw, @@ -45,7 +45,6 @@ profile gnome-maps @{exec_path} { owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/mounts r, - owner @{PROC}/@{pid}/stat r, owner @{PROC}/@{pid}/task/@{tid}/stat r, include if exists diff --git a/apparmor.d/groups/gnome/gnome-music b/apparmor.d/groups/gnome/gnome-music index 7874e95ffa..c3023750e3 100644 --- a/apparmor.d/groups/gnome/gnome-music +++ b/apparmor.d/groups/gnome/gnome-music @@ -10,13 +10,14 @@ include profile gnome-music @{exec_path} flags=(attach_disconnected) { include include - include - include + include + include include include include include include + include include network inet stream, @@ -48,11 +49,9 @@ profile gnome-music @{exec_path} flags=(attach_disconnected) { owner @{user_share_dirs}/grilo-plugins/ rwk, owner @{user_share_dirs}/grilo-plugins/*.db{,-shm,-journal,-wal} rwk, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, owner @{tmp}/grilo-plugin-cache-[0-9A-Z]*/ rw, - owner /var/tmp/etilqs_@{hex15} rw, - owner /var/tmp/etilqs_@{hex16} rw, @{PROC}/sys/net/ipv6/conf/all/disable_ipv6 r, owner @{PROC}/@{pid}/mounts r, diff --git a/apparmor.d/groups/gnome/gnome-photos-thumbnailer b/apparmor.d/groups/gnome/gnome-photos-thumbnailer index 0182e9dade..a954502a32 100644 --- a/apparmor.d/groups/gnome/gnome-photos-thumbnailer +++ b/apparmor.d/groups/gnome/gnome-photos-thumbnailer @@ -9,18 +9,17 @@ include @{exec_path} = @{lib}/gnome-photos-thumbnailer profile gnome-photos-thumbnailer @{exec_path} { include + include include @{exec_path} mr, - /usr/share/mime/mime.cache r, - owner @{user_pictures_dirs}/{,**} r, owner @{user_cache_dirs}/babl/{,**} r, - owner @{user_cache_dirs}/gegl-*/{,**} r, + owner @{user_cache_dirs}/gegl-@{version}/{,**} r, owner @{user_cache_dirs}/gnome-photos/thumbnails/{,**} rw, - owner @{user_share_dirs}/gegl-*/{,**} r, + owner @{user_share_dirs}/gegl-@{version}/{,**} r, owner /dev/shm/DzlCounters-@{int} rw, diff --git a/apparmor.d/groups/gnome/gnome-remote-desktop-daemon b/apparmor.d/groups/gnome/gnome-remote-desktop-daemon index c3631ddb71..bcb5b55a21 100644 --- a/apparmor.d/groups/gnome/gnome-remote-desktop-daemon +++ b/apparmor.d/groups/gnome/gnome-remote-desktop-daemon @@ -9,9 +9,7 @@ include @{exec_path} = @{lib}/gnome-remote-desktop-daemon profile gnome-remote-desktop-daemon @{exec_path} { include - include - include - include + include include include include diff --git a/apparmor.d/groups/gnome/gnome-session b/apparmor.d/groups/gnome/gnome-session index ce6abe6d9e..41d4a5fc04 100644 --- a/apparmor.d/groups/gnome/gnome-session +++ b/apparmor.d/groups/gnome/gnome-session @@ -7,20 +7,37 @@ abi , include @{exec_path} = @{bin}/gnome-session -profile gnome-session @{exec_path} { +profile gnome-session @{exec_path} flags=(attach_disconnected) { include + include + include include + include + include include include + signal receive set=term peer=gdm, + signal receive set=term peer=gdm-session, + + dbus send bus=session path=/org/freedesktop/DBus + interface=org.freedesktop.DBus + member=UpdateActivationEnvironment + peer=(name=org.freedesktop.DBus label="@{p_dbus_session}"), + + dbus receive bus=session + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), + @{exec_path} mrix, @{shells_path} rix, + @{bin}/{,e}grep rix, @{bin}/cat rix, @{bin}/find rix, @{bin}/gettext rix, @{bin}/gettext.sh r, - @{bin}/grep rix, @{bin}/head rix, @{bin}/id rix, @{bin}/locale rix, @@ -28,6 +45,7 @@ profile gnome-session @{exec_path} { @{bin}/manpath rix, @{bin}/readlink rix, @{bin}/realpath rix, + @{bin}/run-parts rix, @{bin}/sed rix, @{bin}/tput rix, @{bin}/tr rix, @@ -35,10 +53,12 @@ profile gnome-session @{exec_path} { @{bin}/uname rix, @{bin}/xargs rix, - @{bin}/dpkg-query rpx, - @{bin}/flatpak rCx -> flatpak, - @{bin}/gsettings rPx, - @{lib}/gnome-session-binary rPx, + @{bin}/dpkg-query px, + @{bin}/flatpak Cx -> flatpak, + @{bin}/systemd-cat Px, + @{bin}/gsettings Px, + @{lib}/gnome-session-binary Px, + @{lib}/gnome-session-init-worker Px, /usr/share/im-config/{,**} r, /usr/share/libdebuginfod-common/debuginfod.sh r, @@ -60,19 +80,21 @@ profile gnome-session @{exec_path} { owner @{HOME}/ r, + owner @{run}/user/@{uid}/gnome-session-leader-fifo rw, + owner @{PROC}/@{pid}/cmdline r, owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/loginuid r, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, - profile flatpak { + profile flatpak flags=(attach_disconnected) { include include @{bin}/flatpak mr, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/gnome/gnome-session-binary b/apparmor.d/groups/gnome/gnome-session-binary index 1f17b35a35..bdcba775c8 100644 --- a/apparmor.d/groups/gnome/gnome-session-binary +++ b/apparmor.d/groups/gnome/gnome-session-binary @@ -9,18 +9,13 @@ include @{exec_path} = @{lib}/gnome-session-binary profile gnome-session-binary @{exec_path} flags=(attach_disconnected) { include - include - include - include - include - include - include - include - include + include + include include include include include + include network inet stream, network inet6 stream, @@ -28,11 +23,11 @@ profile gnome-session-binary @{exec_path} flags=(attach_disconnected) { network inet6 dgram, network netlink raw, - signal (receive) set=(term, hup) peer=gdm*, - signal (send) set=(term) peer=gsd-*, + signal receive set=(term, hup) peer=gdm*, + signal send set=(term) peer=gsd-*, #aa:dbus own bus=session name=org.gnome.SessionManager - #aa:dbus talk bus=system name=org.freedesktop.login1 label=systemd-logind + #aa:dbus talk bus=system name=org.freedesktop.login1 label="@{p_systemd_logind}" dbus send bus=session path=/org/freedesktop/DBus interface=org.freedesktop.DBus @@ -54,30 +49,30 @@ profile gnome-session-binary @{exec_path} flags=(attach_disconnected) { @{lib}/gio-launch-desktop rCx -> open, @{lib}/@{multiarch}/glib-@{version}/gio-launch-desktop rCx -> open, - /usr/share/dconf/profile/gdm r, - /usr/share/gdm/greeter-dconf-defaults r, /usr/share/gdm/greeter/applications/{,**} r, /usr/share/gdm/greeter/autostart/{,*.desktop} r, /usr/share/gnome-session/hardware-compatibility r, /usr/share/gnome-session/sessions/*.session r, + /usr/share/gnome-shell/extensions/ r, /usr/share/gnome-shell/extensions/*/metadata.json r, /usr/share/gnome/autostart/{,*.desktop} r, @{etc_ro}/xdg/autostart/{,*.desktop} r, owner @{gdm_cache_dirs}/gdm/Xauthority r, + owner @{gdm_config_dirs}/ rw, owner @{gdm_config_dirs}/dconf/user rw, owner @{gdm_config_dirs}/gnome-session/ rw, owner @{gdm_config_dirs}/gnome-session/saved-session/ rw, - owner @{GDM_HOME}/greeter-dconf-defaults r, + owner @{gdm_config_dirs}/user-dirs.dirs r, owner @{gdm_share_dirs}/applications/{,**} r, owner @{user_config_dirs}/autostart/{,*.desktop} r, owner @{user_config_dirs}/gnome-session/ rw, owner @{user_config_dirs}/gnome-session/saved-session/ rw, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, - @{att}/@{run}/systemd/sessions/{,@{l}}@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/sessions/{,@{l}}@{int}.ref rw, @{run}/systemd/sessions/* r, @{run}/systemd/users/@{uid} r, @@ -98,12 +93,11 @@ profile gnome-session-binary @{exec_path} flags=(attach_disconnected) { owner @{PROC}/@{pid}/loginuid r, /dev/tty rw, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, profile open flags=(attach_disconnected) { include include - include include @{bin}/env rix, diff --git a/apparmor.d/groups/gnome/gnome-session-check b/apparmor.d/groups/gnome/gnome-session-check index 2a0b4965f4..44755aef20 100644 --- a/apparmor.d/groups/gnome/gnome-session-check +++ b/apparmor.d/groups/gnome/gnome-session-check @@ -10,12 +10,17 @@ include profile gnome-session-check @{exec_path} { include include + include @{exec_path} mr, @{lib}/gnome-session-check-accelerated-gl-helper ix, @{lib}/gnome-session-check-accelerated-gles-helper ix, + /usr/share/gnome-session/hardware-compatibility r, + + @{PROC}/cmdline r, + include if exists } diff --git a/apparmor.d/groups/gnome/gnome-session-ctl b/apparmor.d/groups/gnome/gnome-session-ctl index 04c4ce628e..a70a360c4b 100644 --- a/apparmor.d/groups/gnome/gnome-session-ctl +++ b/apparmor.d/groups/gnome/gnome-session-ctl @@ -7,7 +7,7 @@ abi , include @{exec_path} = @{lib}/gnome-session-ctl -profile gnome-session-ctl @{exec_path} { +profile gnome-session-ctl @{exec_path} flags=(attach_disconnected) { include include @@ -23,7 +23,7 @@ profile gnome-session-ctl @{exec_path} { dbus send bus=session path=/org/gnome/SessionManager interface=org.gnome.SessionManager member=Initialized - peer=(name=org.gnome.SessionManager, label=gnome-session-binary), + peer=(name=org.gnome.SessionManager, label="@{p_gnome_session}"), @{exec_path} mr, diff --git a/apparmor.d/groups/gnome/gnome-session-init-worker b/apparmor.d/groups/gnome/gnome-session-init-worker new file mode 100644 index 0000000000..005c60016d --- /dev/null +++ b/apparmor.d/groups/gnome/gnome-session-init-worker @@ -0,0 +1,27 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/gnome-session-init-worker +profile gnome-session-init-worker @{exec_path} flags=(attach_disconnected) { + include + include + include + include + include + + signal receive set=term peer=gdm, + signal receive set=term peer=gdm-session, + + @{exec_path} mr, + + owner @{run}/user/@{uid}/gnome-session-leader-fifo w, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/gnome/gnome-session-service b/apparmor.d/groups/gnome/gnome-session-service new file mode 100644 index 0000000000..01ae0a009e --- /dev/null +++ b/apparmor.d/groups/gnome/gnome-session-service @@ -0,0 +1,84 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/gnome-session-service +profile gnome-session-service @{exec_path} flags=(attach_disconnected) { + include + include + include + include + include + include + + #aa:dbus own bus=session name=org.gnome.SessionManager + #aa:dbus talk bus=system name=org.freedesktop.login1 label="@{p_systemd_logind}" + + dbus send bus=session path=/org/freedesktop/DBus + interface=org.freedesktop.DBus + member=UpdateActivationEnvironment + peer=(name=org.freedesktop.DBus label="@{p_dbus_session}"), + + dbus receive bus=session + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), + + @{exec_path} mr, + + @{bin}/session-migration rPx, + + @{lib}/gio-launch-desktop rCx -> open, + @{lib}/@{multiarch}/glib-@{version}/gio-launch-desktop rCx -> open, + + /usr/share/gdm/greeter/applications/{,**} r, + /usr/share/gdm/greeter/autostart/{,*.desktop} r, + /usr/share/gnome-session/hardware-compatibility r, + /usr/share/gnome-session/sessions/*.session r, + /usr/share/gnome/autostart/{,*.desktop} r, + + @{etc_ro}/xdg/autostart/{,*.desktop} r, + + owner @{user_config_dirs}/autostart/{,*.desktop} r, + + owner @{user_state_dirs}/ w, + owner @{user_state_dirs}/gnome-session@*.state r, + owner @{user_state_dirs}/gnome-session@*.state.@{rand6} rw, + + @{run}/systemd/sessions/{,@{l}}@{int}{,.ref} rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/sessions/{,@{l}}@{int}{,.ref} rw, + @{run}/systemd/users/@{uid} r, + + owner @{run}/user/@{uid}/systemd/notify w, + + @{PROC}/1/cgroup r, + owner @{PROC}/@{pid}/cgroup r, + + profile open flags=(attach_disconnected) { + include + include + + @{lib}/@{multiarch}/glib-@{version}/gio-launch-desktop mr, + @{lib}/gio-launch-desktop mr, + + @{sh_path} rix, + @{bin}/env rix, + @{lib}/** PUx, + @{bin}/** PUx, + /opt/*/** PUx, + /usr/share/*/** PUx, + /usr/local/bin/** PUx, + /usr/games/** PUx, + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/gnome/gnome-shell b/apparmor.d/groups/gnome/gnome-shell index 15d8f7268a..3ada2d2bb1 100644 --- a/apparmor.d/groups/gnome/gnome-shell +++ b/apparmor.d/groups/gnome/gnome-shell @@ -2,6 +2,8 @@ # Copyright (C) 2021-2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only +# TODO: some gnome extension run from this profile. It would be better to have a way to separate them. + abi , include @@ -10,41 +12,31 @@ include 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 - include - include - include - include - include - include - include - include - include + include + include + include + include + include + include include include include include include - include + include + include + include include include + include + include include + include + include + include + include include - include + include capability sys_nice, capability sys_ptrace, @@ -56,64 +48,84 @@ profile gnome-shell @{exec_path} flags=(attach_disconnected,mediate_deleted) { network netlink raw, network unix stream, - ptrace (read), - ptrace (readby) peer=pipewire, + ptrace read, - signal (receive) set=(term, hup) peer=gdm*, - signal (send), + signal receive set=(term, hup) peer=gdm*, + signal send, unix (send,receive) type=stream addr=none peer=(label=gnome-extension-ding), unix (send,receive) type=stream addr=none peer=(label=xkbcomp), unix (send,receive) type=stream addr=none peer=(label=xwayland), - unix (send,receive, connect) type=stream peer=(addr="@/var/lib/gdm{3,}/.cache/ibus/dbus-????????", label=ibus-daemon), # Owned by gnome-shell + include #aa:lint ignore=abstractions + #aa:dbus own bus=session name=org.gnome.keyring.SystemPrompter #aa:dbus own bus=session name=org.gnome.Mutter #aa:dbus own bus=session name=org.gnome.Shell #aa:dbus own bus=session name=com.canonical.{U,u}nity + #aa:dbus own bus=session name=com.canonical.dbusmenu path=/{,**} + #aa:dbus own bus=session name=com.canonical.Shell.PermissionPrompting #aa:dbus own bus=session name=com.rastersoft.dingextension #aa:dbus own bus=session name=org.ayatana.NotificationItem - #aa:dbus own bus=session name=org.gtk.Actions path=/** + #aa:dbus own bus=session name=org.freedesktop.a11y.Manager + #aa:dbus own bus=session name=org.gnome.Shell + #aa:dbus own bus=session name=org.gtk.Actions path=/{,**} #aa:dbus own bus=session name=org.gtk.MountOperationHandler #aa:dbus own bus=session name=org.gtk.Notifications + #aa:dbus own bus=session name=org.kde.StatusNotifierItem path=/{,**} #aa:dbus own bus=session name=org.kde.StatusNotifierWatcher path=/StatusNotifierWatcher + # owning not strictly needed, but it simplifies things + #aa:dbus own bus=session name=org.mpris.MediaPlayer2 + # Talk with gnome-shell - #aa:dbus talk bus=system name=org.freedesktop.Accounts label=accounts-daemon + # The strategy with dbus rules in this profile is first to declare all communications + # needed on buses and to limit them only to their profiles in apparmor.d. As such, + # only dbus directive is used for this. Later, some communications could be + # restricted. + + #aa:dbus talk bus=system name=net.hadess.PowerProfiles label="@{p_power_profiles_daemon}" + #aa:dbus talk bus=system name=net.hadess.SwitcherooControl label=switcheroo-control + #aa:dbus talk bus=system name=net.reactivated.Fprint label="@{p_fprintd}" + #aa:dbus talk bus=system name=org.freedesktop.Accounts label="@{p_accounts_daemon}" #aa:dbus talk bus=system name=org.freedesktop.bolt label=boltd - #aa:dbus talk bus=system name=org.freedesktop.ColorManager label=colord - #aa:dbus talk bus=system name=org.freedesktop.login1 label=systemd-logind + #aa:dbus talk bus=system name=org.freedesktop.ColorManager label="@{p_colord}" + #aa:dbus talk bus=system name=org.freedesktop.GeoClue2 label=geoclue + #aa:dbus talk bus=system name=org.freedesktop.login1 label="@{p_systemd_logind}" + #aa:dbus talk bus=system name=org.freedesktop.MalcontentTimer1 label=malcontent-timerd + #aa:dbus talk bus=system name=org.freedesktop.ModemManager1 label=ModemManager + #aa:dbus talk bus=system name=org.freedesktop.NetworkManager label=NetworkManager + #aa:dbus talk bus=system name=org.freedesktop.PackageKit label=packagekitd + #aa:dbus talk bus=system name=org.freedesktop.PolicyKit1 label="@{p_polkitd}" + #aa:dbus talk bus=system name=org.freedesktop.RealtimeKit1 label="@{p_rtkit_daemon}" + #aa:dbus talk bus=system name=org.freedesktop.systemd1 label="@{p_systemd}" #aa:dbus talk bus=system name=org.gnome.DisplayManager label=gdm #aa:dbus talk bus=session name=com.rastersoft.ding label=gnome-extension-ding + #aa:dbus talk bus=session name=org.freedesktop.background.Monitor label=xdg-desktop-portal + #aa:dbus talk bus=session name=org.freedesktop.FileManager1 label=nautilus + #aa:dbus talk bus=session name=org.freedesktop.impl.portal.PermissionStore label=xdg-permission-store + #aa:dbus talk bus=session name=org.freedesktop.Notifications label=gjs + #aa:dbus talk bus=session name=org.freedesktop.ScreenSaver label=gsd-screensaver-proxy + #aa:dbus talk bus=session name=org.freedesktop.systemd1 label="@{p_systemd_user}" #aa:dbus talk bus=session name=org.gnome.* label=gnome-* - #aa:dbus talk bus=session name=org.gnome.ScreenSaver label=gjs-console + #aa:dbus talk bus=session name=org.gnome.*.SearchProvider{,2} interface+=org.gnome.Shell.SearchProvider2 label="*" + #aa:dbus talk bus=session name=org.gnome.Nautilus label=nautilus + #aa:dbus talk bus=session name=org.gnome.ScreenSaver label=gjs + #aa:dbus talk bus=session name=org.gnome.SessionManager label="@{p_gnome_session}" #aa:dbus talk bus=session name=org.gnome.SettingsDaemon.* label=gsd-* #aa:dbus talk bus=session name=org.gtk.vfs label="gvfsd{,-*}" - #aa:dbus talk bus=session name=org.gnome.Nautilus label=nautilus - - # System bus - - dbus send bus=system path=/org/freedesktop/PolicyKit1/Authority - interface=org.freedesktop.PolicyKit1.Authority - member=RegisterAuthenticationAgent - peer=(name=:*, label=polkitd), - dbus receive bus=system path=/org/freedesktop/PolicyKit1/AuthenticationAgent - interface=org.freedesktop.PolicyKit1.AuthenticationAgent - member=BeginAuthentication - peer=(name=:*, label=polkitd), - - dbus send bus=system path=/org/freedesktop/NetworkManager/AgentManager - interface=org.freedesktop.NetworkManager.AgentManager - member={RegisterWithCapabilities,Unregister} - peer=(name=:*, label=NetworkManager), # Session bus + # FIXME: too wide + dbus send bus=session path=/org/gnome/** + peer=(name=org.gnome.*), + dbus send bus=session path=/org/freedesktop/DBus interface=org.freedesktop.DBus.Properties member=GetAll @@ -128,76 +140,122 @@ profile gnome-shell @{exec_path} flags=(attach_disconnected,mediate_deleted) { member=Embed peer=(name=org.a11y.atspi.Registry), - dbus receive bus=session path=/org/freedesktop/systemd1 - interface=org.freedesktop.systemd1.Manager - member=JobRemoved - peer=(name=:*, label="@{p_systemd_user}"), - - dbus send bus=session path=/MenuBar - interface=com.canonical.dbusmenu - member={AboutToShow,GetLayout,GetGroupProperties} - peer=(name=:*), - + # Server side of abstractions/bus/org.gnome.keyring.internal.Prompter + dbus receive bus=session path=/org/gnome/keyring/Prompter + interface=org.gnome.keyring.internal.Prompter + member={BeginPrompting,PerformPrompt,StopPrompting} + peer=(name=@{busname}, label=pinentry-*), + dbus send bus=session path=/org/gnome/keyring/Prompt/p@{int} + interface=org.gnome.keyring.internal.Prompter.Callback + member={PromptReady,PromptDone} + peer=(name=@{busname}, label=pinentry-*), + + # Server side of abstractions/bus/session/org.freedesktop.Notifications + dbus send bus=session path=/org/freedesktop/Notifications + interface=org.freedesktop.Notifications + member={ActivationToken,ActionInvoked,NotificationClosed,NotificationReplied} + peer=(name=org.freedesktop.DBus, label=gjs), + + # FIXME: I think gnome-shell is the owner of the notifications, it should then be + # fully allowed to send/receive to/from anyone. + # FIXME: same for dbusmenu; icon things dbus send bus=session path=/StatusNotifierItem interface=org.freedesktop.DBus.Properties member={Get,GetAll} - peer=(name=:*), + peer=(name=@{busname}), dbus send bus=session path=/org/mpris/MediaPlayer2 interface=org.freedesktop.DBus.Properties member={Get,GetAll} - peer=(name=:*), + peer=(name=@{busname}), + # Server side of abstractions/bus/session/org.gtk.Menus + dbus receive bus=session + interface=org.gtk.Menus + member=Changed + peer=(name=@{busname}), + dbus send bus=session + interface=org.gtk.Menus + member={Start,End} + peer=(name=@{busname}), + + # FIXME: must be included in the talk dbus directive + dbus send bus=system path=/net/reactivated/Fprint/Manager + interface=net.reactivated.Fprint.Manager + member=GetDefaultDevice + peer=(name=net.reactivated.Fprint), + + # Needed as a dbus server to administrate the mpris interface + include #aa:lint ignore=abstractions + + # Missing rules from the directive above as these one are not standard + # Part of abstractions/bus/system/org.freedesktop.NetworkManager + dbus send bus=system path=/org/freedesktop + interface=org.freedesktop.DBus.ObjectManager + member=GetManagedObjects + peer=(name=@{busname}, label=NetworkManager), + dbus receive bus=system path=/org/freedesktop + interface=org.freedesktop.DBus.ObjectManager + member={InterfacesAdded,InterfacesRemoved} + peer=(name=@{busname}, label=NetworkManager), + + # Server side of abstractions/gnome-base: introspect everything dbus send bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*), + peer=(name=@{busname}), dbus send bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect peer=(name=org.freedesktop.DBus, label="@{p_dbus_session}"), + dbus send bus=system path=/org/freedesktop/UPower/PowerProfiles + interface=org.freedesktop.DBus.Properties + member=Set + peer=(name=@{busname}, label=power-profiles-daemon), + @{exec_path} mr, @{bin}/unzip rix, @{bin}/flatpak rPx, - @{bin}/gjs-console rPx, + @{bin}/gjs-console rPx -> gnome-extension, @{bin}/glib-compile-schemas rPx, @{bin}/ibus-daemon rPx, + @{bin}/nvidia-smi rPx, # FIXME: for extension only + @{bin}/sensors rPx, @{bin}/tecla rPx, @{bin}/Xwayland rPx, + @{lib}/@{multiarch}/glib-2.0/glib-compile-schemas rPx, @{lib}/{,NetworkManager/}nm-openvpn-auth-dialog rPx, @{lib}/mutter-x11-frames rPx, #aa:exec polkit-agent-helper @{sh_path} rCx -> shell, @{bin}/pkexec rCx -> pkexec, - @{lib}/gio-launch-desktop rCx -> open, @{lib}/@{multiarch}/glib-@{version}/gio-launch-desktop rCx -> open, + @{lib}/gio-launch-desktop rCx -> open, + @{python_path} rCx -> python, @{user_share_dirs}/gnome-shell/extensions/*/** rPUx, /usr/share/gnome-shell/extensions/*/** rPUx, - /opt/**/share/icons/{,**} r, - /snap/*/@{uid}/**.png r, - /usr/share/**.{png,jpg,svg} r, + @{system_share_dirs}/gnome-shell/{,**} r, + /snap/*/@{uid}/**.@{icon_ext} r, + /usr/share/**.@{icon_ext} r, /usr/share/**/icons/{,**} r, /usr/share/backgrounds/{,**} r, /usr/share/byobu/desktop/byobu* r, - /usr/share/dconf/profile/gdm r, /usr/share/desktop-directories/{,*.directory} r, /usr/share/gdm/BuiltInSessions/{,*.desktop} r, - /usr/share/gdm/greeter-dconf-defaults r, /usr/share/gdm/greeter/applications/{,**} r, + /usr/share/gdm/greeter/wayland-sessions/{,*.desktop} r, /usr/share/libgweather/Locations.xml r, /usr/share/libinput*/{,**} r, /usr/share/libwacom/{,*.stylus,*.tablet} r, - /usr/share/poppler/{,**} r, /usr/share/wallpapers/** r, /usr/share/wayland-sessions/{,*.desktop} r, /usr/share/xml/iso-codes/{,**} r, - @{system_share_dirs}/gnome-shell/{,**} r, /etc/fstab r, /etc/timezone r, @@ -209,52 +267,60 @@ profile gnome-shell @{exec_path} flags=(attach_disconnected,mediate_deleted) { /var/lib/flatpak/app/**/gnome-shell/{,**} r, /var/lib/flatpak/appstream/**/icons/** r, + /var/lib/swcatalog/icons/{,**} r, owner @{att}/ r, owner @{att}/.flatpak-info r, - owner @{GDM_HOME}/greeter-dconf-defaults r, owner @{gdm_cache_dirs}/ w, owner @{gdm_cache_dirs}/event-sound-cache.tdb.@{hex32}.@{multiarch} rwk, owner @{gdm_cache_dirs}/fontconfig/{,*} rwl, + owner @{gdm_cache_dirs}/glycin/{,**} rw, owner @{gdm_cache_dirs}/gstreamer-@{int}/ rw, owner @{gdm_cache_dirs}/gstreamer-@{int}/registry.*.bin{,.tmp@{rand6}} rw, owner @{gdm_cache_dirs}/ibus/dbus-@{rand8} rw, owner @{gdm_cache_dirs}/libgweather/ r, - owner @{gdm_config_dirs}/dconf/user r, + owner @{gdm_cache_dirs}/nvidia/GLCache/ rw, + owner @{gdm_cache_dirs}/nvidia/GLCache/** rwk, owner @{gdm_config_dirs}/ibus/ rw, owner @{gdm_config_dirs}/ibus/bus/ rw, owner @{gdm_config_dirs}/ibus/bus/@{hex32}-unix-{,wayland-}@{int} r, owner @{gdm_config_dirs}/pulse/ rw, owner @{gdm_config_dirs}/pulse/client.conf r, owner @{gdm_config_dirs}/pulse/cookie rwk, + owner @{gdm_local_dirs}/ w, + owner @{gdm_share_dirs}/ w, owner @{gdm_share_dirs}/applications/{,**} r, owner @{gdm_share_dirs}/gnome-shell/{,**} rw, owner @{gdm_share_dirs}/icc/ rw, - owner @{gdm_share_dirs}/icc/edid-@{hex32}.icc rw, owner @{gdm_share_dirs}/icc/.goutputstream-@{rand6} rw, + owner @{gdm_share_dirs}/icc/edid-@{hex32}.icc rw, owner @{HOME}/.face r, owner @{HOME}/.mozilla/firefox/firefox-mpris/{,*} r, - owner @{HOME}/.mozilla/native-messaging-hosts/ r, - owner @{HOME}/.mozilla/native-messaging-hosts/org.gnome.shell.extensions.gsconnect.json rw, - owner @{HOME}/.mozilla/native-messaging-hosts/org.gnome.shell.extensions.gsconnect.json.@{rand6} rw, + owner @{HOME}/.mozilla/native-messaging-hosts/ rw, + owner @{HOME}/.mozilla/native-messaging-hosts/org.gnome.shell.*.json{,.@{rand6}} rw, owner @{HOME}/.tpm2_pkcs11/tpm2_pkcs11.sqlite3 rw, - owner @{HOME}/.var/app/**.{png,jpg,svg} r, + owner @{HOME}/.var/app/**.@{icon_ext} r, owner @{HOME}/.var/app/**/ r, owner @{HOME}/@{XDG_SCREENSHOTS_DIR}/{,**} rw, owner @{HOME}/@{XDG_WALLPAPERS_DIR}/{,**} rw, - owner @{user_games_dirs}/**.{png,jpg,svg} r, - owner @{user_music_dirs}/**.{png,jpg,svg} r, + @{system_games_dirs}/**.@{image_ext} r, + owner @{user_games_dirs}/**.@{image_ext} r, + owner @{user_music_dirs}/**.@{image_ext} r, owner @{user_config_dirs}/.goutputstream{,-@{rand6}} rw, + owner @{user_config_dirs}/**/NativeMessagingHosts/ rw, + owner @{user_config_dirs}/**/NativeMessagingHosts/org.gnome.shell.*.json{,.@{rand6}} rw, owner @{user_config_dirs}/background r, owner @{user_config_dirs}/ibus/ w, owner @{user_config_dirs}/monitors.xml{,~} rwl, owner @{user_config_dirs}/tiling-assistant/{,**} rw, owner @{user_share_dirs}/backgrounds/{,**} rw, + owner @{user_share_dirs}/dbus-1/services/ r, + owner @{user_share_dirs}/dbus-1/services/org.gnome.Shell.*.service{,.@{rand6}} rw, owner @{user_share_dirs}/desktop-directories/{,**} r, owner @{user_share_dirs}/gnome-shell/{,**} rw, owner @{user_share_dirs}/gnome-shell/extensions/{,**} r, @@ -262,88 +328,93 @@ profile gnome-shell @{exec_path} flags=(attach_disconnected,mediate_deleted) { owner @{user_share_dirs}/icc/ rw, owner @{user_share_dirs}/icc/.goutputstream-@{rand6} rw, owner @{user_share_dirs}/icc/edid-@{hex32}.icc rw, + owner @{user_share_dirs}/icons/**/org.gnome.Shell.*.svg{,.@{rand6}} w, - owner @{user_share_dirs}/applications/org.gnome.Shell.Extensions.GSConnect{,.Preferences}.desktop rw, - owner @{user_share_dirs}/applications/org.gnome.Shell.Extensions.GSConnect{,.Preferences}.desktop.@{rand6} w, owner @{user_cache_dirs}/evolution/addressbook/*/PHOTO-* r, owner @{user_cache_dirs}/gnome-boxes/*.png r, owner @{user_cache_dirs}/gnome-photos/{,**} r, owner @{user_cache_dirs}/gnome-screenshot/{,**} rw, owner @{user_cache_dirs}/gnome-software/icons/{,**} r, + owner @{user_cache_dirs}/gsconnect/@{hex} r, owner @{user_cache_dirs}/libgweather/{,**} rw, owner @{user_cache_dirs}/media-art/{,**} r, owner @{user_cache_dirs}/vlc/**/*.jpg r, + owner @{user_share_dirs}/applications/org.gnome.Shell.*.desktop{,.@{rand6}} rw, @{run}/gdm{3,}/dbus/dbus-@{rand8} rw, + owner @{run}/user/@{uid}/app/*/.org.chromium.Chromium.@{rand6}/*.@{icon_ext} r, owner @{run}/user/@{uid}/app/*/*.@{rand6} r, owner @{run}/user/@{uid}/gnome-shell-disable-extensions rw, owner @{run}/user/@{uid}/gnome-shell/{,**} rw, owner @{run}/user/@{uid}/gvfsd/socket-@{rand8} rw, - owner @{run}/user/@{uid}/snap.snap*/wayland-cursor-shared-* rw, + owner @{run}/user/@{uid}/snap.*/wayland-cursor-shared-@{rand6} rw, owner @{run}/user/@{uid}/systemd/notify rw, + owner @{att}/dev/shm/.org.chromium.Chromium.@{rand6} rw, owner /dev/shm/.org.chromium.Chromium.@{rand6} rw, owner /dev/shm/wayland.mozilla.ipc.@{int} rw, /tmp/.X@{int}-lock rw, /tmp/dbus-@{rand8} rw, owner @{tmp}/.org.chromium.Chromium.@{rand6} r, + owner @{tmp}/.org.chromium.Chromium.@{rand6}/ r, + owner @{tmp}/.org.chromium.Chromium.@{rand6}/*.@{icon_ext} r, owner @{tmp}/@{rand6}.shell-extension.zip rw, owner @{tmp}/gdkpixbuf-xpm-tmp.@{rand6} rw, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, @{run}/systemd/users/@{uid} r, @{run}/systemd/seats/seat@{int} r, @{run}/systemd/sessions/ r, @{run}/systemd/sessions/* r, + @{run}/polkit/agent-helper.socket rw, + @{run}/udev/tags/seat/ r, - @{run}/udev/data/+input:input@{int} r, # for mouse, keyboard, touchpad - @{run}/udev/data/+platform:* r, + @{run}/udev/data/+acpi:* r, # Exposes ACPI objects (power buttons, batteries, thermal) + @{run}/udev/data/+backlight:* r, # For display backlights on laptops, monitors, and other screens. @{run}/udev/data/+dmi:id r, # for motherboard info - @{run}/udev/data/+acpi* r, + @{run}/udev/data/+drm:card@{int}-* r, # For screen outputs + @{run}/udev/data/+hid:* r, # For Human Interface Device (mice, controllers, drawing tablets, scanners) + @{run}/udev/data/+i2c:* r, # For Inter-Integrated Circuit, low-speed peripherals (sensors, EEPROMs, etc.) + @{run}/udev/data/+input:input@{int} r, # for mouse, keyboard, touchpad @{run}/udev/data/+pci:* r, # Identifies all PCI devices (CPU, GPU, Network, Disks, USB, etc.) + @{run}/udev/data/+platform:* r, # Identifies onboard devices (laptop/board model, power controllers, thermal sensors) @{run}/udev/data/+sound:card@{int} r, # for sound card - @{run}/udev/data/+usb* r, # for USB mouse and keyboard - @{run}/udev/data/+i2c:* r, - @{run}/udev/data/+hid:* r, # for HID-Compliant Keyboard @{run}/udev/data/c10:@{int} r, # for non-serial mice, misc features @{run}/udev/data/c13:@{int} r, # for /dev/input/* @{run}/udev/data/c189:@{int} r, # for /dev/bus/usb/** - @{run}/udev/data/c226:@{int} r, # for /dev/dri/card* - @{run}/udev/data/n@{int} r, + @{run}/udev/data/n@{int} r, # For network interfaces @{sys}/**/uevent r, @{sys}/bus/ r, - @{sys}/class/hwmon/ r, + @{sys}/class/backlight/ r, @{sys}/class/input/ r, @{sys}/class/net/ r, @{sys}/class/power_supply/ r, @{sys}/devices/@{pci}/boot_vga r, + @{sys}/devices/@{pci}/drm/card@{int}/**/{,max_,actual_}brightness r, + @{sys}/devices/@{pci}/drm/card@{int}/**/{uevent,type,enabled} r, + @{sys}/devices/@{pci}/drm/card@{int}/**/brightness r, + @{sys}/devices/@{pci}/gpu_busy_percent r, @{sys}/devices/@{pci}/input@{int}/{properties,name} r, + @{sys}/devices/@{pci}/mem_info_vram_* r, @{sys}/devices/@{pci}/net/*/statistics/collisions r, @{sys}/devices/@{pci}/net/*/statistics/rx_{bytes,errors,packets} r, @{sys}/devices/@{pci}/net/*/statistics/tx_{bytes,errors,packets} r, + @{sys}/devices/@{pci}/usb@{int}/**/leds/ r, @{sys}/devices/@{pci}/usb@{int}/**/net/*/statistics/collisions r, @{sys}/devices/@{pci}/usb@{int}/**/net/*/statistics/rx_{bytes,errors,packets} r, @{sys}/devices/@{pci}/usb@{int}/**/net/*/statistics/tx_{bytes,errors,packets} r, - @{sys}/devices/**/hwmon@{int}/{,name,temp*,fan*} r, - @{sys}/devices/**/hwmon@{int}/**/{,name,temp*,fan*} r, - @{sys}/devices/**/hwmon/{,name,temp*,fan*} r, - @{sys}/devices/**/hwmon/**/{,name,temp*,fan*} r, @{sys}/devices/**/power_supply/{,**} r, @{sys}/devices/platform/**/input@{int}/{properties,name} r, - @{sys}/devices/virtual/dmi/id/bios_vendor r, @{sys}/devices/virtual/net/*/statistics/collisions r, @{sys}/devices/virtual/net/*/statistics/rx_{bytes,errors,packets} r, @{sys}/devices/virtual/net/*/statistics/tx_{bytes,errors,packets} r, - @{sys}/fs/cgroup/user.slice/cpu.max r, - @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/cpu.max r, - @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/cpu.max r, - @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/session.slice/cpu.max r, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/session.slice/cpu.max r, @{PROC}/ r, @{PROC}/@{pid}/attr/current r, @@ -360,12 +431,12 @@ profile gnome-shell @{exec_path} flags=(attach_disconnected,mediate_deleted) { owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/mounts r, owner @{PROC}/@{pid}/stat r, + owner @{PROC}/@{pid}/statm r, owner @{PROC}/@{pid}/task/@{pid}/cmdline r, owner @{PROC}/@{pid}/task/@{tid}/comm rw, owner @{PROC}/@{pid}/task/@{tid}/stat r, - /dev/media@{int} rw, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, @{att}/dev/dri/card@{int} rw, @{att}/dev/input/event@{int} rw, @@ -374,12 +445,14 @@ profile gnome-shell @{exec_path} flags=(attach_disconnected,mediate_deleted) { capability sys_ptrace, - ptrace (read), + ptrace read, @{sh_path} mr, - @{bin}/pmap rix, - @{bin}/grep rix, + @{bin}/cat rix, + @{bin}/{,e}grep rix, + @{bin}/kmod rPx -> gnome-shell//lsmod, + @{bin}/pmap rix, @{sys}/devices/system/node/ r, @@ -392,32 +465,50 @@ profile gnome-shell @{exec_path} flags=(attach_disconnected,mediate_deleted) { include if exists } + profile lsmod flags=(attach_disconnected,mediate_deleted) { + include + include + + @{sys}/module/{,**} r, + + include if exists + } + profile pkexec { include include ptrace read peer=gnome-shell, - @{bin}/pkexec mr, - /usr/local/bin/batteryhealthchargingctl{,-@{user}} rPx, @{bin}/batteryhealthchargingctl{,-@{user}} rPx, include if exists } - profile open flags=(attach_disconnected,mediate_deleted,complain) { + profile python { + include + include + + # /usr/share/gnome-shell/extensions/{,**} + + include if exists + } + + profile open flags=(attach_disconnected,mediate_deleted) { include include network inet stream, network unix stream, + @{bin}/env mr, @{lib}/@{multiarch}/glib-@{version}/gio-launch-desktop mr, @{lib}/gio-launch-desktop mr, @{lib}/** PUx, @{bin}/** PUx, + @{sbin}/** PUx, /opt/*/** PUx, /usr/share/*/** PUx, /usr/local/bin/** PUx, @@ -427,6 +518,12 @@ profile gnome-shell @{exec_path} flags=(attach_disconnected,mediate_deleted) { owner @{run}/user/@{uid}/gnome-shell-disable-extensions w, + @{PROC}/@{pids}/ r, + @{PROC}/@{pids}/cmdline r, + @{PROC}/@{pids}/maps r, + @{PROC}/@{pids}/stat r, + @{PROC}/@{pids}/status r, + deny @{user_share_dirs}/gvfs-metadata/* r, include if exists diff --git a/apparmor.d/groups/gnome/gnome-shell-calendar-server b/apparmor.d/groups/gnome/gnome-shell-calendar-server index 2f3e51670e..d88e5af322 100644 --- a/apparmor.d/groups/gnome/gnome-shell-calendar-server +++ b/apparmor.d/groups/gnome/gnome-shell-calendar-server @@ -7,36 +7,27 @@ abi , include @{exec_path} = @{lib}/{,gnome-shell/}gnome-shell-calendar-server -profile gnome-shell-calendar-server @{exec_path} { +profile gnome-shell-calendar-server @{exec_path} flags=(attach_disconnected) { include include + include include + include include #aa:dbus own bus=session name=org.gnome.Shell.CalendarServer - dbus (send receive) bus=session path=/org/gnome/evolution/dataserver/{,**} - interface=org.freedesktop.DBus.Properties - peer=(name=:*, label=evolution-*), - - dbus (send receive) bus=session path=/org/gnome/evolution/dataserver/{,**} - interface=org.gnome.evolution.dataserver.Calendar* - peer=(name=:*, label=evolution-*), - - dbus send bus=session path=/org/gnome/evolution/dataserver/SourceManager - interface=org.freedesktop.DBus.ObjectManager - member=GetManagedObjects - peer=(name=:*, label=evolution-source-registry), + #aa:dbus talk bus=session name=org.gnome.evolution.dataserver.{Source,Sources@{int}} path=/org/gnome/evolution/dataserver/SourceManager{,/**} label=evolution-source-registry + #aa:dbus talk bus=session name=org.gnome.evolution.dataserver.Calendar{,View,Factory} label=evolution-calendar-factory + #aa:dbus talk bus=session name=org.gnome.evolution.dataserver.Calendar{,View,Factory} path=/org/gnome/evolution/dataserver/Subprocess{,**} label=evolution-calendar-factory dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, - /usr/share/glib-2.0/schemas/gschemas.compiled r, - /etc/sysconfig/clock r, /etc/timezone r, diff --git a/apparmor.d/groups/gnome/gnome-shell-hotplug-sniffer b/apparmor.d/groups/gnome/gnome-shell-hotplug-sniffer index 51d5b43cf1..56e448fd8f 100644 --- a/apparmor.d/groups/gnome/gnome-shell-hotplug-sniffer +++ b/apparmor.d/groups/gnome/gnome-shell-hotplug-sniffer @@ -10,11 +10,10 @@ include profile gnome-shell-hotplug-sniffer @{exec_path} { include include + include @{exec_path} mr, - /usr/share/mime/mime.cache r, - @{MOUNTS}/**/ r, @{MOUNTS}/** r, diff --git a/apparmor.d/groups/gnome/gnome-software b/apparmor.d/groups/gnome/gnome-software index dd872c53a8..bec183985e 100644 --- a/apparmor.d/groups/gnome/gnome-software +++ b/apparmor.d/groups/gnome/gnome-software @@ -7,15 +7,20 @@ abi , include @{exec_path} = @{bin}/gnome-software -profile gnome-software @{exec_path} { +profile gnome-software @{exec_path} flags=(attach_disconnected,mediate_deleted) { include - include + include + include + include + include + include + include include - include - include include + include include include + include network inet dgram, network inet6 dgram, @@ -26,11 +31,28 @@ profile gnome-software @{exec_path} { mount fstype=fuse.revokefs-fuse options=(rw, nosuid, nodev) -> /var/tmp/flatpak-cache-*/*/, umount /var/tmp/flatpak-cache-*/*/, + signal send set=kill peer=fbwrap, + + #aa:dbus own bus=session name=org.freedesktop.PackageKit + #aa:dbus own bus=session name=org.gnome.Software + + #aa:dbus talk bus=system name=org.freedesktop.Flatpak.SystemHelper label=flatpak-system-helper + #aa:dbus talk bus=system name=org.freedesktop.fwupd path=/ label=fwupd + #aa:dbus talk bus=system name=org.freedesktop.PackageKit path=/{,**} label="@{p_packagekitd}" + #aa:dbus talk bus=system name=org.freedesktop.sysupdate1 label=systemd-sysupdate + + dbus receive bus=system path=/org/freedesktop/PolicyKit1/Authority + interface=org.freedesktop.PolicyKit1.Authority + member=Changed + peer=(name=@{busname}, label=polkitd), + @{exec_path} mr, @{bin}/baobab rPUx, - @{bin}/bwrap rPx -> flatpak-app, + @{bin}/bwrap rPx -> flatpak-app, #aa:only apparmor<4.1 + @{bin}/bwrap rPx -> fbwrap, #aa:only apparmor>=4.1 @{bin}/fusermount{,3} rCx -> fusermount, + @{bin}/gnome-control-center rPx, @{bin}/gpg{,2} rCx -> gpg, @{bin}/gpgconf rCx -> gpg, @{bin}/gpgsm rCx -> gpg, @@ -39,7 +61,8 @@ profile gnome-software @{exec_path} { /usr/share/app-info/{,**} r, /usr/share/appdata/{,**} r, - /usr/share/flatpak/remotes.d/ r, + /usr/share/byobu/desktop/{,**} r, + /usr/share/flatpak/remotes.d/{,**} r, /usr/share/metainfo/{,**} r, /usr/share/swcatalog/{,**} r, /usr/share/xml/iso-codes/{,**} r, @@ -67,19 +90,16 @@ profile gnome-software @{exec_path} { /var/lib/PackageKit/prepared-update r, /var/lib/swcatalog/** r, - /var/tmp/flatpak-cache-*/ rw, - /var/tmp/flatpak-cache-*/** rwkl, /var/tmp/#@{int} rw, + /var/tmp/flatpak-cache-@{rand6}/ rw, + /var/tmp/flatpak-cache-@{rand6}/** rwkl, - / r, - + owner @{HOME}/.var/ rw, owner @{HOME}/.var/app/{,**} rw, owner @{user_download_dirs}/*.flatpakref r, owner @{user_cache_dirs}/flatpak/{,**} rwl, - owner @{user_cache_dirs}/gnome-software/ rw, - owner @{user_cache_dirs}/gnome-software/** rwlk -> @{user_cache_dirs}/gnome-software/**, owner @{user_config_dirs}/flatpak/{,**} r, owner @{user_config_dirs}/pulse/*.conf r, @@ -91,14 +111,14 @@ profile gnome-software @{exec_path} { owner @{user_share_dirs}/flatpak/{app,runtime}/*/**/@{hex64}/deploy r, owner @{user_share_dirs}/flatpak/{app,runtime}/*/**/@{hex64}/metadata r, owner @{user_share_dirs}/flatpak/{app,runtime}/*/*/ r, + owner @{user_share_dirs}/flatpak/overrides/ rw, owner @{user_share_dirs}/flatpak/overrides/* r, owner @{user_share_dirs}/flatpak/repo/ rw, - owner @{user_share_dirs}/flatpak/repo/** rwl -> @{user_share_dirs}/flatpak/repo/**, - owner @{user_share_dirs}/gnome-software/{,**} rw, + owner @{user_share_dirs}/flatpak/repo/** rwl, + owner @{tmp}/#@{int} rw, owner @{tmp}/ostree-gpg-@{rand6}/ rw, owner @{tmp}/ostree-gpg-@{rand6}/** rwkl -> /tmp/ostree-gpg-@{rand6}/**, - owner @{tmp}/#@{int} rw, owner @{run}/user/@{uid}/.dbus-proxy/ rw, owner @{run}/user/@{uid}/.dbus-proxy/a11y-bus-proxy-@{rand6} rw, @@ -108,11 +128,12 @@ profile gnome-software @{exec_path} { owner @{run}/user/@{uid}/.flatpak/{,**} rwl, owner @{run}/user/@{uid}/.flatpak/**/*.ref rwk, owner @{run}/user/@{uid}/app/{,*/} rw, + owner @{run}/user/@{uid}/systemd/private rw, owner /dev/shm/flatpak-com.*/ rw, - owner /dev/shm/flatpak-com.*/.flatpak-tmpdir rw, + owner /dev/shm/flatpak-com.*/* rw, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, @{run}/systemd/sessions/@{int} r, @{run}/systemd/users/@{uid} r, @@ -123,15 +144,10 @@ profile gnome-software @{exec_path} { @{PROC}/sys/fs/pipe-max-size r, @{PROC}/sys/net/ipv6/conf/all/disable_ipv6 r, owner @{PROC}/@{pid}/cgroup r, - owner @{PROC}/@{pid}/cmdline r, owner @{PROC}/@{pid}/fdinfo/@{int} r, - owner @{PROC}/@{pid}/stat r, - owner @{PROC}/@{pid}/task/@{tid}/comm rw, /dev/fuse rw, - deny owner @{user_share_dirs}/gvfs-metadata/* r, - profile gpg { include @@ -166,8 +182,13 @@ profile gnome-software @{exec_path} { include include + capability setuid, + + unix (send receive) type=stream peer=(label=gnome-software), + unix (send receive) type=seqpacket peer=(label=flatpak-system-helper), + mount fstype=fuse.revokefs-fuse options=(rw, nosuid, nodev) -> /var/tmp/flatpak-cache-*/*/, - umount /var/tmp/flatpak-cache-*/*/, + umount /var/tmp/flatpak-cache-@{rand6}/*/, include if exists } diff --git a/apparmor.d/groups/gnome/gnome-system-monitor b/apparmor.d/groups/gnome/gnome-system-monitor index 8df82b290b..a68acb86d5 100644 --- a/apparmor.d/groups/gnome/gnome-system-monitor +++ b/apparmor.d/groups/gnome/gnome-system-monitor @@ -9,10 +9,9 @@ include @{exec_path} = @{bin}/gnome-system-monitor profile gnome-system-monitor @{exec_path} flags=(attach_disconnected) { include - include - include - include - include + include + include + include include capability sys_ptrace, @@ -21,9 +20,9 @@ profile gnome-system-monitor @{exec_path} flags=(attach_disconnected) { network inet6 dgram, network netlink raw, - ptrace (read), + ptrace read, - signal (send) set=(kill term cont stop), + signal send set=(kill term cont stop), #aa:dbus own bus=session name=org.gnome.SystemMonitor @@ -32,21 +31,25 @@ profile gnome-system-monitor @{exec_path} flags=(attach_disconnected) { @{sh_path} rix, @{bin}/lsblk rPx, @{bin}/pkexec rCx -> pkexec, + @{bin}/lscpu rPx, @{bin}/sed rix, @{bin}/tr rix, - /usr/share/gnome-system-monitor/{,**} r, + /usr/share/byobu/desktop/{,**} r, /usr/share/firefox{,-esr}/browser/chrome/icons/{,**} r, + /etc/fstab r, + / r, + owner @{user_share_dirs}/gvfs-metadata/{,*} r, + owner @{tmp}/gdkpixbuf-xpm-tmp.@{rand6} rw, owner @{run}/user/@{uid}/doc/ rw, owner @{run}/user/@{uid}/gnome-shell-disable-extensions w, - @{run}/systemd/sessions/* r, - @{run}/systemd/sessions/*.ref r, + @{run}/systemd/sessions/* r, @{run}/mount/utab r, @{sys}/devices/@{pci}/net/*/statistics/collisions r, @@ -74,14 +77,11 @@ profile gnome-system-monitor @{exec_path} flags=(attach_disconnected) { @{PROC}/@{pids}/smaps r, @{PROC}/@{pids}/stat r, @{PROC}/@{pids}/statm r, + @{PROC}/@{pids}/status r, @{PROC}/@{pids}/wchan r, @{PROC}/diskstats r, @{PROC}/vmstat r, - owner @{PROC}/@{pid}/task/@{tid}/comm rw, - - deny owner @{user_share_dirs}/gvfs-metadata/{,*} r, - /dev/tty rw, profile pkexec { diff --git a/apparmor.d/groups/gnome/gnome-terminal-server b/apparmor.d/groups/gnome/gnome-terminal-server index 55a7f46879..119e3fb808 100644 --- a/apparmor.d/groups/gnome/gnome-terminal-server +++ b/apparmor.d/groups/gnome/gnome-terminal-server @@ -10,26 +10,22 @@ include profile gnome-terminal-server @{exec_path} { include include - include - include - include - include - include include include include + include - signal (send) set=(hup) peer=htop, - signal (send) set=(term hup kill) peer=unconfined, + signal send set=(hup) peer=htop, + signal send set=(term hup kill) peer=unconfined, - ptrace (read) peer=htop, - ptrace (read) peer=unconfined, + ptrace read peer=htop, + ptrace read peer=unconfined, - #aa:dbus own bus=session name=org.gnome.Terminal interface+=org.gtk.Actions + #aa:dbus own bus=session name=org.gnome.Terminal dbus receive bus=session path=/org/gnome/Terminal/SearchProvider interface=org.gnome.Shell.SearchProvider2 - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label=gnome-shell), dbus send bus=session path=/org/freedesktop/systemd1 interface=org.freedesktop.systemd1.Manager @@ -38,15 +34,19 @@ profile gnome-terminal-server @{exec_path} { @{exec_path} mr, + @{bin}/byobu PUx, + @{bin}/env ix, + @{lib}/gnome-terminal-preferences ix, + # The shell is not confined on purpose. - @{bin}/@{shells} rUx, + @{bin}/@{shells} Ux, # Some CLI program can be launched directly from Gnome Shell - @{bin}/htop rPx, - @{bin}/micro rPUx, - @{bin}/nvtop rPx, + @{bin}/htop Px, + @{bin}/micro PUx, + @{bin}/nvtop Px, - @{open_path} rPx -> child-open, + @{open_path} Px -> child-open-any, /etc/shells r, diff --git a/apparmor.d/groups/gnome/gnome-text-editor b/apparmor.d/groups/gnome/gnome-text-editor index 693b1618f2..2b1aa8657e 100644 --- a/apparmor.d/groups/gnome/gnome-text-editor +++ b/apparmor.d/groups/gnome/gnome-text-editor @@ -7,24 +7,29 @@ abi , include @{exec_path} = @{bin}/gnome-text-editor -profile gnome-text-editor @{exec_path} { +profile gnome-text-editor @{exec_path} flags=(attach_disconnected) { include - include + include include include + include include include + #aa:dbus own bus=session name=org.gnome.TextEditor #aa:dbus talk bus=session name=org.gtk.vfs label="gvfsd{,-*}" @{exec_path} mr, @{open_path} rPx -> child-open-help, + owner @{HOME}/.goutputstream-@{rand6} rw, + owner @{user_share_dirs}/org.gnome.TextEditor/{,**} rw, + owner @{run}/user/@{uid}/gvfsd/socket-@{rand8} rw, + owner @{PROC}/@{pid}/mountinfo r, - owner @{PROC}/@{pid}/stat r, deny @{user_share_dirs}/gvfs-metadata/* r, diff --git a/apparmor.d/groups/gnome/gnome-tour b/apparmor.d/groups/gnome/gnome-tour index 8ae95f4a08..30fed1139e 100644 --- a/apparmor.d/groups/gnome/gnome-tour +++ b/apparmor.d/groups/gnome/gnome-tour @@ -7,7 +7,7 @@ abi , include @{exec_path} = @{bin}/gnome-tour -profile gnome-tour @{exec_path} { +profile gnome-tour @{exec_path} flags=(attach_disconnected) { include include include diff --git a/apparmor.d/groups/gnome/gnome-tweaks b/apparmor.d/groups/gnome/gnome-tweaks index fa94d56e82..4fbb4d5fa1 100644 --- a/apparmor.d/groups/gnome/gnome-tweaks +++ b/apparmor.d/groups/gnome/gnome-tweaks @@ -27,16 +27,17 @@ profile gnome-tweaks @{exec_path} flags=(attach_disconnected) { @{lib}/@{python_name}/site-packages/gtweak/{,*/,**/}__pycache__/*pyc* w, + @{system_share_dirs}/glib-2.0/schemas/org.gnome.*.gschema.xml r, + /etc/xdg/autostart/{,**} r, owner @{HOME}/@{XDG_WALLPAPERS_DIR}/{,**} r, owner @{user_config_dirs}/autostart/ rw, - owner @{user_config_dirs}/autostart/*.desktop r, + owner @{user_config_dirs}/autostart/*.desktop rw, owner @{user_config_dirs}/gtk-{3,4}.0/settings.ini* rw, owner @{user_share_dirs}/backgrounds/{,**} r, owner @{user_share_dirs}/gnome-shell/extensions/**/schemas/* r, - owner @{user_share_dirs}/recently-used.xbel* rw, @{run}/udev/data/+input:input@{int} r, # for mouse, keyboard, touchpad @{run}/udev/data/c13:@{int} r, # for /dev/input/* diff --git a/apparmor.d/groups/gnome/gnome-weather b/apparmor.d/groups/gnome/gnome-weather index c73ff0a192..698c8fe8b2 100644 --- a/apparmor.d/groups/gnome/gnome-weather +++ b/apparmor.d/groups/gnome/gnome-weather @@ -7,10 +7,12 @@ abi , include @{exec_path} = @{bin}/gnome-weather /usr/share/org.gnome.Weather/org.gnome.Weather -profile gnome-weather @{exec_path} { +profile gnome-weather @{exec_path} flags=(attach_disconnected) { include include + include include + include include include @@ -31,7 +33,6 @@ profile gnome-weather @{exec_path} { @{PROC}/sys/net/ipv6/conf/all/disable_ipv6 r, owner @{PROC}/@{pid}/mounts r, - owner @{PROC}/@{pid}/stat r, owner @{PROC}/@{pid}/task/@{tid}/stat r, deny owner @{user_share_dirs}/gvfs-metadata/* r, diff --git a/apparmor.d/groups/gnome/goa-daemon b/apparmor.d/groups/gnome/goa-daemon index 8176d6c7c7..59e051e221 100644 --- a/apparmor.d/groups/gnome/goa-daemon +++ b/apparmor.d/groups/gnome/goa-daemon @@ -7,16 +7,14 @@ abi , include @{exec_path} = @{lib}/goa-daemon -profile goa-daemon @{exec_path} { +profile goa-daemon @{exec_path} flags=(attach_disconnected) { include - include - include - include - include include include include + include include + include include network inet stream, @@ -30,11 +28,11 @@ profile goa-daemon @{exec_path} { dbus send bus=session path=/org/gnome/Identity interface=org.freedesktop.DBus.ObjectManager member=GetManagedObjects - peer=(name=:*, label=goa-identity-service), + peer=(name=@{busname}, label=goa-identity-service), dbus send bus=session path=/org/gnome/Identity/Manager interface=org.freedesktop.DBus.Properties member=GetAll - peer=(name=:*, label=goa-identity-service), + peer=(name=@{busname}, label=goa-identity-service), @{exec_path} mr, diff --git a/apparmor.d/groups/gnome/goa-identity-service b/apparmor.d/groups/gnome/goa-identity-service index 3992811c24..cd2031ce8d 100644 --- a/apparmor.d/groups/gnome/goa-identity-service +++ b/apparmor.d/groups/gnome/goa-identity-service @@ -11,19 +11,16 @@ profile goa-identity-service @{exec_path} { include include include - include + include #aa:dbus own bus=session name=org.gnome.Identity - dbus send bus=session path=/org/gnome/OnlineAccounts - interface=org.freedesktop.DBus.ObjectManager - member=GetManagedObjects - peer=(name=:*, label=goa-daemon), + #aa:dbus talk bus=session name=org.gnome.OnlineAccounts label=goa-daemon dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, diff --git a/apparmor.d/groups/gnome/gsd-a11y-settings b/apparmor.d/groups/gnome/gsd-a11y-settings index 5f05c21da3..03e15fa421 100644 --- a/apparmor.d/groups/gnome/gsd-a11y-settings +++ b/apparmor.d/groups/gnome/gsd-a11y-settings @@ -9,26 +9,33 @@ include @{exec_path} = @{lib}/gsd-a11y-settings profile gsd-a11y-settings @{exec_path} flags=(attach_disconnected) { include - include include - include + include + include include + include + include signal (receive) set=(term, hup) peer=gdm*, #aa:dbus own bus=session name=org.gnome.SettingsDaemon.A11ySettings + dbus send bus=session path=/org/freedesktop/systemd1 + interface=org.freedesktop.systemd1.Manager + member=DisableUnitFilesWithFlags + peer=(name=org.freedesktop.systemd1, label="@{p_systemd_user}"), + dbus send bus=session path=/org/freedesktop/systemd1 + interface=org.freedesktop.systemd1.Manager + member=StopUnit + peer=(name=org.freedesktop.systemd1, label="@{p_systemd_user}"), + dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, - /usr/share/dconf/profile/gdm r, - /usr/share/gdm/greeter-dconf-defaults r, - /usr/share/glib-2.0/schemas/gschemas.compiled r, - @{gdm_config_dirs}/dconf/user r, @{GDM_HOME}/greeter-dconf-defaults r, diff --git a/apparmor.d/groups/gnome/gsd-color b/apparmor.d/groups/gnome/gsd-color index 92cf3fa0a2..8fe470d7e8 100644 --- a/apparmor.d/groups/gnome/gsd-color +++ b/apparmor.d/groups/gnome/gsd-color @@ -9,18 +9,14 @@ include @{exec_path} = @{lib}/gsd-color profile gsd-color @{exec_path} flags=(attach_disconnected) { include + include include - include - include - include - include - include - include - include include include include + include include + include network inet stream, @@ -28,27 +24,17 @@ profile gsd-color @{exec_path} flags=(attach_disconnected) { #aa:dbus own bus=session name=org.gnome.SettingsDaemon.Color - #aa:dbus talk bus=system name=org.freedesktop.ColorManager label=colord - - dbus receive bus=session path=/org/gtk/Settings - interface=org.freedesktop.DBus.Properties - member=PropertiesChanged - peer=(name=:*, label=gsd-xsettings), + #aa:dbus talk bus=system name=org.freedesktop.ColorManager label="@{p_colord}" @{exec_path} mr, - /usr/share/dconf/profile/gdm r, - /usr/share/gdm/greeter-dconf-defaults r, - /etc/timezone r, - owner @{GDM_HOME}/greeter-dconf-defaults r, - owner @{gdm_config_dirs}/dconf/user r, owner @{gdm_share_dirs}/icc/ rw, - owner @{gdm_share_dirs}/icc/edid-*.icc rw, + owner @{gdm_share_dirs}/icc/edid-@{hex32}.icc rw, owner @{user_share_dirs}/icc/ rw, - owner @{user_share_dirs}/icc/edid-*.icc rw, + owner @{user_share_dirs}/icc/edid-@{hex32}.icc rw, include if exists } diff --git a/apparmor.d/groups/gnome/gsd-datetime b/apparmor.d/groups/gnome/gsd-datetime index 0190ad9b37..8b86f4eaf8 100644 --- a/apparmor.d/groups/gnome/gsd-datetime +++ b/apparmor.d/groups/gnome/gsd-datetime @@ -9,11 +9,15 @@ include @{exec_path} = @{lib}/gsd-datetime profile gsd-datetime @{exec_path} flags=(attach_disconnected) { include - include include - include + include + include + include + include include + include include + include network inet dgram, network inet6 dgram, @@ -28,18 +32,12 @@ profile gsd-datetime @{exec_path} flags=(attach_disconnected) { dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, - /usr/share/dconf/profile/gdm r, - /usr/share/gdm/greeter-dconf-defaults r, - /usr/share/glib-2.0/schemas/gschemas.compiled r, /usr/share/gnome-settings-daemon/datetime/backward r, - owner @{GDM_HOME}/greeter-dconf-defaults r, - owner @{gdm_config_dirs}/dconf/user r, - owner @{user_cache_dirs}/geocode-glib/* r, @{run}/systemd/sessions/@{int} r, diff --git a/apparmor.d/groups/gnome/gsd-disk-utility-notify b/apparmor.d/groups/gnome/gsd-disk-utility-notify index 6e8ae0d90b..cebd18f02e 100644 --- a/apparmor.d/groups/gnome/gsd-disk-utility-notify +++ b/apparmor.d/groups/gnome/gsd-disk-utility-notify @@ -7,18 +7,19 @@ abi , include @{exec_path} = @{lib}/gsd-disk-utility-notify -profile gsd-disk-utility-notify @{exec_path} { +profile gsd-disk-utility-notify @{exec_path} flags=(attach_disconnected) { include include include - include + include #aa:dbus own bus=session name=org.gnome.Disks.NotificationMonitor + #aa:dbus talk bus=system name=org.freedesktop.UDisks2 label=udisksd dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, diff --git a/apparmor.d/groups/gnome/gsd-housekeeping b/apparmor.d/groups/gnome/gsd-housekeeping index 55b0c3a514..92652e760a 100644 --- a/apparmor.d/groups/gnome/gsd-housekeeping +++ b/apparmor.d/groups/gnome/gsd-housekeeping @@ -10,12 +10,11 @@ include profile gsd-housekeeping @{exec_path} flags=(attach_disconnected) { include include + include include - include - include - include include include + include include signal (receive) set=(term, hup) peer=gdm*, @@ -23,20 +22,15 @@ profile gsd-housekeeping @{exec_path} flags=(attach_disconnected) { #aa:dbus own bus=session name=org.gnome.SettingsDaemon.Housekeeping - dbus receive bus=session - interface=org.freedesktop.DBus.Introspectable - member=Introspect - peer=(name=:*, label=gnome-shell), + dbus send bus=session path=/org/freedesktop/systemd1 + interface=org.freedesktop.systemd1.Manager + member=Subscribe + peer=(name=org.freedesktop.systemd1), @{exec_path} mr, /etc/fstab r, - /usr/share/dconf/profile/gdm r, - /usr/share/gdm/greeter-dconf-defaults r, - - owner @{GDM_HOME}/greeter-dconf-defaults r, - owner @{gdm_config_dirs}/dconf/user r, owner @{gdm_share_dirs}/applications/ w, owner @{user_share_dirs}/applications/ rw, diff --git a/apparmor.d/groups/gnome/gsd-keyboard b/apparmor.d/groups/gnome/gsd-keyboard index cbb8ccf714..f5cd16fc33 100644 --- a/apparmor.d/groups/gnome/gsd-keyboard +++ b/apparmor.d/groups/gnome/gsd-keyboard @@ -9,18 +9,13 @@ include @{exec_path} = @{lib}/gsd-keyboard profile gsd-keyboard @{exec_path} flags=(attach_disconnected) { include + include include - include - include - include - include - include - include - include include include include include + include network inet stream, @@ -30,12 +25,7 @@ profile gsd-keyboard @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, - /usr/share/dconf/profile/gdm r, - /usr/share/gdm/greeter-dconf-defaults r, - - owner @{GDM_HOME}/greeter-dconf-defaults r, owner @{gdm_config_dirs}/.gsd-keyboard.settings-ported* rw, - owner @{gdm_config_dirs}/dconf/user r, owner @{user_config_dirs}/.gsd-keyboard.settings-ported* rw, owner @{user_share_dirs}/gnome-settings-daemon/{,input-sources*} rw, diff --git a/apparmor.d/groups/gnome/gsd-media-keys b/apparmor.d/groups/gnome/gsd-media-keys index 1ae8e2ada9..3bdafb5bce 100644 --- a/apparmor.d/groups/gnome/gsd-media-keys +++ b/apparmor.d/groups/gnome/gsd-media-keys @@ -9,22 +9,18 @@ include @{exec_path} = @{lib}/gsd-media-keys profile gsd-media-keys @{exec_path} flags=(attach_disconnected) { include - include include - include - include - include - include - include - include - include - include - include - include + include + include + include + include + include include include include include + include + include signal (receive) set=(term, hup) peer=gdm*, @@ -32,57 +28,43 @@ profile gsd-media-keys @{exec_path} flags=(attach_disconnected) { network netlink raw, #aa:dbus own bus=session name=org.gnome.SettingsDaemon.MediaKeys + #aa:dbus talk bus=session name=org.gnome.SettingsDaemon.Power label=gsd-power #aa:dbus talk bus=session name=org.gnome.SettingsDaemon.Rfkill label=gsd-rfkill #aa:dbus talk bus=session name=org.gnome.Shell label=gnome-shell + dbus send bus=session path=/org/mpris/MediaPlayer2 + interface=org.freedesktop.DBus.Properties + member=GetAll + peer=(name=@{busname}), + + dbus receive bus=session path=/org/mpris/MediaPlayer2 + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name=@{busname}), + dbus send bus=system path=/org/freedesktop/login1 interface=org.freedesktop.login1.Manager member=PowerOff - peer=(name=:*, label=systemd-logind), + peer=(name=@{busname}, label="@{p_systemd_logind}"), dbus send bus=session path=/ interface=org.freedesktop.DBus member=ListNames peer=(name=org.freedesktop.DBus, label="@{p_dbus_session}"), - dbus send bus=session path=/org/gnome/SettingsDaemon/Power - interface=org.freedesktop.DBus.Properties - member=GetAll - peer=(name=:*, label=gsd-power), - - dbus receive bus=session path=/org/gnome/SettingsDaemon/Power - interface=org.freedesktop.DBus.Properties - member=PropertiesChanged - peer=(name=:*, label=gsd-power), - - dbus send bus=session path=/org/mpris/MediaPlayer2 - interface=org.freedesktop.DBus.Properties - member=GetAll - peer=(name=:*), - @{exec_path} mr, @{open_path} rPx -> child-open, - /usr/share/dconf/profile/gdm r, - /usr/share/gdm/greeter-dconf-defaults r, /usr/share/sounds/freedesktop/stereo/*.oga r, - owner @{GDM_HOME}/greeter-dconf-defaults r, - owner @{gdm_config_dirs}/dconf/user r, - - owner @{user_share_dirs}/recently-used.xbel{,.*} rw, - - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, @{run}/udev/data/+sound:card@{int} r, # For sound card @{run}/udev/data/c13:@{int} r, # for /dev/input/* @{run}/udev/data/c189:@{int} r, # For /dev/bus/usb/** - @{sys}/devices/**/usb@{int}/{,**} r, - @{sys}/devices/@{pci}/sound/**/uevent r, - @{sys}/devices/platform/**/uevent r, - @{sys}/devices/virtual/**/uevent r, + @{sys}/devices/**/uevent r, @{PROC}/1/cgroup r, owner @{PROC}/@{pid}/cgroup r, diff --git a/apparmor.d/groups/gnome/gsd-power b/apparmor.d/groups/gnome/gsd-power index 9bba247510..0f3964e624 100644 --- a/apparmor.d/groups/gnome/gsd-power +++ b/apparmor.d/groups/gnome/gsd-power @@ -9,76 +9,52 @@ include @{exec_path} = @{lib}/gsd-power profile gsd-power @{exec_path} flags=(attach_disconnected) { include - include include - include - include - include - include - include - include - include - include - include - include - include - include - include - include + include + include + include + include + include + include include include include include + include + include + include + include network inet stream, network netlink raw, - signal (receive) set=(term, hup) peer=gdm*, + signal receive set=(term, hup) peer=gdm*, #aa:dbus own bus=session name=org.gnome.SettingsDaemon.Power #aa:dbus talk bus=session name=org.gnome.Mutter.DisplayConfig label=gnome-shell + #aa:dbus talk bus=session name=org.gnome.Shell.Brightness label=gnome-shell + #aa:dbus talk bus=system name=org.freedesktop.UPower.PowerProfiles label=power-profiles-daemon dbus send bus=system path=/org/freedesktop/UPower/KbdBacklight interface=org.freedesktop.UPower.KbdBacklight member=GetBrightness - peer=(name=:*, label=upowerd), + peer=(name=@{busname}, label="@{p_upowerd}"), - dbus receive bus=session path=/org/gtk/Settings - interface=org.freedesktop.DBus.Properties - member=PropertiesChanged - peer=(name=:*, label=gsd-xsettings), + dbus send bus=system path=/org/freedesktop/login1 + interface=org.freedesktop.login1.Manager + member=Suspend + peer=(name=@{busname}, label="@{p_systemd_logind}"), @{exec_path} mr, - /usr/share/dconf/profile/gdm r, - /usr/share/gdm/greeter-dconf-defaults r, - - owner @{GDM_HOME}/greeter-dconf-defaults r, - owner @{gdm_config_dirs}/dconf/user r, - - @{run}/udev/data/+backlight:* r, @{run}/udev/data/+drm:card@{int}-* r, # For screen outputs - @{run}/udev/data/+leds:* r, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, @{sys}/bus/ r, - @{sys}/class/ r, - @{sys}/class/backlight/ r, - - @{sys}/devices/@{pci}/*_backlight/{,max_,actual_}brightness rw, - @{sys}/devices/@{pci}/*_backlight/{uevent,type,enabled} r, - @{sys}/devices/@{pci}/backlight/**/{,max_,actual_}brightness rw, - @{sys}/devices/@{pci}/backlight/**/{uevent,type,enabled} r, - @{sys}/devices/@{pci}/backlight/**/brightness rw, + @{sys}/devices/@{pci}/class r, - @{sys}/devices/@{pci}/drm/card@{int}/**/{,max_,actual_}brightness rw, - @{sys}/devices/@{pci}/drm/card@{int}/**/{uevent,type,enabled} r, - @{sys}/devices/@{pci}/drm/card@{int}/**/brightness rw, - @{sys}/devices/**/leds/**/{,max_,actual_}brightness rw, - @{sys}/devices/**/leds/**/{uevent,type,enabled} r, - @{sys}/devices/**/leds/**/brightness_hw_changed r, @{PROC}/cmdline r, @{PROC}/sys/kernel/osrelease r, diff --git a/apparmor.d/groups/gnome/gsd-print-notifications b/apparmor.d/groups/gnome/gsd-print-notifications index 435d0049e8..48d50017b5 100644 --- a/apparmor.d/groups/gnome/gsd-print-notifications +++ b/apparmor.d/groups/gnome/gsd-print-notifications @@ -9,29 +9,30 @@ include @{exec_path} = @{lib}/gsd-print-notifications profile gsd-print-notifications @{exec_path} flags=(attach_disconnected) { include - include include include - include - include + include + include + include + include + include include include + include + include network inet stream, network inet6 stream, - signal (receive) set=(term, hup) peer=gdm*, - signal (send) set=(hup) peer=gsd-printer, + signal receive set=(term, hup) peer=gdm*, + signal send set=(hup) peer=gsd-printer, #aa:dbus own bus=session name=org.gnome.SettingsDaemon.PrintNotifications - # dbus receive bus=system path=/org/cups/cupsd/Notifier - # interface=org.cups.cupsd.Notifier, - dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, @{lib}/gsd-printer rPx, diff --git a/apparmor.d/groups/gnome/gsd-printer b/apparmor.d/groups/gnome/gsd-printer index b85a40f044..aa9ce1a519 100644 --- a/apparmor.d/groups/gnome/gsd-printer +++ b/apparmor.d/groups/gnome/gsd-printer @@ -9,11 +9,11 @@ include @{exec_path} = @{lib}/gsd-printer profile gsd-printer @{exec_path} flags=(attach_disconnected) { include - include include include - include + include include + include signal (receive) set=(term, hup) peer=gdm*, signal (receive) set=(hup) peer=gsd-print-notifications, @@ -24,7 +24,7 @@ profile gsd-printer @{exec_path} flags=(attach_disconnected) { dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, diff --git a/apparmor.d/groups/gnome/gsd-rfkill b/apparmor.d/groups/gnome/gsd-rfkill index 5f1c13d9d7..5b0e6e0b25 100644 --- a/apparmor.d/groups/gnome/gsd-rfkill +++ b/apparmor.d/groups/gnome/gsd-rfkill @@ -9,13 +9,13 @@ include @{exec_path} = @{lib}/gsd-rfkill profile gsd-rfkill @{exec_path} flags=(attach_disconnected) { include - include include include - include - include - include - include + include + include + include + include + include signal (receive) set=(term, hup) peer=gdm*, @@ -23,13 +23,20 @@ profile gsd-rfkill @{exec_path} flags=(attach_disconnected) { #aa:dbus own bus=session name=org.gnome.SettingsDaemon.Rfkill + dbus send bus=system path=/org/freedesktop/NetworkManager + interface=org.freedesktop.DBus.Properties + member=Set + peer=(name=@{busname}, label=NetworkManager), + dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, + / r, + @{sys}/devices/virtual/misc/rfkill/uevent r, @{run}/udev/data/c10:@{int} r, # for non-serial mice, misc features diff --git a/apparmor.d/groups/gnome/gsd-screensaver-proxy b/apparmor.d/groups/gnome/gsd-screensaver-proxy index 546a252d73..57a3429c0c 100644 --- a/apparmor.d/groups/gnome/gsd-screensaver-proxy +++ b/apparmor.d/groups/gnome/gsd-screensaver-proxy @@ -9,19 +9,20 @@ include @{exec_path} = @{lib}/gsd-screensaver-proxy profile gsd-screensaver-proxy @{exec_path} flags=(attach_disconnected) { include - include include - include + include + include + include signal (receive) set=(term, hup) peer=gdm*, - #aa:dbus own bus=session name=org.freedesktop.ScreenSaver + #aa:dbus own bus=session name=org.freedesktop.ScreenSaver path=/{,org/freedesktop/}ScreenSaver #aa:dbus own bus=session name=org.gnome.SettingsDaemon.ScreensaverProxy dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, diff --git a/apparmor.d/groups/gnome/gsd-sharing b/apparmor.d/groups/gnome/gsd-sharing index 45b3ea1b9a..835452f354 100644 --- a/apparmor.d/groups/gnome/gsd-sharing +++ b/apparmor.d/groups/gnome/gsd-sharing @@ -9,12 +9,13 @@ include @{exec_path} = @{lib}/gsd-sharing profile gsd-sharing @{exec_path} flags=(attach_disconnected) { include - include include include - include - include + include include + include + include + include signal (receive) set=(term, hup) peer=gdm*, @@ -28,16 +29,14 @@ profile gsd-sharing @{exec_path} flags=(attach_disconnected) { dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), - @{exec_path} mr, + dbus receive bus=system path=/org/freedesktop/NetworkManager/ActiveConnection/3 + interface=org.freedesktop.NetworkManager.VPN.Connection + member=VpnStateChanged + peer=(name=@{busname}, label=NetworkManager), - /usr/share/dconf/profile/gdm r, - /usr/share/gdm/greeter-dconf-defaults r, - /usr/share/glib-2.0/schemas/gschemas.compiled r, - - owner @{GDM_HOME}/greeter-dconf-defaults r, - owner @{gdm_config_dirs}/dconf/user r, + @{exec_path} mr, @{run}/systemd/sessions/* r, @{run}/systemd/users/@{uid} r, diff --git a/apparmor.d/groups/gnome/gsd-smartcard b/apparmor.d/groups/gnome/gsd-smartcard index bdacbfd006..b3eeffb51b 100644 --- a/apparmor.d/groups/gnome/gsd-smartcard +++ b/apparmor.d/groups/gnome/gsd-smartcard @@ -9,12 +9,15 @@ include @{exec_path} = @{lib}/gsd-smartcard profile gsd-smartcard @{exec_path} flags=(attach_disconnected) { include - include include - include + include + include include + include include include + include + include signal (receive) set=(term, hup) peer=gdm*, @@ -23,23 +26,16 @@ profile gsd-smartcard @{exec_path} flags=(attach_disconnected) { dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, - /usr/share/dconf/profile/gdm r, - /usr/share/gdm/greeter-dconf-defaults r, - /usr/share/glib-2.0/schemas/gschemas.compiled r, - - /etc/{,opensc/}opensc.conf r, /etc/tpm2-tss/* rk, /var/tmp/ r, /tmp/ r, owner @{GDM_HOME}/.tpm2_pkcs11/tpm2_pkcs11.sqlite3{,.lock} rwk, - owner @{GDM_HOME}/greeter-dconf-defaults r, - owner @{gdm_config_dirs}/dconf/user r, owner @{HOME}/.tpm2_pkcs11/tpm2_pkcs11.sqlite3{,.lock} rwk, diff --git a/apparmor.d/groups/gnome/gsd-sound b/apparmor.d/groups/gnome/gsd-sound index 07a6ff6ed8..0730d49793 100644 --- a/apparmor.d/groups/gnome/gsd-sound +++ b/apparmor.d/groups/gnome/gsd-sound @@ -9,30 +9,26 @@ include @{exec_path} = @{lib}/gsd-sound profile gsd-sound @{exec_path} flags=(attach_disconnected) { include - include include include - include - include + include + include + include include + include + include - signal (receive) set=(term, hup) peer=gdm*, + signal receive set=(term, hup) peer=gdm*, #aa:dbus own bus=session name=org.gnome.SettingsDaemon.Sound dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, - /usr/share/dconf/profile/gdm r, - /usr/share/gdm/greeter-dconf-defaults r, - /usr/share/glib-2.0/schemas/gschemas.compiled r, - - owner @{GDM_HOME}/greeter-dconf-defaults r, - owner @{gdm_config_dirs}/dconf/user r, owner @{gdm_share_dirs}/sounds/ rw, owner @{user_share_dirs}/sounds/ rw, diff --git a/apparmor.d/groups/gnome/gsd-usb-protection b/apparmor.d/groups/gnome/gsd-usb-protection index 2359c9f39e..7982cb94c0 100644 --- a/apparmor.d/groups/gnome/gsd-usb-protection +++ b/apparmor.d/groups/gnome/gsd-usb-protection @@ -7,16 +7,24 @@ abi , include @{exec_path} = @{lib}/gsd-usb-protection -profile gsd-usb-protection @{exec_path} { +profile gsd-usb-protection @{exec_path} flags=(attach_disconnected) { include include + include + include include + include + include + include #aa:dbus own bus=session name=org.gnome.SettingsDaemon.UsbProtection - @{exec_path} mr, + dbus receive bus=session + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), - /usr/share/glib-2.0/schemas/gschemas.compiled r, + @{exec_path} mr, include if exists } diff --git a/apparmor.d/groups/gnome/gsd-wacom b/apparmor.d/groups/gnome/gsd-wacom index 484dda29d2..f76ba7df6b 100644 --- a/apparmor.d/groups/gnome/gsd-wacom +++ b/apparmor.d/groups/gnome/gsd-wacom @@ -10,15 +10,11 @@ include profile gsd-wacom @{exec_path} flags=(attach_disconnected) { include include - include - include - include - include - include include include include include + include signal (receive) set=(term, hup) peer=gdm*, @@ -26,13 +22,8 @@ profile gsd-wacom @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, - /usr/share/dconf/profile/gdm r, - /usr/share/gdm/greeter-dconf-defaults r, /usr/share/libwacom/{,*} r, - owner @{gdm_config_dirs}/dconf/user r, - owner @{GDM_HOME}/greeter-dconf-defaults r, - include if exists } diff --git a/apparmor.d/groups/gnome/gsd-wwan b/apparmor.d/groups/gnome/gsd-wwan index ab2b2b0898..045cf7b94e 100644 --- a/apparmor.d/groups/gnome/gsd-wwan +++ b/apparmor.d/groups/gnome/gsd-wwan @@ -10,10 +10,19 @@ include profile gsd-wwan @{exec_path} { include include + include include + include + include + include #aa:dbus own bus=session name=org.gnome.SettingsDaemon.Wwan + dbus receive bus=session + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), + @{exec_path} mr, include if exists diff --git a/apparmor.d/groups/gnome/gsd-xsettings b/apparmor.d/groups/gnome/gsd-xsettings index c7478292ce..a41eb9272a 100644 --- a/apparmor.d/groups/gnome/gsd-xsettings +++ b/apparmor.d/groups/gnome/gsd-xsettings @@ -7,22 +7,18 @@ abi , include @{exec_path} = @{lib}/gsd-xsettings -profile gsd-xsettings @{exec_path} { +profile gsd-xsettings @{exec_path} flags=(attach_disconnected) { include - include - include - include - include - include - include - include - include - include + include + include + include + include include - include + include include include include + include network inet stream, network inet6 stream, @@ -33,17 +29,25 @@ profile gsd-xsettings @{exec_path} { #aa:dbus own bus=session name=org.gnome.SettingsDaemon.XSettings #aa:dbus own bus=session name=org.gtk.Settings - dbus send bus=system path=/org/freedesktop/Accounts/User@{uid} - interface=org.freedesktop.Accounts.User - member=SetInputSources - peer=(name=:*, label=accounts-daemon), + #aa:dbus talk bus=session name=org.gnome.Mutter.X11 label=gnome-shell dbus send bus=session path=/org/freedesktop/DBus interface=org.freedesktop.DBus member=GetId peer=(name=org.freedesktop.DBus, label="@{p_dbus_session}"), + dbus receive bus=system path=/org/freedesktop/Accounts + interface=org.freedesktop.Accounts + member={UserAdded,UserDeleted} + peer=(name=@{busname}, label="@{p_accounts_daemon}"), + + dbus send bus=system path=/org/freedesktop/Accounts/User@{uid} + interface=org.freedesktop.Accounts.User + member=SetInputSources + peer=(name=@{busname}, label="@{p_accounts_daemon}"), + @{exec_path} mr, + @{sh_path} mr, @{bin}/cat rix, @{bin}/sed rix, @@ -56,24 +60,17 @@ profile gsd-xsettings @{exec_path} { @{bin}/xrdb rPx, @{lib}/{,ibus/}ibus-x11 rPx, - /usr/share/dconf/profile/gdm r, - /usr/share/gdm/greeter-dconf-defaults r, - /etc/X11/Xsession.options r, @{etc_ro}/xdg/Xwayland-session.d/ r, @{etc_ro}/xdg/Xwayland-session.d/* rix, - owner @{GDM_HOME}/greeter-dconf-defaults r, - owner @{gdm_cache_dirs}/fontconfig/[a-f0-9]*.cache-?{,.NEW,.LCK,.TMP-*} rw, - owner @{gdm_config_dirs}/dconf/user r, - @{run}/systemd/sessions/* r, @{run}/systemd/users/@{uid} r, owner @{PROC}/@{pid}/fd/ r, /dev/tty rw, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, profile run-parts { include diff --git a/apparmor.d/groups/gnome/kgx b/apparmor.d/groups/gnome/kgx index c9177de5c4..10343d0b8a 100644 --- a/apparmor.d/groups/gnome/kgx +++ b/apparmor.d/groups/gnome/kgx @@ -7,7 +7,7 @@ abi , include @{exec_path} = @{bin}/kgx -profile kgx @{exec_path} { +profile kgx @{exec_path} flags=(attach_disconnected) { include include include @@ -17,7 +17,7 @@ profile kgx @{exec_path} { capability sys_ptrace, - ptrace (read), + ptrace read, @{exec_path} mr, @@ -25,20 +25,21 @@ profile kgx @{exec_path} { @{bin}/@{shells} rUx, # Some CLI program can be launched directly from Gnome Shell - @{bin}/btop rPUx, - @{bin}/htop rPx, - @{bin}/micro rPUx, - @{bin}/nvtop rPx, - @{bin}/nvtop rPx, - @{bin}/vim rUx, + @{bin}/btop PUx, + @{bin}/htop Px, + @{bin}/micro PUx, + @{bin}/nvtop Px, + @{bin}/nvtop Px, + @{bin}/vim Ux, - @{open_path} rPx -> child-open-help, + @{open_path} Px -> child-open-help, owner @{tmp}/#@{int} rw, @{PROC}/ r, @{PROC}/@{pids}/cmdline r, @{PROC}/@{pids}/stat r, + @{PROC}/@{pids}/status r, @{PROC}/1/cgroup r, owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/task/@{tid}/comm rw, diff --git a/apparmor.d/groups/gnome/localsearch b/apparmor.d/groups/gnome/localsearch index 448e517a5a..662ee14bc6 100644 --- a/apparmor.d/groups/gnome/localsearch +++ b/apparmor.d/groups/gnome/localsearch @@ -9,31 +9,42 @@ include @{exec_path} = @{bin}/localsearch @{lib}/localsearch-3 profile localsearch @{exec_path} flags=(attach_disconnected) { include - include - include - include - include - include - include + include + include + include include include + include include - include include include include include + include + include network netlink raw, + #aa:dbus own bus=session name=org.freedesktop.Tracker3.Miner.Files #aa:dbus own bus=session name=org.freedesktop.LocalSearch3 + dbus receive bus=session path=/org/freedesktop/Tracker3/Endpoint + interface=org.freedesktop.DBus.Peer + member=Ping + peer=(name=@{busname}, label=nautilus), + dbus receive bus=session path=/org/freedesktop/Tracker3/Endpoint + interface=org.freedesktop.Tracker3.Endpoint + member=Query + peer=(name=@{busname}, label=nautilus), + @{exec_path} mr, @{lib}/localsearch-extractor-3 ix, # nnp /usr/share/localsearch3/{,**} r, - /usr/share/poppler/{,**} r, + /usr/share/osinfo/{,**} r, + + /etc/fstab r, # Allow to search user files owner @{HOME}/ r, @@ -45,13 +56,13 @@ profile localsearch @{exec_path} flags=(attach_disconnected) { owner @{user_cache_dirs}/tracker3/files/ rw, owner @{user_cache_dirs}/tracker3/files/** rwk, - owner /var/tmp/etilqs_@{hex15} rw, - owner /var/tmp/etilqs_@{hex16} rw, - owner @{tmp}/etilqs_@{hex12}@{hex2} rw, - owner @{tmp}/etilqs_@{hex15} rw, - owner @{tmp}/etilqs_@{hex16} rw, + owner @{GDM_HOME}/ r, + owner @{GDM_HOME}/*/ r, + owner @{gdm_cache_dirs}/tracker3/{,**} rwk, + owner @{gdm_config_dirs}/user-dirs.dirs r, - @{run}/mount/utab r, + @{run}/mount/utab r, + owner @{run}/user/@{uid}/systemd/notify w, @{run}/udev/data/c@{dynamic}:@{int} r, # For dynamic assignment range 234 to 254, 384 to 511 @@ -59,10 +70,12 @@ profile localsearch @{exec_path} flags=(attach_disconnected) { @{PROC}/sys/fs/inotify/max_user_watches r, owner @{PROC}/@{pid}/cmdline r, owner @{PROC}/@{pid}/mountinfo r, + owner @{PROC}/@{pid}/mounts r, owner @{PROC}/@{pid}/task/@{tid}/comm rw, - /dev/media@{int} rw, - /dev/video@{int} rw, + # No access to camera and microphone devices + deny /dev/video@{int} rw, + deny /dev/media@{int} rw, include if exists } diff --git a/apparmor.d/groups/gnome/loupe b/apparmor.d/groups/gnome/loupe index 75835395ab..ab0bb68052 100644 --- a/apparmor.d/groups/gnome/loupe +++ b/apparmor.d/groups/gnome/loupe @@ -9,59 +9,43 @@ include @{exec_path} = @{bin}/loupe profile loupe @{exec_path} flags=(attach_disconnected) { include + include include include include include + include include include include - signal send set=kill peer=loupe//bwrap, + #aa:dbus own bus=session name=org.gnome.Loupe #aa:dbus talk bus=session name=org.gtk.vfs label="gvfsd{,-*}" @{exec_path} mr, - @{bin}/bwrap rCx -> bwrap, @{open_path} rPx -> child-open-help, - /usr/share/glycin-loaders/{,**} r, - / r, - owner @{user_cache_dirs}/glycin/{,**} rw, - - @{run}/mount/utab r, + @{run}/mount/utab r, + owner @{run}/user/@{uid}/gvfsd/socket-@{rand8} rw, - @{sys}/fs/cgroup/user.slice/cpu.max r, - @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/cpu.max r, - @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/cpu.max r, - @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/cpu.max r, + @{sys}/fs/cgroup/user.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/cpu.max r, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/session.slice/cpu.max r, owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/cmdline r, owner @{PROC}/@{pid}/mountinfo r, + owner @{PROC}/@{pid}/stat r, owner @{PROC}/@{pid}/task/@{tid}/comm rw, deny @{user_share_dirs}/gvfs-metadata/* r, - profile bwrap flags=(attach_disconnected) { - include - include - - signal (receive) set=(kill) peer=loupe, - - @{bin}/bwrap mr, - @{lib}/glycin-loaders/*/glycin-* rix, - - owner @{PROC}/@{pid}/fd/ r, - - deny @{user_share_dirs}/gvfs-metadata/* r, - - include if exists - } - include if exists } diff --git a/apparmor.d/groups/gnome/mutter-x11-frames b/apparmor.d/groups/gnome/mutter-x11-frames index 2ad89fe0a0..f478a8844e 100644 --- a/apparmor.d/groups/gnome/mutter-x11-frames +++ b/apparmor.d/groups/gnome/mutter-x11-frames @@ -10,11 +10,6 @@ include profile mutter-x11-frames @{exec_path} flags=(attach_disconnected) { include include - include - include - include - include - include include include include @@ -25,12 +20,8 @@ profile mutter-x11-frames @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, - /usr/share/dconf/profile/gdm r, - /usr/share/gdm/greeter-dconf-defaults r, - - owner @{GDM_HOME}/greeter-dconf-defaults r, - owner @{gdm_cache_dirs}/fontconfig/@{hex32}-*.cache-?{,.NEW,.LCK,.TMP-@{rand6}} rw, - owner @{gdm_config_dirs}/dconf/user r, + owner @{gdm_cache_dirs}/fontconfig/ rw, + owner @{gdm_cache_dirs}/fontconfig/@{hex32}-*.cache-?{,.NEW,.LCK,.TMP-@{rand6}} rwl, @{sys}/devices/@{pci}/boot_vga r, diff --git a/apparmor.d/groups/gnome/nautilus b/apparmor.d/groups/gnome/nautilus index 373593440e..ada468df7b 100644 --- a/apparmor.d/groups/gnome/nautilus +++ b/apparmor.d/groups/gnome/nautilus @@ -9,37 +9,53 @@ include @{exec_path} = @{bin}/nautilus profile nautilus @{exec_path} flags=(attach_disconnected) { include - include - include - include - include - include - include - include - include - include - include + include + include + include + include + include include include include include include + include + include + include include mqueue r type=posix /, - #aa:dbus own bus=session name=org.gnome.Nautilus interface+="org.gtk.{Application,Actions}" + unix type=stream peer=(label=gnome-shell), + + signal send set=kill peer=gnome-desktop-thumbnailers, + #aa:dbus own bus=session name=org.freedesktop.FileManager1 + #aa:dbus own bus=session name=org.gnome.Nautilus.SearchProvider interface+=org.gnome.Shell.SearchProvider2 + #aa:dbus own bus=session name=org.gnome.Nautilus + #aa:dbus talk bus=session name=org.freedesktop.impl.portal.FileChooser path=/org/freedesktop/portal/desktop label=xdg-desktop-portal-gnome + #aa:dbus talk bus=session name=org.freedesktop.portal.FileTransfer path=/org/freedesktop/portal/documents label=xdg-document-portal + #aa:dbus talk bus=session name=org.gnome.Settings label=gnome-control-center #aa:dbus talk bus=session name=org.gtk.MountOperationHandler label=gnome-shell - #aa:dbus talk bus=session name=org.gtk.vfs label="gvfsd{,-*}" #aa:dbus talk bus=session name=org.gtk.Notifications label=gnome-shell + #aa:dbus talk bus=session name=org.gtk.vfs label="gvfsd{,-*}" + + dbus send bus=session path=/org/gnome/Mutter/ServiceChannel + interface=org.gnome.Mutter.ServiceChannel + member=OpenWaylandServiceConnection + peer=(name=@{busname}, label=gnome-shell), dbus (send, receive) bus=session path=/org/gtk/Application/CommandLine interface=org.gtk.private.CommandLine member=Print peer=(name=@{busname}, label=nautilus), + dbus send bus=session path=/org/freedesktop/DBus + interface=org.freedesktop.DBus.Properties + member=GetAll + peer=(name=org.freedesktop.DBus, label="@{p_dbus_session}"), + dbus send bus=session path=/org/freedesktop/DBus interface=org.freedesktop.DBus member=ListActivatableNames @@ -50,6 +66,11 @@ profile nautilus @{exec_path} flags=(attach_disconnected) { member=NameHasOwner peer=(name=org.freedesktop.DBus, label="@{p_dbus_session}"), + # Server side of abstractions/bus/session/org.freedesktop.Application + dbus send bus=session + interface=org.freedesktop.Application + member=Open, + @{exec_path} mr, @{sh_path} rix, @@ -57,12 +78,14 @@ profile nautilus @{exec_path} flags=(attach_disconnected) { @{bin}/file-roller rPx, @{bin}/firejail rPUx, @{bin}/net rPUx, - @{bin}/tracker3 rPUx, - @{open_path} rPx -> child-open, + @{bin}/* r, + @{open_path} mrPx -> child-open-any, + + /snap/*/@{uid}/**.@{icon_ext} r, + /usr/share/**.@{icon_ext} r, /usr/share/nautilus/{,**} r, - /usr/share/poppler/{,**} r, /usr/share/sounds/freedesktop/stereo/*.oga r, /usr/share/terminfo/** r, /usr/share/thumbnailers/{,**} r, @@ -72,6 +95,7 @@ profile nautilus @{exec_path} flags=(attach_disconnected) { /var/cache/fontconfig/ rw, + #aa:lint ignore=too-wide # Full access to user's data / r, /*/ r, @@ -88,7 +112,7 @@ profile nautilus @{exec_path} flags=(attach_disconnected) { owner @{tmp}/** rw, # Silence non user's data - deny /boot/{,**} r, + deny @{efi}/{,**} r, deny /opt/{,**} r, deny /root/{,**} r, deny /tmp/.* rw, @@ -98,13 +122,9 @@ profile nautilus @{exec_path} flags=(attach_disconnected) { @{run}/mount/utab r, - @{sys}/devices/**/hwmon@{int}/{,name,temp*,fan*} r, - @{sys}/devices/**/hwmon@{int}/**/{,name,temp*,fan*} r, - @{sys}/devices/**/hwmon/{,name,temp*,fan*} r, - @{sys}/devices/**/hwmon/**/{,name,temp*,fan*} r, - @{PROC}/@{pids}/net/wireless r, @{PROC}/sys/dev/i915/perf_stream_paranoid r, + owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/cmdline r, owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/mountinfo r, diff --git a/apparmor.d/groups/gnome/org.gnome.NautilusPreviewer b/apparmor.d/groups/gnome/org.gnome.NautilusPreviewer index db440bf4cd..01b9454dbf 100644 --- a/apparmor.d/groups/gnome/org.gnome.NautilusPreviewer +++ b/apparmor.d/groups/gnome/org.gnome.NautilusPreviewer @@ -10,25 +10,24 @@ 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, @{exec_path} mr, - @{bin}/gjs-console r, - @{open_path} rPx -> child-open, + @{open_path} rPx -> child-open-any, /usr/share/ladspa/rdf/{,**} r, - /usr/share/poppler/{,**} r, /usr/share/sushi/org.gnome.NautilusPreviewer.*.gresource r, /etc/machine-id r, @@ -37,8 +36,8 @@ profile org.gnome.NautilusPreviewer @{exec_path} flags=(attach_disconnected) { owner @{MOUNTS}/{,**} r, owner @{HOME}/{,**} r, - @{run}/udev/data/c@{dynamic}:@{int} r, # For dynamic assignment range 234 to 254, 384 to 511 - + @{sys}/devices/@{pci_bus}/uevent r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/session-@{word}.scope/memory.* r, @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/*org.gnome.NautilusPreviewer.slice/*/memory.* r, @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/session.slice/dbus.service/memory.* r, @@ -51,7 +50,7 @@ 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, + /dev/ r, include if exists } diff --git a/apparmor.d/groups/gnome/papers b/apparmor.d/groups/gnome/papers new file mode 100644 index 0000000000..3785993d8c --- /dev/null +++ b/apparmor.d/groups/gnome/papers @@ -0,0 +1,76 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/papers +profile papers @{exec_path} flags=(attach_disconnected) { + include + include + include + include + include + include + include + include + include + include + include + include + + #aa:dbus own bus=session name=org.gnome.Papers + + dbus send bus=session path=/org/freedesktop/portal/desktop/session/** + interface=org.freedesktop.portal.Session + member=Close + peer=(name=org.freedesktop.portal.Desktop, label=xdg-desktop-portal), + + dbus send bus=session path=/org/freedesktop/portal/desktop + interface=org.freedesktop.portal.Print + member={PreparePrint,Print} + peer=(name=@{busname}, label=xdg-desktop-portal), + + @{exec_path} mr, + + @{open_path} Cx -> open, + + owner @{user_config_dirs}/cpdb/print-settings r, + + owner @{HOME}/.pki/nssdb/pkcs11.txt r, + owner @{HOME}/.mozilla/firefox/*/{cert9,key4}.db rwk, + owner @{HOME}/.mozilla/firefox/*/pkcs11.txt rw, + owner @{HOME}/.mozilla/firefox/*/{cert9,key4}.db-journal rw, + + /tmp/ r, + /var/tmp/ r, + owner @{tmp}/.goutputstream-@{rand6} rw, + owner @{tmp}/papers-@{int}/{,**} rw, + owner @{tmp}/gtkprint_@{rand6} rw, + owner @{tmp}/gtkprint@{rand6} rw, + + @{run}/mount/utab r, + + @{PROC}/sys/kernel/random/boot_id r, + owner @{PROC}/@{pid}/cgroup r, + owner @{PROC}/@{pid}/mountinfo r, + + profile open { + include + include + + @{browsers_path} Px, + @{help_path} Px, + @{bin}/papers Px, + @{bin}/snap Px, + @{bin}/flatpak Px, + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/gnome/ptyxis b/apparmor.d/groups/gnome/ptyxis new file mode 100644 index 0000000000..c1cc75d24e --- /dev/null +++ b/apparmor.d/groups/gnome/ptyxis @@ -0,0 +1,43 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/ptyxis +profile ptyxis @{exec_path} flags=(attach_disconnected) { + include + include + include + + unix type=stream peer=(label=ptyxis-agent), + + #aa:dbus own bus=session name=org.gnome.Ptyxis + + @{exec_path} mr, + + @{lib}/ptyxis-agent Px, + @{open_path} Px -> child-open-help, + + /etc/shells r, + + owner @{user_cache_dirs}/org.gnome.Ptyxis/ rw, + owner @{user_cache_dirs}/org.gnome.Ptyxis/** rwlk -> @{user_cache_dirs}/org.gnome.Ptyxis/**, + + owner @{user_config_dirs}/org.gnome.Ptyxis/ rw, + owner @{user_config_dirs}/org.gnome.Ptyxis/** rwlk -> @{user_config_dirs}/org.gnome.Ptyxis/**, + owner @{user_config_dirs}/*-xdg-terminals.list r, + + owner @{user_share_dirs}/org.gnome.Ptyxis/ rw, + owner @{user_share_dirs}/org.gnome.Ptyxis/** rwlk -> @{user_share_dirs}/org.gnome.Ptyxis/**, + + owner /tmp/#@{int} rw, + + /dev/ptmx rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/gnome/ptyxis-agent b/apparmor.d/groups/gnome/ptyxis-agent new file mode 100644 index 0000000000..a3613cd1a5 --- /dev/null +++ b/apparmor.d/groups/gnome/ptyxis-agent @@ -0,0 +1,80 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/ptyxis-agent +profile ptyxis-agent @{exec_path} flags=(attach_disconnected) { + include + include + include + include + include + include + include + include + + signal send set=hup peer=@{p_systemd}, + signal send set=kill, + + ptrace read, + + unix type=stream peer=(label=ptyxis), + + dbus receive bus=session + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), + + @{exec_path} mr, + + @{bin}/podman PUx, + @{bin}/systemd-run Cx -> shell, + + owner @{user_config_dirs}/gnome-xdg-terminals.list rw, + owner @{user_config_dirs}/gnome-xdg-terminals.list.@{rand6} rw, + owner @{user_config_dirs}/xdg-terminals.list rw, + owner @{user_config_dirs}/xdg-terminals.list.@{rand6} rw, + + owner @{user_share_dirs}/containers/ w, + owner @{user_share_dirs}/containers/storage/ w, + owner @{user_share_dirs}/containers/storage/overlay-containers/ w, + + @{PROC}/@{pid}/cmdline r, + + /dev/ptmx rw, + + profile shell flags=(attach_disconnected) { + include + include + + signal send, + + unix bind type=stream addr=@@{udbus}/bus/systemd-run/, + + @{bin}/systemd-run mr, + @{bin}/env ix, + + # The shell is not confined on purpose. + @{bin}/@{shells} Ux, + + # Some CLI program can be launched directly from Gnome Shell + @{lib}/** PUx, + @{bin}/** PUx, + /opt/*/** PUx, + /usr/share/*/** PUx, + /usr/local/bin/** PUx, + /usr/games/** PUx, + + owner @{run}/user/@{uid}/systemd/private rw, + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/gnome/seahorse b/apparmor.d/groups/gnome/seahorse index 921f6aa30c..14dc39f923 100644 --- a/apparmor.d/groups/gnome/seahorse +++ b/apparmor.d/groups/gnome/seahorse @@ -7,21 +7,18 @@ abi , include @{exec_path} = @{bin}/seahorse -profile seahorse @{exec_path} { +profile seahorse @{exec_path} flags=(attach_disconnected) { include - include - include - include - include - include - include - include + include + include include include include + include + include include - #aa:dbus own bus=session name=org.gnome.seahorse.Application + #aa:dbus own bus=session name=org.gnome.seahorse.Application interface+=org.gnome.Shell.SearchProvider2 @{exec_path} mr, @@ -33,7 +30,6 @@ profile seahorse @{exec_path} { /etc/pki/trust/blocklist/ r, /etc/gcrypt/hwf.deny r, - /etc/{,opensc/}opensc.conf r, owner @{HOME}/@{XDG_SSH_DIR}/{,**} r, diff --git a/apparmor.d/groups/gnome/session-migration b/apparmor.d/groups/gnome/session-migration index 9af0d4714b..5ad1f97806 100644 --- a/apparmor.d/groups/gnome/session-migration +++ b/apparmor.d/groups/gnome/session-migration @@ -9,24 +9,30 @@ include @{exec_path} = @{bin}/session-migration profile session-migration @{exec_path} { include - include include + include + include + include include @{exec_path} mr, - @{sh_path} rix, - @{python_path} rix, - @{bin}/gsettings rPx, - /usr/share/session-migration/scripts/* rix, + @{sh_path} rix, + @{python_path} rix, + @{bin}/dconf rPx, + @{bin}/{,e}grep rix, + @{bin}/gsettings rPx, + @{bin}/tr rix, + @{bin}/update-alternatives rPx, + /usr/share/session-migration/scripts/* rix, - /usr/share/glib-2.0/schemas/gschemas.compiled r, /usr/share/session-migration/{,**} r, + owner @{gdm_share_dirs}/ w, owner @{gdm_share_dirs}/session_migration-* rw, owner @{user_share_dirs}/session_migration-* rw, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/gnome/showtime b/apparmor.d/groups/gnome/showtime new file mode 100644 index 0000000000..3778ae0fa6 --- /dev/null +++ b/apparmor.d/groups/gnome/showtime @@ -0,0 +1,35 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/showtime +profile showtime @{exec_path} flags=(attach_disconnected) { + include + include + include + include + include + include + include + + @{exec_path} mr, + + @{open_path} Px -> child-open-help, + + /usr/share/xml/iso-codes/{,**} r, + + owner @{user_music_dirs}/{,**} rw, + owner @{user_pictures_dirs}/{,**} rw, + owner @{user_torrents_dirs}/{,**} rw, + owner @{user_videos_dirs}/{,**} rw, + + owner @{PROC}/@{pid}/mounts r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/gnome/tracker-extract b/apparmor.d/groups/gnome/tracker-extract index 83bf18b9b9..eb515720d7 100644 --- a/apparmor.d/groups/gnome/tracker-extract +++ b/apparmor.d/groups/gnome/tracker-extract @@ -9,10 +9,9 @@ include @{exec_path} = @{lib}/tracker-extract-3 profile tracker-extract @{exec_path} flags=(attach_disconnected) { include - include - include - include - include + include + include + include include include include @@ -20,6 +19,7 @@ profile tracker-extract @{exec_path} flags=(attach_disconnected) { include include include + include include network netlink raw, @@ -32,24 +32,18 @@ profile tracker-extract @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, - /usr/share/dconf/profile/gdm r, /usr/share/gdm/greeter/applications/*.desktop r, /usr/share/ladspa/rdf/{,**} r, /usr/share/osinfo/{,**} r, - /usr/share/poppler/{,**} r, /usr/share/tracker3-miners/{,**} r, /usr/share/tracker3/{,**} r, /etc/blkid.conf r, /etc/fstab r, - owner @{GDM_HOME}/greeter-dconf-defaults r, owner @{gdm_cache_dirs}/ rw, owner @{gdm_cache_dirs}/fontconfig/[a-f0-9]*.cache-?{,.NEW,.LCK,.TMP-*} rw, - owner @{gdm_cache_dirs}/gstreamer-1.0/ rw, - owner @{gdm_cache_dirs}/gstreamer-1.0/registry.*.bin{,.tmp@{rand6}} rw, owner @{gdm_cache_dirs}/tracker3/{,**} rw, - owner @{gdm_config_dirs}/dconf/user r, # Allow to search user files owner @{HOME}/{,**} r, @@ -70,13 +64,11 @@ profile tracker-extract @{exec_path} flags=(attach_disconnected) { owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/mountinfo r, + owner @{PROC}/@{pid}/mounts r, owner @{PROC}/@{pid}/task/@{tid}/comm rw, - /dev/media@{int} r, - /dev/video@{int} rw, - # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/gnome/tracker-miner b/apparmor.d/groups/gnome/tracker-miner index e10d81bb2c..876004d133 100644 --- a/apparmor.d/groups/gnome/tracker-miner +++ b/apparmor.d/groups/gnome/tracker-miner @@ -9,18 +9,18 @@ include @{exec_path} = @{lib}/tracker-miner-fs-{,control-,rss-}3 profile tracker-miner @{exec_path} flags=(attach_disconnected) { include - include - include - include - include - include - include + include + include + include include include include include include + include include + include + include network netlink raw, @@ -33,22 +33,20 @@ profile tracker-miner @{exec_path} flags=(attach_disconnected) { dbus receive bus=session path=/org/freedesktop/Tracker3/Endpoint interface=org.freedesktop.DBus.Peer member=Ping - peer=(name=:*, label=nautilus), + peer=(name=@{busname}, label=nautilus), dbus receive bus=session path=/org/freedesktop/Tracker3/Endpoint interface=org.freedesktop.Tracker3.Endpoint member=Query - peer=(name=:*, label=nautilus), + peer=(name=@{busname}, label=nautilus), @{exec_path} mr, @{lib}/tracker-extract-3 rix, - /usr/share/dconf/profile/gdm r, /usr/share/gdm/greeter/applications/{,mimeinfo.cache,*.list} r, /usr/share/gvfs/remote-volume-monitors/{,*.monitor} r, /usr/share/ladspa/rdf/{,**} r, /usr/share/osinfo/{,**} r, - /usr/share/poppler/{,**} r, /usr/share/tracker3-miners/{,**} r, /usr/share/tracker3/{,**} r, @@ -57,17 +55,10 @@ profile tracker-miner @{exec_path} flags=(attach_disconnected) { /etc/timezone r, owner @{GDM_HOME}/ r, - owner @{GDM_HOME}/greeter-dconf-defaults r, owner @{gdm_cache_dirs}/gstreamer-*/registry.*.bin r, owner @{gdm_cache_dirs}/tracker3/{,tracker3/}files/{,**} rwk, - owner @{gdm_config_dirs}/dconf/user r, owner @{gdm_share_dirs}/applications/ r, - owner /var/tmp/etilqs_@{hex15} rw, - owner /var/tmp/etilqs_@{hex16} rw, - owner @{tmp}/etilqs_@{hex15} rw, - owner @{tmp}/etilqs_@{hex16} rw, - # Allow to search user files owner @{HOME}/{,**} r, owner @{MOUNTS}/{,**} r, @@ -90,9 +81,7 @@ profile tracker-miner @{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, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/gnome/tracker-writeback b/apparmor.d/groups/gnome/tracker-writeback index a5346b463e..1472ee7cef 100644 --- a/apparmor.d/groups/gnome/tracker-writeback +++ b/apparmor.d/groups/gnome/tracker-writeback @@ -9,7 +9,6 @@ include @{exec_path} = @{lib}/tracker-writeback profile tracker-writeback @{exec_path} { include - include include #aa:dbus own bus=session name=org.freedesktop.Tracker3.Writeback diff --git a/apparmor.d/groups/gnome/tracker-xdg-portal b/apparmor.d/groups/gnome/tracker-xdg-portal index 20ed6bdce0..7dd8bbb141 100644 --- a/apparmor.d/groups/gnome/tracker-xdg-portal +++ b/apparmor.d/groups/gnome/tracker-xdg-portal @@ -9,7 +9,6 @@ include @{exec_path} = @{lib}/tracker-xdg-portal-3 profile tracker-xdg-portal @{exec_path} flags=(complain) { include - include include #aa:dbus own bus=session name=org.freedesktop.portal.Tracker diff --git a/apparmor.d/groups/gnome/yelp b/apparmor.d/groups/gnome/yelp index b3f27187b4..7693951f9c 100644 --- a/apparmor.d/groups/gnome/yelp +++ b/apparmor.d/groups/gnome/yelp @@ -7,19 +7,29 @@ abi , include @{exec_path} = @{bin}/yelp @{bin}/gnome-help -profile yelp @{exec_path} { +profile yelp @{exec_path} flags=(attach_disconnected) { include include + include # FIXME: In namespace include + include + include + capability dac_override, + + network inet dgram, + network inet stream, + network inet6 dgram, + network inet6 stream, network netlink raw, #aa:dbus own bus=accessibility name=org.gnome.Yelp - #aa:dbus own bus=session name=org.gnome.Yelp interface+=org.gtk.Actions + #aa:dbus own bus=session name=org.gnome.Yelp @{exec_path} mr, @{open_path} rPx -> child-open-help, + @{bin}/bwrap rix, @{lib}/{,@{multiarch}/}webkit{2,}gtk-*/WebKitNetworkProcess rix, @{lib}/{,@{multiarch}/}webkit{2,}gtk-*/WebKitWebProcess rix, @@ -29,7 +39,14 @@ profile yelp @{exec_path} { /etc/xml/{,**} r, - @{sys}/devices/virtual/dmi/id/chassis_type r, +# owner @{run}/user/@{uid}/.flatpak/ rw, +# owner @{run}/user/@{uid}/.flatpak/webkit-@{int}-@{int}/ w, +# owner @{run}/user/@{uid}/.flatpak/webkit-@{int}-@{int}/bwrapinfo.json rw, + + owner @{att}@{run}/user/@{uid}/wayland-@{int} rw, + + @{sys}/firmware/acpi/pm_profile r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/app-gnome-yelp-*.scope/memory.* r, owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/*.slice/*/memory.* r, owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/session.slice/xdg-desktop-portal.service/memory.current r, diff --git a/apparmor.d/groups/gpg/dirmngr b/apparmor.d/groups/gpg/dirmngr index 2fbdfb086d..ad355e10e5 100644 --- a/apparmor.d/groups/gpg/dirmngr +++ b/apparmor.d/groups/gpg/dirmngr @@ -25,16 +25,18 @@ profile dirmngr @{exec_path} { /usr/share/gnupg/sks-keyservers.netCA.pem r, owner @{HOME}/@{XDG_GPG_DIR}/ rw, - owner @{HOME}/@{XDG_GPG_DIR}/dirmngr.conf r, - owner @{HOME}/@{XDG_GPG_DIR}/dirmngr_ldapservers.conf r, + owner @{HOME}/@{XDG_GPG_DIR}/common.conf r, owner @{HOME}/@{XDG_GPG_DIR}/crls.d/ rw, owner @{HOME}/@{XDG_GPG_DIR}/crls.d/DIR.txt rw, + owner @{HOME}/@{XDG_GPG_DIR}/dirmngr_ldapservers.conf r, + owner @{HOME}/@{XDG_GPG_DIR}/dirmngr.conf r, owner @{MOUNTS}/{,/*}/@{XDG_GPG_DIR}/ rw, - owner @{MOUNTS}/{,/*}/@{XDG_GPG_DIR}/dirmngr.conf r, - owner @{MOUNTS}/{,/*}/@{XDG_GPG_DIR}/dirmngr_ldapservers.conf r, + owner @{MOUNTS}/{,/*}/@{XDG_GPG_DIR}/common.conf r, owner @{MOUNTS}/{,/*}/@{XDG_GPG_DIR}/crls.d/ rw, owner @{MOUNTS}/{,/*}/@{XDG_GPG_DIR}/crls.d/DIR.txt rw, + owner @{MOUNTS}/{,/*}/@{XDG_GPG_DIR}/dirmngr_ldapservers.conf r, + owner @{MOUNTS}/{,/*}/@{XDG_GPG_DIR}/dirmngr.conf r, owner @{run}/user/@{uid}/gnupg/ rw, owner @{run}/user/@{uid}/gnupg/S.dirmngr rw, diff --git a/apparmor.d/groups/gpg/gpg b/apparmor.d/groups/gpg/gpg index 247c6e4ac6..eecacef514 100644 --- a/apparmor.d/groups/gpg/gpg +++ b/apparmor.d/groups/gpg/gpg @@ -8,7 +8,7 @@ abi , include @{exec_path} = @{bin}/gpg{,2} -profile gpg @{exec_path} { +profile gpg @{exec_path} flags=(attach_disconnected) { include include include @@ -27,17 +27,20 @@ profile gpg @{exec_path} { @{bin}/gpgconf rPx, @{bin}/gpgsm rPx, @{lib}/{,gnupg/}scdaemon rPx, + @{lib}/{,gnupg/}keyboxd rPx, /usr/share/terminfo/** r, + /usr/share/keyrings/** rw, #aa:only apt + /usr/share/pacman/keyrings/** r, #aa:only pacman /etc/inputrc r, #aa:only pacman - /etc/pacman.d/gnupg/gpg.conf r, - /etc/pacman.d/gnupg/pubring.gpg r, - /etc/pacman.d/gnupg/trustdb.gpg r, + /etc/pacman.d/gnupg/ rw, + /etc/pacman.d/gnupg/** rwkl -> /etc/pacman.d/gnupg/**, #aa:only apt + /etc/apt/trusted.gpg.d/{,*} r, owner /etc/apt/keyrings/ rw, owner /etc/apt/keyrings/** rwkl -> /etc/apt/keyrings/**, @@ -66,14 +69,27 @@ profile gpg @{exec_path} { owner @{tmp}/ostree-gpg-@{rand6}/ r, owner @{tmp}/ostree-gpg-@{rand6}/** rwkl -> /tmp/ostree-gpg-@{rand6}/**, - owner /tmp/@{int}@{int} rw, + #aa:only ubuntu + /tmp/ubuntu-release-upgrader-@{rand8}/*.tar.gz rw, + /tmp/ubuntu-release-upgrader-@{rand8}/*.tar.gz.gpg rw, + + owner @{tmp}/@{int}@{int} rw, + owner @{tmp}/.git_vtag_tmp@{rand6} rw, owner @{run}/user/@{uid}/gnupg/d.*/ rw, + owner @{run}/user/@{uid}/gnupg/d.*/S.gpg-agent rw, + owner @{run}/user/@{uid}/gnupg/S.gpg-agent rw, + owner @{run}/user/@{uid}/gnupg/S.keyboxd rw, owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/task/@{tid}/comm rw, owner @{PROC}/@{pid}/task/@{tid}/stat rw, + #aa:only test + /tmp/*-test@{word8}/{,**} rwlk, + /tmp/*tests@{word8}/{,**} rwlk, + /tmp/gpg.*/{,**} rwlk, + include if exists } diff --git a/apparmor.d/groups/gpg/gpg-agent b/apparmor.d/groups/gpg/gpg-agent index 708ccc5f3c..70f3acef2e 100644 --- a/apparmor.d/groups/gpg/gpg-agent +++ b/apparmor.d/groups/gpg/gpg-agent @@ -49,9 +49,11 @@ profile gpg-agent @{exec_path} { owner @{run}/user/@{uid}/gnupg/*.conf r, owner @{run}/user/@{uid}/gnupg/d.@{rand}/ rw, owner @{run}/user/@{uid}/gnupg/d.@{rand}/S.gpg-agent{,.ssh,.browser,.extra} rw, + owner @{run}/user/@{uid}/gnupg/d.@{rand}/S.scdaemon rw, owner @{run}/user/@{uid}/gnupg/private-keys-v1.d/ rw, owner @{run}/user/@{uid}/gnupg/private-keys-v1.d/@{hex}.key{,.tmp} rw, owner @{run}/user/@{uid}/gnupg/S.gpg-agent{,.ssh,.browser,.extra} rw, + owner @{run}/user/@{uid}/gnupg/S.scdaemon rw, owner @{run}/user/@{uid}/gnupg/sshcontrol r, owner @{tmp}/**/{.,}gnupg/ rw, @@ -61,6 +63,10 @@ profile gpg-agent @{exec_path} { owner @{tmp}/**/{.,}gnupg/{,d.@{rand}/}S.gpg-agent{,.ssh,.browser,.extra} rw, owner @{tmp}/**/{.,}gnupg/sshcontrol r, + owner /tmp/ostree-gpg-@{rand6}/{,*/}private-keys-v1.d/ rw, + owner /tmp/ostree-gpg-@{rand6}/{,*/}private-keys-v1.d/@{hex}.key rw, + owner /tmp/ostree-gpg-@{rand6}/{,*/}S.gpg-agent{,.ssh,.browser,.extra} rw, + #aa:only pacman owner /etc/pacman.d/gnupg/ rw, owner /etc/pacman.d/gnupg/*.conf r, @@ -93,7 +99,7 @@ profile gpg-agent @{exec_path} { deny @{bin}/.gnupg/ w, # file inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/gpg/gpg-connect-agent b/apparmor.d/groups/gpg/gpg-connect-agent index ebea13b56e..29773f27dc 100644 --- a/apparmor.d/groups/gpg/gpg-connect-agent +++ b/apparmor.d/groups/gpg/gpg-connect-agent @@ -20,6 +20,7 @@ profile gpg-connect-agent @{exec_path} { owner @{run}/user/@{uid}/gnupg/ w, owner @{run}/user/@{uid}/gnupg/d.*/ rw, + owner @{run}/user/@{uid}/gnupg/d.*/S.gpg-agent rw, owner @{run}/user/@{uid}/gnupg/S.dirmngr rw, owner @{run}/user/@{uid}/gnupg/S.gpg-agent rw, diff --git a/apparmor.d/groups/gpg/gpgconf b/apparmor.d/groups/gpg/gpgconf index d7f8cb353d..23cd07845a 100644 --- a/apparmor.d/groups/gpg/gpgconf +++ b/apparmor.d/groups/gpg/gpgconf @@ -24,7 +24,7 @@ profile gpgconf @{exec_path} { @{bin}/gpgsm rPx, @{bin}/pinentry{,-*} rPx, @{bin}/scdaemon rPx, - @{lib}/{,gnupg/}keyboxd rPUx, + @{lib}/{,gnupg/}keyboxd rPx, @{lib}/{,gnupg/}scdaemon rPx, @{lib}/{,gnupg/}tpm2daemon rPUx, diff --git a/apparmor.d/groups/gpg/gpgsm b/apparmor.d/groups/gpg/gpgsm index bfa71cf534..2ef1a9d4a0 100644 --- a/apparmor.d/groups/gpg/gpgsm +++ b/apparmor.d/groups/gpg/gpgsm @@ -23,11 +23,11 @@ profile gpgsm @{exec_path} { /etc/gcrypt/hwf.deny r, - deny /usr/bin/.gnupg/ w, + owner /var/lib/*/.gnupg/** rwkl -> /var/lib/*/.gnupg/**, owner @{HOME}/@{XDG_GPG_DIR}/** rwkl -> @{HOME}/@{XDG_GPG_DIR}/**, - owner /var/lib/*/.gnupg/** rwkl -> /var/lib/*/.gnupg/**, + deny @{bin}/.gnupg/ w, include if exists } diff --git a/apparmor.d/groups/gpg/keyboxd b/apparmor.d/groups/gpg/keyboxd index 51ec8b134f..3eb23ee782 100644 --- a/apparmor.d/groups/gpg/keyboxd +++ b/apparmor.d/groups/gpg/keyboxd @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{lib}/gnupg/keyboxd +@{exec_path} = @{lib}/{,gnupg/}keyboxd profile keyboxd @{exec_path} { include include @@ -18,6 +18,8 @@ profile keyboxd @{exec_path} { owner @{HOME}/@{XDG_GPG_DIR}/public-keys.d/ rw, owner @{HOME}/@{XDG_GPG_DIR}/public-keys.d/* rwlk, + owner @{run}/user/@{uid}/gnupg/S.keyboxd rw, + owner @{PROC}/@{pid}/fd/ r, include if exists diff --git a/apparmor.d/groups/gpg/scdaemon b/apparmor.d/groups/gpg/scdaemon index 5d2cafd950..5cb9cd8286 100644 --- a/apparmor.d/groups/gpg/scdaemon +++ b/apparmor.d/groups/gpg/scdaemon @@ -24,8 +24,10 @@ profile scdaemon @{exec_path} { owner /etc/pacman.d/gnupg/scdaemon.conf r, owner /etc/pacman.d/gnupg/S.scdaemon rw, + / r, + owner @{HOME}/@{XDG_GPG_DIR}/scdaemon.conf r, - owner @{HOME}/@{XDG_GPG_DIR}common.conf r, + owner @{HOME}/@{XDG_GPG_DIR}/common.conf r, owner @{HOME}/@{XDG_GPG_DIR}/reader_@{int}.status rw, owner @{run}/user/@{uid}/gnupg/S.scdaemon rw, @@ -35,9 +37,10 @@ profile scdaemon @{exec_path} { owner /var/tmp/zypp.*/zypp-general-kr*/S.scdaemon w, owner /var/tmp/zypp.*/zypp-trusted-*/S.scdaemon w, - @{PROC}/@{pid}/task/@{tid}/comm rw, + # comm=pipe-connection ???? + @{sys}/devices/**/uevent r, - @{sys}/devices/@{pci}/bConfigurationValue r, + @{PROC}/@{pid}/task/@{tid}/comm rw, include if exists } diff --git a/apparmor.d/groups/grub/grub-check-signatures b/apparmor.d/groups/grub/grub-check-signatures index d33b332652..7a4d38e220 100644 --- a/apparmor.d/groups/grub/grub-check-signatures +++ b/apparmor.d/groups/grub/grub-check-signatures @@ -9,20 +9,35 @@ include @{exec_path} = /usr/share/grub/grub-check-signatures profile grub-check-signatures @{exec_path} { include - include + include @{exec_path} mr, - @{sh_path} rix, - @{bin}/{m,g,}awk rix, - @{bin}//mktemp rix, - @{bin}//od rix, - - /usr/share/debconf/frontend rPx, - - /usr/share/debconf/confmodule r, - - owner @{tmp}/tmp.@{rand10}/ rw, + @{bin}/{,e}grep ix, + @{bin}/{m,g,}awk ix, + @{bin}/cp ix, + @{bin}/dpkg Px -> child-dpkg, + @{bin}/find ix, + @{bin}/gzip ix, + @{bin}/ls ix, + @{bin}/mktemp ix, + @{bin}/mokutil ix, + @{bin}/od ix, + @{bin}/openssl ix, + @{bin}/rm ix, + @{bin}/sbattach ix, + @{bin}/sbverify ix, + @{bin}/sed ix, + @{bin}/sort ix, + @{bin}/uname ix, + @{bin}/wc ix, + @{bin}/zcat ix, + + / r, + @{efi}/ r, + + @{tmp}/tmp.@{rand10} rw, + @{tmp}/tmp.@{rand10}/{,**} rw, @{sys}/firmware/efi/efivars/SecureBoot-@{uuid} r, diff --git a/apparmor.d/groups/grub/grub-editenv b/apparmor.d/groups/grub/grub-editenv index 6bdc7362a0..8996d165d6 100644 --- a/apparmor.d/groups/grub/grub-editenv +++ b/apparmor.d/groups/grub/grub-editenv @@ -10,10 +10,19 @@ include profile grub-editenv @{exec_path} { include include + include + + capability sys_admin, @{exec_path} mr, - /boot/grub/grubenv rw, + @{efi}/grub/grubenv rw, + @{efi}/grub/grubenv.new rw, + + @{PROC}/@{pid}/mountinfo r, + @{PROC}/devices r, + + /dev/mapper/control rw, include if exists } diff --git a/apparmor.d/groups/grub/grub-install b/apparmor.d/groups/grub/grub-install index e52e96b8a3..e3ed753345 100644 --- a/apparmor.d/groups/grub/grub-install +++ b/apparmor.d/groups/grub/grub-install @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/grub-install +@{exec_path} = @{sbin}/grub-install profile grub-install @{exec_path} flags=(complain) { include include @@ -19,9 +19,9 @@ profile grub-install @{exec_path} flags=(complain) { @{exec_path} mr, @{sh_path} rix, - @{bin}/efibootmgr rix, + @{sbin}/efibootmgr rix, @{bin}/kmod rPx, - @{bin}/lsb_release rPx -> lsb_release, + @{bin}/lsb_release rPx, @{bin}/udevadm rPx, /usr/share/grub/{,**} r, @@ -30,12 +30,12 @@ profile grub-install @{exec_path} flags=(complain) { /etc/default/grub.d/{,**} r, /etc/default/grub r, - /boot/efi/ r, - /boot/EFI/*/grubx*.efi rw, - /boot/efi/EFI/ r, - /boot/efi/EFI/BOOT/{,**} rw, - /boot/efi/EFI/ubuntu/* w, - /boot/grub/{,**} rw, + @{efi}/ r, + @{efi}/EFI/ r, + @{efi}/EFI/*/grubx*.efi rw, + @{efi}/EFI/BOOT/{,**} rw, + @{efi}/EFI/ubuntu/* w, + @{efi}/grub/{,**} rw, @{sys}/devices/**/hid r, @{sys}/devices/**/path r, @@ -44,7 +44,7 @@ profile grub-install @{exec_path} flags=(complain) { @{sys}/firmware/efi/efivars/ r, @{sys}/firmware/efi/efivars/Boot@{hex}-@{uuid} rw, @{sys}/firmware/efi/efivars/BootCurrent-@{uuid} r, - @{sys}/firmware/efi/efivars/BootOrder-@{uuid} r, + @{sys}/firmware/efi/efivars/BootOrder-@{uuid} rw, @{sys}/firmware/efi/efivars/Timeout-@{uuid} r, @{sys}/firmware/efi/fw_platform_size r, @{sys}/firmware/efi/w_platform_size r, diff --git a/apparmor.d/groups/grub/grub-macbless b/apparmor.d/groups/grub/grub-macbless index c2571ea73a..17e71a25c6 100644 --- a/apparmor.d/groups/grub/grub-macbless +++ b/apparmor.d/groups/grub/grub-macbless @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/grub-macbless +@{exec_path} = @{sbin}/grub-macbless profile grub-macbless @{exec_path} { include include diff --git a/apparmor.d/groups/grub/grub-mkconfig b/apparmor.d/groups/grub/grub-mkconfig index 1ff23f1fe0..c722ef22b2 100644 --- a/apparmor.d/groups/grub/grub-mkconfig +++ b/apparmor.d/groups/grub/grub-mkconfig @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/grub-mkconfig +@{exec_path} = @{sbin}/grub-mkconfig @{sbin}/grub2-mkconfig profile grub-mkconfig @{exec_path} flags=(attach_disconnected) { include include @@ -21,25 +21,25 @@ profile grub-mkconfig @{exec_path} flags=(attach_disconnected) { @{bin}/{e,f,}grep rix, @{bin}/{m,g,}awk rix, @{bin}/basename rix, - @{bin}/btrfs rPx, + @{sbin}/btrfs rPx, @{bin}/cat rix, @{bin}/chmod rix, @{bin}/cut rix, @{bin}/date rix, @{bin}/dirname rix, - @{bin}/dmsetup rPUx, + @{sbin}/dmsetup rPx, @{bin}/dpkg rPx, @{bin}/find rix, @{bin}/findmnt rPx, @{bin}/gettext rix, @{bin}/grub-editenv rPx, @{bin}/grub-mkrelpath rPx, - @{bin}/grub-probe rPx, + @{sbin}/grub-probe rPx, @{bin}/grub-script-check rPx, @{bin}/head rix, @{bin}/id rPx, @{bin}/ls rix, - @{bin}/lsb_release rPx -> lsb_release, + @{bin}/lsb_release rPx, @{bin}/mktemp rix, @{bin}/mount rPx, @{bin}/mountpoint rix, @@ -56,7 +56,7 @@ profile grub-mkconfig @{exec_path} flags=(attach_disconnected) { @{bin}/tr rix, @{bin}/umount rPx, @{bin}/uname rix, - @{bin}/which{.debianutils,} rix, + @{bin}/which{,.debianutils} rix, @{bin}/zfs rPx, @{bin}/zpool rPx, /etc/grub.d/{,**} rix, @@ -81,8 +81,8 @@ profile grub-mkconfig @{exec_path} flags=(attach_disconnected) { /.zfs/snapshot/*/etc/fstab r, /.zfs/snapshot/*/etc/machine-id r, - /boot/{,**} r, - /boot/grub/{,**} rw, + @{efi}/{,**} r, + @{efi}/grub/{,**} rw, /tmp/grub-*.@{rand10}/{,**} rw, @@ -91,7 +91,7 @@ profile grub-mkconfig @{exec_path} flags=(attach_disconnected) { @{PROC}/@{pids}/mountinfo r, @{PROC}/@{pids}/mounts r, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/grub/grub-mkdevicemap b/apparmor.d/groups/grub/grub-mkdevicemap index 533f9780b9..d3ba847ede 100644 --- a/apparmor.d/groups/grub/grub-mkdevicemap +++ b/apparmor.d/groups/grub/grub-mkdevicemap @@ -6,13 +6,22 @@ abi , include -@{exec_path} = @{bin}/grub-mkdevicemap +@{exec_path} = @{sbin}/grub-mkdevicemap profile grub-mkdevicemap @{exec_path} { include include + include + + capability sys_admin, @{exec_path} mr, + @{efi}/grub/device.map rw, + + @{PROC}/devices r, + + /dev/mapper/control rw, + include if exists } diff --git a/apparmor.d/groups/grub/grub-mkrelpath b/apparmor.d/groups/grub/grub-mkrelpath index a60a6aaba7..d4508b4c5a 100644 --- a/apparmor.d/groups/grub/grub-mkrelpath +++ b/apparmor.d/groups/grub/grub-mkrelpath @@ -21,12 +21,12 @@ profile grub-mkrelpath @{exec_path} { / r, /usr/share/grub/* r, - /boot/ r, - /boot/grub/themes/{,**} r, + @{efi}/ r, + @{efi}/grub/themes/{,**} r, /tmp/grub-btrfs.*/@snapshots/@{int}/snapshot/boot/ r, /tmp/grub-btrfs.*/@/.snapshots/@{int}/snapshot/boot/ r, - /tmp/grub-btrfs.*/@_backup_@{int}/boot/ r, + /tmp/grub-btrfs.*/@_backup_*/boot/ r, /tmp/grub-btrfs.*/ r, @{PROC}/@{pids}/mountinfo r, diff --git a/apparmor.d/groups/grub/grub-multi-install b/apparmor.d/groups/grub/grub-multi-install index 94c4c7e2be..68c4b07791 100644 --- a/apparmor.d/groups/grub/grub-multi-install +++ b/apparmor.d/groups/grub/grub-multi-install @@ -13,23 +13,28 @@ profile grub-multi-install @{exec_path} { @{exec_path} mr, - @{bin}/grub-install rPx, + @{sbin}/grub-install rPx, @{sh_path} rix, @{bin}/{,e}grep rix, @{bin}/cat rix, @{bin}/cut rix, @{bin}/dpkg-query rpx, + @{bin}/expr rix, + @{bin}/grub-mkrelpath rPx, @{bin}/readlink rix, @{bin}/sed rix, @{bin}/sort rix, @{bin}/touch rix, @{bin}/udevadm rPx, - /usr/share/debconf/frontend rPx, + @{bin}/uname rix, + @{bin}/which{,.debianutils} rix, - /usr/lib/terminfo/x/xterm-256color r, + /usr/share/debconf/frontend rix, + + @{lib}/terminfo/x/xterm-256color r, /usr/share/debconf/confmodule r, - /boot/grub/grub.cfg rw, + @{efi}/grub/grub.cfg rw, owner @{PROC}/@{pid}/mounts r, diff --git a/apparmor.d/groups/grub/grub-probe b/apparmor.d/groups/grub/grub-probe index 3c22c2d27c..dd6832c3b5 100644 --- a/apparmor.d/groups/grub/grub-probe +++ b/apparmor.d/groups/grub/grub-probe @@ -7,8 +7,8 @@ abi , include -@{exec_path} = @{bin}/grub-probe -profile grub-probe @{exec_path} { +@{exec_path} = @{sbin}/grub-probe +profile grub-probe @{exec_path} flags=(attach_disconnected) { include include include @@ -16,19 +16,22 @@ profile grub-probe @{exec_path} { capability dac_read_search, capability sys_admin, + mqueue (read getattr) type=posix /, + mqueue (read getattr) type=posix /att/grub-probe/, + @{exec_path} mr, /{usr/,}{local/,}{s,}bin/zpool rPx, - @{bin}/lsb_release rPx -> lsb_release, - @{bin}/lvm rPx, + @{bin}/lsb_release rPx, + @{sbin}/lvm rPx, @{bin}/udevadm rPx, /usr/share/grub/* r, / r, - /boot/ r, - /boot/grub/ r, - /boot/grub/themes/{,**} r, + @{efi}/ r, + @{efi}/grub/ r, + @{efi}/grub/themes/{,**} r, @{PROC}/@{pids}/mountinfo r, @{PROC}/devices r, diff --git a/apparmor.d/groups/grub/grub-reboot b/apparmor.d/groups/grub/grub-reboot index 7d94a22afa..310b416bf1 100644 --- a/apparmor.d/groups/grub/grub-reboot +++ b/apparmor.d/groups/grub/grub-reboot @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/grub-reboot +@{exec_path} = @{sbin}/grub-reboot profile grub-reboot @{exec_path} { include include diff --git a/apparmor.d/groups/grub/grub-script-check b/apparmor.d/groups/grub/grub-script-check index 93b344cf82..9961a778eb 100644 --- a/apparmor.d/groups/grub/grub-script-check +++ b/apparmor.d/groups/grub/grub-script-check @@ -13,7 +13,7 @@ profile grub-script-check @{exec_path} { @{exec_path} mr, - /boot/grub/grub* rw, + @{efi}/grub/grub* rw, include if exists } diff --git a/apparmor.d/groups/grub/grub-set-default b/apparmor.d/groups/grub/grub-set-default index 11c78024b2..9e3c964642 100644 --- a/apparmor.d/groups/grub/grub-set-default +++ b/apparmor.d/groups/grub/grub-set-default @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/grub-set-default +@{exec_path} = @{sbin}/grub-set-default profile grub-set-default @{exec_path} { include include diff --git a/apparmor.d/groups/grub/grub-sort-version b/apparmor.d/groups/grub/grub-sort-version index 5e65fe8359..6ece8a60bb 100644 --- a/apparmor.d/groups/grub/grub-sort-version +++ b/apparmor.d/groups/grub/grub-sort-version @@ -9,7 +9,7 @@ include @{exec_path} = @{lib}/grub/grub-sort-version profile grub-sort-version @{exec_path} { include - include + include include include include diff --git a/apparmor.d/groups/grub/update-grub b/apparmor.d/groups/grub/update-grub index 03df052953..e79f310c37 100644 --- a/apparmor.d/groups/grub/update-grub +++ b/apparmor.d/groups/grub/update-grub @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/update-grub{2,} +@{exec_path} = @{sbin}/update-grub profile update-grub @{exec_path} { include include @@ -14,10 +14,11 @@ profile update-grub @{exec_path} { capability dac_read_search, @{exec_path} mr, - @{sh_path} rix, - @{bin}/grub-mkconfig rPx, - /dev/tty@{int} rw, + @{sh_path} rix, + @{sbin}/grub-mkconfig rPx, + + /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/gvfs/gvfs-afc-volume-monitor b/apparmor.d/groups/gvfs/gvfs-afc-volume-monitor index 7f50d8b45c..322549b28d 100644 --- a/apparmor.d/groups/gvfs/gvfs-afc-volume-monitor +++ b/apparmor.d/groups/gvfs/gvfs-afc-volume-monitor @@ -17,7 +17,7 @@ profile gvfs-afc-volume-monitor @{exec_path} { dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, diff --git a/apparmor.d/groups/gvfs/gvfs-goa-volume-monitor b/apparmor.d/groups/gvfs/gvfs-goa-volume-monitor index 3f2fb01380..a162e58075 100644 --- a/apparmor.d/groups/gvfs/gvfs-goa-volume-monitor +++ b/apparmor.d/groups/gvfs/gvfs-goa-volume-monitor @@ -14,15 +14,12 @@ profile gvfs-goa-volume-monitor @{exec_path} { #aa:dbus own bus=session name=org.gtk.vfs.GoaVolumeMonitor interface+=org.gtk.Private.RemoteVolumeMonitor path=/org/gtk/Private/RemoteVolumeMonitor + #aa:dbus talk bus=session name=org.gnome.OnlineAccounts label=goa-daemon + dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), - - dbus send bus=session path=/org/gnome/OnlineAccounts - interface=org.freedesktop.DBus.ObjectManager - member=GetManagedObjects - peer=(name=:*, label=goa-daemon), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, diff --git a/apparmor.d/groups/gvfs/gvfs-gphoto2-volume-monitor b/apparmor.d/groups/gvfs/gvfs-gphoto2-volume-monitor index dd03254b11..6e61cf85ca 100644 --- a/apparmor.d/groups/gvfs/gvfs-gphoto2-volume-monitor +++ b/apparmor.d/groups/gvfs/gvfs-gphoto2-volume-monitor @@ -21,13 +21,16 @@ profile gvfs-gphoto2-volume-monitor @{exec_path} { dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, /etc/fstab r, + / r, + @{sys}/class/scsi_generic/ r, + @{sys}/devices/**/uevent r, owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/mounts r, diff --git a/apparmor.d/groups/gvfs/gvfs-mtp-volume-monitor b/apparmor.d/groups/gvfs/gvfs-mtp-volume-monitor index 6fbbc6092c..e0703c3e01 100644 --- a/apparmor.d/groups/gvfs/gvfs-mtp-volume-monitor +++ b/apparmor.d/groups/gvfs/gvfs-mtp-volume-monitor @@ -11,6 +11,7 @@ include profile gvfs-mtp-volume-monitor @{exec_path} { include include + include include network netlink raw, @@ -20,10 +21,14 @@ profile gvfs-mtp-volume-monitor @{exec_path} { dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, + / r, + + @{sys}/devices/**/uevent r, + include if exists } diff --git a/apparmor.d/groups/gvfs/gvfs-udisks2-volume-monitor b/apparmor.d/groups/gvfs/gvfs-udisks2-volume-monitor index 4ed214b716..c2a1b83a4b 100644 --- a/apparmor.d/groups/gvfs/gvfs-udisks2-volume-monitor +++ b/apparmor.d/groups/gvfs/gvfs-udisks2-volume-monitor @@ -12,12 +12,14 @@ profile gvfs-udisks2-volume-monitor @{exec_path} flags=(attach_disconnected) { include include include - include + include include include include - include + include + include include + include capability sys_ptrace, @@ -35,7 +37,7 @@ profile gvfs-udisks2-volume-monitor @{exec_path} flags=(attach_disconnected) { dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, @@ -54,8 +56,6 @@ profile gvfs-udisks2-volume-monitor @{exec_path} flags=(attach_disconnected) { owner @{MOUNTS}/autorun.inf r, - owner @{desktop_config_dirs}/dconf/user r, - @{run}/mount/utab r, @{PROC}/ r, diff --git a/apparmor.d/groups/gvfs/gvfsd b/apparmor.d/groups/gvfs/gvfsd index c5c4dc3c1f..ba904522ec 100644 --- a/apparmor.d/groups/gvfs/gvfsd +++ b/apparmor.d/groups/gvfs/gvfsd @@ -14,29 +14,33 @@ profile gvfsd @{exec_path} { include signal receive set=usr1 peer=pacman, + signal receive set=usr1 peer=pacman//pkill, #aa:dbus own bus=session name=org.gtk.vfs.Daemon #aa:dbus own bus=session name=org.gtk.vfs.MountTracker path=/org/gtk/vfs/mounttracker + # The server side of abstractions/bus/session/org.gtk.vfs.Mountable dbus send bus=session path=/org/gtk/vfs/mountable interface=org.gtk.vfs.Mountable member=Mount - peer=(name=:*, label=gvfsd-*), + peer=(name=@{busname}, label=gvfsd-*), + # The server side of abstractions/bus/session/org.gtk.vfs.Spawner dbus receive bus=session path=/org/gtk/gvfs/exec_spaw/@{int} interface=org.gtk.vfs.Spawner member=Spawned - peer=(name=:*, label=gvfsd-*), + peer=(name=@{busname}, label=gvfsd-*), dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mr, @{sh_path} rix, @{lib}/{,gvfs/}gvfsd-* rpx, + @{bin}/pkexec rCx -> pkexec, /usr/share/gvfs/{,**} r, @@ -45,6 +49,17 @@ profile gvfsd @{exec_path} { owner @{PROC}/@{pid}/fd/ r, + profile pkexec { + include + include + + ptrace read peer=gvfsd, + + @{lib}/{,gvfs/}gvfsd-admin rPx, + + include if exists + } + include if exists } diff --git a/apparmor.d/groups/gvfs/gvfsd-admin b/apparmor.d/groups/gvfs/gvfsd-admin index 7a1584d487..38dfb39e09 100644 --- a/apparmor.d/groups/gvfs/gvfsd-admin +++ b/apparmor.d/groups/gvfs/gvfsd-admin @@ -10,9 +10,30 @@ include @{exec_path} = @{lib}/{,gvfs/}gvfsd-admin profile gvfsd-admin @{exec_path} { include + include + include + include + include + include + + capability chown, + capability dac_override, + capability dac_read_search, + capability fowner, + capability setuid, @{exec_path} mr, + #aa:lint ignore=too-wide + # Full access to system's data, but no write access to sensitive system directories + / r, + /*/ r, + /*/** rw, + deny @{sys}/** w, + deny @{PROC}/** w, + deny @{efi}/** w, + deny /dev/** w, + include if exists } diff --git a/apparmor.d/groups/gvfs/gvfsd-afc b/apparmor.d/groups/gvfs/gvfsd-afc index 68d4b689ec..18d5d491fd 100644 --- a/apparmor.d/groups/gvfs/gvfsd-afc +++ b/apparmor.d/groups/gvfs/gvfsd-afc @@ -10,6 +10,8 @@ include @{exec_path} = @{lib}/{,gvfs/}gvfsd-afc profile gvfsd-afc @{exec_path} { include + include + include @{exec_path} mr, diff --git a/apparmor.d/groups/gvfs/gvfsd-afp b/apparmor.d/groups/gvfs/gvfsd-afp index eeaaec0590..b844778a41 100644 --- a/apparmor.d/groups/gvfs/gvfsd-afp +++ b/apparmor.d/groups/gvfs/gvfsd-afp @@ -10,6 +10,8 @@ include @{exec_path} = @{lib}/{,gvfs/}gvfsd-afp profile gvfsd-afp @{exec_path} { include + include + include @{exec_path} mr, diff --git a/apparmor.d/groups/gvfs/gvfsd-afp-browse b/apparmor.d/groups/gvfs/gvfsd-afp-browse index 48680f12f1..929b503173 100644 --- a/apparmor.d/groups/gvfs/gvfsd-afp-browse +++ b/apparmor.d/groups/gvfs/gvfsd-afp-browse @@ -10,6 +10,8 @@ include @{exec_path} = @{lib}/{,gvfs/}gvfsd-afp-browse profile gvfsd-afp-browse @{exec_path} { include + include + include @{exec_path} mr, diff --git a/apparmor.d/groups/gvfs/gvfsd-archive b/apparmor.d/groups/gvfs/gvfsd-archive index 918841320e..a1f0e8c172 100644 --- a/apparmor.d/groups/gvfs/gvfsd-archive +++ b/apparmor.d/groups/gvfs/gvfsd-archive @@ -10,7 +10,8 @@ include @{exec_path} = @{lib}/{,gvfs/}gvfsd-archive profile gvfsd-archive @{exec_path} { include - include + include + include include @{exec_path} mr, diff --git a/apparmor.d/groups/gvfs/gvfsd-burn b/apparmor.d/groups/gvfs/gvfsd-burn index b70fa71101..25c6baf9fb 100644 --- a/apparmor.d/groups/gvfs/gvfsd-burn +++ b/apparmor.d/groups/gvfs/gvfsd-burn @@ -10,6 +10,8 @@ include @{exec_path} = @{lib}/{,gvfs/}gvfsd-burn profile gvfsd-burn @{exec_path} { include + include + include @{exec_path} mr, diff --git a/apparmor.d/groups/gvfs/gvfsd-cdda b/apparmor.d/groups/gvfs/gvfsd-cdda index 0648f5dc04..63050efddc 100644 --- a/apparmor.d/groups/gvfs/gvfsd-cdda +++ b/apparmor.d/groups/gvfs/gvfsd-cdda @@ -10,6 +10,8 @@ include @{exec_path} = @{lib}/{,gvfs/}gvfsd-cdda profile gvfsd-cdda @{exec_path} { include + include + include @{exec_path} mr, diff --git a/apparmor.d/groups/gvfs/gvfsd-computer b/apparmor.d/groups/gvfs/gvfsd-computer index 0a520d1388..971df9e3df 100644 --- a/apparmor.d/groups/gvfs/gvfsd-computer +++ b/apparmor.d/groups/gvfs/gvfsd-computer @@ -11,8 +11,10 @@ include profile gvfsd-computer @{exec_path} { include include + include #aa:dbus own bus=session name=org.gtk.vfs.mountpoint_@{int} + #aa:dbus talk bus=session name=org.gtk.Private.RemoteVolumeMonitor label=gvfs-*-volume-monitor @{exec_path} mr, diff --git a/apparmor.d/groups/gvfs/gvfsd-dav b/apparmor.d/groups/gvfs/gvfsd-dav index 77e1a2f6f6..2f6740bf07 100644 --- a/apparmor.d/groups/gvfs/gvfsd-dav +++ b/apparmor.d/groups/gvfs/gvfsd-dav @@ -8,15 +8,21 @@ abi , include @{exec_path} = @{lib}/{,gvfs/}gvfsd-dav -profile gvfsd-dav @{exec_path} { +profile gvfsd-dav @{exec_path} flags=(attach_disconnected) { include + include + include include - include + include + include + include include + include include include include include + include network inet stream, network inet6 stream, @@ -24,6 +30,8 @@ profile gvfsd-dav @{exec_path} { network inet6 dgram, network netlink raw, + unix (send receive) type=stream peer=(label=nautilus), + @{exec_path} mr, owner @{run}/user/@{uid}/gvfsd/ rw, diff --git a/apparmor.d/groups/gvfs/gvfsd-dnssd b/apparmor.d/groups/gvfs/gvfsd-dnssd index fd9b5a22d0..0cbf108fd9 100644 --- a/apparmor.d/groups/gvfs/gvfsd-dnssd +++ b/apparmor.d/groups/gvfs/gvfsd-dnssd @@ -10,27 +10,12 @@ include @{exec_path} = @{lib}/{,gvfs/}gvfsd-dnssd profile gvfsd-dnssd @{exec_path} { include + include include include - include + include #aa:dbus own bus=session name=org.gtk.vfs.mountpoint_dnssd - #aa:dbus talk bus=session name=org.gtk.vfs.MountTracker label=gvfsd - - dbus receive bus=session path=/org/gtk/vfs/Daemon - interface=org.gtk.vfs.Daemon - member=GetConnection - peer=(name=:*, label=gvfsd-network), - - dbus receive bus=session path=/org/gtk/vfs/mountable - interface=org.gtk.vfs.Mountable - member=Mount - peer=(name=:*, label=gvfsd), - - dbus send bus=session path=/org/gtk/gvfs/exec_spaw/@{int} - interface=org.gtk.vfs.Spawner - member=Spawned - peer=(name=:*, label=gvfsd), @{exec_path} mr, diff --git a/apparmor.d/groups/gvfs/gvfsd-ftp b/apparmor.d/groups/gvfs/gvfsd-ftp index 5b7c833a5e..77afc6e751 100644 --- a/apparmor.d/groups/gvfs/gvfsd-ftp +++ b/apparmor.d/groups/gvfs/gvfsd-ftp @@ -10,6 +10,8 @@ include @{exec_path} = @{lib}/{,gvfs/}gvfsd-ftp profile gvfsd-ftp @{exec_path} { include + include + include include include include diff --git a/apparmor.d/groups/gvfs/gvfsd-fuse b/apparmor.d/groups/gvfs/gvfsd-fuse index bb19d54549..6aed209e64 100644 --- a/apparmor.d/groups/gvfs/gvfsd-fuse +++ b/apparmor.d/groups/gvfs/gvfsd-fuse @@ -11,7 +11,7 @@ include profile gvfsd-fuse @{exec_path} { include include - include + include include capability sys_admin, @@ -20,20 +20,13 @@ profile gvfsd-fuse @{exec_path} { unix (send,receive) type=stream addr=none peer=(label=gvfsd-fuse//fusermount), - dbus send bus=session path=/org/gtk/vfs/mounttracker - interface=org.gtk.vfs.MountTracker - member=RegisterFuse - peer=(name=:*, label=gvfsd), - - dbus receive bus=session path=/ - interface=org.freedesktop.DBus.Introspectable - member=Introspect - peer=(name=:*, label=gnome-shell), - @{exec_path} mr, @{bin}/fusermount{,3} rCx -> fusermount, + owner @{run}/user/@{uid}/gvfsd-fuse/ rw, + owner @{run}/user/@{uid}/gvfsd/socket-@{rand8} w, + @{PROC}/sys/fs/pipe-max-size r, /dev/fuse rw, @@ -49,8 +42,7 @@ profile gvfsd-fuse @{exec_path} { unix (send,receive) type=stream addr=none peer=(label=gvfsd-fuse), - @{bin}/mount rix, - @{bin}/umount rix, + /etc/machine-id r, include if exists } diff --git a/apparmor.d/groups/gvfs/gvfsd-google b/apparmor.d/groups/gvfs/gvfsd-google index eb80f3a7a4..1709457dc1 100644 --- a/apparmor.d/groups/gvfs/gvfsd-google +++ b/apparmor.d/groups/gvfs/gvfsd-google @@ -10,6 +10,8 @@ include @{exec_path} = @{lib}/{,gvfs/}gvfsd-google profile gvfsd-google @{exec_path} { include + include + include @{exec_path} mr, diff --git a/apparmor.d/groups/gvfs/gvfsd-gphoto2 b/apparmor.d/groups/gvfs/gvfsd-gphoto2 index 688f03c27a..e82299f271 100644 --- a/apparmor.d/groups/gvfs/gvfsd-gphoto2 +++ b/apparmor.d/groups/gvfs/gvfsd-gphoto2 @@ -10,6 +10,8 @@ include @{exec_path} = @{lib}/{,gvfs/}gvfsd-gphoto2 profile gvfsd-gphoto2 @{exec_path} { include + include + include @{exec_path} mr, diff --git a/apparmor.d/groups/gvfs/gvfsd-http b/apparmor.d/groups/gvfs/gvfsd-http index 2fe0a1e2bc..af13058631 100644 --- a/apparmor.d/groups/gvfs/gvfsd-http +++ b/apparmor.d/groups/gvfs/gvfsd-http @@ -11,9 +11,13 @@ include profile gvfsd-http @{exec_path} { include include + include include - include + include + include + include include + include include include @@ -23,20 +27,10 @@ profile gvfsd-http @{exec_path} { network inet6 dgram, network netlink raw, - #aa:dbus own bus=session name=org.gtk.vfs.mountpoint_http + unix type=stream peer=(label=gnome-shell), + unix type=stream peer=(label=gnome-extension-gsconnect), - dbus receive bus=session path=/org/gtk/vfs/mountable - interface=org.gtk.vfs.Mountable - member=Mount - peer=(name=:*, label=gvfsd), - dbus send bus=session path=/org/gtk/gvfs/exec_spaw/@{int} - interface=org.gtk.vfs.Spawner - member=Spawned - peer=(name=:*, label=gvfsd), - dbus send bus=session path=/org/gtk/vfs/mounttracker - interface=org.gtk.vfs.MountTracker - member=RegisterMount - peer=(name=:*, label=gvfsd), + #aa:dbus own bus=session name=org.gtk.vfs.mountpoint_http @{exec_path} mr, diff --git a/apparmor.d/groups/gvfs/gvfsd-localtest b/apparmor.d/groups/gvfs/gvfsd-localtest index 5ffbabb40b..840be20129 100644 --- a/apparmor.d/groups/gvfs/gvfsd-localtest +++ b/apparmor.d/groups/gvfs/gvfsd-localtest @@ -10,6 +10,8 @@ include @{exec_path} = @{lib}/{,gvfs/}gvfsd-localtest profile gvfsd-localtest @{exec_path} { include + include + include @{exec_path} mr, diff --git a/apparmor.d/groups/gvfs/gvfsd-metadata b/apparmor.d/groups/gvfs/gvfsd-metadata index f6f3820bb2..3e585a504f 100644 --- a/apparmor.d/groups/gvfs/gvfsd-metadata +++ b/apparmor.d/groups/gvfs/gvfsd-metadata @@ -11,6 +11,7 @@ include profile gvfsd-metadata @{exec_path} { include include + include include network netlink raw, @@ -19,13 +20,10 @@ profile gvfsd-metadata @{exec_path} { #aa:dbus own bus=session name=org.gtk.vfs.Metadata path=/org/gtk/vfs/{m,M}etadata - dbus receive bus=session - interface=org.freedesktop.DBus.Introspectable - member=Introspect - peer=(name=:*, label=gnome-shell), - @{exec_path} mr, + / r, + owner @{gdm_share_dirs}/gvfs-metadata/{,*} rw, owner @{HOME}/.local/ w, diff --git a/apparmor.d/groups/gvfs/gvfsd-mtp b/apparmor.d/groups/gvfs/gvfsd-mtp index 3c747b8b3f..7bd7c4a3f2 100644 --- a/apparmor.d/groups/gvfs/gvfsd-mtp +++ b/apparmor.d/groups/gvfs/gvfsd-mtp @@ -10,22 +10,32 @@ include @{exec_path} = @{lib}/{,gvfs/}gvfsd-mtp profile gvfsd-mtp @{exec_path} { include + include include include include - include + include + include + include include include network netlink raw, + #aa:dbus own bus=session name=org.gtk.vfs.mountpoint_@{int} + @{exec_path} mr, - owner @{HOME}/{,**} rw, # FIXME: ? - owner @{MOUNTS}/{,**} rw, + / r, + + owner @{HOME}/ r, + owner @{HOME}/** rw, + owner @{MOUNTS}/** rw, owner @{run}/user/@{uid}/gvfsd/socket-@{rand8} rw, + @{sys}/devices/**/uevent r, + include if exists } diff --git a/apparmor.d/groups/gvfs/gvfsd-network b/apparmor.d/groups/gvfs/gvfsd-network index 87851fc168..a7f449c0dc 100644 --- a/apparmor.d/groups/gvfs/gvfsd-network +++ b/apparmor.d/groups/gvfs/gvfsd-network @@ -8,42 +8,17 @@ abi , include @{exec_path} = @{lib}/{,gvfs/}gvfsd-network -profile gvfsd-network @{exec_path} { +profile gvfsd-network @{exec_path} flags=(attach_disconnected) { include include + include include + include #aa:dbus own bus=session name=org.gtk.vfs.mountpoint_@{int} - dbus send bus=session path=/org/gtk/gvfs/exec_spaw/@{int} - interface=org.gtk.vfs.Spawner - member=Spawned - peer=(name=:*, label=gvfsd), - - dbus receive bus=session path=/org/gtk/vfs/mountable - interface=org.gtk.vfs.Mountable - member=Mount - peer=(name=:*, label=gvfsd), - - dbus send bus=session path=/org/gtk/vfs/mounttracker - interface=org.gtk.vfs.MountTracker - member={MountLocation,LookupMount,RegisterMount} - peer=(name=:*, label=gvfsd), - - dbus send bus=session path=/org/gtk/vfs/Daemon - interface=org.gtk.vfs.Daemon - member=GetConnection - peer=(name=:*, label=gvfsd-dnssd), - - dbus receive bus=session path=/org/gtk/vfs/Daemon - interface=org.gtk.vfs.Daemon - member=GetConnection - peer=(name=:*, label=gnome-control-center), - @{exec_path} mr, - /usr/share/glib-2.0/schemas/gschemas.compiled r, - owner @{run}/user/@{uid}/gvfsd/ rw, owner @{run}/user/@{uid}/gvfsd/socket-@{rand8} rw, diff --git a/apparmor.d/groups/gvfs/gvfsd-nfs b/apparmor.d/groups/gvfs/gvfsd-nfs index 575d9de39c..6fd0d740a2 100644 --- a/apparmor.d/groups/gvfs/gvfsd-nfs +++ b/apparmor.d/groups/gvfs/gvfsd-nfs @@ -10,6 +10,8 @@ include @{exec_path} = @{lib}/{,gvfs/}gvfsd-nfs profile gvfsd-nfs @{exec_path} { include + include + include include network inet stream, diff --git a/apparmor.d/groups/gvfs/gvfsd-recent b/apparmor.d/groups/gvfs/gvfsd-recent index 1ec5f2e60b..93bf6abd4e 100644 --- a/apparmor.d/groups/gvfs/gvfsd-recent +++ b/apparmor.d/groups/gvfs/gvfsd-recent @@ -8,31 +8,17 @@ abi , include @{exec_path} = @{lib}/{,gvfs/}gvfsd-recent -profile gvfsd-recent @{exec_path} { +profile gvfsd-recent @{exec_path} flags=(attach_disconnected) { include include - include - include include - include + include + include include include #aa:dbus own bus=session name=org.gtk.vfs.mountpoint_@{int} - dbus receive bus=session path=/org/gtk/vfs/mountable - interface=org.gtk.vfs.Mountable - member=Mount - peer=(name=:*, label=gvfsd), - dbus send bus=session path=/org/gtk/gvfs/exec_spaw/@{int} - interface=org.gtk.vfs.Spawner - member=Spawned - peer=(name=:*, label=gvfsd), - dbus send bus=session path=/org/gtk/vfs/mounttracker - interface=org.gtk.vfs.MountTracker - member=RegisterMount - peer=(name=:*, label=gvfsd), - @{exec_path} mr, # Full access to user's data diff --git a/apparmor.d/groups/gvfs/gvfsd-sftp b/apparmor.d/groups/gvfs/gvfsd-sftp index 157af621cb..ae5358014f 100644 --- a/apparmor.d/groups/gvfs/gvfsd-sftp +++ b/apparmor.d/groups/gvfs/gvfsd-sftp @@ -10,9 +10,14 @@ include @{exec_path} = @{lib}/{,gvfs/}gvfsd-sftp profile gvfsd-sftp @{exec_path} { include + include include - include + include + include include + include + + #aa:dbus own bus=session name=org.gtk.vfs.mountpoint_@{int} @{exec_path} mr, diff --git a/apparmor.d/groups/gvfs/gvfsd-smb b/apparmor.d/groups/gvfs/gvfsd-smb index 24891e9c36..34c098192e 100644 --- a/apparmor.d/groups/gvfs/gvfsd-smb +++ b/apparmor.d/groups/gvfs/gvfsd-smb @@ -10,8 +10,9 @@ include @{exec_path} = @{lib}/{,gvfs/}gvfsd-smb profile gvfsd-smb @{exec_path} { include + include + include include - include network netlink raw, network inet stream, diff --git a/apparmor.d/groups/gvfs/gvfsd-smb-browse b/apparmor.d/groups/gvfs/gvfsd-smb-browse index f285a3c150..8002ec677f 100644 --- a/apparmor.d/groups/gvfs/gvfsd-smb-browse +++ b/apparmor.d/groups/gvfs/gvfsd-smb-browse @@ -11,8 +11,9 @@ include profile gvfsd-smb-browse @{exec_path} { include include - include + include include + include include network netlink raw, @@ -23,20 +24,8 @@ profile gvfsd-smb-browse @{exec_path} { #aa:dbus own bus=session name=org.gtk.vfs.mountpoint_smb_browse - dbus receive bus=session path=/org/gtk/vfs/mountable - interface=org.gtk.vfs.Mountable - member=Mount - peer=(name=:*, label=gvfsd), - - dbus send bus=session path=/org/gtk/gvfs/exec_spaw/@{int} - interface=org.gtk.vfs.Spawner - member=Spawned - peer=(name=:*, label=gvfsd), - @{exec_path} mr, - /usr/share/glib-2.0/schemas/gschemas.compiled r, - /etc/samba/* r, /var/cache/samba/ rw, diff --git a/apparmor.d/groups/gvfs/gvfsd-trash b/apparmor.d/groups/gvfs/gvfsd-trash index 683d271a86..96955bed35 100644 --- a/apparmor.d/groups/gvfs/gvfsd-trash +++ b/apparmor.d/groups/gvfs/gvfsd-trash @@ -11,7 +11,8 @@ include profile gvfsd-trash @{exec_path} { include include - include + include + include include include @@ -19,32 +20,9 @@ profile gvfsd-trash @{exec_path} { network inet stream, network inet6 stream, - #aa:dbus own bus=session name=org.gtk.vfs.mountpoint_@{int} - - dbus receive bus=session path=/org/gtk/vfs/Daemon - interface=org.gtk.vfs.Daemon - member=GetConnection - peer=(name=:*, label="{gnome-shell,nautilus}"), - - dbus receive bus=session path=/org/gtk/vfs/mountable - interface=org.gtk.vfs.Mountable - member=Mount - peer=(name=:*, label=gvfsd), + unix (send receive) type=stream, - dbus send bus=session path=/org/gtk/gvfs/exec_spaw/@{int} - interface=org.gtk.vfs.Spawner - member=Spawned - peer=(name=:*, label=gvfsd), - - dbus send bus=session path=/org/gtk/vfs/mounttracker - interface=org.gtk.vfs.MountTracker - member=RegisterMount - peer=(name=:*, label=gvfsd), - - dbus receive bus=session - interface=org.freedesktop.DBus.Introspectable - member=Introspect - peer=(name=:*, label=gnome-shell), + #aa:dbus own bus=session name=org.gtk.vfs.mountpoint_@{int} @{exec_path} mr, diff --git a/apparmor.d/groups/gvfs/gvfsd-wsdd b/apparmor.d/groups/gvfs/gvfsd-wsdd index 6c29d96803..c2cfc66298 100644 --- a/apparmor.d/groups/gvfs/gvfsd-wsdd +++ b/apparmor.d/groups/gvfs/gvfsd-wsdd @@ -7,22 +7,29 @@ abi , include @{exec_path} = @{lib}/{,gvfs/}gvfsd-wsdd -profile gvfsd-wsdd @{exec_path} { +profile gvfsd-wsdd @{exec_path} flags=(attach_disconnected) { include + include include + include + include + include + include + ## network inet dgram, # ip=127.0.0.1 peer=(ip=127.0.0.*, port=53), + network inet dgram, network netlink raw, #aa:dbus own bus=session name=org.gtk.vfs.mountpoint_wsdd - #aa:dbus talk bus=session name=org.gtk.vfs.MountTracker label=gvfsd @{exec_path} mr, - @{bin}/env r, + @{bin}/env mr, @{bin}/wsdd rPx, @{run}/mount/utab r, owner @{run}/user/@{uid}/gvfsd/socket-@{rand8} rw, + owner @{run}/user/@{uid}/gvfsd/wsdd rw, include if exists } diff --git a/apparmor.d/groups/hyprland/hyprland b/apparmor.d/groups/hyprland/hyprland index 68356741d0..f0cc85069f 100644 --- a/apparmor.d/groups/hyprland/hyprland +++ b/apparmor.d/groups/hyprland/hyprland @@ -14,12 +14,14 @@ profile hyprland @{exec_path} flags=(attach_disconnected) { include include include + include capability sys_ptrace, network netlink raw, signal send, + signal receive set=term peer=start-hyprland, ptrace read, @@ -27,31 +29,39 @@ profile hyprland @{exec_path} flags=(attach_disconnected) { /usr/share/hypr{,land}/{,*} r, /usr/share/libinput/{,*} r, + /usr/share/file/misc/magic.mgc r, + + /etc/os-release r, + + /var/cache/hyprpm/juan/split-monitor-workspaces/split-monitor-workspaces.so mr, owner @{user_cache_dirs}/hyprland/{,**} rw, owner @{user_config_dirs}/hypr/** r, owner @{user_share_dirs}/hyprpm/** mr, + owner @{user_share_dirs}/hyprland/** rw, owner @{run}/user/@{uid}/gamescope-* rw, owner @{run}/user/@{uid}/.hyprpaper_* rw, owner @{run}/user/@{uid}/.hyprpicker_* rw, owner @{run}/user/@{uid}/hypr/{,**} rw, + owner @{att}/dev/shm/.org.chromium.Chromium.@{rand6} rw, owner /dev/shm/.org.chromium.Chromium.@{rand6} rw, + owner /dev/shm/.com.google.Chrome.@{rand6} rw, @{run}/systemd/sessions/@{int} r, - @{run}/udev/data/+acpi:* r, # for acpi + @{run}/udev/data/+acpi:* r, # Exposes ACPI objects (power buttons, batteries, thermal) @{run}/udev/data/+dmi:id r, # for motherboard info @{run}/udev/data/+drm:card@{int}-* r, # For screen outputs - @{run}/udev/data/+hid:* r, # for HID-Compliant Keyboard + @{run}/udev/data/+hid:* r, # For Human Interface Device (mice, controllers, drawing tablets, scanners) + @{run}/udev/data/+i2c:* r, # For Inter-Integrated Circuit, low-speed peripherals (sensors, EEPROMs, etc.) @{run}/udev/data/+input:input@{int} r, # for mouse, keyboard, touchpad @{run}/udev/data/+pci:* r, # Identifies all PCI devices (CPU, GPU, Network, Disks, USB, etc.) - @{run}/udev/data/+platform:* r, + @{run}/udev/data/+platform:* r, # Identifies onboard devices (laptop/board model, power controllers, thermal sensors) @{run}/udev/data/+sound:card@{int} r, # for sound card - @{run}/udev/data/+usb* r, # for USB mouse and keyboard + @{run}/udev/data/+usb:* r, # Identifies all USB devices @{run}/udev/data/c13:@{int} r, # for /dev/input/* @{run}/udev/data/c189:@{int} r, # for /dev/bus/usb/** - @{run}/udev/data/c226:@{int} r, # for /dev/dri/card* @{sys}/bus/ r, @{sys}/class/input/ r, @@ -60,9 +70,12 @@ profile hyprland @{exec_path} flags=(attach_disconnected) { owner @{PROC}/@{pid}/environ r, + @{att}/dev/dri/card@{int} rw, + @{att}/dev/input/event@{int} rw, + /dev/input/event@{int} rw, /dev/tty r, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/hyprland/hyprlock b/apparmor.d/groups/hyprland/hyprlock index fab1c2a2e7..a6cab4e0f7 100644 --- a/apparmor.d/groups/hyprland/hyprlock +++ b/apparmor.d/groups/hyprland/hyprlock @@ -13,7 +13,7 @@ profile hyprlock @{exec_path} flags=(attach_disconnected) { include include include - include + include network netlink raw, @@ -29,7 +29,7 @@ profile hyprlock @{exec_path} flags=(attach_disconnected) { owner @{run}/faillock/@{user} rwk, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/hyprland/hyprpaper b/apparmor.d/groups/hyprland/hyprpaper index 3cb8dca92f..6d0674d9fc 100644 --- a/apparmor.d/groups/hyprland/hyprpaper +++ b/apparmor.d/groups/hyprland/hyprpaper @@ -9,12 +9,11 @@ include @{exec_path} = @{bin}/hyprpaper profile hyprpaper @{exec_path} flags=(attach_disconnected) { include + include include @{exec_path} mr, - /usr/share/icons/** r, - owner @{HOME}/@{XDG_WALLPAPERS_DIR}/** r, owner @{user_config_dirs}/hypr/hyprpaper.conf r, diff --git a/apparmor.d/groups/hyprland/hyprpicker b/apparmor.d/groups/hyprland/hyprpicker index 78375c8b2b..6ef564ce4f 100644 --- a/apparmor.d/groups/hyprland/hyprpicker +++ b/apparmor.d/groups/hyprland/hyprpicker @@ -9,16 +9,16 @@ include @{exec_path} = @{bin}/hyprpicker profile hyprpicker @{exec_path} { include + include @{exec_path} mr, @{bin}/wl-copy Px, - /usr/share/icons/** r, - owner @{run}/user/@{uid}/.hyprpicker* rw, owner /dev/shm/wlroots-@{rand6} r, + owner /dev/shm/@{uuid} r, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/hyprland/hyprpm b/apparmor.d/groups/hyprland/hyprpm index 3a58788083..cad7d918da 100644 --- a/apparmor.d/groups/hyprland/hyprpm +++ b/apparmor.d/groups/hyprland/hyprpm @@ -11,7 +11,6 @@ profile hyprpm @{exec_path} { include include include - include network inet dgram, network inet stream, @@ -28,6 +27,8 @@ profile hyprpm @{exec_path} { /usr/share/git-core/** r, /usr/share/pkgconfig/** r, + /var/cache/hyprpm/{,**} r, + owner @{HOME}/.gitconfig r, owner @{user_share_dirs}/hyprpm/{,**} rw, diff --git a/apparmor.d/groups/hyprland/pypr b/apparmor.d/groups/hyprland/pypr index 2f489e055b..1c345a44e9 100644 --- a/apparmor.d/groups/hyprland/pypr +++ b/apparmor.d/groups/hyprland/pypr @@ -22,7 +22,7 @@ profile pypr @{exec_path} flags=(attach_disconnected) { owner @{run}/user/@{uid}/hypr/*/.pyprland.sock rw, - owner /dev/tty@{int} rw, # file_inherit + owner /dev/tty@{u8} rw, # file_inherit include if exists } diff --git a/apparmor.d/groups/kde/DiscoverNotifier b/apparmor.d/groups/kde/DiscoverNotifier index 197f90f889..1cc72fc9fd 100644 --- a/apparmor.d/groups/kde/DiscoverNotifier +++ b/apparmor.d/groups/kde/DiscoverNotifier @@ -8,12 +8,13 @@ include @{exec_path} = @{lib}/DiscoverNotifier @{exec_path} += @{lib}/@{multiarch}/{,libexec/}DiscoverNotifier -profile DiscoverNotifier @{exec_path} { +profile DiscoverNotifier @{exec_path} flags=(attach_disconnected) { include include include include include + include include network inet dgram, @@ -23,32 +24,39 @@ profile DiscoverNotifier @{exec_path} { network netlink dgram, network netlink raw, + #aa:dbus own bus=session name=org.kde.discover.notifier + + #aa:dbus talk bus=system name=org.freedesktop.PackageKit label=packagekitd + @{exec_path} mr, @{bin}/apt-config rPx, + @{bin}/plasma-discover rPx, @{bin}/gpg{,2} rCx -> gpg, @{bin}/gpgconf rCx -> gpg, @{bin}/gpgsm rCx -> gpg, + /usr/share/flatpak/remotes.d/{,**} r, /usr/share/metainfo/{,**} r, /etc/machine-id r, /etc/flatpak/remotes.d/{,**} r, + /var/lib/apt/lists/* r, /var/lib/flatpak/{,**} r, - /var/cache/swcatalog/cache/ w, - /var/cache/swcatalog/xml/{,**} r, + /var/cache/swcatalog/cache/{,**} rw, + /var/cache/swcatalog/{,**} r, - owner @{user_cache_dirs}/appstream/ r, + owner @{user_cache_dirs}/appstream/ rw, owner @{user_cache_dirs}/appstream/** rw, owner @{user_cache_dirs}/flatpak/{,**} rw, - owner @{user_config_dirs}/@{int} rw, + owner @{user_config_dirs}/#@{int} rw, owner @{user_config_dirs}/breezerc r, owner @{user_config_dirs}/PlasmaDiscoverUpdates rw, - owner @{user_config_dirs}/PlasmaDiscoverUpdates.@{rand6} rwl -> @{user_config_dirs}/@{int}, + owner @{user_config_dirs}/PlasmaDiscoverUpdates.@{rand6} rwl -> @{user_config_dirs}/#@{int}, owner @{user_config_dirs}/PlasmaDiscoverUpdates.lock rwk, owner @{user_share_dirs}/flatpak/{,**} rw, diff --git a/apparmor.d/groups/kde/baloo b/apparmor.d/groups/kde/baloo index 75532a7730..948c8023b1 100644 --- a/apparmor.d/groups/kde/baloo +++ b/apparmor.d/groups/kde/baloo @@ -8,8 +8,9 @@ include @{exec_path} = @{bin}/baloo_file @{lib}/{,kf6/}baloo_file @{exec_path} += @{lib}/@{multiarch}/{,libexec/}baloo_file -profile baloo @{exec_path} { +profile baloo @{exec_path} flags=(attach_disconnected) { include + include include include include @@ -24,11 +25,11 @@ profile baloo @{exec_path} { @{lib}/{,kf6/}baloo_file_extractor rix, - /usr/share/poppler/{,**} r, - /etc/fstab r, /etc/machine-id r, + / r, + # Allow to search user files owner @{HOME}/{,**} r, owner @{MOUNTS}/{,**} r, @@ -44,22 +45,8 @@ profile baloo @{exec_path} { @{run}/mount/utab r, - @{run}/udev/data/+*:* r, - - @{run}/udev/data/c1:@{int} r, # For RAM disk - @{run}/udev/data/c4:@{int} r, # For TTY devices - @{run}/udev/data/c5:@{int} r, # for /dev/tty, /dev/console, /dev/ptmx - @{run}/udev/data/c7:@{int} r, # For Virtual console capture devices - @{run}/udev/data/c10:@{int} r, # For non-serial mice, misc features - @{run}/udev/data/c13:@{int} r, # For /dev/input/* - @{run}/udev/data/c29:@{int} r, # For /dev/fb[0-9]* - @{run}/udev/data/c89:@{int} r, # For I2C bus interface - @{run}/udev/data/c99:@{int} r, # For raw parallel ports /dev/parport* - @{run}/udev/data/c116:@{int} r, # For ALSA - @{run}/udev/data/c202:@{int} r, # CPU model-specific registers - @{run}/udev/data/c203:@{int} r, # CPU CPUID information - @{run}/udev/data/c226:@{int} r, # For /dev/dri/card[0-9]* - @{run}/udev/data/c@{dynamic}:@{int} r, # For dynamic assignment range 234 to 254, 384 to 511 + @{run}/udev/data/+*:* r, # Identifies all subsystems + @{run}/udev/data/c@{int}:@{int} r, # Identifies all character devices @{sys}/bus/ r, @{sys}/bus/*/devices/ r, diff --git a/apparmor.d/groups/kde/baloorunner b/apparmor.d/groups/kde/baloorunner index e3fca1f8f7..33660a776f 100644 --- a/apparmor.d/groups/kde/baloorunner +++ b/apparmor.d/groups/kde/baloorunner @@ -10,6 +10,7 @@ include @{exec_path} += @{lib}/@{multiarch}/{,libexec/}baloorunner profile baloorunner @{exec_path} { include + include include include include @@ -28,33 +29,8 @@ profile baloorunner @{exec_path} { /tmp/ r, - @{run}/udev/data/+acpi:* r, # for acpi - @{run}/udev/data/+bluetooth:* r, - @{run}/udev/data/+dmi* r, # for motherboard info - @{run}/udev/data/+hid:* r, # for HID-Compliant Keyboard - @{run}/udev/data/+i2c:* r, - @{run}/udev/data/+input:input@{int} r, # for mouse, keyboard, touchpad - @{run}/udev/data/+leds:* r, - @{run}/udev/data/+pci:* r, # Identifies all PCI devices (CPU, GPU, Network, Disks, USB, etc.) - @{run}/udev/data/+platform:* r, - @{run}/udev/data/+power_supply* r, - @{run}/udev/data/+rfkill:* r, - @{run}/udev/data/+sound:card@{int} r, # for sound card - - @{run}/udev/data/c1:@{int} r, # For RAM disk - @{run}/udev/data/c4:@{int} r, # For TTY devices - @{run}/udev/data/c5:@{int} r, # for /dev/tty, /dev/console, /dev/ptmx - @{run}/udev/data/c7:@{int} r, # For Virtual console capture devices - @{run}/udev/data/c10:@{int} r, # for non-serial mice, misc features - @{run}/udev/data/c116:@{int} r, # For ALSA - @{run}/udev/data/c13:@{int} r, # For /dev/input/* - @{run}/udev/data/c18[0,8,9]:@{int} r, # USB devices & USB serial converters - @{run}/udev/data/c29:@{int} r, # For /dev/fb[0-9]* - @{run}/udev/data/c89:@{int} r, # For I2C bus interface - @{run}/udev/data/c202:@{int} r, # CPU model-specific registers - @{run}/udev/data/c203:@{int} r, # CPU CPUID information - @{run}/udev/data/c226:@{int} r, # For /dev/dri/card[0-9]* - @{run}/udev/data/c@{dynamic}:@{int} r, # For dynamic assignment range 234 to 254, 384 to 511 + @{run}/udev/data/+*:* r, # Identifies all subsystems + @{run}/udev/data/c@{int}:@{int} r, # Identifies all character devices @{sys}/bus/ r, @{sys}/bus/*/devices/ r, diff --git a/apparmor.d/groups/kde/dolphin b/apparmor.d/groups/kde/dolphin index 93780d8892..bb849176eb 100644 --- a/apparmor.d/groups/kde/dolphin +++ b/apparmor.d/groups/kde/dolphin @@ -11,8 +11,7 @@ profile dolphin @{exec_path} { include include include - include - include + include include include include @@ -25,12 +24,21 @@ 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, - @{bin}/ldd rix, - @{bin}/lsb_release rPx -> lsb_release, + @{lib}/libheif/ r, + @{lib}/libheif/*.so* mr, + + #aa:only apparmor>=4.1 + priority=1 @{ldd_path} rix, + + @{bin}/lsb_release rPx, @{lib}/{,@{multiarch}/}utempter/utempter rPx, @{thunderbird_path} rPx, @@ -38,20 +46,24 @@ profile dolphin @{exec_path} { /usr/share/kf5/kmoretools/{,**} r, /usr/share/kio/{,**} r, + /usr/share/konsole/{,**} r, /usr/share/kservices{5,6}/{,**} r, /usr/share/kservicetypes5/{,**} r, /usr/share/misc/termcap r, + /usr/share/templates/{,*.desktop} r, /usr/share/thumbnailers/{,**} r, + /usr/share/color-schemes/{,**} r, /etc/fstab r, /etc/exports r, /etc/machine-id r, /etc/xdg/arkrc r, /etc/xdg/dolphinrc r, - /etc/xdg/menus/ r, - /etc/xdg/menus/applications-merged/ r, /etc/xdg/ui/ui_standards.rc r, + /var/lib/samba/usershare/ r, + + #aa:lint ignore=too-wide # Full access to user's data / r, /*/ r, @@ -65,85 +77,79 @@ profile dolphin @{exec_path} { owner @{tmp}/{,**} rw, # Silence non user's data - deny /boot/{,**} r, + deny @{efi}/{,**} r, deny /opt/{,**} r, deny /root/{,**} r, deny /tmp/.* rw, deny /tmp/.*/{,**} rw, + owner @{user_state_dirs}/#@{int} rwk, + owner @{user_state_dirs}/dolphinstaterc{,.@{rand6}} rwl -> @{user_state_dirs}/#@{int}, + owner @{user_state_dirs}/UserFeedback.org.kde.dolphin.lock k, + owner @{user_state_dirs}/UserFeedback.org.kde.dolphin.@{rand6} l -> @{user_state_dirs}/#@{int}, owner @{user_share_dirs}/dolphin/ rw, owner @{user_share_dirs}/dolphin/** rwkl -> @{user_share_dirs}/dolphin/#@{int}, - owner @{user_share_dirs}/recently-used.xbel{,.*} rwlk, - owner @{user_state_dirs}/dolphinstaterc{,.*} rwlk, owner @{user_config_dirs}/#@{int} rw, - owner @{user_config_dirs}/dolphinrc rwl -> @{user_config_dirs}/#@{int}, - owner @{user_config_dirs}/dolphinrc.@{rand6} rwl -> @{user_config_dirs}/#@{int}, + owner @{user_config_dirs}/dolphinrc{,.@{rand6}} rwl -> @{user_config_dirs}/#@{int}, owner @{user_config_dirs}/dolphinrc.lock rwk, - owner @{user_config_dirs}/kde.org/#@{int} rw, - owner @{user_config_dirs}/kde.org/UserFeedback.org.kde.dolphin.conf{,.*} rwlk -> @{user_config_dirs}/kde.org/#@{int}, + owner @{user_config_dirs}/kde.org/#@{int} rwk, + owner @{user_config_dirs}/kde.org/UserFeedback.org.kde.dolphin.conf{,.@{rand6}} rwl -> @{user_config_dirs}/kde.org/#@{int}, owner @{user_config_dirs}/kde.org/UserFeedback.org.kde.dolphin.conf.lock rwk, - - owner @{user_config_dirs}/session/ rw, - owner @{user_config_dirs}/session/#@{int} rw, - owner @{user_config_dirs}/session/dolphin_* rwlk -> @{user_config_dirs}/session/#@{int}, + owner @{user_config_dirs}/kdeglobals.@{rand6} l -> @{user_config_dirs}/#@{int}, + owner @{user_config_dirs}/kdeglobals.lock k, + owner @{user_config_dirs}/kiorc l -> @{user_config_dirs}/#@{int}, + owner @{user_config_dirs}/kiorc.lock k, + owner @{user_config_dirs}/kservicemenurc l -> @{user_config_dirs}/#@{int}, + owner @{user_config_dirs}/kservicemenurc.lock k, + owner @{user_config_dirs}/ktrashrc l -> @{user_config_dirs}/#@{int}, + owner @{user_config_dirs}/ktrashrc.lock k, + owner @{user_config_dirs}/knfsshare.{,.@{rand6}} rwk, + owner @{user_config_dirs}/knfsshare.lock rwk, + owner @{user_config_dirs}/session/#@{int} rwk, + owner @{user_config_dirs}/session/dolphin_dolphin_dolphin.@{rand6} rwl -> @{user_config_dirs}/session/#@{int}, owner @{user_cache_dirs}/ksplash/qmlcache/*.qmlc rwl -> @{user_cache_dirs}/dolphin/qmlcache/#@{int}, owner @{user_cache_dirs}/ksplash/qmlcache/*.qmlc.@{rand6} rwl -> @{user_cache_dirs}/dolphin/qmlcache/#@{int}, owner @{user_state_dirs}/dolphinstaterc{,.*} rwlk -> @{user_state_dirs}/#@{int}, - owner @{tmp}/dolphin.@{rand6} rwl, + owner @{tmp}/#@{int} rwk, + owner @{tmp}/dolphin.@{rand6} rwl -> @{tmp}/#@{int}, + owner @{tmp}/dolphin.@{rand6}.@{rand6} l -> @{tmp}/#@{int}, + owner @{tmp}/dolphin.@{rand6}.lock rwk, @{run}/issue r, @{run}/mount/utab r, owner @{run}/user/@{uid}/#@{int} rw, owner @{run}/user/@{uid}/dolphin@{rand6}.@{int}.kioworker.socket rwl -> @{run}/user/@{uid}/#@{int}, - @{run}/udev/data/+acpi:* r, # for acpi - @{run}/udev/data/+backlight:* r, - @{run}/udev/data/+bluetooth:* r, - @{run}/udev/data/+dmi* r, # for motherboard info - @{run}/udev/data/+drm:card@{int}-* r, # For screen outputs - @{run}/udev/data/+hid:* r, # for HID-Compliant Keyboard - @{run}/udev/data/+i2c:* r, - @{run}/udev/data/+input:input@{int} r, # for mouse, keyboard, touchpad - @{run}/udev/data/+leds:* r, - @{run}/udev/data/+pci:* r, # Identifies all PCI devices (CPU, GPU, Network, Disks, USB, etc.) - @{run}/udev/data/+platform:* r, - @{run}/udev/data/+power_supply* r, - @{run}/udev/data/+rfkill:* r, - @{run}/udev/data/+sound:card@{int} r, # for sound card - - @{run}/udev/data/c1:@{int} r, # For RAM disk - @{run}/udev/data/c4:@{int} r, # For TTY devices - @{run}/udev/data/c5:@{int} r, # for /dev/tty, /dev/console, /dev/ptmx - @{run}/udev/data/c7:@{int} r, # For Virtual console capture devices - @{run}/udev/data/c10:@{int} r, # for non-serial mice, misc features - @{run}/udev/data/c116:@{int} r, # For ALSA - @{run}/udev/data/c13:@{int} r, # For /dev/input/* - @{run}/udev/data/c18[0,8,9]:@{int} r, # USB devices & USB serial converters - @{run}/udev/data/c29:@{int} r, # For /dev/fb[0-9]* - @{run}/udev/data/c81:@{int} r, # For video4linux - @{run}/udev/data/c89:@{int} r, # For I2C bus interface - @{run}/udev/data/c90:@{int} r, # For RAM, ROM, Flash - @{run}/udev/data/c202:@{int} r, # CPU model-specific registers - @{run}/udev/data/c203:@{int} r, # CPU CPUID information - @{run}/udev/data/c226:@{int} r, # For /dev/dri/card[0-9]* - @{run}/udev/data/c@{dynamic}:@{int} r, # For dynamic assignment range 234 to 254, 384 to 511 + @{run}/udev/data/+*:* r, # Identifies all subsystems + @{run}/udev/data/c@{int}:@{int} r, # Identifies all character devices @{sys}/bus/ r, @{sys}/bus/*/devices/ r, @{sys}/class/*/ r, @{sys}/devices/**/uevent r, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/app-org.kde.dolphin-@{int}.scope/cgroup.controllers r, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/app-org.kde.dolphin-@{int}.scope/cgroup.subtree_control w, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/app-org.kde.dolphin-@{int}.scope/main.scope/ w, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/app-org.kde.dolphin-@{int}.scope/main.scope/cgroup.procs w, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/app-org.kde.dolphin-@{int}.scope/tab(@{int}).scope/ w, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/app-org.kde.dolphin-@{int}.scope/tab(@{int}).scope/cgroup.procs w, + + owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/cmdline r, + owner @{PROC}/@{pid}/fdinfo/@{int} r, owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/mounts r, + owner @{PROC}/@{pid}/stat r, + owner @{PROC}/@{pid}/task/@{tid}/children 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/drkonqi b/apparmor.d/groups/kde/drkonqi index fbadf053be..7bebd976ff 100644 --- a/apparmor.d/groups/kde/drkonqi +++ b/apparmor.d/groups/kde/drkonqi @@ -11,6 +11,8 @@ include profile drkonqi @{exec_path} { include include + include + include include network inet stream, @@ -19,17 +21,17 @@ profile drkonqi @{exec_path} { signal send set=(cont, stop) peer=/usr/bin/akonadiserver, + ptrace read peer=@{p_systemd_user}, ptrace read peer=/usr/bin/akonadiserver, @{exec_path} mr, + @{bin}/kwin_x11 r, + @{bin}/lsb_release Px, @{bin}/plasmashell r, - @{bin}/lsb_release rPx -> lsb_release, /usr/share/drkonqi/{,**} r, - /etc/machine-id r, - / r, owner @{user_cache_dirs}/drkonqi/ rw, @@ -47,12 +49,12 @@ profile drkonqi @{exec_path} { /{run,var}/log/journal/@{hex32}/user-@{uid}@@{hex32}-@{hex16}-@{hex16}.journal* r, /{run,var}/log/journal/remote/ r, - /dev/tty r, - owner @{PROC}/@{pid}/cmdline r, owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/stat r, + /dev/tty r, + include if exists } diff --git a/apparmor.d/groups/kde/drkonqi-coredump-cleanup b/apparmor.d/groups/kde/drkonqi-coredump-cleanup index c74276b956..199dd9c8f1 100644 --- a/apparmor.d/groups/kde/drkonqi-coredump-cleanup +++ b/apparmor.d/groups/kde/drkonqi-coredump-cleanup @@ -14,7 +14,8 @@ profile drkonqi-coredump-cleanup @{exec_path} { @{exec_path} mr, @{user_cache_dirs}/kcrash-metadata/ r, - owner @{user_cache_dirs}/kcrash-metadata/plasmashell.@{hex32}.@{int4}.ini w, + owner @{user_cache_dirs}/kcrash-metadata/plasmashell.@{hex32}.@{int4}.ini rw, + owner @{user_cache_dirs}/kcrash-metadata/@{int}.ini rw, include if exists } diff --git a/apparmor.d/groups/kde/gmenudbusmenuproxy b/apparmor.d/groups/kde/gmenudbusmenuproxy index d9879941b6..651ef4a908 100644 --- a/apparmor.d/groups/kde/gmenudbusmenuproxy +++ b/apparmor.d/groups/kde/gmenudbusmenuproxy @@ -7,10 +7,10 @@ abi , include @{exec_path} = @{bin}/gmenudbusmenuproxy -profile gmenudbusmenuproxy @{exec_path} { +profile gmenudbusmenuproxy @{exec_path} flags=(attach_disconnected,mediate_deleted) { include + include include - include include include @@ -25,6 +25,9 @@ profile gmenudbusmenuproxy @{exec_path} { owner @{user_config_dirs}/gtk-{2,3}.0/#@{int} rw, owner @{user_config_dirs}/gtk-{2,3}.0/settings.ini{,.@{rand6}} rwl, owner @{user_config_dirs}/gtk-{2,3}.0/settings.ini.lock rwk, + owner @{user_config_dirs}/gtk-{2,3}.0/settings.ini.lock.rmlock rwk, + + /dev/tty r, include if exists } diff --git a/apparmor.d/groups/kde/kaccess b/apparmor.d/groups/kde/kaccess index 42c1400efd..4d3d55cef6 100644 --- a/apparmor.d/groups/kde/kaccess +++ b/apparmor.d/groups/kde/kaccess @@ -7,25 +7,26 @@ abi , include @{exec_path} = @{bin}/kaccess -profile kaccess @{exec_path} { +profile kaccess @{exec_path} flags=(attach_disconnected) { include include include include + include include + #aa:dbus own bus=session name=org.kde.kaccess + #aa:dbus talk bus=session name=org.kde.kglobalaccel path=/kglobalaccel label=kglobalacceld + @{exec_path} mr, @{bin}/gsettings rPx, - /usr/share/icons/{,**} r, - - /etc/machine-id r, - owner @{user_config_dirs}/breezerc r, owner @{user_config_dirs}/kaccessrc r, + owner @{user_config_dirs}/Kvantum/{,**} r, - owner @{user_share_dirs}/mime/generic-icons r, + owner @{PROC}/@{pid}/stat r, /dev/tty r, diff --git a/apparmor.d/groups/kde/kactivitymanagerd b/apparmor.d/groups/kde/kactivitymanagerd index fdc0730c45..03602ce668 100644 --- a/apparmor.d/groups/kde/kactivitymanagerd +++ b/apparmor.d/groups/kde/kactivitymanagerd @@ -8,16 +8,21 @@ include @{exec_path} = @{lib}/kactivitymanagerd @{exec_path} += @{lib}/@{multiarch}/{,libexec/}kactivitymanagerd -profile kactivitymanagerd @{exec_path} { +profile kactivitymanagerd @{exec_path} flags=(attach_disconnected,mediate_deleted) { include + include include include include + include include include include include + #aa:dbus own bus=session name=org.kde.ActivityManager path=/ActivityManager + #aa:dbus own bus=session name=org.kde.runners.activities + @{exec_path} mr, /etc/xdg/menus/{,*/} r, @@ -38,9 +43,12 @@ profile kactivitymanagerd @{exec_path} { owner @{user_share_dirs}/kactivitymanagerd/{,**} rwlk, owner @{user_share_dirs}/kservices{5,6}/{,**} r, - owner @{user_share_dirs}/recently-used.xbel r, owner @{user_share_dirs}/user-places.xbel r, + owner @{user_state_dirs}/kactivitymanagerdstaterc r, + + owner @{tmp}/kmail2.@{rand6} r, + owner @{run}/user/@{uid}/#@{int} rw, owner @{run}/user/@{uid}/*@{rand6}.*.socket rwl -> @{run}/user/@{uid}/#@{int}, diff --git a/apparmor.d/groups/kde/kalendarac b/apparmor.d/groups/kde/kalendarac index 661090bc11..65c319ede7 100644 --- a/apparmor.d/groups/kde/kalendarac +++ b/apparmor.d/groups/kde/kalendarac @@ -12,6 +12,7 @@ profile kalendarac @{exec_path} { include include include + include include @{exec_path} mr, @@ -25,6 +26,7 @@ profile kalendarac @{exec_path} { owner @{user_config_dirs}/#@{int} rw, owner @{user_config_dirs}/akonadi-firstrunrc r, + owner @{user_config_dirs}/akonadi/ rw, owner @{user_config_dirs}/akonadi/akonadiconnectionrc r, owner @{user_config_dirs}/emaildefaults r, owner @{user_config_dirs}/emailidentities r, @@ -33,6 +35,11 @@ profile kalendarac @{exec_path} { owner @{user_config_dirs}/kalendaracrc.lock rwk, owner @{user_config_dirs}/kmail2rc r, + owner @{user_state_dirs}/#@{int} rw, + owner @{user_state_dirs}/kalendaracstaterc rw, + owner @{user_state_dirs}/kalendaracstaterc.@{rand6} rwl, + owner @{user_state_dirs}/kalendaracstaterc.lock rwk, + /dev/tty r, include if exists diff --git a/apparmor.d/groups/kde/kauth-backlighthelper b/apparmor.d/groups/kde/kauth-backlighthelper index 61308e83b0..6f56c332f7 100644 --- a/apparmor.d/groups/kde/kauth-backlighthelper +++ b/apparmor.d/groups/kde/kauth-backlighthelper @@ -7,30 +7,22 @@ abi , include @{exec_path} = @{lib}/{,kf6/}kauth/{,libexec/}backlighthelper -profile kauth-backlighthelper @{exec_path} { +profile kauth-backlighthelper @{exec_path} flags=(attach_disconnected) { include + include include - include + include include include capability net_admin, + #aa:dbus own bus=system name=org.kde.powerdevil.backlighthelper + @{exec_path} mr, /usr/share/icu/@{int}.@{int}/*.dat r, - @{sys}/class/backlight/ r, - @{sys}/class/leds/ r, - @{sys}/devices/@{pci}/*_backlight/{,max_,actual_}brightness rw, - @{sys}/devices/@{pci}/*_backlight/{uevent,type,enabled} r, - @{sys}/devices/@{pci}/backlight/**/{,max_,actual_}brightness rw, - @{sys}/devices/@{pci}/backlight/**/{uevent,type,enabled} r, - @{sys}/devices/@{pci}/backlight/**/brightness rw, - @{sys}/devices/@{pci}/drm/card@{int}/**/{,max_,actual_}brightness rw, - @{sys}/devices/@{pci}/drm/card@{int}/**/{uevent,type,enabled} r, - @{sys}/devices/@{pci}/drm/card@{int}/**/brightness rw, - /dev/tty r, include if exists diff --git a/apparmor.d/groups/kde/kauth-chargethresholdhelper b/apparmor.d/groups/kde/kauth-chargethresholdhelper index 8ed8bf82e8..8907586b2c 100644 --- a/apparmor.d/groups/kde/kauth-chargethresholdhelper +++ b/apparmor.d/groups/kde/kauth-chargethresholdhelper @@ -7,16 +7,23 @@ abi , include @{exec_path} = @{lib}/{,kf6/}kauth/{,libexec/}chargethresholdhelper -profile kauth-chargethresholdhelper @{exec_path} { +profile kauth-chargethresholdhelper @{exec_path} flags=(attach_disconnected) { include + include + include include + #aa:dbus own bus=system name=org.kde.powerdevil.chargethresholdhelper + #aa:dbus talk bus=system name=org.kde.kf[56]auth path=/ label=kde-powerdevil + @{exec_path} mr, /usr/share/icu/@{int}.@{int}/*.dat r, @{sys}/class/power_supply/ r, @{sys}/devices/**/power_supply/** r, + @{sys}/devices/**/power_supply/BAT@{int}/charge_control_end_threshold w, + @{sys}/devices/**/power_supply/BAT@{int}/charge_control_start_threshold w, include if exists } diff --git a/apparmor.d/groups/kde/kauth-discretegpuhelper b/apparmor.d/groups/kde/kauth-discretegpuhelper index f03dfb007a..a7be22d818 100644 --- a/apparmor.d/groups/kde/kauth-discretegpuhelper +++ b/apparmor.d/groups/kde/kauth-discretegpuhelper @@ -7,10 +7,14 @@ abi , include @{exec_path} = @{lib}/{,kf6/}kauth/{,libexec/}discretegpuhelper -profile kauth-discretegpuhelper @{exec_path} { +profile kauth-discretegpuhelper @{exec_path} flags=(attach_disconnected) { include + include + include include + #aa:dbus own bus=system name=org.kde.powerdevil.discretegpuhelper + @{exec_path} mr, /usr/share/icu/@{int}.@{int}/*.dat r, diff --git a/apparmor.d/groups/kde/kauth-kded-smart-helper b/apparmor.d/groups/kde/kauth-kded-smart-helper index 6483fe39f8..fe471df541 100644 --- a/apparmor.d/groups/kde/kauth-kded-smart-helper +++ b/apparmor.d/groups/kde/kauth-kded-smart-helper @@ -7,22 +7,26 @@ abi , include @{exec_path} = @{lib}/{,kf6/}kauth/{,libexec/}kded-smart-helper -profile kauth-kded-smart-helper @{exec_path} { +profile kauth-kded-smart-helper @{exec_path} flags=(attach_disconnected) { include include - include + include include #aa:dbus own bus=system name=org.kde.kded.smart + dbus receive bus=system path=/ + interface=org.kde.kf5auth + member=performAction + peer=(name=@{busname}, label=kded), dbus send bus=system path=/ interface=org.kde.kf5auth member=remoteSignal - peer=(name=org.freedesktop.DBus, label=kded5), + peer=(name=org.freedesktop.DBus, label=kded), @{exec_path} mr, - @{bin}/smartctl rPx, + @{sbin}/smartctl rPx, /usr/share/icu/@{int}.@{int}/*.dat r, diff --git a/apparmor.d/groups/kde/kauth-kinfocenter-dmidecode-helper b/apparmor.d/groups/kde/kauth-kinfocenter-dmidecode-helper index 5ae1f5f12c..afecd8d53d 100644 --- a/apparmor.d/groups/kde/kauth-kinfocenter-dmidecode-helper +++ b/apparmor.d/groups/kde/kauth-kinfocenter-dmidecode-helper @@ -13,7 +13,7 @@ profile kauth-kinfocenter-dmidecode-helper @{exec_path} { @{exec_path} mr, - @{bin}/dmidecode rPx, + @{sbin}/dmidecode rPx, include if exists } diff --git a/apparmor.d/groups/kde/kcminit b/apparmor.d/groups/kde/kcminit index 93378bf761..45a554db17 100644 --- a/apparmor.d/groups/kde/kcminit +++ b/apparmor.d/groups/kde/kcminit @@ -10,8 +10,11 @@ include profile kcminit @{exec_path} { include include - include + include include + include + + #aa:dbus own bus=session name=org.kde.{KCM,kcm}init path=/kcminit @{exec_path} mr, @@ -26,6 +29,9 @@ profile kcminit @{exec_path} { owner @{user_config_dirs}/#@{int} rw, owner @{user_config_dirs}/gtkrc-2.0{,.@{rand6}} rwl, owner @{user_config_dirs}/gtkrc{,.@{rand6}} rwl, + owner @{user_config_dirs}/kcmfonts r, + owner @{user_config_dirs}/kcminputrc{,.@{rand6}} rwl, + owner @{user_config_dirs}/kcminputrc.lock rwk, owner @{user_config_dirs}/kgammarc r, owner @{user_config_dirs}/touchpadrc r, owner @{user_config_dirs}/touchpadxlibinputrc r, diff --git a/apparmor.d/groups/kde/kconf_update b/apparmor.d/groups/kde/kconf_update index 49da5e3cac..d8176ba049 100644 --- a/apparmor.d/groups/kde/kconf_update +++ b/apparmor.d/groups/kde/kconf_update @@ -12,7 +12,6 @@ profile kconf_update @{exec_path} { include include include - include include include include @@ -32,17 +31,15 @@ profile kconf_update @{exec_path} { @{bin}/qtchooser rPx, @{lib}/kconf_update_bin/* rix, @{lib}/@{multiarch}/kconf_update_bin/* rix, + @{lib}/qt6/bin/qtpaths rix, /usr/share/kconf_update/*.py rix, /usr/share/kconf_update/*.sh rix, /usr/share/kconf_update/{,**} r, /usr/share/kglobalaccel/org.kde.krunner.desktop r, - /etc/xdg/konsolerc r, - /etc/xdg/ui/ui_standards.rc r, - - /etc/machine-id r, - /var/lib/dbus/machine-id r, + /etc/xdg/*rc r, + /etc/xdg/ui/*rc r, owner @{HOME}/.gtkrc-@{version} w, diff --git a/apparmor.d/groups/kde/kde-powerdevil b/apparmor.d/groups/kde/kde-powerdevil index f5ffa6a82b..556fc3be0c 100644 --- a/apparmor.d/groups/kde/kde-powerdevil +++ b/apparmor.d/groups/kde/kde-powerdevil @@ -11,20 +11,35 @@ include profile kde-powerdevil @{exec_path} flags=(attach_disconnected mediate_deleted) { include include + include + include include include + include include include + include + include capability wake_alarm, network netlink raw, + #aa:dbus own bus=system name=org.freedesktop.Policy.Power + #aa:dbus own bus=system name=org.kde.kf[56]auth path=/ + + #aa:dbus own bus=session name=local.org_kde_powerdevil + #aa:dbus own bus=session name=org.freedesktop.PowerManagement + #aa:dbus own bus=session name=org.kde.Solid.PowerManagement + + #aa:dbus talk bus=session name=org.kde.KWin path=/ label="kwin_{wayland,x11}" + #aa:dbus talk bus=system name=org.freedesktop.login1 label="@{p_systemd_logind}" + @{exec_path} mrix, @{sh_path} rix, @{bin}/find rix, - @{bin}/grep rix, + @{bin}/{,e}grep rix, @{bin}/kcminit rPx, @{bin}/sed rix, @{bin}/uname rPx, @@ -34,9 +49,10 @@ profile kde-powerdevil @{exec_path} flags=(attach_disconnected mediate_deleted) /etc/fstab r, /etc/machine-id r, + / r, owner @{HOME}/ r, - owner @{user_cache_dirs}/ddcutil/* r, + owner @{user_cache_dirs}/ddcutil/* rw, owner @{user_cache_dirs}/kcrash-metadata/{,*} rw, owner @{user_config_dirs}/#@{int} rw, @@ -46,7 +62,7 @@ profile kde-powerdevil @{exec_path} flags=(attach_disconnected mediate_deleted) owner @{user_config_dirs}/powermanagementprofilesrc.lock rwk, owner @{user_config_dirs}/powermanagementprofilesrc{,.@{rand6}} rwl -> @{user_config_dirs}/#@{int}, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, @{run}/mount/utab r, owner @{run}/user/@{uid}kcrash_@{int} rw, @@ -70,12 +86,13 @@ profile kde-powerdevil @{exec_path} flags=(attach_disconnected mediate_deleted) @{sys}/devices/@{pci}/drm/card@{int}/*/edid r, @{sys}/devices/@{pci}/drm/card@{int}/*/enabled r, @{sys}/devices/@{pci}/drm/card@{int}/*/status r, - @{sys}/devices/@{pci}/i2c-@{int}/{,**/}name r, - @{sys}/devices/@{pci}/i2c-@{int}/**/dev r, + @{sys}/devices/@{pci}/i2c-*/{,**/}name r, + @{sys}/devices/@{pci}/i2c-*/**/dev r, @{sys}/devices/**/ r, - @{sys}/devices/i2c-@{int}/name r, - @{sys}/devices/platform/**/i2c-@{int}/**/name r, - @{sys}/devices/platform/*/i2c-@{int}/name r, + @{sys}/devices/**/uevent r, + @{sys}/devices/i2c-*/name r, + @{sys}/devices/platform/**/i2c-*/**/name r, + @{sys}/devices/platform/*/i2c-*/name r, @{PROC}/@{pid}/fd/ r, @{PROC}/@{pid}/mountinfo r, diff --git a/apparmor.d/groups/kde/kded b/apparmor.d/groups/kde/kded index 9efaec4fcb..21841fd812 100644 --- a/apparmor.d/groups/kde/kded +++ b/apparmor.d/groups/kde/kded @@ -7,54 +7,90 @@ abi , include @{exec_path} = @{bin}/kded5 @{bin}/kded6 -profile kded @{exec_path} { +profile kded @{exec_path} flags=(attach_disconnected,mediate_deleted) { include + include #aa:only apt include - include - include - include + include + include + include include include include include - include include include include + include include capability sys_ptrace, network inet dgram, + network inet stream, network inet6 dgram, - network netlink raw, + network inet6 stream, network netlink dgram, + network netlink raw, - ptrace (read), + ptrace read, signal send set=hup peer=xsettingsd, signal send set=term peer=kioworker, + # Owned by KDE + #aa:dbus own bus=system name=com.redhat.NewPrinterNotification - #aa:dbus talk bus=system name=org.freedesktop.NetworkManager label=NetworkManager + + #aa:dbus own bus=session name=org.gtk.Settings + #aa:dbus own bus=session name=org.kde.DistroReleaseNotifier + #aa:dbus own bus=session name=org.kde.GtkConfig + #aa:dbus own bus=session name=org.kde.kappmenu + #aa:dbus own bus=session name=org.kde.kcookiejar5 + #aa:dbus own bus=session name=org.kde.kded5 + #aa:dbus own bus=session name=org.kde.keyboard + #aa:dbus own bus=session name=org.kde.KeyboardLayouts + #aa:dbus own bus=session name=org.kde.plasmanetworkmanagement + #aa:dbus own bus=session name=org.kde.plasmashell.accentColor + #aa:dbus own bus=session name=org.kde.StatusNotifierWatcher + #aa:dbus own bus=session name=org.kde.Wacom + #aa:dbus own bus=session name=org.kubuntu.NotificationHelper + #aa:dbus own bus=session name=org.kubuntu.restrictedInstall + + # Talk with KDE + + # The strategy with dbus rules in this profile is first to declare all communications + # needed on buses and to limit them only to their profiles in apparmor.d. As such, + # only dbus directive is used for this. Later, some communications could be + # restricted. + #aa:dbus talk bus=system name=org.freedesktop.bolt label=boltd + #aa:dbus talk bus=system name=org.freedesktop.ModemManager1 label=ModemManager + #aa:dbus talk bus=system name=org.freedesktop.NetworkManager label=NetworkManager + #aa:dbus talk bus=system name=org.freedesktop.PolicyKit1 label="@{p_polkitd}" + + #aa:dbus talk bus=session name=org.kde.NightColor path=/ColorCorrect label="{kwin_wayland,kwin_x11}" + #aa:dbus talk bus=session name=org.kde.KGlobalAccel path=/ label="{kglobalacceld,kwin_wayland}" dbus receive bus=system path=/ - interface=org.kde.kf5auth + interface=org.kde.kf{5,6}auth member=remoteSignal - peer=(name=:*, label=kauth-kded-smart-helper), + peer=(name=@{busname}, label=kauth-kded-smart-helper), dbus send bus=system path=/ - interface=org.kde.kf5auth + interface=org.kde.kf{5,6}auth member=performAction - peer=(name="{:*,org.kde.kded.smart}", label=kauth-kded-smart-helper), + peer=(name="{@{busname},org.kde.kded.smart}", label=kauth-kded-smart-helper), @{exec_path} mrix, + @{python_path} rix, + @{bin}/dpkg rPx -> child-dpkg, + @{bin}/flatpak rPx, @{bin}/kcminit rPx, + @{bin}/lsb_release rPx, @{bin}/pgrep rCx -> pgrep, @{bin}/plasma-welcome rPUx, - @{python_path} rix, @{bin}/setxkbmap rix, @{bin}/xmodmap rPUx, @{bin}/xrdb rPx, @@ -66,30 +102,46 @@ profile kded @{exec_path} { #aa:exec kconf_update /usr/share/color-schemes/{,**} r, + /usr/share/distro-info/{,**} r, + /usr/share/distro-release-notifier/{,**} r, /usr/share/kconf_update/ r, /usr/share/kded{5,6}/{,**} r, /usr/share/kf{5,6}/kcookiejar/* r, /usr/share/khotkeys/{,**} r, /usr/share/kservices{5,6}/{,**} r, /usr/share/kservicetypes5/{,**} r, + /usr/share/ubuntu-release-upgrader/{,*} r, /etc/fstab r, /etc/xdg/accept-languages.codes r, /etc/xdg/kde* r, /etc/xdg/kioslaverc r, /etc/xdg/menus/{,**} r, + /etc/update-manager/{,**} r, /etc/machine-id r, /var/lib/dbus/machine-id r, / r, + @{efi}/ r, + /home/ r, + + owner /var/lib/update-manager/meta-release-lts rw, + owner @{MOUNTS}/ r, owner @{HOME}/ r, owner @{HOME}/.gtkrc-2.0 rw, + owner @{HOME}/.var/ w, + owner @{HOME}/.var/app/ w, + owner @{HOME}/.var/app/**/org.kde.plasma.browser_integration.json w, + owner @{HOME}/.var/app/**/plasma-browser-integration-host w, + owner @{HOME}/.var/app/org.mozilla.firefox/**/ w, + @{user_cache_dirs}/ksycoca{5,6}_* rwlk -> @{user_cache_dirs}/#@{int}, owner @{user_cache_dirs}/plasmashell/ rw, owner @{user_cache_dirs}/plasmashell/** rwlk -> @{user_cache_dirs}/plasmashell/**, + owner @{user_cache_dirs}/update-manager-core/meta-release-lts rw, @{user_config_dirs}/kcookiejarrc.lock rwk, @{user_config_dirs}/kcookiejarrc{,.@{rand6}} rwl -> @{user_config_dirs}/#@{int}, @@ -106,11 +158,13 @@ profile kded @{exec_path} { owner @{user_config_dirs}/Trolltech.conf.lock rwk, owner @{user_config_dirs}/Trolltech.conf{,.@{rand6}} rwl, owner @{user_config_dirs}/xsettingsd/{,**} rw, + owner @{user_config_dirs}/kcmfonts r, + owner @{user_config_dirs}/Kvantum/{,**} r, owner @{user_share_dirs}/icc/{,edid-*} r, owner @{user_share_dirs}/kcookiejar/#@{int} rw, owner @{user_share_dirs}/kcookiejar/cookies.lock rwk, - owner @{user_share_dirs}/kcookiejar/cookies{,.@{rand6}} rwkl -> @{user_share_dirs}/kcookiejar/#@{int}, + owner @{user_share_dirs}/kcookiejar/cookies{,.@{rand6}} rwkl, owner @{user_share_dirs}/kded{5,6}/{,**} rw, owner @{user_share_dirs}/kscreen/{,**} rwl, owner @{user_share_dirs}/kservices{5,6}/{,**} r, @@ -118,12 +172,12 @@ profile kded @{exec_path} { owner @{user_share_dirs}/remoteview/ r, owner @{user_share_dirs}/services5/{,**} r, owner @{user_share_dirs}/user-places.xbel r, + owner @{user_share_dirs}/aurorae/themes/Layan/* r, owner @{user_state_dirs}/#@{int} rw, owner @{user_state_dirs}/plasmashellstaterc{,*} rwlk, @{run}/mount/utab r, - @{run}/udev/data/c189:@{int} r, # for /dev/bus/usb/** @{run}/user/@{uid}/gvfs/ r, owner @{run}/user/@{uid}/#@{int} rw, owner @{run}/user/@{uid}/kded{5,6}*kioworker.socket rwl, @@ -133,6 +187,11 @@ profile kded @{exec_path} { owner @{tmp}/plasma-csd-generator.@{rand6}/{,**} rw, @{sys}/class/leds/ r, + @{sys}/devices/**/input@{int}/{,**/}uevent r, + + @{run}/udev/data/b8:@{int} r, # for /dev/sd* + @{run}/udev/data/b254:@{int} r, # for /dev/zram* + @{run}/udev/data/b259:@{int} r, # Block Extended Major @{PROC}/ r, @{PROC}/@{pids}/cmdline/ r, @@ -152,8 +211,6 @@ profile kded @{exec_path} { include include - @{PROC}/tty/drivers r, - include if exists } diff --git a/apparmor.d/groups/kde/kglobalacceld b/apparmor.d/groups/kde/kglobalacceld index 9da19046d2..d039dbdb9a 100644 --- a/apparmor.d/groups/kde/kglobalacceld +++ b/apparmor.d/groups/kde/kglobalacceld @@ -9,24 +9,21 @@ include @{exec_path} = @{bin}/kglobalaccel5 @{lib}/kglobalacceld profile kglobalacceld @{exec_path} { include + include include + #aa:dbus own bus=session name=org.kde.KGlobalAccel path=/kglobalaccel + @{exec_path} mr, @{bin}/kstart rPx, /usr/share/kglobalaccel/{,**} r, - /etc/machine-id r, - /etc/xdg/menus/ r, - /etc/xdg/menus/applications-merged/ r, - owner @{user_config_dirs}/#@{int} rw, owner @{user_config_dirs}/kglobalshortcutsrc.lock rwk, owner @{user_config_dirs}/kglobalshortcutsrc* rwl, owner @{user_config_dirs}/khotkeysrc r, - owner @{user_config_dirs}/menus/ r, - owner @{user_config_dirs}/menus/applications-merged/ r, @{PROC}/sys/kernel/random/boot_id r, diff --git a/apparmor.d/groups/kde/kiod b/apparmor.d/groups/kde/kiod index f6a7ba95a0..c0ec1bd539 100644 --- a/apparmor.d/groups/kde/kiod +++ b/apparmor.d/groups/kde/kiod @@ -10,6 +10,7 @@ include @{exec_path} += @{lib}/@{multiarch}/{,libexec/}kf{5,6}/kiod{5,6} profile kiod @{exec_path} { include + include include include include @@ -19,13 +20,16 @@ profile kiod @{exec_path} { @{exec_path} mr, - /usr/share/icons/breeze/index.theme r, - /usr/share/mime/{,**} r, - owner @{user_config_dirs}/#@{int} rw, owner @{user_config_dirs}/ksslcertificatemanager rwl -> @{user_config_dirs}/#@{int}, owner @{user_config_dirs}/ksslcertificatemanager.lock rwk, + owner @{user_config_dirs}/Kvantum/{,**} r, + + /etc/fstab r, + + @{run}/mount/utab r, + owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/mounts r, /dev/tty r, diff --git a/apparmor.d/groups/kde/kioworker b/apparmor.d/groups/kde/kioworker index 592e5811e1..940d8ccbad 100644 --- a/apparmor.d/groups/kde/kioworker +++ b/apparmor.d/groups/kde/kioworker @@ -10,6 +10,7 @@ include @{exec_path} += @{lib}/kf5/kioslave5 @{lib}/@{multiarch}/{,libexec/}kf5/kioslave5 profile kioworker @{exec_path} { include + include include include include @@ -32,30 +33,44 @@ profile kioworker @{exec_path} { signal receive set=term peer=plasmashell, signal receive set=term peer=xdg-desktop-portal-kde, + #aa:dbus talk bus=session name=org.kde.kded5 path=/kded label=kded + @{exec_path} mr, @{lib}/libheif/ r, @{lib}/libheif/*.so* rm, @{bin}/wrestool rPUx, - @{bin}/gs rPUx, + @{bin}/kcmshell6 rPUx, + @{bin}/alts ix, + @{bin}/gs{,.bin} rCx -> gs, #aa:exec kio_http_cache_cleaner - /usr/share/kio_desktop/directory.desktop r, + /usr/share/kio_desktop/{,**} r, /usr/share/kservices{5,6}/{,**} r, /usr/share/kservicetypes{5,6}/*.desktop r, - /usr/share/remoteview/* r, + /usr/share/libalternatives/gs/{,**} r, + /usr/share/org.kde.syntax-highlighting/{,**} r, + /usr/share/remoteview/{,*} r, + /usr/share/thumbnailers/{,**} r, + /usr/share/wallpapers/{,**} r, /etc/fstab r, + /etc/sysconfig/proxy r, /etc/xdg/kioslaverc r, /etc/xdg/menus/{,**} r, + owner /var/cache/samba/gencache.tdb w, + + #aa:lint ignore=too-wide # Full access to user's data / r, /*/ r, @{bin}/ r, @{bin}/* r, + @{sbin}/ r, + @{sbin}/* r, @{lib}/ r, @{MOUNTDIRS}/ r, @{MOUNTS}/ r, @@ -64,9 +79,10 @@ profile kioworker @{exec_path} { owner @{run}/user/@{uid}/{,**} rw, owner @{tmp}/{,**} rw, + #aa:lint ignore=too-wide # Silence non user's data - deny /boot/{,**} r, - deny /etc/{,**} r, + deny @{efi}/{,**} r, + deny /etc/{,**} w, deny /opt/{,**} r, deny /root/{,**} r, deny /tmp/.* rw, @@ -75,9 +91,12 @@ profile kioworker @{exec_path} { owner @{HOME}/@{XDG_DESKTOP_DIR}/.directory l -> @{HOME}/@{XDG_DESKTOP_DIR}/#@{int}, owner @{user_cache_dirs}/kio_http/* rwl, + owner @{user_cache_dirs}/samba/gencache.tdb k, owner @{user_config_dirs}/kio_httprc r, owner @{user_config_dirs}/menus/{,**} r, + owner @{user_config_dirs}/libaccounts-glib/accounts.db k, + owner @{user_config_dirs}/libaccounts-glib/accounts.db-shm k, owner @{user_share_dirs}/baloo/index rw, owner @{user_share_dirs}/baloo/index-lock rwk, @@ -89,16 +108,31 @@ profile kioworker @{exec_path} { owner @{tmp}/#@{int} rw, @{run}/mount/utab r, + @{run}/sshd.pid r, + @{run}/utmp r, owner @{run}/user/@{uid}/#@{int} rw, owner @{run}/user/@{uid}/kio_*.socket rwl -> @{run}/user/@{uid}/#@{int}, owner @{run}/user/@{uid}/kioworker*.kioworker.socket rwl -> @{run}/user/@{uid}/#@{int}, + @{PROC}/cmdline r, owner @{PROC}/@{pid}/cmdline r, owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/mounts r, /dev/tty r, + profile gs { + include + + @{bin}/gs{,.bin} mr, + @{lib}/ghostscript/** mr, + + /usr/share/ghostscript/{,**} r, + /usr/share/org.kde.syntax-highlighting/{,**} r, + + include if exists + } + include if exists } diff --git a/apparmor.d/groups/kde/konsole b/apparmor.d/groups/kde/konsole index 8f9ff48dd0..cd4c7f44b2 100644 --- a/apparmor.d/groups/kde/konsole +++ b/apparmor.d/groups/kde/konsole @@ -11,25 +11,28 @@ include profile konsole @{exec_path} flags=(attach_disconnected,mediate_deleted) { include include - include include include include include include - ptrace (read), + ptrace read, - signal (send) set=(hup), + signal send, + + #aa:dbus own bus=session name=org.kde.konsole-@{int} @{exec_path} mr, - @{bin}/@{shells} rUx, @{browsers_path} rPx, @{lib}/libheif/ r, @{lib}/libheif/** mr, @{lib}/{,@{multiarch}/}utempter/utempter rPx, + # The shell is not confined on purpose. + @{bin}/@{shells} rUx, + # Some CLI program can be launched directly from KDE @{bin}/btop rPUx, @{bin}/htop rPx, @@ -53,13 +56,16 @@ profile konsole @{exec_path} flags=(attach_disconnected,mediate_deleted) { owner @{user_config_dirs}/breezerc r, owner @{user_config_dirs}/kbookmarkrc r, owner @{user_config_dirs}/konsole.notifyrc r, - owner @{user_config_dirs}/konsolerc{,*} rwlk, + owner @{user_config_dirs}/konsolerc rwl, + owner @{user_config_dirs}/konsolerc.@{rand6} rwl, + owner @{user_config_dirs}/konsolerc.lock rwk, owner @{user_config_dirs}/konsolesshconfig rwl -> @{user_config_dirs}/#@{int}, owner @{user_config_dirs}/konsolesshconfig.@{rand6} rwl -> @{user_config_dirs}/#@{int}, owner @{user_config_dirs}/konsolesshconfig.lock rwk, owner @{user_config_dirs}/kservicemenurc r, owner @{user_config_dirs}/menus/{,**} r, owner @{user_config_dirs}/session/** rwlk, + owner @{user_config_dirs}/Kvantum/{,**} r, owner @{user_share_dirs}/color-schemes/{,**} r, owner @{user_share_dirs}/konsole/ rw, @@ -76,8 +82,10 @@ profile konsole @{exec_path} flags=(attach_disconnected,mediate_deleted) { owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/app-org.kde.konsole-@{int}.scope/** rw, - @{PROC}/@{pid}/cmdline r, - @{PROC}/@{pid}/stat r, + @{PROC}/@{pid}/task/@{tid}/children r, + @{PROC}/@{pids}/cmdline r, + @{PROC}/@{pids}/stat r, + @{PROC}/@{pids}/status r, owner @{PROC}/@{pid}/cgroup r, /dev/ptmx rw, diff --git a/apparmor.d/groups/kde/kscreen_backend_launcher b/apparmor.d/groups/kde/kscreen_backend_launcher index d4b547c7c4..10d342a043 100644 --- a/apparmor.d/groups/kde/kscreen_backend_launcher +++ b/apparmor.d/groups/kde/kscreen_backend_launcher @@ -10,9 +10,11 @@ include @{exec_path} += @{lib}/@{multiarch}/{,libexec/}kf{5,6}/kscreen_backend_launcher profile kscreen_backend_launcher @{exec_path} { include - include include + #aa:dbus own bus=session name=org.kde.KScreen + #aa:dbus talk bus=system name=org.kde.kf5auth path=/ label=kde-powerdevil + @{exec_path} mr, /dev/tty r, diff --git a/apparmor.d/groups/kde/kscreenlocker_greet b/apparmor.d/groups/kde/kscreenlocker_greet index 2c129b426c..d6452afe12 100644 --- a/apparmor.d/groups/kde/kscreenlocker_greet +++ b/apparmor.d/groups/kde/kscreenlocker_greet @@ -11,35 +11,36 @@ include @{exec_path} += @{lib}/@{multiarch}/{,libexec/}kscreenlocker_greet profile kscreenlocker_greet @{exec_path} { include - include - include - include - include - include + include include include include include include include + include network netlink raw, + ptrace read peer=ksmserver, + signal (receive) set=(term) peer=kwin_wayland, signal (receive) set=(usr1, term) peer=ksmserver, signal (send) peer=kcheckpass, + unix bind type=stream addr=@@{udbus}/bus/QThread/system, + dbus send bus=system path=/org/freedesktop/DisplayManager/Seat@{int} interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=sddm), + peer=(name=@{busname}, label=sddm), @{exec_path} mr, @{lib}/libheif/ r, @{lib}/libheif/*.so* rm, - @{bin}/unix_chkpwd rPx, + @{sbin}/unix_chkpwd rPx, @{lib}/@{multiarch}/libexec/kcheckpass rPx, /usr/share/plasma/** r, @@ -65,6 +66,7 @@ profile kscreenlocker_greet @{exec_path} { /var/lib/dbus/machine-id r, + owner @{HOME}/.face r, owner @{HOME}/.face.icon r, owner @{user_pictures_dirs}/{,**} r, @@ -99,12 +101,13 @@ profile kscreenlocker_greet @{exec_path} { @{sys}/devices/system/node/ r, @{sys}/devices/system/node/node@{int}/meminfo r, - @{PROC}/@{pid}/cgroup r, - @{PROC}/@{pid}/cmdline r, - @{PROC}/@{pid}/fd/ r, - @{PROC}/@{pid}/loginuid r, - @{PROC}/@{pid}/mountinfo r, - @{PROC}/@{pid}/mounts r, + @{PROC}/@{pids}/cgroup r, + @{PROC}/@{pids}/cmdline r, + @{PROC}/@{pids}/fd/ r, + @{PROC}/@{pids}/loginuid r, + @{PROC}/@{pids}/mountinfo r, + @{PROC}/@{pids}/mounts r, + @{PROC}/@{pids}/status r, owner @{PROC}/@{pid}/loginuid r, /dev/tty r, diff --git a/apparmor.d/groups/kde/ksecretd b/apparmor.d/groups/kde/ksecretd new file mode 100644 index 0000000000..588d5a861b --- /dev/null +++ b/apparmor.d/groups/kde/ksecretd @@ -0,0 +1,31 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/ksecretd +profile ksecretd @{exec_path} flags=(attach_disconnected,mediate_deleted) { + include + include + include + + @{exec_path} mr, + + owner @{user_config_dirs}/kwalletrc r, + + owner @{user_share_dirs}/kwalletd/ rw, + owner @{user_share_dirs}/kwalletd/** rwkl -> @{user_share_dirs}/kwalletd/#@{int}, + + owner @{run}/user/@{uid}/kwallet5.socket rw, + + @{PROC}/sys/kernel/random/boot_id r, + + /dev/tty r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/kde/ksmserver b/apparmor.d/groups/kde/ksmserver index eb53bc0783..ed661ff896 100644 --- a/apparmor.d/groups/kde/ksmserver +++ b/apparmor.d/groups/kde/ksmserver @@ -11,7 +11,8 @@ profile ksmserver @{exec_path} flags=(attach_disconnected,mediate_deleted) { include include include - include + include + include include include include @@ -20,6 +21,14 @@ profile ksmserver @{exec_path} flags=(attach_disconnected,mediate_deleted) { ptrace (read) peer=kbuildsycoca5, + #aa:dbus own bus=session name=org.freedesktop.ScreenSaver + #aa:dbus own bus=session name=org.kde.ksmserver path=/KSMServer + #aa:dbus own bus=session name=org.kde.KSMServerInterface path=/KSMServer + #aa:dbus own bus=session name=org.kde.screensaver + + #aa:dbus talk bus=session name=org.kde.KGlobalAccel path=/ label=kglobalacceld + #aa:dbus talk bus=session name=org.kde.KWin.Session path=/Session label=kwin_wayland + @{exec_path} mr, @{bin}/rm rix, @@ -49,9 +58,6 @@ profile ksmserver @{exec_path} flags=(attach_disconnected,mediate_deleted) { owner @{user_config_dirs}/ksmserverrc rw, owner @{user_config_dirs}/ksmserverrc.@{rand6} rwl, owner @{user_config_dirs}/ksmserverrc.lock rwk, - owner @{user_config_dirs}/menus/ r, - owner @{user_config_dirs}/menus/applications-merged/ r, - owner @{user_config_dirs}/session/*_[0-9]*_[0-9]*_[0-9]* rw, owner @{user_share_dirs}/kservices{5,6}/ r, owner @{user_share_dirs}/kservices{5,6}/ServiceMenus/ r, @@ -64,7 +70,7 @@ profile ksmserver @{exec_path} flags=(attach_disconnected,mediate_deleted) { owner @{tmp}/@{rand6} rw, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, owner @{run}/user/@{uid}/KSMserver__[0-9] rw, /dev/tty r, diff --git a/apparmor.d/groups/kde/ksmserver-logout-greeter b/apparmor.d/groups/kde/ksmserver-logout-greeter index 01fe51783e..ee35f7ff9d 100644 --- a/apparmor.d/groups/kde/ksmserver-logout-greeter +++ b/apparmor.d/groups/kde/ksmserver-logout-greeter @@ -9,8 +9,9 @@ include @{exec_path} = @{bin}/ksmserver-logout-greeter @{exec_path} += @{lib}/@{multiarch}/{,libexec/}ksmserver-logout-greeter -profile ksmserver-logout-greeter @{exec_path} flags=(attach_disconnected) { +profile ksmserver-logout-greeter @{exec_path} flags=(attach_disconnected,mediate_deleted) { include + include include include include @@ -18,6 +19,11 @@ profile ksmserver-logout-greeter @{exec_path} flags=(attach_disconnected) { include include + #aa:dbus own bus=session name=org.kde.LogoutPrompt path=/LogoutPrompt + + #aa:dbus talk bus=session name=org.kde.LogoutPrompt path=/Shutdown label=plasma-shutdown + #aa:dbus talk bus=session name=org.kde.KWin label=kwin_wayland + @{exec_path} mr, @{lib}/os-release r, @@ -31,6 +37,7 @@ profile ksmserver-logout-greeter @{exec_path} flags=(attach_disconnected) { /var/lib/AccountsService/icons/ r, owner @{HOME}/ r, + owner @{HOME}/.face r, owner @{user_cache_dirs}/ r, owner @{user_cache_dirs}/#@{int} rwlk, @@ -53,7 +60,6 @@ profile ksmserver-logout-greeter @{exec_path} flags=(attach_disconnected) { @{PROC}/sys/dev/i915/perf_stream_paranoid r, owner @{PROC}/@{pid}/exe r, - owner @{PROC}/@{pid}/status r, include if exists } diff --git a/apparmor.d/groups/kde/ksplashqml b/apparmor.d/groups/kde/ksplashqml index be59fe8425..3796328ad8 100644 --- a/apparmor.d/groups/kde/ksplashqml +++ b/apparmor.d/groups/kde/ksplashqml @@ -7,18 +7,25 @@ abi , include @{exec_path} = @{bin}/ksplashqml -profile ksplashqml @{exec_path} { +profile ksplashqml @{exec_path} flags=(attach_disconnected,mediate_deleted) { include + include include include include include + ptrace read peer=startplasma, + + #aa:dbus own bus=session name=org.kde.KSplash path=/KSplash + @{exec_path} mr, @{lib}/libheif/ r, @{lib}/libheif/*.so* rm, + @{bin}/ r, + /usr/share/color-schemes/* r, /usr/share/plasma/** r, /etc/machine-id r, diff --git a/apparmor.d/groups/kde/kstart b/apparmor.d/groups/kde/kstart index fa0f88f754..2773458638 100644 --- a/apparmor.d/groups/kde/kstart +++ b/apparmor.d/groups/kde/kstart @@ -10,12 +10,10 @@ include @{exec_path} = @{bin}/kstart profile kstart @{exec_path} flags=(attach_disconnected) { include - include - include include + include include include - include include @{exec_path} mr, diff --git a/apparmor.d/groups/kde/kwalletd b/apparmor.d/groups/kde/kwalletd index c4e25e9ffd..40f5483154 100644 --- a/apparmor.d/groups/kde/kwalletd +++ b/apparmor.d/groups/kde/kwalletd @@ -11,14 +11,17 @@ include profile kwalletd @{exec_path} { include include + include include include include - include include include include + #aa:dbus own bus=session name=org.freedesktop.secrets + #aa:dbus own bus=session name=org.kde.kwalletd{,5,6} + @{exec_path} mr, @{bin}/gpgconf rCx -> gpg, @@ -35,10 +38,13 @@ profile kwalletd @{exec_path} { owner @{user_config_dirs}/kwalletrc r, owner @{user_config_dirs}/kwalletrc rwl -> @{user_config_dirs}/#@{int}, owner @{user_config_dirs}/kwalletrc.lock rwk, + owner @{user_config_dirs}/Kvantum/{,**} r, owner @{user_share_dirs}/kwalletd/ rw, owner @{user_share_dirs}/kwalletd/** rwkl -> @{user_share_dirs}/kwalletd/#@{int}, + owner @{run}/user/@{uid}/kwallet{5,6}.socket rw, + owner @{tmp}/kwalletd5.* rw, owner @{PROC}/@{pid}/cmdline r, diff --git a/apparmor.d/groups/kde/kwalletmanager b/apparmor.d/groups/kde/kwalletmanager index dc64cbb9e5..5ffcafd4f2 100644 --- a/apparmor.d/groups/kde/kwalletmanager +++ b/apparmor.d/groups/kde/kwalletmanager @@ -36,9 +36,6 @@ profile kwalletmanager @{exec_path} { owner @{user_config_dirs}/kwalletrc rw, owner @{user_config_dirs}/kwalletrc.* rwl -> @{user_config_dirs}/#@{int}, owner @{user_config_dirs}/kwalletrc.lock rwk, - owner @{user_config_dirs}/session/#@{int} rw, - owner @{user_config_dirs}/session/kwalletmanager5_* rwl -> @{user_config_dirs}/session/#@{int}, - owner @{user_config_dirs}/session/kwalletmanager5_*.lock rwk, @{PROC}/@{pid}/mountinfo r, @{PROC}/@{pid}/mounts r, diff --git a/apparmor.d/groups/kde/kwin_wayland b/apparmor.d/groups/kde/kwin_wayland index 101affd8c4..4d1fa5013c 100644 --- a/apparmor.d/groups/kde/kwin_wayland +++ b/apparmor.d/groups/kde/kwin_wayland @@ -7,30 +7,50 @@ abi , include @{exec_path} = @{bin}/kwin_wayland -profile kwin_wayland @{exec_path} flags=(attach_disconnected mediate_deleted) { +profile kwin_wayland @{exec_path} flags=(attach_disconnected,mediate_deleted) { include include + include + include include include include include include + include + # See https://community.kde.org/Distributions/Packaging_Recommendations#KWin_package_configuration capability sys_nice, + capability sys_ptrace, - ptrace (read), + network netlink raw, - signal (receive) set=term peer=sddm, - signal (receive) set=(kill, term) peer=kwin_wayland_wrapper, - signal (send) set=(kill, term) peer=xwayland, + ptrace read, - network netlink raw, + signal receive set=term peer=sddm, + signal receive set=(kill, term) peer=kwin_wayland_wrapper, + signal send set=(kill, term) peer=xwayland, + signal send set=term peer=unconfined, + signal send set=term peer=plasma-keyboard, + + unix type=stream peer=(label=xkbcomp), + unix type=stream peer=(label=xwayland), + + #aa:dbus own bus=session name=org.freedesktop.ScreenSaver + #aa:dbus own bus=session name=org.kde.kglobalaccel path=/kglobalaccel + #aa:dbus own bus=session name=org.kde.KWin + #aa:dbus own bus=session name=org.kde.NightColor path=/ColorCorrect + #aa:dbus own bus=session name=org.kde.screensaver + + #aa:dbus talk bus=system name=org.freedesktop.login1 label=systemd-logind + #aa:dbus talk bus=session name=org.kde.ActivityManager path=/ActivityManager label=kactivitymanagerd @{exec_path} mr, /etc/xdg/Xwayland-session.d/00-at-spi Cx -> at-spi, /etc/xdg/Xwayland-session.d/00-pulseaudio-x11 Cx -> pulseaudio, + /etc/xdg/Xwayland-session.d/10-ibus-x11 Cx -> ibus, #aa:exec kscreenlocker_greet /usr/share/color-schemes/*.colors r, @@ -38,6 +58,7 @@ profile kwin_wayland @{exec_path} flags=(attach_disconnected mediate_deleted) { /usr/share/kglobalaccel/{,**} r, /usr/share/kservices{5,6}/{,**} r, /usr/share/kservicetypes5/{,*.desktop} r, + /usr/share/kwin-wayland/{,**} r, /usr/share/kwin/{,**} r, /usr/share/libinput-*/{,**} r, /usr/share/libinput/{,**} r, @@ -47,25 +68,23 @@ profile kwin_wayland @{exec_path} flags=(attach_disconnected mediate_deleted) { /etc/pipewire/client.conf.d/ r, /etc/xdg/** r, - /etc/machine-id r, - /var/lib/dbus/machine-id r, - / r, owner @{HOME}/ r, owner @{sddm_cache_dirs}/#@{int} rwk, - owner @{sddm_cache_dirs}/fontconfig/* rwk, - owner @{sddm_cache_dirs}/fontconfig/*-le64.cache-@{int}.LCK l -> @{sddm_cache_dirs}/fontconfig/*-le64.cache-@{int}.TMP-@{rand6}, - owner @{sddm_cache_dirs}/fontconfig/*-le64.cache-@{int}{,TMP-@{rand6},NEW,LCK} w, owner @{sddm_cache_dirs}/ksycoca{5,6}_* rwkl -> @{sddm_cache_dirs}/#@{int}, + owner @{sddm_cache_dirs}/kwin/ rw, + owner @{sddm_cache_dirs}/kwin/** rwlk, owner @{sddm_config_dirs}/#@{int} rw, owner @{sddm_config_dirs}/kcminputrc r, + owner @{sddm_config_dirs}/kdedefaults/* r, owner @{sddm_config_dirs}/kdeglobals r, owner @{sddm_config_dirs}/kglobalshortcutsrc.lock rwk, - owner @{sddm_config_dirs}/kglobalshortcutsrc{,.@{rand6}} rwl -> @{sddm_config_dirs}/#@{int}, + owner @{sddm_config_dirs}/kglobalshortcutsrc{,.@{rand6}} rwl, + owner @{sddm_config_dirs}/kwinoutputconfig.json rw, owner @{sddm_config_dirs}/kwinrc.lock rwk, - owner @{sddm_config_dirs}/kwinrc{,.@{rand6}} rwl -> @{sddm_config_dirs}/#@{int}, + owner @{sddm_config_dirs}/kwinrc{,.@{rand6}} rwl, owner @{user_cache_dirs}/ r, owner @{user_cache_dirs}/ksvg-elements r, @@ -80,63 +99,72 @@ profile kwin_wayland @{exec_path} flags=(attach_disconnected mediate_deleted) { owner @{user_config_dirs}/breezerc r, owner @{user_config_dirs}/kdedefaults/* r, owner @{user_config_dirs}/kglobalshortcutsrc.lock rwk, - owner @{user_config_dirs}/kglobalshortcutsrc{,.@{rand6}} rwl -> @{user_config_dirs}/#@{int}, + owner @{user_config_dirs}/kglobalshortcutsrc{,.@{rand6}} rwl, owner @{user_config_dirs}/khotkeysrc r, owner @{user_config_dirs}/klaunchrc r, owner @{user_config_dirs}/kscreenlockerrc r, owner @{user_config_dirs}/kwinoutputconfig.json rw, owner @{user_config_dirs}/kwinrc.lock rwk, - owner @{user_config_dirs}/kwinrc{,.@{rand6}} rwl -> @{user_config_dirs}/#@{int}, + owner @{user_config_dirs}/kwinrc{,.@{rand6}} rwl, owner @{user_config_dirs}/kwinrulesrc r, owner @{user_config_dirs}/kxkbrc r, owner @{user_config_dirs}/menus/** r, owner @{user_config_dirs}/plasmarc r, owner @{user_config_dirs}/session/* r, + owner @{user_config_dirs}/breezerc w, + owner @{user_config_dirs}/breezerc.@{rand6} rw, + owner @{user_config_dirs}/breezerc.lock rwk, + owner @{user_config_dirs}/Kvantum/{,**} r, + owner @{user_config_dirs}/breezerc.@{rand6} rwl -> @{user_config_dirs}/#@{int}, + owner @{user_share_dirs}/aurorae/themes/{,**} r, owner @{user_share_dirs}/kscreen/* r, + owner @{user_share_dirs}/kwin/effects/{,**} r, owner @{user_share_dirs}/kwin/scripts/{,**} r, + owner @{user_share_dirs}/plasma/desktoptheme/{,**} r, + owner @{user_share_dirs}/smod/decorations/{,**} r, + + owner @{run}/user/@{uid}/pipewire-@{int} rw, owner /dev/shm/.org.chromium.Chromium.@{rand6} rw, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, @{sys}/bus/ r, @{sys}/class/ r, @{sys}/class/drm/ r, @{sys}/class/input/ r, @{sys}/devices/**/uevent r, - @{sys}/devices/virtual/dmi/id/bios_vendor r, - @{sys}/devices/virtual/dmi/id/board_vendor r, - @{sys}/devices/virtual/dmi/id/product_name r, - @{sys}/devices/virtual/dmi/id/sys_vendor r, - @{run}/udev/data/+acpi:* r, # for ACPI + @{run}/udev/data/+acpi:* r, # Exposes ACPI objects (power buttons, batteries, thermal) @{run}/udev/data/+dmi:* r, # for motherboard info - @{run}/udev/data/+hid:* r, # for HID subsystem + @{run}/udev/data/+hid:* r, # For Human Interface Device (mice, controllers, drawing tablets, scanners) @{run}/udev/data/+input:input@{int} r, # for mouse, keyboard, touchpad @{run}/udev/data/+pci:* r, # Identifies all PCI devices (CPU, GPU, Network, Disks, USB, etc.) - @{run}/udev/data/+platform:* r, # for ? + @{run}/udev/data/+platform:* r, # Identifies onboard devices (laptop/board model, power controllers, thermal sensors) @{run}/udev/data/+serio:* r, # for touchpad @{run}/udev/data/+sound:card@{int} r, # for sound card - @{run}/udev/data/+usb:* r, + @{run}/udev/data/+usb:* r, # Identifies all USB devices @{run}/udev/data/c10:@{int} r, # for non-serial mice, misc features @{run}/udev/data/c13:@{int} r, # for /dev/input/* @{run}/udev/data/c189:@{int} r, # for /dev/bus/usb/** - @{run}/udev/data/c226:@{int} r, # for /dev/dri/card* - @{PROC}/@{pid}/task/@{tid}/comm rw, + owner @{PROC}/@{pid}/task/@{tid}/comm rw, @{att}/dev/input/event@{int} rw, @{att}/dev/dri/card@{int} rw, /dev/tty r, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, profile at-spi { include + include include + unix bind type=stream addr=@@{udbus}/bus/busctl/busctl, + @{sh_path} r, @{bin}/busctl rix, @{bin}/sed rix, @@ -164,6 +192,21 @@ profile kwin_wayland @{exec_path} flags=(attach_disconnected mediate_deleted) { include if exists } + profile ibus { + include + include + + @{sh_path} r, + @{lib}/{,ibus/}ibus-x11 rPx, + + /etc/xdg/Xwayland-session.d/10-ibus-x11 r, + + /home/ r, + owner @{HOME}/ r, + + include if exists + } + include if exists } diff --git a/apparmor.d/groups/kde/kwin_wayland_wrapper b/apparmor.d/groups/kde/kwin_wayland_wrapper index 1a7573d775..5b81e7c7b1 100644 --- a/apparmor.d/groups/kde/kwin_wayland_wrapper +++ b/apparmor.d/groups/kde/kwin_wayland_wrapper @@ -9,11 +9,14 @@ include @{exec_path} = @{bin}/kwin_wayland_wrapper profile kwin_wayland_wrapper @{exec_path} { include - include + include + include include signal (send) set=(term, kill) peer=kwin_wayland, + #aa:dbus own bus=session name=org.kde.KWinWrapper + @{exec_path} mr, @{bin}/kwin_wayland rPx, diff --git a/apparmor.d/groups/kde/kwin_x11 b/apparmor.d/groups/kde/kwin_x11 index e05e443ff2..3c58a7ecb3 100644 --- a/apparmor.d/groups/kde/kwin_x11 +++ b/apparmor.d/groups/kde/kwin_x11 @@ -9,7 +9,8 @@ include @{exec_path} = @{bin}/kwin_x11 profile kwin_x11 @{exec_path} { include - include + include + include include include include @@ -22,13 +23,22 @@ profile kwin_x11 @{exec_path} { network inet6 stream, network netlink raw, + #aa:dbus own bus=session name=org.kde.KWin + #aa:dbus own bus=session name=org.kde.NightColor path=/ColorCorrect + + #aa:dbus talk bus=session name=org.kde.ActivityManager label=kactivitymanagerd + #aa:dbus talk bus=session name=org.kde.KGlobalAccel path=/kglobalaccel label=kglobalacceld + @{exec_path} mrix, @{sh_path} rix, + @{bin}/kdialog rix, @{lib}/kwin_killer_helper rix, + @{bin}/ r, #aa:exec drkonqi + /usr/share/kwin-x11/{,**} r, /usr/share/kwin/{,**} r, /usr/share/plasma/desktoptheme/{,**} r, @@ -47,6 +57,7 @@ profile kwin_x11 @{exec_path} { owner @{user_cache_dirs}/session/#@{int} rw, owner @{user_config_dirs}/#@{int} rw, + owner @{user_config_dirs}/kaccessrc r, owner @{user_config_dirs}/kdedefaults/plasmarc r, owner @{user_config_dirs}/kwinoutputconfig.json rw, owner @{user_config_dirs}/kwinrc.lock rwk, @@ -54,8 +65,6 @@ profile kwin_x11 @{exec_path} { owner @{user_config_dirs}/kwinrulesrc r, owner @{user_config_dirs}/kxkbrc r, owner @{user_config_dirs}/plasmarc r, - owner @{user_config_dirs}/session/#@{int} rw, - owner @{user_config_dirs}/session/kwin_* rwk, owner @{user_share_dirs}/kwin/scripts/ r, diff --git a/apparmor.d/groups/kde/okular b/apparmor.d/groups/kde/okular index 7618a10d46..a25532d208 100644 --- a/apparmor.d/groups/kde/okular +++ b/apparmor.d/groups/kde/okular @@ -10,7 +10,7 @@ include @{exec_path} = @{bin}/okular profile okular @{exec_path} { include - include + include include include include @@ -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, @@ -38,12 +40,9 @@ profile okular @{exec_path} { /usr/share/color-schemes/{,**} r, /usr/share/okular/{,**} r, - /usr/share/poppler/{,**} r, /etc/fstab r, /etc/xdg/dolphinrc r, - /etc/xdg/menus/ r, - /etc/xdg/menus/applications-merged/ r, / r, @{MOUNTS}/ r, @@ -51,43 +50,43 @@ profile okular @{exec_path} { owner @{user_cache_dirs}/okular/{,**} rw, owner @{user_config_dirs}/#@{int} rw, - owner @{user_config_dirs}/okularpartrc rw, - owner @{user_config_dirs}/okularpartrc.@{rand6} rwl -> @{user_config_dirs}/#@{int}, - owner @{user_config_dirs}/okularpartrc.lock rwk, - owner @{user_config_dirs}/okularrc rw, - owner @{user_config_dirs}/okularrc.@{rand6} rwl -> @{user_config_dirs}/#@{int}, - owner @{user_config_dirs}/okularrc.lock rwk, - owner @{user_config_dirs}/okular-generator-popplerrc r, owner @{user_config_dirs}/KDE/*.conf r, owner @{user_config_dirs}/kioslaverc r, owner @{user_config_dirs}/kservicemenurc r, owner @{user_config_dirs}/kwalletrc r, - owner @{user_config_dirs}/menus/ r, - owner @{user_config_dirs}/menus/applications-merged/ r, + owner @{user_config_dirs}/okular-generator-popplerrc r, + owner @{user_config_dirs}/okularpartrc rw, + owner @{user_config_dirs}/okularpartrc.@{rand6} rwl, + owner @{user_config_dirs}/okularpartrc.lock rwk, + owner @{user_config_dirs}/okularrc rw, + owner @{user_config_dirs}/okularrc.@{rand6} rwl, + owner @{user_config_dirs}/okularrc.lock rwk, owner @{user_share_dirs}/#@{int} rw, owner @{user_share_dirs}/kxmlgui{5,6}/okular/{,*} r, owner @{user_share_dirs}/okular/ rw, - owner @{user_share_dirs}/okular/** rwlk -> @{user_share_dirs}/okular/**, - owner @{user_share_dirs}/recently-used.xbel.@{rand6} rwl -> @{user_share_dirs}/#@{int}, - owner @{user_share_dirs}/recently-used.xbel.lock rk, + owner @{user_share_dirs}/okular/** rwlk, owner @{user_share_dirs}/user-places.xbel r, 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, owner @{user_state_dirs}/okularstaterc.lock rwk, + owner @{tmp}/@{hex12}@{h} w, # when opening pdf files as attchments in Thunderbird owner @{tmp}/#@{int} rw, - owner @{tmp}/okular.@{rand6} rwl -> /tmp/#@{int}, - owner @{tmp}/okular_@{rand6}.ps rwl -> /tmp/#@{int}, + owner @{tmp}/kmail2.@{rand6} r, owner @{tmp}/messageviewer_attachment_@{rand6}/{,*} r, # files opened from KMail as mail attachment, + owner @{tmp}/okular_@{rand6}.ps rwl -> /tmp/#@{int}, + owner @{tmp}/okular.@{rand6} rwl -> /tmp/#@{int}, owner @{run}/user/@{uid}/#@{int} rw, - owner @{run}/user/@{uid}/okular@{rand6}.@{int}.kioworker.socket rwl -> @{run}/user/@{uid}/#@{int}, + owner @{run}/user/@{uid}/okular@{rand6}.@{int}.kioworker.socket rwl, + owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/mounts r, + owner @{PROC}/@{pid}/stat r, profile gpg { include diff --git a/apparmor.d/groups/kde/pam_kwallet_init b/apparmor.d/groups/kde/pam_kwallet_init index 764917a1f1..84aa2f5786 100644 --- a/apparmor.d/groups/kde/pam_kwallet_init +++ b/apparmor.d/groups/kde/pam_kwallet_init @@ -18,6 +18,8 @@ profile pam_kwallet_init @{exec_path} { /dev/tty rw, + owner @{run}/user/@{uid}/kwallet5.socket rw, + include if exists } diff --git a/apparmor.d/groups/kde/plasma-browser-integration-host b/apparmor.d/groups/kde/plasma-browser-integration-host index dce3545f72..9835e65500 100644 --- a/apparmor.d/groups/kde/plasma-browser-integration-host +++ b/apparmor.d/groups/kde/plasma-browser-integration-host @@ -10,7 +10,6 @@ include profile plasma-browser-integration-host @{exec_path} { include include - include include include include @@ -21,22 +20,19 @@ profile plasma-browser-integration-host @{exec_path} { @{exec_path} mr, - /etc/xdg/menus/applications-merged/ r, - /usr/share/kservices{5,6}/{,**} r, - /etc/xdg/menus/ r, /etc/xdg/taskmanagerrulesrc r, - owner @{user_config_dirs}/menus/ r, - owner @{user_config_dirs}/menus/applications-merged/ r, - owner @{user_share_dirs}/kservices{5,6}/ r, owner @{user_share_dirs}/kservices{5,6}/ServiceMenus/ r, owner @{PROC}/@{pid}/cmdline r, owner @{PROC}/@{pid}/stat r, + owner /tmp/#@{int} rw, + owner @{tmp}/plasma-browser-integration_artwork_@{rand6}.jpg rwl -> /tmp/#@{int}, + include if exists } diff --git a/apparmor.d/groups/kde/plasma-keyboard b/apparmor.d/groups/kde/plasma-keyboard new file mode 100644 index 0000000000..cdadff45ff --- /dev/null +++ b/apparmor.d/groups/kde/plasma-keyboard @@ -0,0 +1,31 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/plasma-keyboard +profile plasma-keyboard @{exec_path} flags=(attach_disconnected,mediate_deleted) { + include + include + include + + signal receive set=term peer=kwin_wayland, + + @{exec_path} mr, + + /usr/share/plasma/keyboard/{,**} r, + + owner @{sddm_cache_dirs}/plasma-keyboard/ rw, + owner @{sddm_cache_dirs}/plasma-keyboard/** rwkl, + owner @{sddm_config_dirs}/kdedefaults/* r, + owner @{sddm_config_dirs}/kdeglobals r, + + @{PROC}/sys/kernel/random/boot_id r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/kde/plasma-login-greeter b/apparmor.d/groups/kde/plasma-login-greeter new file mode 100644 index 0000000000..072d5ee72f --- /dev/null +++ b/apparmor.d/groups/kde/plasma-login-greeter @@ -0,0 +1,51 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/plasma-login-greeter +profile plasma-login-greeter @{exec_path} flags=(attach_disconnected,mediate_deleted) { + include + include + include + include + include + include + include + + network netlink raw, + + dbus send bus=system path=/org/freedesktop/DBus + interface=org.freedesktop.DBus + member=ListActivatableNames + peer=(name=org.freedesktop.DBus, label="@{p_dbus_system}"), + + @{exec_path} mr, + + /usr/share/plasma/{,**} r, + /usr/share/wayland-sessions/{,*.desktop} r, + + @{etc_ro}/login.defs r, + @{etc_ro}/login.defs.d/{,*} r, + /etc/fstab r, + + /var/lib/AccountsService/icons/@{user} r, + + / r, + + owner @{SDDM_HOME}/** rw, + owner @{sddm_cache_dirs}/** mrwkl -> @{sddm_cache_dirs}/**, + + owner @{tmp}/plasmalogin--@{rand6} rw, + + @{sys}/devices/**/uevent r, + + owner @{PROC}/@{pid}/mountinfo r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/kde/plasma-login-wallpaper b/apparmor.d/groups/kde/plasma-login-wallpaper new file mode 100644 index 0000000000..7ba1ca781d --- /dev/null +++ b/apparmor.d/groups/kde/plasma-login-wallpaper @@ -0,0 +1,30 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/plasma-login-wallpaper +profile plasma-login-wallpaper @{exec_path} { + include + include + include + + @{exec_path} mr, + + /usr/share/plasma/{,**} r, + /usr/share/wallpapers/{,**} r, + + @{etc_ro}/login.defs r, + + owner @{sddm_cache_dirs}/plasma-login-wallpaper/ rw, + owner @{sddm_cache_dirs}/plasma-login-wallpaper/** rwkl, + owner @{sddm_config_dirs}/kdedefaults/* r, + owner @{sddm_config_dirs}/kdeglobals r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/kde/plasma_session b/apparmor.d/groups/kde/plasma_session index 1fbeda384b..5d38125940 100644 --- a/apparmor.d/groups/kde/plasma_session +++ b/apparmor.d/groups/kde/plasma_session @@ -36,7 +36,6 @@ profile plasma_session @{exec_path} { /etc/xdg/autostart/ r, /etc/xdg/autostart/*.desktop r, - /etc/xdg/menus/ r, owner @{user_config_dirs}/kdedefaults/ksplashrc r, owner @{user_config_dirs}/plasma-welcomerc r, diff --git a/apparmor.d/groups/kde/plasma_waitforname b/apparmor.d/groups/kde/plasma_waitforname index a509135af2..e809e65fd4 100644 --- a/apparmor.d/groups/kde/plasma_waitforname +++ b/apparmor.d/groups/kde/plasma_waitforname @@ -7,8 +7,9 @@ abi , include @{exec_path} = @{bin}/plasma_waitforname -profile plasma_waitforname @{exec_path} { +profile plasma_waitforname @{exec_path} flags=(attach_disconnected) { include + include include include diff --git a/apparmor.d/groups/kde/plasmalogin b/apparmor.d/groups/kde/plasmalogin new file mode 100644 index 0000000000..8b261caf7a --- /dev/null +++ b/apparmor.d/groups/kde/plasmalogin @@ -0,0 +1,39 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/plasmalogin +profile plasmalogin @{exec_path} flags=(attach_disconnected) { + include + include + include + include + + capability chown, + capability net_admin, + capability sys_tty_config, + + signal send set=term peer=plasmalogin-helper, + + @{exec_path} mr, + + @{lib}/plasmalogin-helper Px, + + /usr/share/wayland-sessions/plasma.desktop r, + + /tmp/.@{rand6}/ rw, + /tmp/.@{rand6}/** rw, + /tmp/plasmalogin--@{rand6} rw, + /tmp/plasmalogin-auth-@{uuid} rw, + + /dev/tty rw, + /dev/tty@{u8} rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/kde/plasmalogin-helper b/apparmor.d/groups/kde/plasmalogin-helper new file mode 100644 index 0000000000..13a7d03bba --- /dev/null +++ b/apparmor.d/groups/kde/plasmalogin-helper @@ -0,0 +1,94 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/plasmalogin-helper +profile plasmalogin-helper @{exec_path} flags=(attach_disconnected) { + include + include + include + include + include + + capability audit_write, + capability chown, + capability dac_read_search, + capability fowner, + capability kill, + capability net_admin, + capability setgid, + capability setuid, + capability sys_tty_config, + + network netlink raw, + + unix bind type=stream addr=@@{udbus}/bus/plasmalogin-hel/system, + + signal receive set=term peer=plasmalogin, + signal send set=term peer=startplasma-login-wayland, + signal send set=term peer=startplasma, + + @{exec_path} mr, + + @{bin}/startplasma-login-wayland Px, + @{shells_path} Px -> plasmalogin-shell, + @{bin}/ksecretd PUx, + + @{bin}/cat rix, + @{bin}/find rix, + @{bin}/tr rix, + @{bin}/tty rix, + @{bin}/xargs rix, + + @{bin}/pidof Px, + @{bin}/flatpak Cx -> flatpak, + + /usr/share/plasmalogin/scripts/wayland-session rix, + /usr/share/plasmalogin/scripts/Xsession rix, + /usr/share/plasmalogin/scripts/Xsetup rix, + /usr/share/plasmalogin/scripts/Xstop rix, + + @{etc_ro}/profile.d/{,*} r, + /etc/debuginfod/{,*} r, + /etc/machine-id r, + /etc/profile r, + /etc/shells r, + + /var/lib/lastlog/ r, + /var/lib/lastlog/* rwk, + + owner @{SDDM_HOME}/ rw, + + owner @{user_share_dirs}/kwalletd/ rw, + owner @{user_share_dirs}/kwalletd/kdewallet.salt rw, + owner @{user_share_dirs}/plasmalogin/wayland-session.log w, + + /tmp/plasmalogin-auth-@{uuid} rw, + + @{run}/faillock/@{user} rwk, + @{run}/systemd/io.systemd.Login rw, + owner @{run}/user/@{uid}/kwallet5.socket w, + + @{PROC}/@{pid}/loginuid w, + @{PROC}/@{pid}/uid_map r, + owner @{PROC}/@{pid}/fd/ r, + + /dev/tty@{u8} rw, + /dev/tty rw, + + profile flatpak { + include + + @{bin}/flatpak mr, + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/kde/plasmalogin-shell b/apparmor.d/groups/kde/plasmalogin-shell new file mode 100644 index 0000000000..6e964b513d --- /dev/null +++ b/apparmor.d/groups/kde/plasmalogin-shell @@ -0,0 +1,52 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/plasmalogin-shell +profile plasmalogin-shell @{exec_path} { + include + include + include + + @{shells_path} mr, + + @{bin}/cat rix, + @{bin}/find rix, + @{bin}/tr rix, + @{bin}/tty rix, + @{bin}/xargs rix, + + @{bin}/pidof Px, + @{bin}/flatpak Cx -> flatpak, + + @{bin}/startplasma-wayland Px, + @{bin}/startplasma-x11 Px, + + @{lib}/plasma-dbus-run-session-if-needed rix, + @{lib}/@{multiarch}/libexec/plasma-dbus-run-session-if-needed rix, + + /usr/share/plasmalogin/scripts/{,**} r, + + /etc/debuginfod/{,*} r, + + owner @{user_share_dirs}/plasmalogin/wayland-session.log w, + + owner @{PROC}/@{pid}/fd/ r, + + profile flatpak { + include + include + + @{bin}/flatpak mr, + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/kde/plasmashell b/apparmor.d/groups/kde/plasmashell index 07fbc8e14e..6b11a9db4a 100644 --- a/apparmor.d/groups/kde/plasmashell +++ b/apparmor.d/groups/kde/plasmashell @@ -7,14 +7,13 @@ abi , include @{exec_path} = @{bin}/plasmashell -profile plasmashell @{exec_path} flags=(mediate_deleted) { +profile plasmashell @{exec_path} flags=(attach_disconnected,mediate_deleted) { include include include include - include - include - include + include + include include include include @@ -26,7 +25,9 @@ profile plasmashell @{exec_path} flags=(mediate_deleted) { include include include - include + include + include + include userns, @@ -43,22 +44,43 @@ profile plasmashell @{exec_path} flags=(mediate_deleted) { signal send, + # Owned by plasmashell + + #aa:dbus own bus=session name=com.canonical.Unity + #aa:dbus own bus=session name=org.freedesktop.Notifications + #aa:dbus own bus=session name=org.kde.JobViewServer + #aa:dbus own bus=session name=org.kde.klipper + #aa:dbus own bus=session name=org.kde.kuiserver + #aa:dbus own bus=session name=org.kde.plasmashell path=/PlasmaShell + #aa:dbus own bus=session name=org.kde.StatusNotifierHost-@{int} + + # Talk with plasmashell + + #aa:dbus talk bus=system name=org.freedesktop.NetworkManager label=NetworkManager + + #aa:dbus talk bus=session name=org.kde.kdeconnect path=/ label=kdeconnectd + #aa:dbus talk bus=session name=org.kde.KeyboardLayouts path=/Layouts label=kded + #aa:dbus talk bus=session name=org.kde.KGlobalAccel path=/kglobalaccel label="{kglobalacceld,kwin_wayland}" + #aa:dbus talk bus=session name=org.kde.KSplash path=/KSplash label=ksplashqml + #aa:dbus talk bus=session name=org.kde.KWin path=/ label="kwin_{wayland,x11}" + #aa:dbus talk bus=session name=org.kde.NightColor path=/ColorCorrect label="kwin_{wayland,x11}" + #aa:dbus talk bus=session name=org.kde.Solid.PowerManagement label=kde-powerdevil + #aa:dbus talk bus=session name=org.kde.StatusNotifierWatcher path=/StatusNotifierWatcher label=kded + @{exec_path} mr, @{lib}/libheif/ r, @{lib}/libheif/{,**} mr, @{bin}/dolphin rPx, - @{bin}/ksysguardd rix, + @{bin}/ksysguardd rPUx, @{bin}/plasma-discover rPUx, @{bin}/xrdb rPx, @{lib}/kf{5,6}/kdesu{,d} rix, #aa:exec kioworker - /opt/**/share/icons/{,**} r, - /opt/*/**/*.desktop r, - /opt/*/**/*.png r, + /snap/*/@{uid}/**.@{image_ext} r, /usr/share/*/icons/{,**} r, /usr/share/akonadi/{,**} r, /usr/share/desktop-directories/kf5-*.directory r, @@ -82,7 +104,6 @@ profile plasmashell @{exec_path} flags=(mediate_deleted) { /etc/appstream.conf r, /etc/fstab r, - /etc/ksysguarddrc r, /etc/machine-id r, /etc/os-release r, /etc/sensors.d/ r, @@ -90,16 +111,19 @@ profile plasmashell @{exec_path} flags=(mediate_deleted) { /etc/xdg/** r, /var/lib/AccountsService/icons/* r, + /var/lib/swcatalog/icons/**.png r, @{MOUNTS}/ r, + @{system_games_dirs}/**.@{icon_ext} r, @{HOME}/ r, + owner @{HOME}/.face r, owner @{HOME}/.mozilla/firefox/firefox-mpris/{,*} r, owner @{HOME}/.var/app/**.{png,jpg,svg} r, - owner @{HOME}/@{XDG_DESKTOP_DIR}/*.desktop r, + owner @{HOME}/@{XDG_DESKTOP_DIR}/* r, owner @{HOME}/@{XDG_WALLPAPERS_DIR}/{,**} r, - owner @{user_games_dirs}/**.{png,jpg,svg} r, - owner @{user_music_dirs}/**.{png,jpg,svg} r, + owner @{user_games_dirs}/**.@{icon_ext} r, + owner @{user_music_dirs}/**.@{icon_ext} r, owner @{user_pictures_dirs}/{,**} r, owner @{user_templates_dirs}/ r, @@ -144,13 +168,20 @@ profile plasmashell @{exec_path} flags=(mediate_deleted) { owner @{user_config_dirs}/klaunchrc r, owner @{user_config_dirs}/klipperrc r, owner @{user_config_dirs}/kmail2.notifyrc r, + owner @{user_config_dirs}/knfsshare r, + owner @{user_config_dirs}/konsole.notifyrc r, owner @{user_config_dirs}/korganizerrc r, owner @{user_config_dirs}/krunnerrc r, owner @{user_config_dirs}/ksmserverrc r, owner @{user_config_dirs}/kwalletrc r, owner @{user_config_dirs}/menus/{,**} r, owner @{user_config_dirs}/networkmanagement.notifyrc r, + owner @{user_config_dirs}/PlasmaUserFeedback r, owner @{user_config_dirs}/plasma* rwlk, + owner @{user_config_dirs}/kscreenlockerrc r, + owner @{user_config_dirs}/Kvantum/{,**} r, + + @{user_share_dirs}/plasma/** rPUx, owner @{user_share_dirs}/*/sessions/ r, owner @{user_share_dirs}/#@{int} rw, @@ -176,14 +207,21 @@ profile plasmashell @{exec_path} flags=(mediate_deleted) { owner @{user_share_dirs}/qalculate/{,**} r, owner @{user_share_dirs}/user-places.xbel{,*} rwl, owner @{user_share_dirs}/wallpapers/{,**} rw, + owner @{user_share_dirs}/knotifications6/apdatifier.notifyrc r, owner @{user_state_dirs}/#@{int} rw, + owner @{user_state_dirs}/kickerstaterc r, + owner @{user_state_dirs}/plasma/* r, owner @{user_state_dirs}/plasmashellstaterc rw, - owner @{user_state_dirs}/plasmashellstaterc.lock rwk, owner @{user_state_dirs}/plasmashellstaterc.@{rand6} rwl, + owner @{user_state_dirs}/plasmashellstaterc.lock rwk, + owner @{user_state_dirs}/UserFeedback.org.kde.plasmashell rw, + owner @{user_state_dirs}/UserFeedback.org.kde.plasmashell.@{rand6} rwl, + owner @{user_state_dirs}/UserFeedback.org.kde.plasmashell.lock rwk, /tmp/.mount_nextcl@{rand6}/{,*} r, owner @{tmp}/#@{int} rw, + owner @{tmp}/plasma-browser-integration_artwork_@{rand6}.jpg r, @{run}/mount/utab r, @{run}/user/@{uid}/gvfs/ r, @@ -198,11 +236,6 @@ profile plasmashell @{exec_path} flags=(mediate_deleted) { @{sys}/devices/platform/** r, @{sys}/devices/@{pci}/name r, - @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_cur_freq r, - @{sys}/devices/virtual/dmi/id/bios_vendor r, - @{sys}/devices/virtual/dmi/id/board_vendor r, - @{sys}/devices/virtual/dmi/id/product_name r, - @{sys}/devices/virtual/dmi/id/sys_vendor r, @{sys}/devices/virtual/thermal/**/{name,type} r, @{sys}/devices/virtual/thermal/thermal_zone@{int}/hwmon@{int}/ r, diff --git a/apparmor.d/groups/kde/sddm b/apparmor.d/groups/kde/sddm index 4d883303fa..d30a013f9a 100644 --- a/apparmor.d/groups/kde/sddm +++ b/apparmor.d/groups/kde/sddm @@ -11,15 +11,13 @@ include profile sddm @{exec_path} flags=(attach_disconnected,mediate_deleted) { include include - include - include - include - include + include include include include include include + include include capability audit_write, @@ -50,20 +48,12 @@ profile sddm @{exec_path} flags=(attach_disconnected,mediate_deleted) { signal (send) set=(term) peer=startplasma-wayland, signal (send) set=(term) peer=startlxqtwayland, - dbus receive bus=system path=/org/freedesktop/DisplayManager/Seat@{int} - interface=org.freedesktop.DBus.Introspectable - member=Introspect - peer=(name=:*, label=kscreenlocker-greet), + unix type=stream addr=@@{udbus}/bus/sddm-helper/system, - dbus receive bus=system path=/org/freedesktop/DisplayManager/Seat@{int} - interface=org.freedesktop.DBus.Properties - member=PropertiesChanged - peer=(name=:*, label=systemd-logind), + #aa:dbus own bus=system name=org.freedesktop.DisplayManager - dbus send bus=system path=/org/freedesktop/DisplayManager/Seat@{int} - interface=org.freedesktop.DBus.Introspectable - member=Introspect - peer=(name=org.freedesktop.DBus, label=kscreenlocker-greet), + #aa:dbus talk bus=system name=org.freedesktop.home1 interface=org.freedesktop.home1.Manager label="@{p_systemd_homed}" + #aa:dbus talk bus=system name=org.freedesktop.login1 interface=org.freedesktop.login1.Manager label="@{p_systemd_logind}" @{exec_path} mr, @@ -75,38 +65,51 @@ profile sddm @{exec_path} flags=(attach_disconnected,mediate_deleted) { @{lib}/{,sddm/}sddm-helper-start-x11user rix, @{shells_path} rix, + @{bin}/{,e}grep rix, + @{bin}/basename rix, @{bin}/cat rix, - @{bin}/checkproc rix, + @{bin}/date rix, + @{bin}/dirname rix, @{bin}/disable-paste rix, + @{bin}/find rix, + @{bin}/id rix, @{bin}/locale rix, @{bin}/manpath rix, @{bin}/mktemp rix, @{bin}/pidof rix, @{bin}/readlink rix, @{bin}/realpath rix, + @{bin}/sed rix, @{bin}/tr rix, @{bin}/tty rix, @{bin}/uname rix, + @{bin}/xargs rix, @{bin}/xdm r, @{bin}/xmodmap rix, + @{bin}/zoxide rix, + @{sbin}/checkproc rix, @{bin}/dbus-run-session rPx -> dbus-session, @{bin}/dbus-update-activation-environment rPx -> dbus-session, @{bin}/flatpak rPx, @{bin}/gnome-keyring-daemon rPx, @{bin}/Hyprland rPx, + @{bin}/ksecretd rPUx, @{bin}/kwalletd{5,6} rPx, @{bin}/kwin_wayland rPx, @{bin}/labwc rPx, @{bin}/sddm-greeter{,-qt6} rPx, + @{bin}/start-hyprland rPx, @{bin}/startlxqt rPx, @{bin}/startlxqtwayland rPx, @{bin}/startplasma-wayland rPx, @{bin}/startplasma-x11 rPx, @{bin}/sway rPUx, @{bin}/systemctl rCx -> systemctl, + @{bin}/uwsm rPUx, @{bin}/xauth rCx -> xauth, @{bin}/Xorg rPx, + @{bin}/xrandr rPx, @{bin}/xrdb rPx, @{bin}/xset rPx, @{bin}/xsetroot rPx, @@ -114,7 +117,7 @@ profile sddm @{exec_path} flags=(attach_disconnected,mediate_deleted) { @{etc_ro}/sddm/Xsession rPx, @{etc_ro}/X11/xdm/Xsession rPx, - /usr/etc/X11/xdm/Xsetup rix, + @{etc_ro}/X11/xdm/Xsetup rix, /usr/share/sddm/scripts/wayland-session rix, /usr/share/sddm/scripts/Xsession rix, /usr/share/sddm/scripts/Xsetup rix, @@ -129,10 +132,7 @@ profile sddm @{exec_path} flags=(attach_disconnected,mediate_deleted) { /etc/X11/xinit/xinitrc.d/{,*} r, - @{etc_ro}/environment r, - @{etc_ro}/security/limits.d/{,*.conf} r, @{etc_ro}/X11/Xmodmap r, - /etc/debuginfod/{,*} r, /etc/manpath.config r, /etc/default/locale r, /etc/locale.conf r, @@ -179,7 +179,8 @@ profile sddm @{exec_path} flags=(attach_disconnected,mediate_deleted) { owner @{tmp}/#@{int} rw, owner @{tmp}/sddm-auth* rw, - @{att}/@{run}/systemd/sessions/{,@{l}}@{int}.ref rw, + @{run}/systemd/io.systemd.Login rw, + @{att}@{run}/systemd/sessions/{,@{l}}@{int}.ref rw, @{run}/faillock/@{user} rwk, @{run}/sddm.pid rw, @@ -201,9 +202,67 @@ profile sddm @{exec_path} flags=(attach_disconnected,mediate_deleted) { owner @{PROC}/@{pid}/uid_map r, owner @{PROC}/1/limits r, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, /dev/tty rw, + profile shell { + include + include + include + + ptrace read, + + @{shells_path} mrix, + + @{bin}/{,e}grep rix, + @{bin}/basename rix, + @{bin}/cat rix, + @{bin}/date rix, + @{bin}/dirname rix, + @{bin}/disable-paste rix, + @{bin}/find rix, + @{bin}/id rix, + @{bin}/locale rix, + @{bin}/manpath rix, + @{bin}/mktemp rix, + @{bin}/pidof rix, + @{bin}/readlink rix, + @{bin}/realpath rix, + @{bin}/sed rix, + @{bin}/tr rix, + @{bin}/tty rix, + @{bin}/uname rix, + @{bin}/xargs rix, + @{bin}/xdm r, + @{bin}/xmodmap rix, + @{bin}/zoxide rix, + @{sbin}/checkproc rix, + + @{bin}/flatpak Px, + @{bin}/pacman Px -> sddm//pacman, + + @{bin}/startplasma-wayland rPx, + @{bin}/startplasma-x11 rPx, + + @{lib}/plasma-dbus-run-session-if-needed rix, + @{lib}/@{multiarch}/libexec/plasma-dbus-run-session-if-needed rix, + + /usr/share/sddm/scripts/{,**} r, + + /etc/debuginfod/{,*} r, + + owner @{user_share_dirs}/sddm/wayland-session.log w, + owner @{user_share_dirs}/sddm/xorg-session.log w, + + @{PROC}/ r, + @{PROC}/@{pids}/ r, + @{PROC}/@{pids}/cmdline r, + @{PROC}/@{pids}/stat r, + owner @{PROC}/@{pid}/fd/ r, + + include if exists + } + profile systemctl { include include @@ -231,6 +290,16 @@ profile sddm @{exec_path} flags=(attach_disconnected,mediate_deleted) { include if exists } + profile pacman { + include + + @{bin}/pacman mr, + + /var/lib/pacman/local/{,**} r, + + include if exists + } + include if exists } diff --git a/apparmor.d/groups/kde/sddm-greeter b/apparmor.d/groups/kde/sddm-greeter index f2c133cecc..682c8de6aa 100644 --- a/apparmor.d/groups/kde/sddm-greeter +++ b/apparmor.d/groups/kde/sddm-greeter @@ -8,21 +8,26 @@ abi , include @{exec_path} = @{bin}/sddm-greeter{,-qt6} -profile sddm-greeter @{exec_path} { +profile sddm-greeter @{exec_path} flags=(attach_disconnected,mediate_deleted) { include - include - include - include - include + include include include include include include include + include network netlink raw, + signal receive set=term peer=sddm, + + dbus send bus=system path=/org/freedesktop/DBus + interface=org.freedesktop.DBus + member=ListActivatableNames + peer=(name=org.freedesktop.DBus, label="@{p_dbus_system}"), + @{exec_path} mr, @{lib}/libheif/ r, @@ -41,8 +46,8 @@ profile sddm-greeter @{exec_path} { /etc/sddm.conf r, /etc/sddm.conf.d/{,*} r, /etc/xdg/plasmarc r, + /var/lib/AccountsService/icons/* r, - /var/lib/dbus/machine-id r, @{SDDM_HOME}/state.conf r, owner @{SDDM_HOME}/** rw, diff --git a/apparmor.d/groups/kde/sddm-xsession b/apparmor.d/groups/kde/sddm-xsession index b5cceee955..8fbba5fce8 100644 --- a/apparmor.d/groups/kde/sddm-xsession +++ b/apparmor.d/groups/kde/sddm-xsession @@ -25,9 +25,11 @@ profile sddm-xsession @{exec_path} { @{bin}/chmod rix, @{bin}/csh rix, @{bin}/date rix, + @{bin}/dpkg-query rpx, @{bin}/fish rix, + @{bin}/gettext rix, @{bin}/gettext.sh r, - @{bin}/gpgconf rCx -> gpg, + @{bin}/gpgconf rCx -> gpg, @{bin}/id rix, @{bin}/locale rix, @{bin}/locale-check rix, @@ -40,12 +42,13 @@ profile sddm-xsession @{exec_path} { @{bin}/tcsh rix, @{bin}/tempfile rix, @{bin}/touch rix, - @{bin}/which{,.*} rix, - @{bin}/zsh rix, + @{bin}/tr rix, + @{bin}/which{,.debianutils} rix, @{bin}/dbus-update-activation-environment rCx -> dbus, @{bin}/flatpak rPx, @{bin}/numlockx rPx, + @{bin}/xbrlapi rPx, @{bin}/xhost rPx, @{bin}/xrdb rPx, /etc/X11/Xsession rPx, @@ -60,7 +63,9 @@ profile sddm-xsession @{exec_path} { @{system_share_dirs}/im-config/data/{,*} r, @{system_share_dirs}/im-config/xinputrc.common r, + @{system_share_dirs}/libdebuginfod-common/debuginfod.sh r, + /etc/debuginfod/{,**} r, /etc/default/{,*} r, /etc/X11/{,**} r, @@ -71,7 +76,7 @@ profile sddm-xsession @{exec_path} { owner @{tmp}/xsess-env-* rw, owner @{tmp}/file* rw, - audit owner @{tmp}/tmp.* rw, + owner @{tmp}/tmp.@{rand10} rw, owner @{PROC}/@{pid}/loginuid r, @@ -90,6 +95,16 @@ profile sddm-xsession @{exec_path} { profile dbus { include + include + + dbus send bus=session path=/org/freedesktop/DBus + interface=org.freedesktop.DBus + member=UpdateActivationEnvironment + peer=(name=org.freedesktop.DBus, label="@{p_dbus_session}"), + dbus send bus=session path=/org/freedesktop/systemd1 + interface=org.freedesktop.systemd1.Manager + member=SetEnvironment + peer=(name=org.freedesktop.systemd1, label="@{p_systemd_user}"), @{bin}/dbus-update-activation-environment mr, @@ -123,8 +138,10 @@ profile sddm-xsession @{exec_path} { @{PROC}/@{pid}/fd/ r, @{PROC}/@{pid}/task/@{tid}/comm rw, - /dev/tty@{int} rw, - owner /dev/pts/@{int} rw, + owner @{HOME}/.xsession-errors w, + + /dev/tty@{u8} rw, + owner /dev/pts/@{u16} rw, deny @{user_share_dirs}/sddm/* rw, diff --git a/apparmor.d/groups/kde/startplasma b/apparmor.d/groups/kde/startplasma index 773122f570..04e957a8cc 100644 --- a/apparmor.d/groups/kde/startplasma +++ b/apparmor.d/groups/kde/startplasma @@ -11,17 +11,22 @@ profile startplasma @{exec_path} { include include include + include include include signal (receive) set=(hup) peer=@{p_systemd}, signal (receive) set=(term) peer=sddm, + signal receive set=term peer=plasmalogin-helper, + + #aa:dbus talk bus=session name=org.freedesktop.systemd1 label="@{p_systemd_user}" + #aa:dbus talk bus=session name=org.kde.KSplash path=/KSplash label=ksplashqml @{exec_path} mr, @{sh_path} rix, @{bin}/env rix, - @{bin}/grep rix, + @{bin}/{,e}grep rix, @{bin}/kapplymousetheme rPUx, @{bin}/kdeinit5_shutdown rPUx, @{bin}/ksplashqml rPUx, @@ -31,6 +36,7 @@ profile startplasma @{exec_path} { @{lib}/@{multiarch}/libexec/plasma-sourceenv.sh r, + /usr/share/byobu/desktop/{,**} r, /usr/share/color-schemes/{,**} r, /usr/share/desktop-directories/{,**} r, /usr/share/kservices{5,6}/{,**} r, @@ -40,8 +46,7 @@ profile startplasma @{exec_path} { /etc/machine-id r, /etc/xdg/menus/{,**} r, /etc/xdg/plasma-workspace/env/{,*} r, - - /var/lib/flatpak/exports/share/mime/ r, + /etc/xdg/plasmarc r, @{user_cache_dirs}/ksycoca{5,6}_* rwkl -> @{user_cache_dirs}/#@{int}, owner @{user_cache_dirs}/#@{int} rwk, @@ -61,10 +66,12 @@ profile startplasma @{exec_path} { owner @{user_config_dirs}/startkderc r, owner @{user_config_dirs}/Trolltech.conf.lock rwk, owner @{user_config_dirs}/Trolltech.conf{,.@{rand6}} rwl, + owner @{user_config_dirs}/plasma-workspace/env/qt-media-backend.sh r, owner link @{user_config_dirs}/kdeglobals -> @{user_config_dirs}/#@{int}, owner @{user_share_dirs}/color-schemes/{,**} r, owner @{user_share_dirs}/kservices{5,6}/{,**} r, + owner @{user_share_dirs}/plasmalogin/wayland-session.log rw, owner @{user_share_dirs}/sddm/wayland-session.log rw, owner @{user_share_dirs}/sddm/xorg-session.log rw, @@ -75,8 +82,8 @@ profile startplasma @{exec_path} { @{PROC}/sys/kernel/random/boot_id r, - /dev/tty r, - /dev/tty@{int} rw, + /dev/tty rw, + /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/kde/startplasma-login-wayland b/apparmor.d/groups/kde/startplasma-login-wayland new file mode 100644 index 0000000000..a037f9e081 --- /dev/null +++ b/apparmor.d/groups/kde/startplasma-login-wayland @@ -0,0 +1,42 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/startplasma-login-wayland +profile startplasma-login-wayland @{exec_path} { + include + include + include + include + include + include + + signal receive set=term peer=plasmalogin-helper, + + @{exec_path} mr, + + /usr/share/color-schemes/{,**} r, + /usr/share/plasma/look-and-feel/{,**} r, + + /etc/xdg/menus/{,**} r, + + owner @{sddm_cache_dirs}/#@{int} rw, + owner @{sddm_cache_dirs}/ksycoca{5,6}_* rwkl -> @{sddm_cache_dirs}/#@{int}, + owner @{sddm_config_dirs}/kdedefaults/kdeglobals r, + owner @{sddm_config_dirs}/kdedefaults/package r, + owner @{sddm_config_dirs}/kdeglobals r, + owner @{sddm_config_dirs}/plasma-localerc r, + + @{PROC}/sys/kernel/random/boot_id r, + + /dev/tty rw, + /dev/tty@{u8} rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/kde/systemsettings b/apparmor.d/groups/kde/systemsettings index e68d248b6a..681a4b2170 100644 --- a/apparmor.d/groups/kde/systemsettings +++ b/apparmor.d/groups/kde/systemsettings @@ -7,13 +7,15 @@ abi , include @{exec_path} = @{bin}/systemsettings -profile systemsettings @{exec_path} { +profile systemsettings @{exec_path} flags=(attach_disconnected,mediate_deleted) { include include include + include include include include + include include include include @@ -23,7 +25,10 @@ profile systemsettings @{exec_path} { signal send set=term peer=kioworker, - @{exec_path} mr, + #aa:dbus own bus=session name=org.kde.internal.KSettingsWidget_kcm_networkmanagement + #aa:dbus own bus=session name=org.kde.systemsettings + + @{exec_path} mrix, @{sh_path} rix, @{bin}/cat rix, @@ -31,91 +36,94 @@ profile systemsettings @{exec_path} { @{bin}/kcminit rPx, @{bin}/lspci rPx, @{bin}/openssl rix, + @{bin}/orca rPUx, + @{bin}/rsync rix, @{bin}/pactl rPx, @{bin}/plasma-discover rPx, @{bin}/plasmashell rPx, @{bin}/xdpyinfo rPUx, @{lib}/qt{5,6}/bin/qdbus rPx, + @{lib}/bup/cmd/bup rPUx, #aa:exec kioworker + /usr/share/i18n/locales/{,*} r, + /usr/share/iso-codes/json/*.json r, /usr/share/kcm_networkmanagement/{,**} r, /usr/share/kcm_recentFiles/{,**} r, /usr/share/kcmkeys/{,*.kksrc} r, /usr/share/kglobalaccel/* r, /usr/share/kinfocenter/{,**} r, - /usr/share/solid/{,**} r, /usr/share/kpackage/{,**} r, /usr/share/kservices{5,6}/{,**} r, /usr/share/kservicetypes5/{,**} r, /usr/share/kwin/{,**} r, /usr/share/kxmlgui5/systemsettings/systemsettingsui.rc r, + /usr/share/libwacom/{,**} r, /usr/share/plasma/{,**} r, /usr/share/sddm/themes/{,**} r, + /usr/share/solid/{,**} r, /usr/share/systemsettings/{,**} r, - /usr/share/wallpapers/{,**} r, /usr/share/thumbnailers/{,**} r, + /usr/share/wallpapers/{,**} r, + @{etc_ro}/login.defs r, /etc/fstab r, - /etc/machine-id r, - /etc/xdg/menus/{,applications-merged/} r, + /etc/xdg/* r, /etc/xdg/plasmanotifyrc r, /etc/xdg/ui/ui_standards.rc r, - /var/lib/dbus/machine-id r, - /etc/xdg/* r, /var/cache/cracklib/cracklib_dict.* r, /var/cache/samba/ rw, /var/lib/AccountsService/icons/* r, /var/lib/flatpak/repo/{,**} r, + owner @{HOME}/.face r, owner @{HOME}/@{XDG_WALLPAPERS_DIR}/{,**} r, - owner @{user_cache_dirs}/kcrash-metadata/*.ini rw, - owner @{user_cache_dirs}/kinfocenter/{,**} rwlk, - owner @{user_cache_dirs}/ksvg-elements rw, - owner @{user_cache_dirs}/ksvg-elements.@{rand6} rwlk -> @{user_cache_dirs}/#@{int}, - owner @{user_cache_dirs}/ksvg-elements.lock rwlk, - owner @{user_cache_dirs}/plasma_theme_*.kcache rw, + owner @{user_cache_dirs}/[kK]* rwlk -> @{user_cache_dirs}/#@{int}, + owner @{user_cache_dirs}/[kK]*/ rw, + owner @{user_cache_dirs}/[kK]*/** rwlk -> @{user_cache_dirs}/[kK]*/**, + owner @{user_cache_dirs}/#@{int} rwk, + owner @{user_cache_dirs}/plasma*/{,**} r, + owner @{user_cache_dirs}/plasma* rw, owner @{user_cache_dirs}/systemsettings/ rw, owner @{user_cache_dirs}/systemsettings/** rwlk -> @{user_cache_dirs}/systemsettings/**, + owner @{user_config_dirs}/[kK]* rwlk -> @{user_config_dirs}/#@{int}, + owner @{user_config_dirs}/[kK]*/ rw, + owner @{user_config_dirs}/[kK]*/** rwlk -> @{user_config_dirs}/[kK]*/**, owner @{user_config_dirs}/{P,p}lasma* r, owner @{user_config_dirs}/*rc r, - owner @{user_config_dirs}/#@{int} rw, + owner @{user_config_dirs}/#@{int} rwk, + owner @{user_config_dirs}/autostart/ r, owner @{user_config_dirs}/device_automounter_kcmrc.lock rwk, owner @{user_config_dirs}/emaildefaults r, - owner @{user_config_dirs}/kde.org/{,**} rwlk, - owner @{user_config_dirs}/kdedefaults/kscreenlockerrc r, - owner @{user_config_dirs}/kdedefaults/plasmarc r, - owner @{user_config_dirs}/kinfocenterrc* rwlk, owner @{user_config_dirs}/libaccounts-glib/ rw, owner @{user_config_dirs}/libaccounts-glib/accounts.db{,-shm,-wal,-journal} rwk, - owner @{user_config_dirs}/menus/ r, - owner @{user_config_dirs}/menus/applications-merged/ r, + owner @{user_config_dirs}/plasma*/{,**} r, + owner @{user_config_dirs}/powerdevilrc.lock rwk, + owner @{user_config_dirs}/powerdevilrc{,.@{rand6}} rwl -> @{user_config_dirs}/#@{int}, owner @{user_config_dirs}/session/ rw, owner @{user_config_dirs}/session/** rwlk, owner @{user_config_dirs}/systemsettingsrc.lock rwk, owner @{user_config_dirs}/systemsettingsrc{,.@{rand6}} rwl -> @{user_config_dirs}/#@{int}, - owner @{user_share_dirs}/baloo/index r, - owner @{user_share_dirs}/kactivitymanagerd/resources/database rwk, - owner @{user_share_dirs}/kactivitymanagerd/resources/database-shm rwk, - owner @{user_share_dirs}/kactivitymanagerd/resources/database-wal rw, - owner @{user_share_dirs}/kinfocenter/ rw, - owner @{user_share_dirs}/kinfocenter/** rwlk, - owner @{user_share_dirs}/knotifications{5,6}/{,**} r, - owner @{user_share_dirs}/krdpserver/ rw, - owner @{user_share_dirs}/kservices{5,6}/{,ServiceMenus/} r, + owner @{user_share_dirs}/[kK]* rwlk -> @{user_share_dirs}/#@{int}, + owner @{user_share_dirs}/[kK]*/ rw, + owner @{user_share_dirs}/[kK]*/** rwlk -> @{user_share_dirs}/[kK]*/**, + owner @{user_share_dirs}/#@{int} rwk, + owner @{user_share_dirs}/baloo/index r, owner @{user_share_dirs}/systemsettings/ rw, - owner @{user_share_dirs}/systemsettings/** rwlk, + owner @{user_share_dirs}/systemsettings/** rwlk -> @{user_share_dirs}/systemsettings/**, + owner @{user_share_dirs}/user-places.xbel r, owner @{user_share_dirs}/wallpapers/{,**} r, - owner @{user_state_dirs}/#@{int} rw, - owner @{user_state_dirs}/systemsettingsstaterc rw, - owner @{user_state_dirs}/systemsettingsstaterc.@{rand6} rwlk, + owner @{user_state_dirs}/#@{int} rwk, + owner @{user_state_dirs}/systemsettingsstaterc{,.@{rand6}} rwlk, owner @{user_state_dirs}/systemsettingsstaterc.lock rwlk, - owner @{run}/user/@{uid}/#@{int} rw, + @{run}/mount/utab r, + owner @{run}/user/@{uid}/#@{int} rwl, owner @{run}/user/@{uid}/systemsettings@{rand6}.@{int}.kioworker.socket rwl -> @{run}/user/@{uid}/#@{int}, @{run}/udev/data/+drm:card@{int}-* r, # For screen outputs diff --git a/apparmor.d/groups/kde/wayland-session b/apparmor.d/groups/kde/wayland-session index 124cf2fdad..2c73fa80cc 100644 --- a/apparmor.d/groups/kde/wayland-session +++ b/apparmor.d/groups/kde/wayland-session @@ -9,23 +9,38 @@ include @{exec_path} = @{etc_ro}/sddm/wayland-session profile wayland-session @{exec_path} { include + include + include include @{exec_path} mr, - @{shells_path} rix, - @{bin}/id rix, - - @{lib}/plasma-dbus-run-session-if-needed rix, - @{lib}/@{multiarch}/libexec/plasma-dbus-run-session-if-needed rix, - @{bin}/startplasma-wayland rPx, - + @{shells_path} rix, + @{bin}/cat ix, + @{bin}/dpkg-query px, + @{bin}/gettext ix, + @{bin}/gettext.sh r, + @{bin}/id ix, + @{bin}/locale ix, + @{bin}/locale-check ix, + @{bin}/sed ix, + @{bin}/tr ix, + + @{bin}/startplasma-wayland Px, + @{lib}/@{multiarch}/libexec/plasma-dbus-run-session-if-needed ix, + @{lib}/plasma-dbus-run-session-if-needed ix, + + /usr/share/im-config/{,**} r, + /usr/share/libdebuginfod-common/debuginfod.sh r, + + /etc/debuginfod/{,**} r, + /etc/default/im-config r, /etc/machine-id r, + /etc/X11/xinit/xinputrc r, + /etc/X11/Xsession.d/*im-config_launch r, owner @{user_share_dirs}/sddm/wayland-session.log rw, - /dev/tty rw, - include if exists } diff --git a/apparmor.d/groups/kde/xembedsniproxy b/apparmor.d/groups/kde/xembedsniproxy index 6cb93163ce..e76068b5b4 100644 --- a/apparmor.d/groups/kde/xembedsniproxy +++ b/apparmor.d/groups/kde/xembedsniproxy @@ -7,24 +7,22 @@ abi , include @{exec_path} = @{bin}/xembedsniproxy -profile xembedsniproxy @{exec_path} { +profile xembedsniproxy @{exec_path} flags=(attach_disconnected) { include - include include + include include - include @{exec_path} mr, - /usr/share/hwdata/*.ids r, - /usr/share/icu/@{int}.@{int}/*.dat r, - owner @{tmp}/xauth_@{rand6} r, owner @{run}/user/@{uid}/iceauth_@{rand6} r, @{run}/user/@{uid}/xauth_@{rand6} rl, + /dev/tty r, + include if exists } diff --git a/apparmor.d/groups/kde/xsettingsd b/apparmor.d/groups/kde/xsettingsd index 7cebbb43c1..1adbf1d9fb 100644 --- a/apparmor.d/groups/kde/xsettingsd +++ b/apparmor.d/groups/kde/xsettingsd @@ -9,6 +9,7 @@ include @{exec_path} = @{bin}/xsettingsd profile xsettingsd @{exec_path} { include + include signal (receive) set=hup peer=kded, diff --git a/apparmor.d/groups/kde/xwaylandvideobridge b/apparmor.d/groups/kde/xwaylandvideobridge index 889018a138..be9be5a627 100644 --- a/apparmor.d/groups/kde/xwaylandvideobridge +++ b/apparmor.d/groups/kde/xwaylandvideobridge @@ -15,11 +15,15 @@ profile xwaylandvideobridge @{exec_path} { @{exec_path} mr, + /usr/share/color-schemes/{,*} r, + /etc/machine-id r, owner @{user_cache_dirs}/xwaylandvideobridge/ rw, owner @{user_cache_dirs}/xwaylandvideobridge/** rwk, + owner @{user_config_dirs}/breezerc r, + include if exists } diff --git a/apparmor.d/groups/lxqt/lxqt-config-powermanagement b/apparmor.d/groups/lxqt/lxqt-config-powermanagement index 4b96ccb361..891ba9899b 100644 --- a/apparmor.d/groups/lxqt/lxqt-config-powermanagement +++ b/apparmor.d/groups/lxqt/lxqt-config-powermanagement @@ -10,29 +10,17 @@ include @{exec_path} = @{bin}/lxqt-config-powermanagement profile lxqt-config-powermanagement @{exec_path} { include - include + include include include @{exec_path} mr, - /etc/machine-id r, - owner @{user_config_dirs}/lxqt/#@{int} rw, owner @{user_config_dirs}/lxqt/lxqt-powermanagement.conf.lock rwk, owner @{user_config_dirs}/lxqt/lxqt-powermanagement.conf.@{rand6} rw, owner @{user_config_dirs}/lxqt/lxqt-powermanagement.conf.@{rand6} l -> @{user_config_dirs}/lxqt/#@{int}, - @{sys}/class/leds/ r, - @{sys}/devices/@{pci}/backlight/**/{,max_,actual_}brightness rw, - @{sys}/devices/@{pci}/backlight/**/{uevent,type,enabled} r, - @{sys}/devices/@{pci}/backlight/**/brightness rw, - @{sys}/devices/@{pci}/drm/card@{int}/**/{,max_,actual_}brightness rw, - @{sys}/devices/@{pci}/drm/card@{int}/**/{uevent,type,enabled} r, - @{sys}/devices/@{pci}/drm/card@{int}/**/brightness rw, - @{sys}/devices/@{pci}/*_backlight/{,max_,actual_}brightness rw, - @{sys}/devices/@{pci}/*_backlight/{uevent,type,enabled} r, - owner /tmp/@{int} r, /dev/tty rw, diff --git a/apparmor.d/groups/lxqt/lxqt-globalkeysd b/apparmor.d/groups/lxqt/lxqt-globalkeysd index 8729b1abb1..a9a75aa90b 100644 --- a/apparmor.d/groups/lxqt/lxqt-globalkeysd +++ b/apparmor.d/groups/lxqt/lxqt-globalkeysd @@ -10,7 +10,6 @@ include @{exec_path} = @{bin}/lxqt-globalkeysd profile lxqt-globalkeysd @{exec_path} { include - include include include diff --git a/apparmor.d/groups/lxqt/lxqt-panel b/apparmor.d/groups/lxqt/lxqt-panel index 650a7e4024..12c377f48f 100644 --- a/apparmor.d/groups/lxqt/lxqt-panel +++ b/apparmor.d/groups/lxqt/lxqt-panel @@ -63,7 +63,8 @@ profile lxqt-panel @{exec_path} { owner @{user_config_dirs}/lxqt/panel.conf.@{rand6} l -> @{user_config_dirs}/lxqt/#@{int}, owner @{user_config_dirs}/pulse/{,**} rwk, - @{run}/udev/data/* r, + @{run}/udev/data/+*:* r, # Identifies all subsystems + @{run}/udev/data/c@{int}:@{int} r, # Identifies all character devices @{sys}/class/i2c-adapter/ r, @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_{cur,min,max}_freq r, @@ -73,8 +74,8 @@ profile lxqt-panel @{exec_path} { owner @{PROC}/@{pid}/mounts r, /dev/tty rw, - /dev/tty@{int} rw, - /dev/pts/@{int} rw, + /dev/tty@{u8} rw, + /dev/pts/@{u16} rw, /dev/snd/controlC@{int} rw, profile root { diff --git a/apparmor.d/groups/lxqt/lxqt-runner b/apparmor.d/groups/lxqt/lxqt-runner index 9477c1bda0..5783c1fa08 100644 --- a/apparmor.d/groups/lxqt/lxqt-runner +++ b/apparmor.d/groups/lxqt/lxqt-runner @@ -14,7 +14,6 @@ profile lxqt-runner @{exec_path} { @{exec_path} mr, - /usr/share/icons/ r, /usr/share/desktop-directories/ r, /usr/share/desktop-directories/{,**} r, diff --git a/apparmor.d/groups/lxqt/lxqt-session b/apparmor.d/groups/lxqt/lxqt-session index 3a4a6cd61e..b2c6c70f75 100644 --- a/apparmor.d/groups/lxqt/lxqt-session +++ b/apparmor.d/groups/lxqt/lxqt-session @@ -11,7 +11,6 @@ include profile lxqt-session @{exec_path} flags=(attach_disconnected) { include include - include include include include @@ -47,7 +46,6 @@ profile lxqt-session @{exec_path} flags=(attach_disconnected) { @{bin}/xdg-user-dirs-update rPx, /usr/share/ r, - /usr/share/mime/ r, /usr/share/cursors/ r, /usr/share/backintime/common/* r, /usr/share/desktop-directories/* r, @@ -68,7 +66,7 @@ profile lxqt-session @{exec_path} flags=(attach_disconnected) { owner @{user_config_dirs}/mimeapps.list{,.@{rand6}} rw, owner @{user_config_dirs}/openbox/rc.xml r, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, @{PROC}/ r, @{PROC}/uptime r, diff --git a/apparmor.d/groups/lxqt/startlxqt b/apparmor.d/groups/lxqt/startlxqt index 06967e6948..e1b406a06d 100644 --- a/apparmor.d/groups/lxqt/startlxqt +++ b/apparmor.d/groups/lxqt/startlxqt @@ -31,7 +31,6 @@ profile startlxqt @{exec_path} { /usr/share/color-schemes/{,**} r, /usr/share/desktop-directories/{,**} r, /usr/share/kservices5/{,**} r, - /usr/share/mime/{,**} r, /etc/machine-id r, /etc/xdg/menus/{,**} r, @@ -54,10 +53,8 @@ profile startlxqt @{exec_path} { owner @{run}/user/@{uid}/ r, - owner @{PROC}/@{pid}/maps r, - /dev/tty rw, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, include if exists diff --git a/apparmor.d/groups/network/ModemManager b/apparmor.d/groups/network/ModemManager index b92ad8e68a..1ebde3be43 100644 --- a/apparmor.d/groups/network/ModemManager +++ b/apparmor.d/groups/network/ModemManager @@ -6,17 +6,18 @@ abi , include -@{exec_path} = @{bin}/ModemManager +@{exec_path} = @{sbin}/ModemManager profile ModemManager @{exec_path} flags=(attach_disconnected) { include include - include - include + include + include include include - include + include capability net_admin, + capability sys_admin, network qipcrtr dgram, network netlink raw, @@ -25,20 +26,23 @@ profile ModemManager @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, - @{run}/udev/data/+acpi:* r, # for acpi + /usr/share/gvfs/remote-volume-monitors/{,**} r, + + @{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/+platform:* r, - @{run}/udev/data/+pnp:* r, - @{run}/udev/data/+serial*:* r, - @{run}/udev/data/+usb:* r, - @{run}/udev/data/+vmbus:* r, + @{run}/udev/data/+platform:* r, # Identifies onboard devices (laptop/board model, power controllers, thermal sensors) + @{run}/udev/data/+pnp:* r, # For Plug and Play devices (legacy hardware, sound cards, etc.) + @{run}/udev/data/+serial*:* r, # For serial devices (modems, serial ports, etc.) + @{run}/udev/data/+usb:* r, # Identifies all USB devices + @{run}/udev/data/+vmbus:* r, # For Hyper-V devices, (network adapters, storage controllers, and other virtual devices) @{run}/udev/data/c16[6,7]:@{int} r, # USB modems @{run}/udev/data/c18[0,8,9]:@{int} r, # USB devices & USB serial converters @{run}/udev/data/c4:@{int} r, # for /dev/tty[0-9]* @{run}/udev/data/c5:@{int} r, # for /dev/tty, /dev/console, /dev/ptmx - @{run}/udev/data/n@{int} r, + @{run}/udev/data/c229:@{int} r, # for /dev/hvc* + @{run}/udev/data/n@{int} r, # For network interfaces - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, @{sys}/bus/ r, @{sys}/bus/usb/devices/ r, @@ -47,7 +51,10 @@ profile ModemManager @{exec_path} flags=(attach_disconnected) { @{sys}/class/tty/ r, @{sys}/class/wwan/ r, - @{sys}/devices/@{pci}/revision r, + @{sys}/devices/**/@{uuid}/@{pci}/device r, + @{sys}/devices/**/@{uuid}/@{pci}/revision r, + @{sys}/devices/**/@{uuid}/@{pci}/subsystem_vendor r, + @{sys}/devices/**/@{uuid}/@{pci}/vendor r, @{sys}/devices/**/net/*/ r, @{sys}/devices/**/uevent r, @{sys}/devices/virtual/tty/*/ r, diff --git a/apparmor.d/groups/network/NetworkManager b/apparmor.d/groups/network/NetworkManager index d41f38b1be..8e4b8f882a 100644 --- a/apparmor.d/groups/network/NetworkManager +++ b/apparmor.d/groups/network/NetworkManager @@ -6,16 +6,15 @@ abi , include -@{exec_path} = @{bin}/NetworkManager +@{exec_path} = @{sbin}/NetworkManager profile NetworkManager @{exec_path} flags=(attach_disconnected) { include include - include - include - include - include - include - include + include + include + include + include + include include include @@ -28,7 +27,7 @@ profile NetworkManager @{exec_path} flags=(attach_disconnected) { capability setgid, capability setuid, capability sys_chroot, - capability sys_module, + capability bpf, network inet stream, network inet6 stream, @@ -39,48 +38,50 @@ profile NetworkManager @{exec_path} flags=(attach_disconnected) { network netlink raw, network packet dgram, - signal (send) set=(term) peer=dnsmasq, + signal send set=(term) peer=dnsmasq, #aa:dbus own bus=system name=org.freedesktop.NetworkManager #aa:dbus talk bus=system name=fi.w1.wpa_supplicant1 label=wpa-supplicant #aa:dbus talk bus=system name=org.fedoraproject.FirewallD1 label=firewalld + #aa:dbus talk bus=system name=org.freedesktop.ModemManager1 label=ModemManager #aa:dbus talk bus=system name=org.freedesktop.nm_dispatcher label=nm-dispatcher - #aa:dbus talk bus=system name=org.freedesktop.resolve1 label=systemd-resolved + #aa:dbus talk bus=system name=org.freedesktop.resolve1 label="@{p_systemd_resolved}" dbus send bus=system path=/org/freedesktop/nm_dispatcher interface=org.freedesktop.nm_dispatcher + member=Action2 peer=(name=org.freedesktop.nm_dispatcher), - dbus receive bus=system path=/org/freedesktop - interface=org.freedesktop.DBus.ObjectManager - member=GetManagedObjects - peer=(name=:*), - - dbus receive bus=system path=/ - interface=org.freedesktop.DBus.ObjectManager - member=InterfacesRemoved - peer=(name=:*, label=bluetoothd), + dbus send bus=system path=/uk/org/thekelleys/dnsmasq + interface=org.freedesktop.NetworkManager.dnsmasq + member=SetServersEx + peer=(name=@{busname}, label=dnsmasq), - dbus send bus=system path=/ + # Server side of bus/system/org.freedesktop.NetworkManager not covered by the directive + dbus receive bus=system path=/org/freedesktop interface=org.freedesktop.DBus.ObjectManager member=GetManagedObjects - peer=(name=:*, label=bluetoothd), - + peer=(name=@{busname}), dbus send bus=system path=/org/freedesktop interface=org.freedesktop.DBus.ObjectManager - member=InterfacesAdded - peer=(name=org.freedesktop.DBus, label=nm-online), + member={InterfacesAdded,InterfacesRemoved} + peer=(name=org.freedesktop.DBus), + + dbus receive bus=system path=/{,org/freedesktop} + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=@{busname}, label=cockpit-bridge), @{exec_path} mr, - @{sh_path} rix, - @{bin}/nft rix, + @{sh_path} rix, + @{sbin}/nft rix, + @{sbin}/xtables-{nft,legacy}-multi rix, - @{bin}/dnsmasq rPx, - @{bin}/kmod rPx, + @{bin}/kmod rCx -> kmod, @{bin}/netconfig rPUx, - @{bin}/resolvconf rPx, + @{bin}/resolvectl rPx, @{bin}/systemctl rCx -> systemctl, @{lib}/{,NetworkManager/}nm-daemon-helper rPx, @{lib}/{,NetworkManager/}nm-dhcp-helper rPx, @@ -90,50 +91,60 @@ profile NetworkManager @{exec_path} flags=(attach_disconnected) { @{lib}/{,NetworkManager/}nm-openvpn-auth-dialog rPx, @{lib}/{,NetworkManager/}nm-openvpn-service rPx, @{lib}/{,NetworkManager/}nm-openvpn-service-openvpn-helper rPx, + @{lib}/netplan/configure rPx, + @{sbin}/dnsmasq rPx, + @{sbin}/resolvconf rPx, /usr/share/netplan/netplan.script rPx, + @{lib}/netplan/@{int2}-network-manager-all.yaml w, + /usr/share/gvfs/remote-volume-monitors/{,*.monitor} r, /usr/share/iproute2/{,**} r, + /etc/netplan/ r, + /etc/netplan/90-NM-@{uuid}.yaml r, + + / r, @{att}/ r, /etc/ r, + @{etc_rw}/netplan/50-cloud-init.yaml rw, + @{etc_rw}/netplan/90-NM-@{uuid}.yaml w, + @{etc_rw}/resolv.conf rw, + @{etc_rw}/resolv.conf.[0-9A-Z]* rw, /etc/iproute2/* r, /etc/machine-id r, /etc/network/interfaces r, /etc/network/interfaces.d/{,*} r, /etc/NetworkManager/{,**} r, /etc/NetworkManager/system-connections/{,**} w, - @{etc_rw}/netplan/90-NM-@{uuid}.yaml w, - @{etc_rw}/resolv.conf rw, - @{etc_rw}/resolv.conf.[0-9A-Z]* rw, /var/lib/iwd/*open* rw, /var/lib/NetworkManager/{,**} rw, - @{sys}/bus/ r, - @{sys}/class/ r, - @{sys}/class/net/ r, - @{sys}/class/net/rfkill/ r, - @{sys}/class/rfkill/ r, - - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/userdb/io.systemd.Machine rw, + @{run}/netplan/ r, @{run}/network/ifstate r, @{run}/NetworkManager/{,**} rw, @{run}/nm-*.pid rw, @{run}/nscd/db* rwl, @{run}/systemd/users/@{uid} r, @{run}/udev/data/+pci:* r, # Identifies all PCI devices (CPU, GPU, Network, Disks, USB, etc.) - @{run}/udev/data/+platform:* r, - @{run}/udev/data/+rfkill:* r, - @{run}/udev/data/n@{int} r, + @{run}/udev/data/+platform:* r, # Identifies onboard devices (laptop/board model, power controllers, thermal sensors) + @{run}/udev/data/+rfkill:* r, # Kill switch for wireless devices (Wi-Fi, Bluetooth, NFC) to save power + @{run}/udev/data/n@{int} r, # For network interfaces + @{run}/udev/data/+ieee80211:* r, # For Wi-Fi devices, such as wireless network cards and access points. - @{sys}/devices/@{pci}/net/*/{,**} r, - @{sys}/devices/@{pci}/usb@{int}/**/net/{,**} r, - @{sys}/devices/**/@{uuid}/net/*/{,**} r, + @{sys}/bus/ r, + @{sys}/class/ r, + @{sys}/class/net/ r, + @{sys}/class/net/rfkill/ r, + @{sys}/class/rfkill/ r, + @{sys}/devices/**/net/{,**} r, @{sys}/devices/**/uevent r, - @{sys}/devices/virtual/net/{,**} r, + @{sys}/module/af_alg/uevent r, @{PROC}/@{pids}/stat r, @{PROC}/1/environ r, @@ -143,8 +154,25 @@ profile NetworkManager @{exec_path} flags=(attach_disconnected) { owner @{PROC}/@{pid}/cmdline r, owner @{PROC}/@{pid}/fd/ r, + /dev/net/tun rw, /dev/rfkill rw, + #aa:only test + /etc/netplan/10-test.yaml rw, + /tmp/tmp@{word8}/NetworkManager.conf r, + + profile kmod { + include + include + + capability sys_module, + + @{sys}/module/compression r, + @{sys}/module/nf_*/initstate r, + + include if exists + } + profile systemctl { include include diff --git a/apparmor.d/groups/network/dhcpcd b/apparmor.d/groups/network/dhcpcd index c1b5d04c5d..ed7fe79a0d 100644 --- a/apparmor.d/groups/network/dhcpcd +++ b/apparmor.d/groups/network/dhcpcd @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/dhcpcd +@{exec_path} = @{sbin}/dhcpcd profile dhcpcd @{exec_path} flags=(attach_disconnected) { include include @@ -35,19 +35,23 @@ profile dhcpcd @{exec_path} flags=(attach_disconnected) { @{bin}/chmod rix, @{bin}/cmp rix, @{bin}/mkdir rix, - @{bin}/resolvconf rPx, + @{bin}/resolvectl rPx, @{bin}/rm rix, @{bin}/sed rix, + @{sbin}/resolvconf rPx, @{lib}/dhcpcd/dhcpcd-run-hooks rix, + /usr/share/dhcpcd/{,**} r, + /etc/dhcpcd.conf r, /etc/resolv.conf rw, /var/lib/dhcpcd/** rw, + @{run}/dhcpcd/ rw, @{run}/dhcpcd/** rwk, - @{run}/udev/data/n@{int} r, + @{run}/udev/data/n@{int} r, # For network interfaces @{sys}/devices/@{pci}/uevent r, @{sys}/devices/virtual/dmi/id/product_uuid r, @@ -56,6 +60,7 @@ profile dhcpcd @{exec_path} flags=(attach_disconnected) { @{PROC}/sys/kernel/hostname r, @{PROC}/sys/net/ipv{4,6}/conf/** r, @{PROC}/sys/net/ipv{4,6}/conf/*/accept_ra rw, + @{PROC}/sys/net/ipv{4,6}/conf/*/autoconf w, @{PROC}/sys/net/ipv{4,6}/conf/*/hop_limit w, @{PROC}/sys/net/ipv{4,6}/neigh/*/{base_reachable_time_ms,retrans_time_ms} w, owner @{PROC}/@{pid}/net/if_inet6 r, diff --git a/apparmor.d/groups/network/iwd b/apparmor.d/groups/network/iwd index d3c114a43a..015791f5bb 100644 --- a/apparmor.d/groups/network/iwd +++ b/apparmor.d/groups/network/iwd @@ -20,11 +20,13 @@ profile iwd @{exec_path} { network inet6 stream, network netlink raw, network netlink dgram, - network alg seqpacket, + network alg seqpacket, # kernel crypto API network packet dgram, @{exec_path} mr, - @{bin}/resolvconf rPx, + @{sbin}/resolvconf rPx, + + /etc/udev/hwdb.bin r, /etc/iwd/{,**} r, /var/lib/iwd/{,**} rw, diff --git a/apparmor.d/groups/network/mullvad-daemon b/apparmor.d/groups/network/mullvad-daemon index 6c4c41e6c9..830a0779d9 100644 --- a/apparmor.d/groups/network/mullvad-daemon +++ b/apparmor.d/groups/network/mullvad-daemon @@ -10,13 +10,13 @@ include @{exec_path} += /opt/Mullvad*/resources/mullvad-daemon profile mullvad-daemon @{exec_path} flags=(attach_disconnected) { include + include include capability dac_override, - - capability net_admin, capability fowner, capability fsetid, + capability net_admin, capability net_raw, capability sys_admin, @@ -29,7 +29,15 @@ profile mullvad-daemon @{exec_path} flags=(attach_disconnected) { network netlink raw, network netlink dgram, - mount fstype=cgroup -> /sys/fs/cgroup/net_cls/, + mount fstype=cgroup -> @{sys}/fs/cgroup/net_cls/, + + #aa:dbus talk bus=system name=org.freedesktop.NetworkManager label=NetworkManager + #aa:dbus talk bus=system name=org.freedesktop.resolve1 label=systemd-resolved + + dbus send bus=system path=/org/freedesktop/systemd1 + interface=org.freedesktop.DBus.Properties + member=Get + peer=(name=org.freedesktop.systemd1, label="@{p_systemd}"), @{exec_path} mr, @@ -39,7 +47,8 @@ profile mullvad-daemon @{exec_path} flags=(attach_disconnected) { "/opt/Mullvad VPN/resources/*.so*" mr, "/opt/Mullvad VPN/resources/*" r, - /etc/mullvad-vpn/{,*} r, + /etc/mullvad-vpn/ rw, + /etc/mullvad-vpn/* r, /etc/mullvad-vpn/@{uuid} rw, /etc/mullvad-vpn/*.json rw, @{etc_rw}/resolv.conf rw, @@ -49,16 +58,23 @@ profile mullvad-daemon @{exec_path} flags=(attach_disconnected) { owner /var/log/mullvad-vpn/{,*} rw, owner /var/log/private/mullvad-vpn/*.log rw, + owner @{tmp}/@{uuid} rw, + owner @{tmp}/talpid-openvpn-@{uuid} rw, + @{run}/NetworkManager/resolv.conf r, owner @{run}/mullvad-vpn rw, @{sys}/fs/cgroup/net_cls/ w, + @{sys}/fs/cgroup/net_cls/cgroup.procs rw, @{sys}/fs/cgroup/net_cls/mullvad-exclusions/ w, + @{sys}/fs/cgroup/net_cls/mullvad-exclusions/cgroup.procs rw, @{sys}/fs/cgroup/net_cls/mullvad-exclusions/net_cls.classid rw, + @{sys}/fs/cgroup/system.slice/cpu.max r, + @{sys}/fs/cgroup/system.slice/mullvad-daemon.service/cpu.max r, + @{sys}/fs/cgroup/system.slice/mullvad-early-boot-blocking.service/cpu.max r, - owner @{tmp}/@{uuid} rw, - owner @{tmp}/talpid-openvpn-@{uuid} rw, - + @{PROC}/@{pid}/cgroup r, + @{PROC}/@{pid}/mountinfo r, @{PROC}/sys/net/ipv{4,6}/conf/all/arp_ignore rw, @{PROC}/sys/net/ipv{4,6}/conf/all/src_valid_mark rw, owner @{PROC}/@{pid}/mounts r, diff --git a/apparmor.d/groups/network/mullvad-exclude b/apparmor.d/groups/network/mullvad-exclude new file mode 100644 index 0000000000..f9188bc57d --- /dev/null +++ b/apparmor.d/groups/network/mullvad-exclude @@ -0,0 +1,34 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/mullvad-exclude +profile mullvad-exclude @{exec_path} { + include + include + + capability setuid, + + unix (send receive) type=stream peer=(label=mullvad-gui), + + @{exec_path} mr, + + @{bin}/** PUx, + @{lib}/** PUx, + @{user_bin_dirs}/** PUx, + /opt/*/** PUx, + /usr/local/bin/** PUx, + /usr/share/** PUx, + + @{sys}/fs/cgroup/net_cls/mullvad-exclusions/cgroup.procs rw, + + @{PROC}/@{pid}/mounts r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/network/mullvad-gui b/apparmor.d/groups/network/mullvad-gui index 6075f14b2a..b6a47e48eb 100644 --- a/apparmor.d/groups/network/mullvad-gui +++ b/apparmor.d/groups/network/mullvad-gui @@ -6,15 +6,18 @@ abi , include -@{name} = Mullvad?VPN -@{lib_dirs} = /opt/@{name} +@{name} = Mullvad?VPN mullvad-vpn +@{domain} = org.chromium.Chromium +@{lib_dirs} = /opt/@{name} @{lib}/@{name} @{config_dirs} = @{user_config_dirs}/@{name} @{cache_dirs} = @{user_cache_dirs}/@{name} -@{exec_path} = @{lib_dirs}/mullvad-gui +@{exec_path} = @{lib_dirs}/mullvad-gui @{bin}/mullvad-vpn profile mullvad-gui @{exec_path} flags=(attach_disconnected) { include + include include + include network inet stream, network inet6 stream, @@ -22,24 +25,25 @@ profile mullvad-gui @{exec_path} flags=(attach_disconnected) { network inet6 dgram, network netlink raw, - @{exec_path} mrix, - @{sh_path} rix, + unix (send receive) type=stream peer=(label=gsettings), + + dbus send bus=system path=/org/freedesktop/login1 + interface=org.freedesktop.login1.Manager + member=Inhibit + peer=(name=org.freedesktop.login1, label=systemd-logind), - @{bin}/gsettings rix, - @{open_path} rPx -> child-open-browsers, + @{exec_path} mrix, + @{bin}/gsettings Px, + @{bin}/mullvad-exclude Px, - owner @{user_cache_dirs}/dconf/user rw, + @{open_path} Px -> child-open-browsers, - owner @{tmp}/.org.chromium.Chromium.@{rand6}/@{name}*.png rw, + owner @{user_config_dirs}/autostart/mullvad-vpn.desktop rw, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{run}/mullvad-vpn rw, /dev/tty rw, - deny @{user_share_dirs}/gvfs-metadata/* r, - deny /etc/machine-id r, - deny /var/lib/dbus/machine-id r, - include if exists } diff --git a/apparmor.d/groups/network/netplan b/apparmor.d/groups/network/netplan new file mode 100644 index 0000000000..14ab82f132 --- /dev/null +++ b/apparmor.d/groups/network/netplan @@ -0,0 +1,63 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = /usr/share/netplan/netplan.script +profile netplan @{exec_path} flags=(attach_disconnected) { + include + include + include + include + + #aa:dbus own bus=system name=io.netplan.Netplan + + @{exec_path} mr, + + @{bin}/ip rPx, + @{bin}/networkctl rPx, + @{bin}/nmcli rPx, + @{bin}/ovs-vsctl rPUx, + @{bin}/systemctl rCx -> systemctl, + @{bin}/udevadm rPx, + @{lib}/netplan/generate rPx, + + /usr/share/netplan/{,**} r, + + /etc/netplan/{,*} r, + + @{run}/netplan/ r, + @{run}/NetworkManager/system-connections/netplan-* r, + @{run}/systemd/network/ r, + @{run}/systemd/system/ r, + @{run}/systemd/system/systemd-networkd.service.wants/ r, + + /tmp/@{word8} rw, + /tmp/#@{int} rw, + /tmp/netplan_@{word8}/{,**} rw, + /tmp/tmp@{word8}/{,**} rwlk, + + profile systemctl { + include + include + + capability net_admin, + capability sys_resource, + + ptrace read peer=@{p_systemd}, + + signal send set=(cont term) peer=systemd-tty-ask-password-agent, + + @{run}/udev/control rw, + @{bin}/systemd-tty-ask-password-agent rPx, + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/network/netplan-generate b/apparmor.d/groups/network/netplan-generate index 60ec7656fc..dd7b05c94e 100644 --- a/apparmor.d/groups/network/netplan-generate +++ b/apparmor.d/groups/network/netplan-generate @@ -6,9 +6,10 @@ abi , include -@{exec_path} = @{lib}/netplan/generate +@{exec_path} = @{lib}/netplan/generate @{lib}/netplan/configure profile netplan-generate @{exec_path} flags=(attach_disconnected) { include + include include capability chown, @@ -21,18 +22,27 @@ profile netplan-generate @{exec_path} flags=(attach_disconnected) { /etc/netplan/{,*} r, + @{run}/NetworkManager/ rw, + @{run}/NetworkManager/conf.d/ rw, @{run}/NetworkManager/conf.d/@{int}-globally-managed-devices.conf rw, @{run}/NetworkManager/conf.d/@{int}-globally-managed-devices.conf.@{rand6} rw, - @{run}/NetworkManager/system-connections/ r, + @{run}/NetworkManager/conf.d/netplan.conf rw, + @{run}/NetworkManager/conf.d/netplan.conf.@{rand6} rw, + @{run}/NetworkManager/system-connections/ rw, @{run}/NetworkManager/system-connections/* rw, + @{run}/systemd/generator.late/*.service.d/ w, + @{run}/systemd/generator.late/*.service.d/*netplan.conf* rw, + @{run}/systemd/generator.late/netplan-* rw, + @{run}/systemd/generator.late/systemd-networkd.service.wants/ w, + @{run}/systemd/generator.late/systemd-networkd.service.wants/netplan-*.service rw, @{run}/systemd/generator/multi-user.target.wants/ w, @{run}/systemd/generator/multi-user.target.wants/systemd-networkd.service w, @{run}/systemd/generator/netplan.stamp w, @{run}/systemd/generator/network-online.target.wants/ w, @{run}/systemd/generator/network-online.target.wants/systemd-networkd-wait-online.service w, @{run}/systemd/network/ rw, - @{run}/systemd/network/@{int}-netplan{,-*}.{network,link}{,.@{rand6}} rw, + @{run}/systemd/network/@{int}-netplan{,*} rw, @{run}/systemd/system/ r, @{run}/systemd/system/netplan-* rw, @{run}/systemd/system/systemd-networkd-wait-online.service.d/ rw, @@ -43,20 +53,20 @@ profile netplan-generate @{exec_path} flags=(attach_disconnected) { @{run}/udev/rules.d/ rw, @{run}/udev/rules.d/@{int}-netplan{,-*}.rules{,.@{rand6}} rw, - @{sys}/devices/**/net/*/address r, - @{run}/netplan/ r, @{run}/udev/rules.d/ r, @{run}/udev/rules.d/@{int}-netplan{,-*}.rules{,.@{rand6}} rw, - profile systemctl { + @{sys}/devices/**/net/*/address r, + + profile systemctl flags=(attach_disconnected) { include include capability net_admin, - @{att}/@{run}/systemd/private rw, + @{att}@{run}/systemd/private rw, include if exists } diff --git a/apparmor.d/groups/network/netplan.script b/apparmor.d/groups/network/netplan.script deleted file mode 100644 index 094726865a..0000000000 --- a/apparmor.d/groups/network/netplan.script +++ /dev/null @@ -1,51 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - -abi , - -include - -@{exec_path} = /usr/share/netplan/netplan.script -profile netplan.script @{exec_path} flags=(attach_disconnected) { - include - include - include - - @{exec_path} mr, - - @{lib}/netplan/generate rPx, - @{bin}/udevadm rCx -> udevadm, - @{bin}/systemctl rCx -> systemctl, - - /usr/share/netplan/{,**} r, - - @{run}/netplan/ r, - - profile udevadm { - include - include - - capability net_admin, - - @{att}/@{run}/udev/control rw, - - @{run}/udev/rules.d/90-netplan.rules rw, - @{run}/udev/rules.d/90-netplan.rules.@{rand6} rw, - - include if exists - } - - profile systemctl { - include - include - - capability net_admin, - - include if exists - } - - include if exists -} - -# vim:syntax=apparmor diff --git a/apparmor.d/groups/network/networkd-dispatcher b/apparmor.d/groups/network/networkd-dispatcher index f593db162e..1e748f00a4 100644 --- a/apparmor.d/groups/network/networkd-dispatcher +++ b/apparmor.d/groups/network/networkd-dispatcher @@ -16,7 +16,7 @@ profile networkd-dispatcher @{exec_path} { dbus receive bus=system path=/org/freedesktop/network1{,/link/*} interface=org.freedesktop.DBus.Properties member=PropertiesChanged - peer=(name=:*, label=systemd-networkd), + peer=(name=@{busname}, label="@{p_systemd_networkd}"), @{exec_path} mr, @@ -33,8 +33,6 @@ profile networkd-dispatcher @{exec_path} { /var/spool/postfix/pid/master.pid r, - @{run}/systemd/notify rw, - owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/mounts r, diff --git a/apparmor.d/groups/network/nm-dhcp-helper b/apparmor.d/groups/network/nm-dhcp-helper index 5e93bdbf5e..625a56f9b3 100644 --- a/apparmor.d/groups/network/nm-dhcp-helper +++ b/apparmor.d/groups/network/nm-dhcp-helper @@ -9,13 +9,11 @@ include @{exec_path} = @{lib}/{,NetworkManager/}nm-dhcp-helper profile nm-dhcp-helper @{exec_path} { include - include + include network inet dgram, network inet6 dgram, - ptrace (readby) peer=NetworkManager, - signal (receive) peer=NetworkManager, signal (send) peer=dhclient, diff --git a/apparmor.d/groups/network/nm-dispatcher b/apparmor.d/groups/network/nm-dispatcher index e6150c5098..e1fcdeeea3 100644 --- a/apparmor.d/groups/network/nm-dispatcher +++ b/apparmor.d/groups/network/nm-dispatcher @@ -16,6 +16,7 @@ profile nm-dispatcher @{exec_path} flags=(attach_disconnected) { include capability net_admin, + capability sys_admin, # optional: no audit capability sys_nice, capability sys_ptrace, @@ -26,26 +27,30 @@ profile nm-dispatcher @{exec_path} flags=(attach_disconnected) { dbus send bus=system path=/org/freedesktop interface=org.freedesktop.DBus.ObjectManager member=GetManagedObjects - peer=(name=:*, label=NetworkManager), + peer=(name=@{busname}, label=NetworkManager), + + dbus send bus=system path=/org/freedesktop/NetworkManager/Settings/@{int} + interface=org.freedesktop.NetworkManager.Settings.Connection + member=GetSettings + peer=(name=@{busname}, label=NetworkManager), @{exec_path} mr, @{sh_path} rix, + @{bin}/{,e}grep rix, + @{bin}/{m,g,}awk rix, @{bin}/basename rix, @{bin}/cat rix, @{bin}/chown rix, @{bin}/chronyc rPUx, + @{bin}/cp rix, @{bin}/date rix, - @{bin}/gawk rix, - @{bin}/grep rix, @{bin}/id rix, - @{bin}/invoke-rc.d rCx -> invoke-rc, @{bin}/logger rix, @{bin}/mkdir rix, @{bin}/mktemp rix, @{bin}/netconfig rPUx, @{bin}/nmcli rix, - @{python_path} rix, @{bin}/readlink rix, @{bin}/rm rix, @{bin}/run-parts rCx -> run-parts, @@ -53,6 +58,8 @@ profile nm-dispatcher @{exec_path} flags=(attach_disconnected) { @{bin}/systemctl rCx -> systemctl, @{bin}/systemd-cat rix, @{bin}/tr rix, + @{python_path} rix, + @{sbin}/invoke-rc.d rCx -> invoke-rc, /usr/share/tlp/tlp-readconfs rPUx, @{lib}/NetworkManager/dispatcher.d/ r, @@ -72,7 +79,6 @@ profile nm-dispatcher @{exec_path} flags=(attach_disconnected) { @{run}/chrony-dhcp/ rw, @{run}/ntp.conf.dhcp rw, @{run}/systemd/netif/leases/ r, - @{run}/systemd/notify rw, @{run}/tlp/{,*} rw, owner @{run}/ntp.conf.dhcp.@{rand6} rw, @@ -101,7 +107,7 @@ profile nm-dispatcher @{exec_path} flags=(attach_disconnected) { profile invoke-rc { include - @{bin}/invoke-rc.d rm, + @{sbin}/invoke-rc.d rm, @{sh_path} rix, @{bin}/basename rix, @{bin}/ls rix, diff --git a/apparmor.d/groups/network/nm-online b/apparmor.d/groups/network/nm-online index 189afd74d6..dad0604be9 100644 --- a/apparmor.d/groups/network/nm-online +++ b/apparmor.d/groups/network/nm-online @@ -7,21 +7,21 @@ abi , include @{exec_path} = @{bin}/nm-online -profile nm-online @{exec_path} { +profile nm-online @{exec_path} flags=(attach_disconnected) { include include - include include + include dbus receive bus=system path=/org/freedesktop/NetworkManager/ActiveConnection/@{int} interface=org.freedesktop.NetworkManager.Connection.Active member=StateChanged - peer=(name=:*, label=NetworkManager), + peer=(name=@{busname}, label=NetworkManager), dbus send bus=system path=/org/freedesktop/NetworkManager/Settings/@{int} interface=org.freedesktop.NetworkManager.Settings.Connection member=GetSettings - peer=(name=:*, label=NetworkManager), + peer=(name=@{busname}, label=NetworkManager), @{exec_path} mr, diff --git a/apparmor.d/groups/network/nm-openvpn-service b/apparmor.d/groups/network/nm-openvpn-service index 675c14679d..a3db0c896d 100644 --- a/apparmor.d/groups/network/nm-openvpn-service +++ b/apparmor.d/groups/network/nm-openvpn-service @@ -7,8 +7,9 @@ abi , include @{exec_path} = @{lib}/{,NetworkManager/}nm-openvpn-service -profile nm-openvpn-service @{exec_path} { +profile nm-openvpn-service @{exec_path} flags=(attach_disconnected) { include + include include capability kill, @@ -20,7 +21,7 @@ profile nm-openvpn-service @{exec_path} { @{sh_path} rix, @{bin}/kmod rPx, - @{bin}/openvpn rPx, + @{sbin}/openvpn rPx, @{lib}/{,NetworkManager/}nm-openvpn-auth-dialog rPx, @{lib}/{,NetworkManager/}nm-openvpn-service-openvpn-helper rPx, diff --git a/apparmor.d/groups/network/nmcli b/apparmor.d/groups/network/nmcli index 43a9d0dca3..8636abefd2 100644 --- a/apparmor.d/groups/network/nmcli +++ b/apparmor.d/groups/network/nmcli @@ -7,7 +7,7 @@ abi , include @{exec_path} = @{bin}/nmcli -profile nmcli @{exec_path} { +profile nmcli @{exec_path} flags=(attach_disconnected) { include include include @@ -16,20 +16,37 @@ profile nmcli @{exec_path} { capability sys_nice, #aa:dbus talk bus=system name=org.freedesktop.NetworkManager label=NetworkManager + dbus receive bus=system path=/org/freedesktop + interface=org.freedesktop.DBus.ObjectManager + member=InterfacesAdded + peer=(name=@{busname}, label=NetworkManager), + dbus receive bus=system path=/org/freedesktop + interface=org.freedesktop.DBus.ObjectManager + member=InterfacesRemoved + peer=(name=@{busname}, label=NetworkManager), + dbus send bus=system path=/org/freedesktop + interface=org.freedesktop.DBus.ObjectManager + member=GetManagedObjects + peer=(name=@{busname}, label=NetworkManager), @{exec_path} mr, @{pager_path} rPx -> child-pager, + /etc/netplan/* r, + owner @{HOME}/.nm-vpngate/*.ovpn r, owner @{HOME}/.cert/nm-openvpn/*.pem rw, @{run}/udev/data/+pci:* r, # Identifies all PCI devices (CPU, GPU, Network, Disks, USB, etc.) - @{run}/udev/data/n@{int} r, + @{run}/udev/data/n@{int} r, # For network interfaces @{sys}/devices/virtual/net/{,**} r, @{sys}/devices/@{pci}/net/*/{,**} r, + #aa:only test + /tmp/openvpn/** r, + include if exists } diff --git a/apparmor.d/groups/network/openvpn b/apparmor.d/groups/network/openvpn index 608b989940..4e63814cc0 100644 --- a/apparmor.d/groups/network/openvpn +++ b/apparmor.d/groups/network/openvpn @@ -22,22 +22,17 @@ abi , include -@{exec_path} = @{bin}/openvpn +@{exec_path} = @{sbin}/openvpn profile openvpn @{exec_path} flags=(attach_disconnected) { include include - # Needed to remove the following errors: - # ERROR: Cannot ioctl TUNSETIFF tun: Operation not permitted (errno=1) - # Exiting due to fatal error - capability net_admin, - - # These are needed when user/group are set in a OpenVPN config file - capability setuid, - capability setgid, - - capability dac_read_search, capability dac_override, + capability dac_read_search, + capability net_admin, # create tun + capability setgid, # when user/group are set in a OpenVPN config file + capability setuid, + capability sys_module, network inet dgram, network inet6 dgram, @@ -45,13 +40,22 @@ profile openvpn @{exec_path} flags=(attach_disconnected) { network inet6 stream, network netlink raw, - signal (receive) set=(term) peer=nm-openvpn-service, + signal receive set=term peer=nm-openvpn-service, + signal receive set=term peer=pgrep, @{exec_path} mr, - @{lib}/{,NetworkManager/}nm-openvpn-service-openvpn-helper rPx, + @{bin}/ip rix, # TODO: rCx + @{bin}/systemd-ask-password rPx, + + @{lib}/nm-openvpn-service-openvpn-helper rPx, + @{lib}/{,NetworkManager/}nm-openvpn-service-openvpn-helper rPx, + + /etc/openvpn/force-user-traffic-via-vpn.sh rCx -> force-user-traffic-via-vpn, + /etc/openvpn/update-resolv-conf{,.sh} rCx -> update-resolv, /etc/openvpn/{,**} r, + /etc/openvpn/static.key w, @{HOME}/.cert/{,**} r, @@ -61,16 +65,13 @@ profile openvpn @{exec_path} flags=(attach_disconnected) { @{run}/openvpn/*.{pid,status} rw, @{run}/systemd/journal/dev-log r, - @{bin}/ip rix, - @{bin}/systemd-ask-password rPx, - @{lib}/nm-openvpn-service-openvpn-helper rPx, - /etc/openvpn/force-user-traffic-via-vpn.sh rCx -> force-user-traffic-via-vpn, - /etc/openvpn/update-resolv-conf{,.sh} rCx -> update-resolv, - - /dev/net/tun rw, + owner /tmp/openvpn.log w, + owner /tmp/openvpn/{,**} r, owner @{PROC}/@{pid}/net/route r, + /dev/net/tun rw, + profile update-resolv { include include @@ -85,7 +86,7 @@ profile openvpn @{exec_path} flags=(attach_disconnected) { @{bin}/cut rix, @{bin}/ip rix, @{bin}/which{,.debianutils} rix, - @{bin}/xtables-nft-multi rix, + @{sbin}/xtables-{nft,legacy}-multi rix, /etc/iproute2/rt_tables r, /etc/iproute2/rt_tables.d/{,*} r, @@ -111,7 +112,7 @@ profile openvpn @{exec_path} flags=(attach_disconnected) { @{bin}/cut rix, @{bin}/env rix, @{bin}/ip rix, - @{bin}/nft rix, + @{sbin}/nft rix, @{bin}/sed rix, /etc/iproute2/rt_realms r, diff --git a/apparmor.d/groups/network/rpcbind b/apparmor.d/groups/network/rpcbind index f9dcac8d19..39d33aa323 100644 --- a/apparmor.d/groups/network/rpcbind +++ b/apparmor.d/groups/network/rpcbind @@ -1,17 +1,35 @@ # apparmor.d - Full set of apparmor profiles # Copyright (C) 2023 Jeroen Rijken +# Copyright (C) 2025 Jose Maldonado # SPDX-License-Identifier: GPL-2.0-only abi , include -@{exec_path} = @{bin}/rpcbind +@{exec_path} = @{sbin}/rpcbind profile rpcbind @{exec_path} flags=(complain) { include + include + include + + capability setgid, + capability setuid, + + network inet dgram, + network inet6 dgram, + network inet stream, + network inet6 stream, + network netlink raw, @{exec_path} rm, + /etc/netconfig r, + + @{run}/rpcbind.lock rwkl, + @{run}/rpcbind.sock rw, + @{run}/rpcbind/*.xdr rwkl, + include if exists } diff --git a/apparmor.d/groups/network/tailscaled b/apparmor.d/groups/network/tailscaled index ac29b0b283..0fd176f6b4 100644 --- a/apparmor.d/groups/network/tailscaled +++ b/apparmor.d/groups/network/tailscaled @@ -12,6 +12,7 @@ profile tailscaled @{exec_path} flags=(attach_disconnected) { include include include + include capability dac_read_search, capability mknod, @@ -31,13 +32,13 @@ profile tailscaled @{exec_path} flags=(attach_disconnected) { ptrace (read), - #aa:dbus talk bus=system name=org.freedesktop.resolve1 label=systemd-resolved + #aa:dbus talk bus=system name=org.freedesktop.resolve1 label="@{p_systemd_resolved}" @{exec_path} mr, @{bin}/ip rix, @{bin}/resolvectl rPx, - @{bin}/xtables-nft-multi rix, + @{sbin}/xtables-{nft,legacy}-multi rix, @{bin}/systemctl rCx -> systemctl, @@ -53,11 +54,8 @@ profile tailscaled @{exec_path} flags=(attach_disconnected) { owner @{user_share_dirs}/tailscale/{,**} rw, - owner @{run}/systemd/notify w, owner @{run}/tailscale/{,**} rw, - @{sys}/devices/virtual/dmi/id/{bios_vendor,product_name} r, - @{PROC}/ r, @{PROC}/@{pid}/mounts r, @{PROC}/@{pid}/net/{,**} r, diff --git a/apparmor.d/groups/network/wg-quick b/apparmor.d/groups/network/wg-quick index b5e8d88e83..def051d8ac 100644 --- a/apparmor.d/groups/network/wg-quick +++ b/apparmor.d/groups/network/wg-quick @@ -9,6 +9,7 @@ include @{exec_path} = @{bin}/wg-quick profile wg-quick @{exec_path} flags=(attach_disconnected) { include + include include include @@ -17,39 +18,51 @@ profile wg-quick @{exec_path} flags=(attach_disconnected) { network netlink raw, + dbus send bus=system path=/org/freedesktop/resolve1 + interface=org.freedesktop.resolve1.Manager + member={SetLinkDNSEx,SetLinkDomains} + peer=(name=org.freedesktop.resolve1, label="@{p_systemd_resolved}"), + @{exec_path} mr, @{sh_path} rix, @{bin}/cat rix, @{bin}/ip rPx, @{bin}/mv rix, - @{bin}/nft rix, @{bin}/readlink rix, - @{bin}/resolvconf rPx, @{bin}/resolvectl rPx, @{bin}/rm rix, @{bin}/sort rix, @{bin}/stat rix, @{bin}/sync rix, - @{bin}/sysctl rCx -> sysctl, @{bin}/wg rPx, - @{bin}/xtables-nft-multi rix, + @{sbin}/nft rix, + @{sbin}/resolvconf rPx, + @{sbin}/sysctl rCx -> sysctl, + @{sbin}/xtables-{nft,legacy}-multi rix, + /usr/share/iproute2/group r, + /usr/share/iproute2/rt_realms r, /usr/share/terminfo/** r, + @{etc_rw}/wireguard/{,**} rw, /etc/iproute2/group r, /etc/iproute2/rt_realms r, /etc/resolvconf/interface-order r, - /etc/wireguard/{,**} rw, + @{sys}/fs/cgroup/user.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/session.slice/cpu.max r, @{sys}/module/wireguard r, + @{PROC}/@{pid}/cgroup r, @{PROC}/@{pid}/net/ip_tables_names r, profile sysctl flags=(attach_disconnected) { include - @{bin}/sysctl mr, + @{sbin}/sysctl mr, @{PROC}/sys/net/ipv4/conf/all/src_valid_mark w, diff --git a/apparmor.d/groups/pacman/arch-audit b/apparmor.d/groups/pacman/arch-audit index 7539c1c7f6..7432fc3490 100644 --- a/apparmor.d/groups/pacman/arch-audit +++ b/apparmor.d/groups/pacman/arch-audit @@ -34,7 +34,7 @@ profile arch-audit @{exec_path} { owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/mountinfo r, - /dev/pts/@{int} rw, + /dev/pts/@{u16} rw, include if exists } diff --git a/apparmor.d/groups/pacman/archlinux-java b/apparmor.d/groups/pacman/archlinux-java index fe83e168d3..38cd95d0a6 100644 --- a/apparmor.d/groups/pacman/archlinux-java +++ b/apparmor.d/groups/pacman/archlinux-java @@ -14,8 +14,8 @@ profile archlinux-java @{exec_path} { @{exec_path} mr, + @{sh_path} rix, @{bin}/basename rix, - @{bin}/bash rix, @{bin}/dirname rix, @{bin}/find rix, @{bin}/id rix, diff --git a/apparmor.d/groups/pacman/archlinux-keyring-wkd-sync b/apparmor.d/groups/pacman/archlinux-keyring-wkd-sync index 0140734435..cc452e1ed3 100644 --- a/apparmor.d/groups/pacman/archlinux-keyring-wkd-sync +++ b/apparmor.d/groups/pacman/archlinux-keyring-wkd-sync @@ -7,7 +7,7 @@ abi , include @{exec_path} = @{bin}/archlinux-keyring-wkd-sync -profile archlinux-keyring-wkd-sync @{exec_path} { +profile archlinux-keyring-wkd-sync @{exec_path} flags=(attach_disconnected) { include include include @@ -33,6 +33,9 @@ profile archlinux-keyring-wkd-sync @{exec_path} { /etc/pacman.d/gnupg/** rwlk -> /etc/pacman.d/gnupg/**, /etc/pacman.d/mirrorlist r, + @{att}/etc/pacman.d/gnupg/S.dirmngr rw, + @{att}/etc/pacman.d/gnupg/S.gpg-agent rw, + owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/task/@{tid}/comm rw, diff --git a/apparmor.d/groups/pacman/aurpublish b/apparmor.d/groups/pacman/aurpublish index a7a7bf225d..373077f2c6 100644 --- a/apparmor.d/groups/pacman/aurpublish +++ b/apparmor.d/groups/pacman/aurpublish @@ -7,8 +7,9 @@ abi , include @{exec_path} = /usr/share/aurpublish/*.hook -profile aurpublish @{exec_path} { +profile aurpublish @{exec_path} flags=(attach_disconnected) { include + include include include @@ -23,6 +24,7 @@ profile aurpublish @{exec_path} { @{exec_path} mr, @{sh_path} rix, + @{bin}/{,e}grep rix, @{bin}/cat rix, @{bin}/chmod rix, @{bin}/curl rix, @@ -30,7 +32,6 @@ profile aurpublish @{exec_path} { @{bin}/gettext rix, @{bin}/git rPx, @{bin}/gpg{,2} rCx -> gpg, - @{bin}/grep rix, @{bin}/makepkg rix, @{bin}/mkdir rix, @{bin}/mktemp rix, @@ -38,6 +39,7 @@ profile aurpublish @{exec_path} { @{bin}/nproc rix, @{bin}/rm rix, @{bin}/sha*sum rix, + @{bin}/sort rix, @{bin}/tput rix, @{bin}/wc rix, @@ -55,6 +57,7 @@ profile aurpublish @{exec_path} { owner @{user_cache_dirs}/makepkg/src/** rw, owner @{user_config_dirs}/pacman/makepkg.conf r, + owner /tmp/*/ rw, owner /tmp/*/src/ w, owner @{tmp}/tmp.@{rand10} rw, @@ -80,10 +83,12 @@ profile aurpublish @{exec_path} { owner @{run}/user/@{uid}/gnupg/d.@{rand}/S.gpg-agent.browser w, owner @{run}/user/@{uid}/gnupg/d.@{rand}/S.gpg-agent.extra w, owner @{run}/user/@{uid}/gnupg/d.@{rand}/S.gpg-agent.ssh w, + owner @{run}/user/@{uid}/gnupg/d.@{rand}/S.scdaemon w, owner @{tmp}/tmp.@{rand10} rw, owner @{PROC}/@{pid}/fd/ r, + owner @{PROC}/@{pid}/task/@{tid}/comm rw, include if exists } diff --git a/apparmor.d/groups/pacman/makepkg b/apparmor.d/groups/pacman/makepkg index 30650d80c0..c1bc6fe28b 100644 --- a/apparmor.d/groups/pacman/makepkg +++ b/apparmor.d/groups/pacman/makepkg @@ -7,12 +7,11 @@ abi , include @{exec_path} = @{bin}/makepkg -profile makepkg @{exec_path} { +profile makepkg @{exec_path} flags=(attach_disconnected,mediate_deleted) { include include + include include - include - include include include include @@ -26,17 +25,21 @@ profile makepkg @{exec_path} { signal send set=winch peer=pacman, signal send set=winch peer=pacman//systemctl, + unix (bind listen) type=stream, + file, + @{pager_path} Px -> child-pager, @{bin}/gpg{,2} Cx -> gpg, @{bin}/gpgconf Cx -> gpg, @{bin}/gpgsm Cx -> gpg, + @{bin}/lsb_release Px, @{bin}/sudo Cx -> sudo, deny capability sys_ptrace, deny ptrace read, - profile gpg { + profile gpg flags=(attach_disconnected) { include include include @@ -72,13 +75,13 @@ profile makepkg @{exec_path} { owner @{run}/user/@{uid}/gnupg/d.@{rand}/S.scdaemon rw, owner @{run}/user/@{uid}/gnupg/S.scdaemon rw, - owner @{PROC}/@{pid}/fd/ r, - owner @{PROC}/@{pid}/task/@{tid}/comm rw, + @{PROC}/@{pid}/fd/ r, + @{PROC}/@{pid}/task/@{tid}/comm rw, include if exists } - profile sudo { + profile sudo flags=(attach_disconnected) { include include @@ -89,6 +92,7 @@ profile makepkg @{exec_path} { signal send set=(term winch) peer=pacman, signal send set=(term winch) peer=pacman//systemctl, signal send set=(term winch) peer=systemd-tty-ask-password-agent, + signal send set=(term winch) peer=unconfined, @{bin}/pacman Px, diff --git a/apparmor.d/groups/pacman/mkinitcpio b/apparmor.d/groups/pacman/mkinitcpio index f1d4818efe..2dcc7202ad 100644 --- a/apparmor.d/groups/pacman/mkinitcpio +++ b/apparmor.d/groups/pacman/mkinitcpio @@ -28,11 +28,9 @@ profile mkinitcpio @{exec_path} flags=(attach_disconnected) { @{bin}/bsdtar rix, @{bin}/fc-match rix, @{bin}/findmnt rPx, - @{bin}/fsck rix, @{bin}/getent rix, @{bin}/gzip rix, @{bin}/hexdump rix, - @{bin}/ldconfig rix, @{bin}/ldd rix, @{bin}/loadkeys rix, @{bin}/objcopy rix, @@ -41,13 +39,13 @@ profile mkinitcpio @{exec_path} flags=(attach_disconnected) { @{bin}/xz rix, @{bin}/zcat rix, @{bin}/zstd rix, + @{bin}/zstdgrep rix, + @{sbin}/fsck rix, + @{sbin}/ldconfig rix, - @{bin}/{depmod,insmod} rPx, - @{bin}/{kmod,lsmod} rPx, - @{bin}/{modinfo,rmmod} rPx, - @{bin}/modprobe rPx, + @{bin}/kmod rPx, @{bin}/plymouth rPx, - @{bin}/plymouth-set-default-theme rPx, + @{sbin}/plymouth-set-default-theme rPx, @{bin}/sbctl rPx, @{bin}/sync rPx, @@ -55,6 +53,7 @@ profile mkinitcpio @{exec_path} flags=(attach_disconnected) { @{lib}/initcpio/post/** rix, @{lib}/ld-*.so* rix, + /etc/cmdline.d/{,**} r, /etc/fstab r, /etc/initcpio/{,**} r, /etc/locale.conf r, @@ -68,6 +67,9 @@ profile mkinitcpio @{exec_path} flags=(attach_disconnected) { /etc/vconsole.conf r, /usr/share/kbd/{,**} r, + /usr/share/xkeyboard-config-2/{,**} r, + /usr/share/pixmaps/archlinux-logo.png r, + /usr/share/X11/locale/ r, /usr/share/plymouth/*.png r, /usr/share/plymouth/plymouthd.defaults r, /usr/share/plymouth/themes/{,**} r, @@ -78,16 +80,18 @@ profile mkinitcpio @{exec_path} flags=(attach_disconnected) { @{bin}/* mr, @{bin}/*/ r, @{lib}/ r, + @{lib}/modules/*/kernel/drivers/{,*,*/,**.ko.xz,**.ko.zst} r, @{lib}/plymouth/plymouthd-* mr, @{lib}/systemd/{,**} mr, @{lib}/udev/* mr, # Manage /boot / r, - /boot/ r, - /{boot,efi}/EFI/{,**} rw, - /boot/initramfs-*.img* rw, - /boot/vmlinuz-* r, + @{efi}/ r, + @{efi}/@{hex32}/{,**} rw, + @{efi}/EFI/{,**} rw, + @{efi}/initramfs-*.img* rw, + @{efi}/vmlinuz-* r, /usr/share/systemd/bootctl/** r, @@ -97,6 +101,7 @@ profile mkinitcpio @{exec_path} flags=(attach_disconnected) { /tmp/mkinitcpio.@{rand6}.tmp rw, owner @{tmp}/mkinitcpio.@{rand6} rw, owner @{tmp}/mkinitcpio.@{rand6}/{,**} rwl, + owner @{tmp}/staging_initramfs.img w, owner @{run}/initcpio-tmp/mkinitcpio.@{rand6}/{,**} rwl, owner @{run}/initramfs/{,**} rw, @@ -105,10 +110,17 @@ profile mkinitcpio @{exec_path} flags=(attach_disconnected) { @{sys}/class/block/ r, @{sys}/devices/{,**} r, @{sys}/firmware/efi/fw_platform_size r, - + @{sys}/fs/cgroup/user.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/session-@{int}.scope/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/session.slice/cpu.max r, + + @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/mountinfo r, - /dev/tty@{int}* rw, + /dev/tty@{u8}* rw, # Inherit silencer deny @{HOME}/** r, diff --git a/apparmor.d/groups/pacman/paccache b/apparmor.d/groups/pacman/paccache index f537afdb35..9a68619b99 100644 --- a/apparmor.d/groups/pacman/paccache +++ b/apparmor.d/groups/pacman/paccache @@ -9,6 +9,7 @@ include @{exec_path} = @{bin}/paccache profile paccache @{exec_path} flags=(attach_disconnected) { include + include include capability dac_read_search, @@ -16,9 +17,10 @@ profile paccache @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, + @{sh_path} rix, @{bin}/{m,g,}awk rix, - @{bin}/bash rix, @{bin}/cat rix, + @{bin}/date rix, @{bin}/gettext rix, @{bin}/gpg{,2} rix, @{bin}/gpgconf rix, @@ -36,10 +38,14 @@ profile paccache @{exec_path} flags=(attach_disconnected) { /etc/pacman.conf r, /etc/pacman.d/{,**} r, + /etc/pacman.d/gnupg/** rwlk -> /etc/pacman.d/gnupg/**, /var/cache/pacman/pkg/{,*} rw, /var/lib/pacman/{,**} r, + @{HOME}/@{XDG_GPG_DIR}/gpg.conf r, + @{HOME}/@{XDG_GPG_DIR}/gpgsm.conf r, + owner @{PROC}/@{pid}/fd/ r, /dev/tty rw, diff --git a/apparmor.d/groups/pacman/pacdiff b/apparmor.d/groups/pacman/pacdiff index 64a813bf47..82f42a9bab 100644 --- a/apparmor.d/groups/pacman/pacdiff +++ b/apparmor.d/groups/pacman/pacdiff @@ -19,26 +19,23 @@ profile pacdiff @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, @{sh_path} rix, - @{bin}/{m,g,}awk rix, - @{bin}/cat rix, - @{bin}/cmp rix, - @{bin}/find rix, - @{bin}/locate rix, - @{bin}/pacman rix, - @{bin}/pacman-conf rPx, - @{bin}/pacsort rix, - @{bin}/rm rix, - @{bin}/sed rix, - @{bin}/tput rix, - @{bin}/vim rix, - - owner @{HOME}/.viminfo{,.tmp} rw, - - owner @{user_cache_dirs}/vim/{,**} rw, - + @{bin}/{m,g,}awk ix, + @{bin}/cat ix, + @{bin}/cmp ix, + @{bin}/find ix, + @{bin}/locate ix, + @{bin}/pacman ix, + @{bin}/pacman-conf Px, + @{bin}/pacsort ix, + @{bin}/rm ix, + @{bin}/sed ix, + @{bin}/tput ix, + @{editor_path} Cx -> editor, + + #aa:lint ignore=too-wide # packages files / r, - /boot/{,**} r, + @{efi}/{,**} r, /etc/{,**} rw, /opt/{,**} r, /srv/{,**} r, @@ -46,7 +43,17 @@ profile pacdiff @{exec_path} flags=(attach_disconnected) { /var/{,**} r, /dev/tty rw, - /dev/pts/@{int} rw, + /dev/pts/@{u16} rw, + + profile editor { + include + include + + #aa:lint ignore=too-wide + /etc/** rw, + + include if exists + } include if exists } diff --git a/apparmor.d/groups/pacman/pacman b/apparmor.d/groups/pacman/pacman index 0043cd0615..bf70c1c39f 100644 --- a/apparmor.d/groups/pacman/pacman +++ b/apparmor.d/groups/pacman/pacman @@ -12,7 +12,6 @@ profile pacman @{exec_path} flags=(attach_disconnected) { include include include - include include capability audit_write, @@ -27,6 +26,7 @@ profile pacman @{exec_path} flags=(attach_disconnected) { capability setfcap, capability setgid, capability setuid, + capability sys_admin, capability sys_chroot, capability sys_ptrace, capability sys_resource, @@ -45,91 +45,75 @@ profile pacman @{exec_path} flags=(attach_disconnected) { @{exec_path} mrix, - @{bin}/gpg{,2} rCx -> gpg, - @{bin}/gpgconf rCx -> gpg, - @{bin}/gpgsm rCx -> gpg, - - # Pacman hooks & install scripts - @{sh_path} rix, - @{coreutils_path} rix, - @{bin}/appstreamcli rPx, - @{bin}/arch-audit rPx, - @{bin}/archlinux-java rPx, - @{bin}/bootctl rPx, - @{bin}/cert-sync rPx, - @{bin}/checkrebuild rPUx, - @{bin}/dconf rPx, - @{bin}/dot rix, - @{bin}/fc-cache{,-32} rPx, - @{bin}/filecap rix, - @{bin}/gdbus rix, - @{bin}/gdk-pixbuf-query-loaders rPx, - @{bin}/getent rix, - @{bin}/gettext rix, - @{bin}/ghc-pkg-@{version} rix, - @{bin}/gio-querymodules rPx, - @{bin}/glib-compile-schemas rPx, - @{bin}/groupadd rPx, - @{bin}/gtk-query-immodules-{2,3}.0 rPx, - @{bin}/gtk{,4}-update-icon-cache rPx, - @{bin}/iconvconfig rix, - @{bin}/install-catalog rPx, - @{bin}/install-info rPx, - @{bin}/iscsi-iname rix, - @{bin}/journalctl rPx, - @{bin}/killall rix, - @{bin}/ldconfig rix, - @{bin}/locale-gen rPx, - @{bin}/mkinitcpio rPx, - @{bin}/needrestart rPx, - @{bin}/pacdiff rPx, - @{bin}/pacman-key rPx, - @{bin}/pkgfile rPUx, - @{bin}/pkill rix, - @{bin}/rsync rix, - @{bin}/sbctl rPx, - @{bin}/setcap rix, - @{bin}/setfacl rix, - @{bin}/sysctl rPx, - @{bin}/systemctl rCx -> systemctl, - @{bin}/systemd-* rPx, - @{bin}/tput rix, - @{bin}/update-ca-trust rPx, - @{bin}/update-desktop-database rPx, - @{bin}/update-grub rPx, - @{bin}/update-mime-database rPx, - @{bin}/vercmp rix, - @{bin}/which rix, - @{bin}/xmlcatalog rix, - @{lib}/systemd/systemd-* rPx, - @{lib}/ghc-@{version}/bin/ghc-pkg-@{version} rix, - @{lib}/vlc/vlc-cache-gen rPx, - /opt/Mullvad*/resources/mullvad-setup rPx, - /usr/share/code-features/patch.py rPx, - /usr/share/code-marketplace/patch.py rPx, - /usr/share/libalpm/scripts/* rPUx, - /usr/share/texmf-dist/scripts/texlive/mktexlsr rPUx, - - # For shell pwd, keept as it can annoy some users to see error in pacman output + # Pacman's keyring + @{bin}/gpg{,2} Cx -> gpg, + @{bin}/gpgconf Cx -> gpg, + @{bin}/gpgsm Cx -> gpg, + + # Common program found in hooks & install scripts + @{sh_path} rix, + @{coreutils_path} rix, + @{bin}/dot ix, + @{bin}/filecap ix, + @{bin}/getent ix, + @{bin}/gettext ix, + @{bin}/gzip ix, + @{bin}/rsync ix, + @{bin}/setfacl ix, + @{bin}/tput ix, + @{bin}/vercmp ix, + @{bin}/which{,.debianutils} ix, + @{bin}/xmlcatalog ix, + @{sbin}/iconvconfig ix, + @{sbin}/iscsi-iname ix, + @{sbin}/setcap ix, + + @{bin}/dbus-send Cx -> bus, + @{bin}/gdbus Cx -> bus, + @{bin}/killall Cx -> pkill, + @{bin}/kmod Cx -> kmod, + @{bin}/pkill Cx -> pkill, + @{bin}/systemctl Cx -> systemctl, + @{sbin}/ldconfig Cx -> ldconfig, + + #aa:lint ignore=too-wide + # Hooks & install scripts can legitimately start/restart anything + # PU is only used as a safety fallback. + @{bin}/** PUx, + @{sbin}/** PUx, + /opt/*/** PUx, + /etc/** PUx, + /usr/share/** PUx, + + priority=-1 @{lib}/** PUx, + @{lib}/ghc-@{version}/bin/ghc-pkg-@{version} Px, + @{lib}/systemd/systemd-* Px, + @{lib}/vlc/vlc-cache-gen Px, + + # For shell pwd, keept as it can annoy users to see error in pacman output /**/ r, # Install/update packages + #aa:lint ignore=too-wide / r, /*{,/} rw, - /boot/** rwl -> /boot/**, - /etc/** rwl -> /etc/**, - /opt/** rwl -> /opt/**, - /srv/** rwl -> /srv/**, - /usr/** rwlk -> /usr/**, - /var/** rwlk -> /var/**, + @{efi}/** rwlk, + /etc/** rwlk, + /opt/** rwlk, + /srv/** rwlk, + /usr/** rwlk, + /var/** rwlk, # Read packages files @{user_pkg_dirs}/{,**} r, owner /var/lib/pacman/{,**} rwl, owner @{tmp}/alpm_@{rand6}/{,**} rw, - owner @{tmp}/checkup-db-@{int}/sync/{,*.db*} rw, + owner @{tmp}/arch-update-@{uid}/checkupdates-@{rand}/sync/** w, owner @{tmp}/checkup-db-@{int}/db.lck rw, + owner @{tmp}/checkup-db-@{int}/sync/{,*.db*} rw, + owner @{tmp}/checkup-db-@{uid}/sync/download-@{rand6}/ rw, + owner @{tmp}/checkup-db-@{uid}/sync/download-@{rand6}/{,*} rw, @{run}/utmp rk, @@ -146,13 +130,8 @@ profile pacman @{exec_path} flags=(attach_disconnected) { owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/mounts r, - /dev/tty@{int} rw, - owner /dev/pts/@{int} rw, - - # Silencer, - deny @{HOME}/ r, - deny @{HOME}/**/ r, - deny /tmp/ r, + /dev/tty@{u8} rw, + owner /dev/pts/@{u16} rw, profile gpg { include @@ -177,27 +156,32 @@ profile pacman @{exec_path} flags=(attach_disconnected) { /etc/pacman.d/gnupg/ rw, /etc/pacman.d/gnupg/** rwkl -> /etc/pacman.d/gnupg/**, + @{run}/user/@{uid}/gnupg/ w, + @{HOME}/@{XDG_GPG_DIR}/*.conf r, @{PROC}/@{pid}/fd/ r, @{PROC}/@{pid}/task/@{tid}/comm rw, - /dev/tty@{int} rw, - owner /dev/pts/@{int} rw, + /dev/tty@{u8} rw, + owner /dev/pts/@{u16} rw, deny @{user_share_dirs}/sddm/* rw, include if exists } - profile systemctl { + profile systemctl flags=(attach_disconnected) { include include + include capability net_admin, capability dac_read_search, capability sys_resource, + ptrace read peer=@{p_systemd}, + signal send set=cont peer=child-pager, signal send set=(cont term) peer=systemd-tty-ask-password-agent, signal receive set=(term winch) peer=makepkg//sudo, @@ -209,11 +193,76 @@ profile pacman @{exec_path} flags=(attach_disconnected) { /{run,var}/log/journal/ r, /{run,var}/log/journal/@{hex32}/ r, - /{run,var}/log/journal/@{hex32}/*.journal* r, + /{run,var}/log/journal/@{hex32}/system.journal* r, + /{run,var}/log/journal/@{hex32}/system@@{hex}-@{hex}.journal* r, + /{run,var}/log/journal/@{hex32}/system@@{hex32}-@{hex16}-@{hex16}.journal* r, + /{run,var}/log/journal/@{hex32}/user-@{hex}.journal* r, + /{run,var}/log/journal/@{hex32}/user-@{uid}@@{hex}-@{hex}.journal* r, + /{run,var}/log/journal/@{hex32}/user-@{uid}@@{hex32}-@{hex16}-@{hex16}.journal* r, include if exists } + profile bus { + include + include + include + include + + @{bin}/gdbus rix, + + include if exists + } + + profile pkill { + include + include + + capability dac_read_search, + capability kill, + + signal send, + + @{bin}/killall mr, + @{bin}/pkill mr, + + include if exists + } + + profile kmod { + include + include + + include if exists + } + + profile ldconfig { + include + include + + capability sys_chroot, + + @{sh_path} rix, + @{sbin}/ldconfig mrix, + + @{lib}/ r, + @{lib}/** rw, + /usr/local/ r, + /usr/local/lib/ r, + + /opt/**/@{lib}/ r, + /opt/**/@{lib}/@{multiarch}/ r, + /opt/**/@{lib}/**.so* r, + + /etc/ld.so.cache rw, + /etc/ld.so.cache~ rw, + + /var/cache/ldconfig/ rw, + owner /var/cache/ldconfig/aux-cache* rw, + + include if exists + } + include if exists include if exists } diff --git a/apparmor.d/groups/pacman/pacman-conf b/apparmor.d/groups/pacman/pacman-conf index 4884d248ce..b22140a91e 100644 --- a/apparmor.d/groups/pacman/pacman-conf +++ b/apparmor.d/groups/pacman/pacman-conf @@ -13,11 +13,15 @@ profile pacman-conf @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, + /usr/share/devtools/pacman.conf.d/* r, + /etc/pacman.conf r, /etc/pacman.d/mirrorlist r, /etc/pacman.d/*-mirrorlist r, - /dev/tty@{int} rw, + /var/lib/archbuild/extra-@{arch}/*/etc/pacman.conf r, + + /dev/tty@{u8} rw, # Inherit Silencer deny network inet6 stream, diff --git a/apparmor.d/groups/pacman/pacman-hook-code b/apparmor.d/groups/pacman/pacman-hook-code index 2496d7a9b4..ca10081ba1 100644 --- a/apparmor.d/groups/pacman/pacman-hook-code +++ b/apparmor.d/groups/pacman/pacman-hook-code @@ -6,9 +6,10 @@ abi , include -@{exec_path} = /usr/share/code-{features,marketplace}/patch.py +@{exec_path} = /usr/share/code-{features,marketplace}{,-insiders}/patch.py profile pacman-hook-code @{exec_path} { include + include include capability dac_read_search, @@ -19,9 +20,14 @@ profile pacman-hook-code @{exec_path} { @{python_path} rix, @{lib}/code/product.json rw, + @{lib}/code/out/vs/code/electron-utility/sharedProcess/sharedProcessMain.js w, - /usr/share/code-{features,marketplace}/{,*} r, - /usr/share/code-{features,marketplace}/cache.json rw, + /usr/share/code-{features,marketplace}{,-insiders}/{,*} r, + /usr/share/code-{features,marketplace}{,-insiders}/cache.json rw, + + # File Inherit + deny network inet stream, + deny network inet6 stream, include if exists } diff --git a/apparmor.d/groups/pacman/pacman-hook-dconf b/apparmor.d/groups/pacman/pacman-hook-dconf index b5a330d75e..73c89293b9 100644 --- a/apparmor.d/groups/pacman/pacman-hook-dconf +++ b/apparmor.d/groups/pacman/pacman-hook-dconf @@ -7,14 +7,14 @@ abi , include @{exec_path} = /usr/share/libalpm/scripts/dconf-update -profile pacman-hook-dconf @{exec_path} { +profile pacman-hook-dconf @{exec_path} flags=(attach_disconnected) { include capability dac_read_search, @{exec_path} mr, - @{bin}/bash rix, + @{sh_path} rix, @{bin}/rm rix, @{bin}/dconf rPx, diff --git a/apparmor.d/groups/pacman/pacman-hook-depmod b/apparmor.d/groups/pacman/pacman-hook-depmod index 45336a100c..8a471e55d7 100644 --- a/apparmor.d/groups/pacman/pacman-hook-depmod +++ b/apparmor.d/groups/pacman/pacman-hook-depmod @@ -7,25 +7,24 @@ abi , include @{exec_path} = /usr/share/libalpm/scripts/depmod -profile pacman-hook-depmod @{exec_path} { +profile pacman-hook-depmod @{exec_path} flags=(attach_disconnected) { include capability dac_read_search, @{exec_path} mr, + @{sh_path} rix, @{bin}/basename rix, - @{bin}/bash rix, - @{bin}/depmod rPx, @{bin}/kmod rPx, @{bin}/rm rix, @{bin}/rmdir rix, - /usr/lib/modules/*/{,**} rw, + @{lib}/modules/*/{,**} rw, /dev/tty rw, - /dev/tty@{int} rw, - owner /dev/pts/@{int} rw, + /dev/tty@{u8} rw, + owner /dev/pts/@{u16} rw, # Inherit Silencer deny network inet6 stream, diff --git a/apparmor.d/groups/pacman/pacman-hook-dkms b/apparmor.d/groups/pacman/pacman-hook-dkms index a039db4149..949094e2f2 100644 --- a/apparmor.d/groups/pacman/pacman-hook-dkms +++ b/apparmor.d/groups/pacman/pacman-hook-dkms @@ -18,10 +18,11 @@ profile pacman-hook-dkms @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, - @{sh_path} rix, - @{bin}/dkms rPx, - @{bin}/kmod rPx, - @{bin}/nproc rix, + @{sh_path} rix, + @{bin}/{,e}grep rix, + @{bin}/kmod Px, + @{bin}/nproc Px, + @{sbin}/dkms Px, /usr/src/ r, /usr/src/**.conf r, diff --git a/apparmor.d/groups/pacman/pacman-hook-fontconfig b/apparmor.d/groups/pacman/pacman-hook-fontconfig index de0d33e162..5c6e98347e 100644 --- a/apparmor.d/groups/pacman/pacman-hook-fontconfig +++ b/apparmor.d/groups/pacman/pacman-hook-fontconfig @@ -14,14 +14,14 @@ profile pacman-hook-fontconfig @{exec_path} { @{exec_path} mr, - @{bin}/bash rix, + @{sh_path} rix, @{bin}/ln rix, @{bin}/rm rix, /etc/fonts/conf.d/* rwl, /usr/share/fontconfig/conf.default/* r, - /dev/pts/@{int} rw, + /dev/pts/@{u16} rw, /dev/tty rw, # Inherit Silencer diff --git a/apparmor.d/groups/pacman/pacman-hook-gio b/apparmor.d/groups/pacman/pacman-hook-gio index 5aa612a3c8..17218158e1 100644 --- a/apparmor.d/groups/pacman/pacman-hook-gio +++ b/apparmor.d/groups/pacman/pacman-hook-gio @@ -14,14 +14,14 @@ profile pacman-hook-gio @{exec_path} { @{exec_path} mr, - @{bin}/bash rix, + @{sh_path} rix, @{bin}/rmdir rix, @{bin}/gio-querymodules rPx, @{lib}/gio/modules/giomodule.cache{,.[0-9A-Z]*} rw, @{lib}/gtk-{3,4}.0/**/*/ rw, - /usr/lib/gio/modules/ rw, + @{lib}/gio/modules/ rw, /dev/tty rw, diff --git a/apparmor.d/groups/pacman/pacman-hook-gtk b/apparmor.d/groups/pacman/pacman-hook-gtk index ce7b931ca6..960db0cbf6 100644 --- a/apparmor.d/groups/pacman/pacman-hook-gtk +++ b/apparmor.d/groups/pacman/pacman-hook-gtk @@ -7,14 +7,14 @@ abi , include @{exec_path} = /usr/share/libalpm/scripts/gtk-update-icon-cache -profile pacman-hook-gtk @{exec_path} { +profile pacman-hook-gtk @{exec_path} flags=(attach_disconnected) { include capability dac_read_search, @{exec_path} mr, - @{bin}/bash rix, + @{sh_path} rix, @{bin}/rm rix, @{bin}/rmdir rix, @@ -24,8 +24,8 @@ profile pacman-hook-gtk @{exec_path} { /usr/share/icons/{,**} rw, /dev/tty rw, - /dev/tty@{int} rw, - owner /dev/pts/@{int} rw, + /dev/tty@{u8} rw, + owner /dev/pts/@{u16} rw, # Inherit Silencer deny network inet6 stream, diff --git a/apparmor.d/groups/pacman/pacman-hook-gtk4-querymodules b/apparmor.d/groups/pacman/pacman-hook-gtk4-querymodules index a0be0e39bf..6f281efa30 100644 --- a/apparmor.d/groups/pacman/pacman-hook-gtk4-querymodules +++ b/apparmor.d/groups/pacman/pacman-hook-gtk4-querymodules @@ -7,7 +7,7 @@ abi , include @{exec_path} = /usr/share/libalpm/scripts/gtk4-querymodules -profile pacman-hook-gtk4-querymodules @{exec_path} { +profile pacman-hook-gtk4-querymodules @{exec_path} flags=(attach_disconnected) { include include diff --git a/apparmor.d/groups/pacman/pacman-hook-mkinitcpio b/apparmor.d/groups/pacman/pacman-hook-mkinitcpio index a9bf40360a..4916271fe7 100644 --- a/apparmor.d/groups/pacman/pacman-hook-mkinitcpio +++ b/apparmor.d/groups/pacman/pacman-hook-mkinitcpio @@ -16,7 +16,7 @@ profile pacman-hook-mkinitcpio @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, - @{bin}/bash rix, + @{sh_path} rix, @{bin}/cmp rix, @{bin}/compgen rix, @{bin}/env rix, @@ -36,21 +36,30 @@ profile pacman-hook-mkinitcpio @{exec_path} flags=(attach_disconnected) { /etc/mkinitcpio.d/*.preset{,.pacsave} rw, / r, - /boot/ r, - /{boot,efi}/EFI/boot/boot*.efi rw, - /boot/initramfs-*-fallback.img rw, - /boot/initramfs-*.img rw, - /boot/vmlinuz-* rw, + @{efi}/ r, + @{efi}/EFI/boot/boot*.efi rw, + @{efi}/initramfs-*-fallback.img rw, + @{efi}/initramfs-*.img rw, + @{efi}/vmlinuz-* rw, + + @{sys}/fs/cgroup/user.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/cpu.max r, + + @{PROC}/@{pid}/cgroup r, /dev/tty rw, - owner /dev/pts/@{int} rw, + owner /dev/pts/@{u16} rw, - # # Inherit Silencer + # Inherit Silencer deny network inet6 stream, deny network inet stream, profile pacman { include + include + include capability dac_read_search, @@ -68,6 +77,10 @@ profile pacman-hook-mkinitcpio @{exec_path} flags=(attach_disconnected) { @{HOME}/@{XDG_GPG_DIR}/*.conf r, + # Inherit Silencer + deny network inet6 stream, + deny network inet stream, + include if exists } diff --git a/apparmor.d/groups/pacman/pacman-hook-mkinitcpio-remove b/apparmor.d/groups/pacman/pacman-hook-mkinitcpio-remove index 7c00061532..6378ca9918 100644 --- a/apparmor.d/groups/pacman/pacman-hook-mkinitcpio-remove +++ b/apparmor.d/groups/pacman/pacman-hook-mkinitcpio-remove @@ -15,7 +15,7 @@ profile pacman-hook-mkinitcpio-remove @{exec_path} { @{exec_path} mr, - @{bin}/bash rix, + @{sh_path} rix, @{bin}/cmp rix, @{bin}/mv rix, @{bin}/rm rix, @@ -24,9 +24,9 @@ profile pacman-hook-mkinitcpio-remove @{exec_path} { /usr/share/mkinitcpio/*.preset r, /etc/mkinitcpio.d/*.preset rw, - /boot/vmlinuz-* rw, - /boot/initramfs-*.img rw, - /boot/initramfs-*-fallback.img rw, + @{efi}/vmlinuz-* rw, + @{efi}/initramfs-*.img rw, + @{efi}/initramfs-*-fallback.img rw, /dev/tty rw, diff --git a/apparmor.d/groups/pacman/pacman-hook-perl b/apparmor.d/groups/pacman/pacman-hook-perl index 07539ae958..d8dbfc714a 100644 --- a/apparmor.d/groups/pacman/pacman-hook-perl +++ b/apparmor.d/groups/pacman/pacman-hook-perl @@ -7,7 +7,7 @@ abi , include @{exec_path} = /usr/share/libalpm/scripts/detect-old-perl-modules.sh -profile pacman-hook-perl @{exec_path} { +profile pacman-hook-perl @{exec_path} flags=(attach_disconnected) { include include @@ -20,10 +20,11 @@ profile pacman-hook-perl @{exec_path} { @{bin}/find rix, @{bin}/pacman rPx, @{bin}/sed rix, + @{bin}/wc rix, /dev/tty rw, - /dev/tty@{int} rw, - owner /dev/pts/@{int} rw, + /dev/tty@{u8} rw, + owner /dev/pts/@{u16} rw, # Inherit silencer deny network inet6 stream, diff --git a/apparmor.d/groups/pacman/pacman-hook-systemd b/apparmor.d/groups/pacman/pacman-hook-systemd index 0878385c54..be5261c2c0 100644 --- a/apparmor.d/groups/pacman/pacman-hook-systemd +++ b/apparmor.d/groups/pacman/pacman-hook-systemd @@ -32,8 +32,8 @@ profile pacman-hook-systemd @{exec_path} { /usr/ rw, /dev/tty rw, - /dev/tty@{int} rw, - owner /dev/pts/@{int} rw, + /dev/tty@{u8} rw, + owner /dev/pts/@{u16} rw, # Inherit silencer deny network inet6 stream, @@ -46,6 +46,8 @@ profile pacman-hook-systemd @{exec_path} { capability net_admin, capability sys_resource, + ptrace read peer=@{p_systemd}, + signal send set=(cont, term) peer=systemd-tty-ask-password-agent, @{bin}/systemd-tty-ask-password-agent Px, diff --git a/apparmor.d/groups/pacman/pacman-key b/apparmor.d/groups/pacman/pacman-key index 287bc026ab..67b67196cc 100644 --- a/apparmor.d/groups/pacman/pacman-key +++ b/apparmor.d/groups/pacman/pacman-key @@ -16,15 +16,15 @@ profile pacman-key @{exec_path} { @{exec_path} mr, + @{sh_path} rix, @{bin}/{m,g,}awk rix, @{bin}/basename rix, - @{bin}/bash rix, @{bin}/chmod rix, @{bin}/gettext rix, - @{bin}/gpg{,2} rCx -> gpg, - @{bin}/grep rix, + @{bin}/gpg{,2} rCx -> &gpg, + @{bin}/{,e}grep rix, @{bin}/ngettext rix, - @{bin}/pacman-conf rPx, + @{bin}/pacman-conf rPx -> &pacman-conf, @{bin}/touch rix, @{bin}/tput rix, @{bin}/vercmp rix, @@ -34,7 +34,11 @@ profile pacman-key @{exec_path} { /usr/share/pacman/keyrings/{,*} r, /usr/share/terminfo/** r, - /etc/pacman.d/gnupg/* rw, + /etc/pacman.d/gnupg/ rw, + /etc/pacman.d/gnupg/** rwkl -> /etc/pacman.d/gnupg/**, + + /var/lib/archbuild/extra-@{arch}/*/etc/pacman.d/gnupg/ rw, + /var/lib/archbuild/extra-@{arch}/*/etc/pacman.d/gnupg/** rwkl -> /etc/pacman.d/gnupg/**, /dev/tty rw, @@ -59,14 +63,14 @@ profile pacman-key @{exec_path} { /etc/pacman.d/gnupg/ rw, /etc/pacman.d/gnupg/** rwkl, - @{HOME}/.gnupg/gpg.conf r, + @{HOME}/@{XDG_GPG_DIR}/gpg.conf r, owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/task/@{tid}/comm rw, owner @{PROC}/@{pid}/task/@{tid}/stat rw, - /dev/pts/@{int} rw, - /dev/tty@{int} rw, + /dev/pts/@{u16} rw, + /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/pacman/pkgctl b/apparmor.d/groups/pacman/pkgctl new file mode 100644 index 0000000000..48b5ebb6a3 --- /dev/null +++ b/apparmor.d/groups/pacman/pkgctl @@ -0,0 +1,25 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# This profile is large on purpose: +# +# - Pkgctl uses a lot of different binaries and scripts inside sandbox. +# - Using the unconfined flag would Pix everything, we do not want that as the +# transitioned profile would have to account for pkgctl paths too. +# - It could be restricted latter using a namsepace approach. + +abi , + +include + +@{exec_path} = @{bin}/pkgctl +profile pkgctl @{exec_path} flags=(attach_disconnected,mediate_deleted) { + include + + all, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/pacman/reflector b/apparmor.d/groups/pacman/reflector index 119f0d2a1a..9abf675369 100644 --- a/apparmor.d/groups/pacman/reflector +++ b/apparmor.d/groups/pacman/reflector @@ -41,8 +41,8 @@ profile reflector @{exec_path} flags=(attach_disconnected) { @{PROC}/cmdline r, @{PROC}/sys/kernel/osrelease r, - /dev/tty@{int} rw, - owner /dev/pts/@{int} rw, + /dev/tty@{u8} rw, + owner /dev/pts/@{u16} rw, include if exists } diff --git a/apparmor.d/groups/pacman/yay b/apparmor.d/groups/pacman/yay index 42932cc2e9..3f58c16f9a 100644 --- a/apparmor.d/groups/pacman/yay +++ b/apparmor.d/groups/pacman/yay @@ -10,6 +10,7 @@ include profile yay @{exec_path} { include include + include include include @@ -19,6 +20,9 @@ profile yay @{exec_path} { network inet6 stream, network netlink raw, + signal send set=term peer=pkttyagent, + signal send set=term peer=systemd-tty-ask-password-agent, + @{exec_path} mr, @{editor_path} Cx -> editor, @@ -28,6 +32,8 @@ profile yay @{exec_path} { @{bin}/pacman Px, @{bin}/pacman-conf Px, @{bin}/sudo Cx -> sudo, + @{bin}/pkttyagent Px, + @{bin}/systemd-tty-ask-password-agent Px, /var/lib/pacman/** r, @@ -36,6 +42,8 @@ profile yay @{exec_path} { owner @{user_config_dirs}/yay/{,**} rw, + owner @{PROC}/@{pid}/stat r, + profile git { include include @@ -90,10 +98,15 @@ profile yay @{exec_path} { owner @{HOME}/@{XDG_GPG_DIR}/ rw, owner @{HOME}/@{XDG_GPG_DIR}/** rwkl -> @{HOME}/@{XDG_GPG_DIR}/**, + owner @{run}/user/@{uid}/gnupg/d.@{hex}/S.dirmngr rw, + owner @{run}/user/@{uid}/gnupg/d.@{hex}/S.gpg-agent rw, + + owner @{PROC}/@{pid}/fd/ r, + include if exists } - profile sudo { + profile sudo flags=(attach_disconnected) { include include diff --git a/apparmor.d/groups/polkit/pkexec b/apparmor.d/groups/polkit/pkexec index f4fc76639d..54d6f7b13d 100644 --- a/apparmor.d/groups/polkit/pkexec +++ b/apparmor.d/groups/polkit/pkexec @@ -21,12 +21,14 @@ profile pkexec @{exec_path} { @{exec_path} mr, @{bin}/* PUx, + @{sbin}/* PUx, @{lib}/** PUx, /opt/*/** PUx, /usr/share/** PUx, /etc/default/locale r, + @{PROC}/@{pid}/cgroup r, @{PROC}/@{pid}/stat r, owner @{PROC}/@{pid}/fd/ r, diff --git a/apparmor.d/groups/polkit/pkttyagent b/apparmor.d/groups/polkit/pkttyagent index de0eeef331..c952abd94b 100644 --- a/apparmor.d/groups/polkit/pkttyagent +++ b/apparmor.d/groups/polkit/pkttyagent @@ -11,21 +11,34 @@ include profile pkttyagent @{exec_path} { include include - include + include include include capability sys_nice, capability audit_write, - ptrace (read), - signal (send,receive), + ptrace read, + signal (send, receive), + + dbus receive bus=system path=/org/freedesktop/PolicyKit1/AuthenticationAgent + interface=org.freedesktop.PolicyKit1.AuthenticationAgent + member=BeginAuthentication + peer=(name=@{busname}, label="@{p_polkitd}"), + + dbus send bus=system path=/org/freedesktop/PolicyKit1/Authority + interface=org.freedesktop.PolicyKit1.Authority + member=RegisterAuthenticationAgentWithOptions + peer=(name=@{busname}, label="@{p_polkitd}"), @{exec_path} mr, @{lib}/polkit-[0-9]/polkit-agent-helper-[0-9] rPx, @{lib}/polkit-agent-helper-[0-9] rPx, + @{run}/polkit/agent-helper.socket rw, + + owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/fdinfo/@{int} r, owner @{PROC}/@{pids}/stat r, diff --git a/apparmor.d/groups/polkit/polkit-agent-helper b/apparmor.d/groups/polkit/polkit-agent-helper index 7f5ecd1074..7a92acccf2 100644 --- a/apparmor.d/groups/polkit/polkit-agent-helper +++ b/apparmor.d/groups/polkit/polkit-agent-helper @@ -17,40 +17,63 @@ profile polkit-agent-helper @{exec_path} flags=(attach_disconnected) { include capability audit_write, + capability chown, capability dac_override, + capability fowner, capability net_admin, capability setgid, capability setuid, capability sys_nice, + capability sys_ptrace, # optional: no audit network netlink raw, - signal (receive) set=(term, kill) peer=gnome-shell, - signal (receive) set=(term, kill) peer=pkexec, - signal (receive) set=(term, kill) peer=pkttyagent, - signal (receive) set=(term, kill) peer=polkit-*-authentication-agent, + ptrace read peer=@{p_systemd}, + ptrace read peer=gnome-shell, + ptrace read peer=pkttyagent, + ptrace read peer=polkit-kde-authentication-agent, + + signal receive set=(term kill) peer=flatpak, + signal receive set=(term kill) peer=gnome-shell, + signal receive set=(term kill) peer=pkexec, + signal receive set=(term kill) peer=pkttyagent, + signal receive set=(term kill) peer=polkit-*-authentication-agent, + signal receive set=(term kill) peer=yay, + + unix bind type=stream addr=@@{udbus}/bus/polkit-agent-he/system, dbus send bus=system path=/org/freedesktop/PolicyKit1/Authority interface=org.freedesktop.DBus.Properties member=GetAll - peer=(name=:*, label=polkitd), + peer=(name=@{busname}, label="@{p_polkitd}"), dbus send bus=system path=/org/freedesktop/PolicyKit1/Authority interface=org.freedesktop.PolicyKit1.Authority - member=AuthenticationAgentResponse2 - peer=(name=:*, label=polkitd), + member=AuthenticationAgentResponse{2,3} + peer=(name=@{busname}, label="@{p_polkitd}"), + + dbus send bus=system path=/org/freedesktop/home1 + interface=org.freedesktop.home1.Manager + member=GetUserRecordByName + peer=(name=org.freedesktop.home1, label=systemd-homed), @{exec_path} mr, + #aa:only apparmor>=4.1 + priority=1 @{sbin}/unix_chkpwd Px -> polkit-agent-helper//&unix-chkpwd, + owner @{HOME}/.xsession-errors w, - @{run}/faillock/@{user} rwk, + @{run}/faillock/@{user} rwk, + @{att}@{run}/systemd/home/@{user}.dont-suspend w, - @{PROC}/1/cgroup r, + @{PROC}/@{pid}/cgroup r, + @{PROC}/@{pid}/stat r, + @{PROC}/@{pid}/fdinfo/@{int} r, owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/loginuid r, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/polkit/polkitd b/apparmor.d/groups/polkit/polkitd index 38f05275bc..c74d40a048 100644 --- a/apparmor.d/groups/polkit/polkitd +++ b/apparmor.d/groups/polkit/polkitd @@ -11,6 +11,7 @@ include profile polkitd @{exec_path} flags=(attach_disconnected) { include include + include include capability setgid, @@ -19,15 +20,23 @@ profile polkitd @{exec_path} flags=(attach_disconnected) { capability sys_ptrace, audit capability net_admin, - ptrace (read), + ptrace read, #aa:dbus own bus=system name=org.freedesktop.PolicyKit1 + dbus send bus=system path=/org/kde/PolicyKit1/AuthenticationAgent + interface=org.freedesktop.PolicyKit1.AuthenticationAgent + member=BeginAuthentication + peer=(name=@{busname}, label=polkit-kde-authentication-agent), + @{exec_path} mr, - @{bin}/pkla-check-authorization rPUx, + @{bin}/pkla-check-authorization rPx, @{bin}/pkla-admin-identities rPx, + /usr/share/gvfs/remote-volume-monitors/{,**} r, + /usr/share/polkit-1/polkitd.conf r, + /etc/machine-id r, # System rules @@ -40,6 +49,7 @@ profile polkitd @{exec_path} flags=(attach_disconnected) { # Vendor rules /usr/share/polkit-1/rules.d/ r, /usr/share/polkit-1/rules.d/*.rules r, + /usr/share/polkit-1/rules.d/*.rules.example r, # Vendor policies /usr/share/polkit-1/actions/ r, @@ -49,18 +59,23 @@ profile polkitd @{exec_path} flags=(attach_disconnected) { /var/lib/polkit{,-1}/localauthority/{,**} r, owner /var/lib/polkit{,-1}/.cache/ rw, - @{att}/@{run}/systemd/notify w, - @{att}/@{run}/systemd/userdb/io.systemd.DynamicUser rw, - @{att}/@{run}/systemd/userdb/io.systemd.Home rw, - @{att}/@{run}/systemd/userdb/io.systemd.Multiplexer rw, + @{run}/polkit-1/rules.d/ r, + @{run}/polkit-1/rules.d/*.policy r, + + @{att}@{run}/systemd/userdb/io.systemd.DynamicUser rw, + @{att}@{run}/systemd/userdb/io.systemd.Home rw, + @{att}@{run}/systemd/userdb/io.systemd.Machine rw, + @{att}@{run}/systemd/userdb/io.systemd.Multiplexer rw, + @{att}@{run}/systemd/userdb/org.gnome.DisplayManager rw, @{run}/systemd/sessions/* r, @{run}/systemd/users/@{uid} r, @{PROC}/@{pids}/cgroup r, @{PROC}/@{pids}/cmdline r, - @{PROC}/@{pid}/fdinfo/@{int} r, + @{PROC}/@{pids}/fdinfo/@{int} r, @{PROC}/@{pids}/stat r, + @{PROC}/@{pids}/status r, @{PROC}/@{pids}/task/@{tid}/stat r, @{PROC}/1/environ r, @{PROC}/cmdline r, @@ -68,9 +83,6 @@ profile polkitd @{exec_path} flags=(attach_disconnected) { owner @{PROC}/@{pid}/fdinfo/@{int} r, - # Silencer - deny /.cache/ rw, - include if exists } diff --git a/apparmor.d/groups/procps/btop b/apparmor.d/groups/procps/btop new file mode 100644 index 0000000000..43ae11a741 --- /dev/null +++ b/apparmor.d/groups/procps/btop @@ -0,0 +1,81 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/btop +profile btop @{exec_path} { + include + include + include + include + include + + capability dac_read_search, + capability kill, + capability perfmon, + capability sys_ptrace, + + network netlink raw, + + signal send, + ptrace read, + + @{exec_path} mr, + + /usr/share/btop/{,**} r, + + /etc/fstab r, + + owner @{user_config_dirs}/btop/{,**} rw, + owner @{user_state_dirs}/btop.log rw, + + @{sys}/bus/pci/devices/ r, + @{sys}/class/power_supply/ r, + @{sys}/devices/@{pci}/ r, + @{sys}/devices/@{pci}/{,**}/ r, + @{sys}/devices/@{pci}/net/*/{,**} r, + @{sys}/devices/@{pci}/nvme/nvme@{int}/ r, + @{sys}/devices/@{pci}/stat r, + @{sys}/devices/@{pci}/usb@{int}/**/power_supply/** r, + @{sys}/devices/**/power_supply/{AC,BAT@{int}}/{,**} r, + @{sys}/devices/*/events/{,*} r, + @{sys}/devices/platform/*/ r, + @{sys}/devices/power/{,**} r, + @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_{cur,min,max}_freq r, + @{sys}/devices/system/node/node@{int}/cpumap r, + @{sys}/devices/virtual/block/dm-@{int}/stat r, + @{sys}/devices/virtual/net/{,**} r, + @{sys}/devices/virtual/powercap/{,**} r, + @{sys}/devices/virtual/thermal/thermal_zone@{int}/{,*} r, + + @{PROC} r, + @{PROC}/@{pids}/cmdline r, + @{PROC}/@{pids}/comm r, + @{PROC}/@{pids}/io r, + @{PROC}/@{pids}/mountinfo r, + @{PROC}/@{pids}/mounts r, + @{PROC}/@{pids}/stat r, + @{PROC}/@{pids}/statm r, + @{PROC}/@{pids}/status r, + @{PROC}/devices r, + @{PROC}/driver/nvidia/capabilities/mig/config r, + @{PROC}/driver/nvidia/capabilities/mig/monitor r, + @{PROC}/driver/nvidia/params r, + @{PROC}/loadavg r, + @{PROC}/spl/kstat/zfs/arcstats r, + @{PROC}/sys/vm/mmap_min_addr r, + @{PROC}/uptime r, + + owner @{PROC}/@{pid}/task/@{tid}/comm rw, + + /dev/nvidia-caps/ rw, + /dev/nvidia-caps/nvidia-cap@{int} rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/procps/free b/apparmor.d/groups/procps/free new file mode 100644 index 0000000000..a965e9933d --- /dev/null +++ b/apparmor.d/groups/procps/free @@ -0,0 +1,19 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/free +profile free @{exec_path} flags=(attach_disconnected) { + include + include + + @{exec_path} mr, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/procps/htop b/apparmor.d/groups/procps/htop index 5e1079802a..02b36c4f44 100644 --- a/apparmor.d/groups/procps/htop +++ b/apparmor.d/groups/procps/htop @@ -8,23 +8,23 @@ abi , include @{exec_path} = @{bin}/htop -profile htop @{exec_path} { +profile htop @{exec_path} flags=(attach_disconnected) { include include include + include + include + include capability dac_read_search, capability kill, capability sys_nice, - capability sys_ptrace, network netlink raw, signal send, signal receive set=hup peer=gnome-terminal-server, - ptrace read, - @{exec_path} mr, @{bin}/lsof rix, @@ -39,25 +39,14 @@ profile htop @{exec_path} { owner @{user_config_dirs}/htop/ rw, owner @{user_config_dirs}/htop/* rw, - @{sys}/bus/dax/devices/ r, - @{sys}/bus/i2c/devices/ r, - @{sys}/bus/soc/devices/ r, - @{sys}/class/hwmon/ r, + @{sys}/bus/*/devices/ r, @{sys}/class/i2c-adapter/ r, @{sys}/class/power_supply/ r, - @{sys}/devices/@{pci}/i2c-@{int}/{,**/}name r, - @{sys}/devices/**/hwmon@{int}/ r, - @{sys}/devices/**/hwmon@{int}/{name,temp*} r, - @{sys}/devices/**/hwmon@{int}/**/ r, - @{sys}/devices/**/hwmon@{int}/**/{name,temp*} r, - @{sys}/devices/**/hwmon/ r, - @{sys}/devices/**/hwmon/{name,temp*} r, - @{sys}/devices/**/hwmon/**/ r, - @{sys}/devices/**/hwmon/**/{name,temp*} r, + @{sys}/devices/@{pci}/i2c-*/{,**/}name r, @{sys}/devices/**/power_supply/**/{uevent,type,online} r, @{sys}/devices/*/name r, - @{sys}/devices/i2c-@{int}/name r, - @{sys}/devices/platform/*/i2c-@{int}/name r, + @{sys}/devices/i2c-*/name r, + @{sys}/devices/platform/*/i2c-*/name r, @{sys}/devices/system/cpu/cpu@{int}/** r, @{sys}/devices/system/cpu/cpufreq/policy@{int}/cpuinfo_{cur,min,max}_freq r, @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_{cur,min,max}_freq r, @@ -67,17 +56,6 @@ profile htop @{exec_path} { @{sys}/devices/system/node/node@{int}/meminfo r, @{sys}/devices/system/node/online r, @{sys}/devices/virtual/block/zram@{int}/{disksize,mm_stat} r, - @{sys}/devices/virtual/dmi/id/ r, - @{sys}/devices/virtual/dmi/id/bios_date r, - @{sys}/devices/virtual/dmi/id/bios_vendor r, - @{sys}/devices/virtual/dmi/id/bios_version r, - @{sys}/devices/virtual/dmi/id/chassis_asset_tag r, - @{sys}/devices/virtual/dmi/id/chassis_type r, - @{sys}/devices/virtual/dmi/id/chassis_vendor r, - @{sys}/devices/virtual/dmi/id/chassis_version r, - @{sys}/devices/virtual/dmi/id/product_name r, - @{sys}/devices/virtual/dmi/id/product_version r, - @{sys}/devices/virtual/dmi/id/sys_vendor r, @{sys}/devices/virtual/thermal/thermal_zone@{int}/temp r, @{sys}/fs/cgroup/cgroup.controllers r, @{sys}/fs/cgroup/cpuset.cpus.effective r, @@ -88,9 +66,11 @@ profile htop @{exec_path} { @{PROC}/ r, @{PROC}/diskstats r, @{PROC}/loadavg r, + @{PROC}/locks r, @{PROC}/pressure/cpu r, @{PROC}/pressure/io r, @{PROC}/pressure/memory r, + @{PROC}/spl/kstat/zfs/arcstats r, @{PROC}/sys/kernel/osrelease r, @{PROC}/sys/kernel/pid_max r, @{PROC}/sys/kernel/sched_autogroup_enabled r, @@ -105,12 +85,15 @@ profile htop @{exec_path} { @{PROC}/@{pids}/comm r, @{PROC}/@{pids}/environ r, @{PROC}/@{pids}/io r, + @{PROC}/@{pids}/maps r, @{PROC}/@{pids}/mounts r, @{PROC}/@{pids}/net/dev r, - @{PROC}/@{pids}/oom_{,score_}adj r, + @{PROC}/@{pids}/oom_adj r, @{PROC}/@{pids}/oom_score r, + @{PROC}/@{pids}/oom_score_adj r, @{PROC}/@{pids}/stat r, @{PROC}/@{pids}/statm r, + @{PROC}/@{pids}/status r, @{PROC}/@{pids}/wchan r, @{PROC}/@{pids}/task/ r, @@ -121,8 +104,9 @@ profile htop @{exec_path} { @{PROC}/@{pids}/task/@{tid}/comm r, @{PROC}/@{pids}/task/@{tid}/environ r, @{PROC}/@{pids}/task/@{tid}/io r, - @{PROC}/@{pids}/task/@{tid}/oom_{,score_}adj r, + @{PROC}/@{pids}/task/@{tid}/oom_adj r, @{PROC}/@{pids}/task/@{tid}/oom_score r, + @{PROC}/@{pids}/task/@{tid}/oom_score_adj r, @{PROC}/@{pids}/task/@{tid}/stat r, @{PROC}/@{pids}/task/@{tid}/statm r, @{PROC}/@{pids}/task/@{tid}/status r, @@ -130,9 +114,24 @@ profile htop @{exec_path} { @{PROC}/cmdline r, owner @{PROC}/@{pid}/cpuset r, + owner @{PROC}/@{pid}/fd/ r, + owner @{PROC}/@{pid}/fdinfo/@{int} r, owner @{PROC}/@{pid}/smaps_rollup r, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, + + # While commands like 'ps', 'ip netns identify ', 'ip netns pids foo', etc + # trigger a 'ptrace trace' denial, they aren't actually tracing other + # processes. Unfortunately, the kernel overloads trace such that the LSMs are + # unable to distinguish between tracing other processes and other accesses. + deny capability sys_ptrace, + deny ptrace trace, + deny ptrace read, + + # Asked when run as root, but not needed + deny capability net_admin, + deny capability perfmon, + deny capability sys_admin, include if exists } diff --git a/apparmor.d/groups/procps/hugetop b/apparmor.d/groups/procps/hugetop new file mode 100644 index 0000000000..9e397cc0b9 --- /dev/null +++ b/apparmor.d/groups/procps/hugetop @@ -0,0 +1,36 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/hugetop +profile hugetop @{exec_path} { + include + include + + capability sys_ptrace, + + ptrace read, + + @{exec_path} mr, + + /usr/share/terminfo/** r, + + @{sys}/devices/system/node/ r, + @{sys}/devices/system/node/node@{int}/hugepages/ r, + @{sys}/devices/system/node/node@{int}/hugepages/hugepages-*/*_hugepages r, + @{sys}/kernel/mm/hugepages/ r, + @{sys}/kernel/mm/hugepages/hugepages-*/*_hugepages r, + + @{PROC}/ r, + @{PROC}/@{pids}/smaps_rollup r, + @{PROC}/@{pids}/stat r, + @{PROC}/@{pids}/ r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/procps/pgrep b/apparmor.d/groups/procps/pgrep new file mode 100644 index 0000000000..be719fae40 --- /dev/null +++ b/apparmor.d/groups/procps/pgrep @@ -0,0 +1,22 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/pgrep +profile pgrep @{exec_path} flags=(attach_disconnected) { + include + include + include + + signal send set=term, + + @{exec_path} mr, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/virt/cni-tuning b/apparmor.d/groups/procps/pidof similarity index 52% rename from apparmor.d/groups/virt/cni-tuning rename to apparmor.d/groups/procps/pidof index c6cc1f1dc3..3413eb6c3b 100644 --- a/apparmor.d/groups/virt/cni-tuning +++ b/apparmor.d/groups/procps/pidof @@ -1,18 +1,18 @@ # apparmor.d - Full set of apparmor profiles -# Copyright (C) 2021-2024 Alexandre Pujol +# Copyright (C) 2025 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only abi , include -@{exec_path} = @{lib}/cni/tuning /opt/cni/bin/tuning -profile cni-tuning @{exec_path} { +@{exec_path} = @{bin}/pidof +profile pidof @{exec_path} { include @{exec_path} mr, - include if exists + include if exists } # vim:syntax=apparmor diff --git a/apparmor.d/groups/procps/pkill b/apparmor.d/groups/procps/pkill new file mode 100644 index 0000000000..62fd31e9a1 --- /dev/null +++ b/apparmor.d/groups/procps/pkill @@ -0,0 +1,23 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/pkill +profile pkill @{exec_path} { + include + include + + capability kill, + + signal send, + + @{exec_path} mr, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/procps/ps b/apparmor.d/groups/procps/ps index 1d9ae50cba..a4febf4b06 100644 --- a/apparmor.d/groups/procps/ps +++ b/apparmor.d/groups/procps/ps @@ -14,9 +14,6 @@ profile ps @{exec_path} flags=(attach_disconnected) { include capability dac_read_search, - capability sys_ptrace, - - ptrace (read), @{exec_path} mr, @@ -27,6 +24,7 @@ profile ps @{exec_path} flags=(attach_disconnected) { @{sys}/devices/system/node/node@{int}/meminfo r, @{PROC}/ r, + @{PROC}/@{pids}/ r, @{PROC}/@{pids}/attr/current r, @{PROC}/@{pids}/cgroup r, @{PROC}/@{pids}/cmdline r, @@ -34,6 +32,7 @@ profile ps @{exec_path} flags=(attach_disconnected) { @{PROC}/@{pids}/loginuid r, @{PROC}/@{pids}/stat r, @{PROC}/@{pids}/statm r, + @{PROC}/@{pids}/status r, @{PROC}/@{pids}/task/ r, @{PROC}/@{pids}/task/@{tid}/cmdline r, @{PROC}/@{pids}/task/@{tid}/stat r, @@ -45,11 +44,24 @@ profile ps @{exec_path} flags=(attach_disconnected) { @{PROC}/tty/drivers r, @{PROC}/uptime r, - # file_inherit - owner @{HOME}/.xsession-errors w, - owner /dev/tty@{int} rw, + # While commands like 'ps', 'ip netns identify ', 'ip netns pids foo', etc + # trigger a 'ptrace trace' denial, they aren't actually tracing other + # processes. Unfortunately, the kernel overloads trace such that the LSMs are + # unable to distinguish between tracing other processes and other accesses. + deny capability perfmon, + deny capability sys_admin, + deny capability sys_ptrace, + deny ptrace trace, + deny ptrace read, - deny @{user_share_dirs}/gvfs-metadata/* r, + # file_inherit + deny network netlink raw, + deny unix (send receive) type=stream, + deny /usr/share/** r, + deny owner @{HOME}/.xsession-errors w, + deny owner @{user_config_dirs}/*/logs/{,**} rw, + deny owner @{user_share_dirs}/gvfs-metadata/* r, + deny /dev/ptmx rw, include if exists } diff --git a/apparmor.d/groups/procps/sysctl b/apparmor.d/groups/procps/sysctl index a25414390c..9275c70541 100644 --- a/apparmor.d/groups/procps/sysctl +++ b/apparmor.d/groups/procps/sysctl @@ -8,7 +8,7 @@ abi , include -@{exec_path} = @{bin}/sysctl +@{exec_path} = @{sbin}/sysctl profile sysctl @{exec_path} { include include @@ -22,7 +22,7 @@ profile sysctl @{exec_path} { /etc/sysctl.conf r, /etc/sysctl.d/{,**} r, - /usr/lib/sysctl.d/{,**} r, + @{lib}/sysctl.d/{,**} r, /etc/ufw/sysctl.conf r, # Add support for ufw diff --git a/apparmor.d/groups/procps/top b/apparmor.d/groups/procps/top index 6a5d272a3f..2e0c9981c3 100644 --- a/apparmor.d/groups/procps/top +++ b/apparmor.d/groups/procps/top @@ -34,12 +34,14 @@ profile top @{exec_path} flags=(attach_disconnected) { owner @{user_config_dirs}/procps/toprc rw, @{run}/systemd/sessions/ r, + @{run}/systemd/sessions/@{int} r, @{sys}/devices/system/node/ r, @{sys}/devices/system/node/node@{int}/cpumap r, @{sys}/devices/system/node/node@{int}/meminfo r, @{PROC}/ r, + @{PROC}/@{pids}/ r, @{PROC}/@{pids}/cgroup r, @{PROC}/@{pids}/cmdline r, @{PROC}/@{pids}/environ r, diff --git a/apparmor.d/groups/procps/uptime b/apparmor.d/groups/procps/uptime index 3da204a382..189a3c2f05 100644 --- a/apparmor.d/groups/procps/uptime +++ b/apparmor.d/groups/procps/uptime @@ -8,7 +8,7 @@ abi , include @{exec_path} = @{bin}/uptime -profile uptime @{exec_path} { +profile uptime @{exec_path} flags=(attach_disconnected) { include include include diff --git a/apparmor.d/groups/procps/vmstat b/apparmor.d/groups/procps/vmstat new file mode 100644 index 0000000000..1276222a23 --- /dev/null +++ b/apparmor.d/groups/procps/vmstat @@ -0,0 +1,27 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/vmstat +profile vmstat @{exec_path} { + include + include + + @{exec_path} mr, + + @{sys}/block/ r, + @{sys}/devices/system/node/ r, + + @{PROC}/diskstats r, + @{PROC}/slabinfo r, + @{PROC}/uptime r, + @{PROC}/vmstat r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/procps/w b/apparmor.d/groups/procps/w index 2445034e90..2d38d56ee7 100644 --- a/apparmor.d/groups/procps/w +++ b/apparmor.d/groups/procps/w @@ -27,10 +27,13 @@ profile w @{exec_path} { @{run}/systemd/sessions/* r, @{PROC}/ r, + @{PROC}/@{pids}/ r, @{PROC}/@{pids}/cmdline r, @{PROC}/@{pids}/stat r, + @{PROC}/@{pids}/status r, @{PROC}/loadavg r, @{PROC}/sys/kernel/osrelease r, + @{PROC}/tty/drivers r, @{PROC}/uptime r, include if exists diff --git a/apparmor.d/groups/shadow/chage b/apparmor.d/groups/shadow/chage index 43f34a7033..7c8b834866 100644 --- a/apparmor.d/groups/shadow/chage +++ b/apparmor.d/groups/shadow/chage @@ -8,7 +8,7 @@ abi , include @{exec_path} = @{bin}/chage -profile chage @{exec_path} { +profile chage @{exec_path} flags=(attach_disconnected) { include include include diff --git a/apparmor.d/groups/shadow/chpasswd b/apparmor.d/groups/shadow/chpasswd index 0dc65b1fbd..5554f68ebb 100644 --- a/apparmor.d/groups/shadow/chpasswd +++ b/apparmor.d/groups/shadow/chpasswd @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/chpasswd +@{exec_path} = @{sbin}/chpasswd profile chpasswd @{exec_path} { include include @@ -23,6 +23,8 @@ profile chpasswd @{exec_path} { @{exec_path} mr, + @{bin}/cat ix, + @{etc_ro}/login.defs r, /etc/.pwd.lock wk, diff --git a/apparmor.d/groups/shadow/gpasswd b/apparmor.d/groups/shadow/gpasswd index ab2d21860a..149c29b559 100644 --- a/apparmor.d/groups/shadow/gpasswd +++ b/apparmor.d/groups/shadow/gpasswd @@ -8,7 +8,7 @@ abi , include @{exec_path} = @{bin}/gpasswd -profile gpasswd @{exec_path} { +profile gpasswd @{exec_path} flags=(attach_disconnected) { include include include diff --git a/apparmor.d/groups/shadow/groupadd b/apparmor.d/groups/shadow/groupadd index 65e7356050..0e9850cd35 100644 --- a/apparmor.d/groups/shadow/groupadd +++ b/apparmor.d/groups/shadow/groupadd @@ -7,14 +7,15 @@ abi , include -@{exec_path} = @{bin}/groupadd -profile groupadd @{exec_path} { +@{exec_path} = @{sbin}/groupadd +profile groupadd @{exec_path} flags=(attach_disconnected) { include include include capability audit_write, capability chown, + capability dac_override, capability fsetid, network netlink raw, @@ -35,6 +36,16 @@ profile groupadd @{exec_path} { # modify the /etc/passwd or /etc/shadow password database. /etc/.pwd.lock rwk, + /var/lib/extrausers/group w, + /var/lib/extrausers/group- w, + /var/lib/extrausers/group.@{pid} w, + /var/lib/extrausers/group.lock wl -> /var/lib/extrausers/group.@{pid}, + /var/lib/extrausers/group+ rw, + /var/lib/extrausers/gshadow rw, + /var/lib/extrausers/gshadow- w, + /var/lib/extrausers/gshadow.lock wl -> /var/lib/extrausers/gshadow.@{pid}, + /var/lib/extrausers/gshadow+ rw, + include if exists } diff --git a/apparmor.d/groups/shadow/groupdel b/apparmor.d/groups/shadow/groupdel index 734b224630..8f8b282395 100644 --- a/apparmor.d/groups/shadow/groupdel +++ b/apparmor.d/groups/shadow/groupdel @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/groupdel +@{exec_path} = @{sbin}/groupdel profile groupdel @{exec_path} { include include diff --git a/apparmor.d/groups/shadow/groupmod b/apparmor.d/groups/shadow/groupmod index 01841483e6..34bf046cda 100644 --- a/apparmor.d/groups/shadow/groupmod +++ b/apparmor.d/groups/shadow/groupmod @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/groupmod +@{exec_path} = @{sbin}/groupmod profile groupmod @{exec_path} { include include diff --git a/apparmor.d/groups/shadow/grpck b/apparmor.d/groups/shadow/grpck index 3b820febb9..1e47307e4c 100644 --- a/apparmor.d/groups/shadow/grpck +++ b/apparmor.d/groups/shadow/grpck @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/grpck +@{exec_path} = @{sbin}/grpck profile grpck @{exec_path} flags=(attach_disconnected) { include include diff --git a/apparmor.d/groups/shadow/newgidmap b/apparmor.d/groups/shadow/newgidmap index 4a7196fc22..6a5b6ed03c 100644 --- a/apparmor.d/groups/shadow/newgidmap +++ b/apparmor.d/groups/shadow/newgidmap @@ -10,14 +10,20 @@ include @{exec_path} = @{bin}/newgidmap profile newgidmap @{exec_path} { include + include include capability dac_override, capability setgid, capability sys_admin, + unix (send receive) type=dgram peer=(label=newuidmap), + unix (send receive) type=dgram peer=(label=podman), + @{exec_path} mr, + @{etc_ro}/login.defs r, + @{etc_ro}/login.defs.d/{,*} r, /etc/subgid r, @{PROC}/@{pids}/ r, diff --git a/apparmor.d/groups/shadow/newuidmap b/apparmor.d/groups/shadow/newuidmap index 549eb06ef4..4a5d51970a 100644 --- a/apparmor.d/groups/shadow/newuidmap +++ b/apparmor.d/groups/shadow/newuidmap @@ -10,14 +10,20 @@ include @{exec_path} = @{bin}/newuidmap profile newuidmap @{exec_path} { include + include include capability dac_override, capability setuid, capability sys_admin, + unix (send receive) type=dgram peer=(label=newgidmap), + unix (send receive) type=dgram peer=(label=podman), + @{exec_path} mr, + @{etc_ro}/login.defs r, + @{etc_ro}/login.defs.d/{,*} r, /etc/subuid r, @{PROC}/@{pids}/ r, diff --git a/apparmor.d/groups/shadow/passwd b/apparmor.d/groups/shadow/passwd index 9d81c0bea9..052ea9961a 100644 --- a/apparmor.d/groups/shadow/passwd +++ b/apparmor.d/groups/shadow/passwd @@ -8,7 +8,7 @@ abi , include @{exec_path} = @{bin}/passwd -profile passwd @{exec_path} { +profile passwd @{exec_path} flags=(attach_disconnected) { include include include diff --git a/apparmor.d/groups/shadow/pwck b/apparmor.d/groups/shadow/pwck index 6aef4d028e..456a15af49 100644 --- a/apparmor.d/groups/shadow/pwck +++ b/apparmor.d/groups/shadow/pwck @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/pwck +@{exec_path} = @{sbin}/pwck profile pwck @{exec_path} flags=(attach_disconnected) { include include diff --git a/apparmor.d/groups/shadow/useradd b/apparmor.d/groups/shadow/useradd index 021ede7830..ed15bf022c 100644 --- a/apparmor.d/groups/shadow/useradd +++ b/apparmor.d/groups/shadow/useradd @@ -7,8 +7,8 @@ abi , include -@{exec_path} = @{bin}/useradd -profile useradd @{exec_path} { +@{exec_path} = @{sbin}/useradd +profile useradd @{exec_path} flags=(attach_disconnected) { include include include @@ -25,7 +25,7 @@ profile useradd @{exec_path} { @{exec_path} mr, @{bin}/nscd rix, - @{bin}/usermod rPx, + @{sbin}/usermod rPx, @{bin}/pam_tally2 rCx -> pam_tally2, @@ -44,6 +44,8 @@ profile useradd @{exec_path} { /etc/subgid.lock wl -> /etc/subgid.@{pid}, /etc/subuid.lock wl -> /etc/subuid.@{pid}, + /var/lib/extrausers/*.lock wl -> /var/lib/extrausers/*.@{pid}, + # A process first uses lckpwdf() to lock the lock file, thereby gaining exclusive rights to # modify the /etc/passwd or /etc/shadow password database. /etc/.pwd.lock rwk, diff --git a/apparmor.d/groups/shadow/userdel b/apparmor.d/groups/shadow/userdel index afaa52a036..06e6bba3ac 100644 --- a/apparmor.d/groups/shadow/userdel +++ b/apparmor.d/groups/shadow/userdel @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/userdel +@{exec_path} = @{sbin}/userdel profile userdel @{exec_path} flags=(attach_disconnected) { include include @@ -51,6 +51,7 @@ profile userdel @{exec_path} flags=(attach_disconnected) { /var/lib/*/{,**} rw, @{PROC}/ r, + @{PROC}/@{pids}/status r, @{PROC}/@{pids}/task/ r, include if exists diff --git a/apparmor.d/groups/shadow/usermod b/apparmor.d/groups/shadow/usermod index 1e5c6e4eb6..96f9cfb030 100644 --- a/apparmor.d/groups/shadow/usermod +++ b/apparmor.d/groups/shadow/usermod @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/usermod +@{exec_path} = @{sbin}/usermod profile usermod @{exec_path} flags=(attach_disconnected) { include include @@ -15,6 +15,7 @@ profile usermod @{exec_path} flags=(attach_disconnected) { capability audit_write, capability chown, + capability dac_override, capability dac_read_search, capability fowner, capability fsetid, @@ -26,6 +27,8 @@ profile usermod @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, + @{sh_path} r, + @{bin}/cat rix, @{bin}/nscd rix, @{etc_ro}/login.defs r, @@ -49,7 +52,7 @@ profile usermod @{exec_path} flags=(attach_disconnected) { @{HOME}/{,**} rw, /var/ r, /var/lib/ r, - /var/lib/*/{,**} rw, + /var/lib/*/{,**} rwl, @{PROC}/ r, @{PROC}/@{pids}/task/ r, diff --git a/apparmor.d/groups/snap/snap b/apparmor.d/groups/snap/snap index 8549d83158..d3cd631635 100644 --- a/apparmor.d/groups/snap/snap +++ b/apparmor.d/groups/snap/snap @@ -6,8 +6,8 @@ abi , include -@{bin_dirs} = @{bin}/ /snap/{snapd,core}/@{int}@{bin} -@{lib_dirs} = @{lib}/ /snap/{snapd,core}/@{int}@{lib} +@{bin_dirs} = @{bin}/ /snap/{snapd,core}/{,x}@{int}@{bin} +@{lib_dirs} = @{lib}/ /snap/{snapd,core}/{,x}@{int}@{lib} @{exec_path} = @{bin_dirs}/snap profile snap @{exec_path} flags=(attach_disconnected) { @@ -17,11 +17,19 @@ profile snap @{exec_path} flags=(attach_disconnected) { include include include + include + capability chown, + capability dac_override, capability dac_read_search, capability setuid, capability sys_admin, + capability sys_ptrace, + network inet dgram, + network inet stream, + network inet6 dgram, + network inet6 stream, network netlink raw, ptrace read peer=snap.*, @@ -34,7 +42,8 @@ profile snap @{exec_path} flags=(attach_disconnected) { #aa:dbus own bus=session name=io.snapcraft.SessionAgent #aa:dbus own bus=session name=io.snapcraft.Settings - #aa:dbus talk bus=session name=io.snapcraft.PrivilegedDesktopLauncher label=snap.snap-store.snap-store + #aa:dbus talk bus=session name=io.snapcraft.PrivilegedDesktopLauncher label=snap.snap-store.* + #aa:dbus talk bus=session name=io.snapcraft.PrivilegedDesktopLauncher label=snap.snapd-desktop-integration.snapd-desktop-integration #aa:dbus talk bus=session name=org.freedesktop.systemd1 label="@{p_systemd_user}" #aa:dbus talk bus=system name=org.freedesktop.systemd1 label="@{p_systemd}" @@ -46,17 +55,23 @@ profile snap @{exec_path} flags=(attach_disconnected) { dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=@{busname}, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), @{exec_path} mrix, - @{bin}/mount rix, + @{sh_path} mr, @{bin}/getent rix, + @{bin}/mount rix, + @{bin}/zenity rix, @{bin}/gpg{,2} rCx -> gpg, @{bin}/systemctl rCx -> systemctl, + @{bin}/systemd-run rCx -> run, # Start snap from the cli + @{bin}/unsquashfs rCx -> unsquashfs, + @{bin}/xdg-settings rCx -> xdg-settings, - @{lib_dirs}/** mr, + @{bin_dirs}/xdelta3 ix, + @{lib_dirs}/** mr, @{lib_dirs}/snapd/snap-confine rPx, @{lib_dirs}/snapd/snap-seccomp rPx, @{lib_dirs}/snapd/snapd rPx, @@ -68,14 +83,23 @@ profile snap @{exec_path} flags=(attach_disconnected) { /var/cache/snapd/names r, @{DESKTOP_HOME}/snap/{,**} rw, - @{HOME}/snap/{,**} rw, /snap/{,**} rw, + @{HOME}/ r, + @{HOME}/.snap.mkdir-new/ rw, + @{HOME}/.snap/{,**} rw, + @{HOME}/snap/{,**} rw, + + @{user_pkg_dirs}/** r, + + @{tmp}/ r, + owner @{tmp}/read-file@{int}/{,**} w, owner @{tmp}/snapd-auto-import-mount-@{int}/ rw, @{run}/user/@{uid}/bus rw, owner @{run}/user/@{uid}/.mutter-Xwaylandauth.@{rand6} r, owner @{run}/user/@{uid}/gdm/Xauthority r, + owner @{run}/user/@{uid}/snap.*/ w, owner @{run}/user/@{uid}/snapd-session-agent.socket rw, owner @{run}/user/@{uid}/systemd/notify rw, @@ -83,22 +107,27 @@ profile snap @{exec_path} flags=(attach_disconnected) { @{run}/snapd.socket rw, @{sys}/fs/cgroup/cgroup.controllers r, + @{sys}/fs/cgroup/system.slice/snapd.seeded.service/cpu.max r, @{sys}/kernel/security/apparmor/features/{,**} r, - @{PROC}/@{pids}/cgroup r, - @{PROC}/@{pids}/mountinfo r, + @{PROC}/@{pid}/cgroup r, + @{PROC}/@{pid}/mountinfo r, @{PROC}/cgroups r, @{PROC}/cmdline r, @{PROC}/sys/kernel/random/uuid r, @{PROC}/sys/kernel/seccomp/actions_avail r, @{PROC}/version r, - owner @{PROC}/@{pid}/attr/apparmor/current r, + @{PROC}/@{pid}/attr/apparmor/current r, owner @{PROC}/@{pid}/mounts r, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, /dev/ttyS@{int} rw, - deny @{user_share_dirs}/gvfs-metadata/* r, + /apparmor/.null rw, + + # file_inherit, safe to deny + deny owner @{user_share_dirs}/gvfs-metadata/* r, + deny owner @{user_share_dirs}/gnome-shell/session.gvdb rw, profile gpg { include @@ -115,12 +144,60 @@ profile snap @{exec_path} flags=(attach_disconnected) { include if exists } + profile xdg-settings { + include + include + + @{bin}/xdg-settings mr, + + @{sh_path} r, + @{bin}/{,e}grep rix, + @{bin}/basename rix, + @{bin}/cat ix, + @{bin}/cut rix, + @{bin}/head ix, + @{bin}/mkdir ix, + @{bin}/mktemp ix, + @{bin}/mv ix, + @{bin}/readlink ix, + @{bin}/realpath rix, + @{bin}/rm ix, + @{bin}/sed ix, + @{bin}/sleep ix, + @{bin}/sort ix, + @{bin}/touch ix, + @{bin}/tr ix, + @{bin}/uname ix, + @{bin}/wc ix, + + @{bin}/xdg-mime Px, + + / r, + + include if exists + } + + profile run { + include + + unix bind type=stream addr=@@{udbus}/bus/systemd-run/, + + @{bin}/systemd-run mr, + + owner @{run}/user/@{uid}/systemd/private rw, + + include if exists + } + profile systemctl { include include - include + include + + capability net_admin, network unix stream, + network (send receive) netlink raw, owner @{run}/user/@{uid}/systemd/notify rw, owner @{run}/user/@{uid}/systemd/private rw, @@ -128,6 +205,18 @@ profile snap @{exec_path} flags=(attach_disconnected) { include if exists } + profile unsquashfs { + include + + @{bin}/unsquashfs mr, + + /**.snap r, + + owner /tmp/read-file@{int}/unpack/{,**} w, + + include if exists + } + include if exists } diff --git a/apparmor.d/groups/snap/snap-discard-ns b/apparmor.d/groups/snap/snap-discard-ns index 38396f3ebe..0ccb3f1c7c 100644 --- a/apparmor.d/groups/snap/snap-discard-ns +++ b/apparmor.d/groups/snap/snap-discard-ns @@ -6,7 +6,7 @@ abi , include -@{lib_dirs} = @{lib}/ /snap/{snapd,core}/@{int}@{lib} +@{lib_dirs} = @{lib}/ /snap/{snapd,core}/{,x}@{int}@{lib} @{exec_path} = @{lib_dirs}/snapd/snap-discard-ns profile snap-discard-ns @{exec_path} { diff --git a/apparmor.d/groups/snap/snap-failure b/apparmor.d/groups/snap/snap-failure index edc9845e8c..5136695008 100644 --- a/apparmor.d/groups/snap/snap-failure +++ b/apparmor.d/groups/snap/snap-failure @@ -6,7 +6,7 @@ abi , include -@{lib_dirs} = @{lib}/ /snap/{snapd,core}/@{int}@{lib} +@{lib_dirs} = @{lib}/ /snap/{snapd,core}/{,x}@{int}@{lib} @{exec_path} = @{lib_dirs}/snapd/snap-failure profile snap-failure @{exec_path} { @@ -15,17 +15,34 @@ profile snap-failure @{exec_path} { @{exec_path} mr, @{lib_dirs}/**.so* mr, - @{bin}/systemctl rCx -> systemctl, - @{lib_dirs}/snapd/snapd rPx, + @{bin}/systemctl Cx -> systemctl, + @{bin}/systemd-run Cx -> run, + @{lib_dirs}/snapd/snapd Px, /var/lib/snapd/sequence/snapd.json r, + /snap/snapd/ r, + /snap/snapd/current w, + /snap/snapd/current.@{rand12}~ rw, + @{PROC}/cmdline r, + profile run { + include + + @{bin}/systemd-run mr, + + include if exists + } + profile systemctl { include include + capability net_admin, + + ptrace read peer=@{p_systemd}, + include if exists } diff --git a/apparmor.d/groups/snap/snap-seccomp b/apparmor.d/groups/snap/snap-seccomp index 7857bcc6ad..0e88ded122 100644 --- a/apparmor.d/groups/snap/snap-seccomp +++ b/apparmor.d/groups/snap/snap-seccomp @@ -6,10 +6,10 @@ abi , include -@{lib_dirs} = @{lib}/ /snap/{snapd,core}/@{int}@{lib} +@{lib_dirs} = @{lib}/ /snap/{snapd,core}/{,x}@{int}@{lib} @{exec_path} = @{lib_dirs}/snapd/snap-seccomp -profile snap-seccomp @{exec_path} { +profile snap-seccomp @{exec_path} flags=(attach_disconnected) { include include include @@ -25,9 +25,16 @@ profile snap-seccomp @{exec_path} { /var/lib/snapd/seccomp/bpf/{,**} rw, + @{sys}/fs/cgroup/system.slice/snapd.service/cpu.max r, + + @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pids}/mountinfo r, - deny @{user_share_dirs}/gvfs-metadata/* r, + /apparmor/.null rw, + + # file_inherit, safe to deny + deny owner @{user_share_dirs}/gnome-shell/session.gvdb rw, + deny owner @{user_share_dirs}/gvfs-metadata/* r, include if exists } diff --git a/apparmor.d/groups/snap/snap-update-ns b/apparmor.d/groups/snap/snap-update-ns index 8628aa7169..b3ea5eacf0 100644 --- a/apparmor.d/groups/snap/snap-update-ns +++ b/apparmor.d/groups/snap/snap-update-ns @@ -6,7 +6,7 @@ abi , include -@{lib_dirs} = @{lib}/ /snap/{snapd,core}/@{int}@{lib} +@{lib_dirs} = @{lib}/ /snap/{snapd,core}/{,x}@{int}@{lib} @{exec_path} = @{lib_dirs}/snapd/snap-update-ns profile snap-update-ns @{exec_path} { @@ -18,33 +18,36 @@ profile snap-update-ns @{exec_path} { network netlink raw, - mount -> /boot/, + mount -> @{efi}/, mount -> /snap/**, mount -> /tmp/.snap/**, mount -> /usr/**, + mount -> /var/cache/fontconfig/, mount -> /var/lib/dhcp/, - umount @{lib}/@{multiarch}/webkit2gtk-@{version}/, + umount @{lib}/**/, umount /snap/**, umount /tmp/.snap/**, - umount /usr/share/xml/iso-codes/, + umount /usr/share/{,**/}, + umount /var/cache/fontconfig/, umount /var/lib/dhcp/, @{exec_path} mr, @{lib_dirs}/**.so* mr, - @{lib}/@{multiarch}/webkit2gtk-@{version}/ w, - /usr/share/xml/iso-codes/ w, + @{lib}/**/ w, /var/lib/snapd/mount/{,*} r, / r, /tmp/ r, + @{lib}/ r, /usr/ r, /usr/local/ r, /usr/local/share/ r, - /usr/local/share/doc/ rw, - /usr/local/share/fonts/ rw, + /usr/local/share/*/ rw, + /usr/share/ r, + /usr/share/**/ rw, owner /snap/{,**} rw, @@ -61,9 +64,12 @@ profile snap-update-ns @{exec_path} { @{sys}/fs/cgroup/{,**/} r, @{sys}/fs/cgroup/system.slice/snap.*.service/cgroup.freeze rw, + @{sys}/fs/cgroup/system.slice/snapd.service/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/snap*.scope/cgroup.freeze rw, @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/snap*.service/cgroup.freeze rw, @{PROC}/@{pids}/cgroup r, + @{PROC}/@{pids}/mountinfo r, @{PROC}/cmdline r, @{PROC}/version r, diff --git a/apparmor.d/groups/snap/snapd b/apparmor.d/groups/snap/snapd index f1cd465374..6afb6c1621 100644 --- a/apparmor.d/groups/snap/snapd +++ b/apparmor.d/groups/snap/snapd @@ -6,21 +6,23 @@ abi , include -@{bin_dirs} = @{bin}/ /snap/{snapd,core}/@{int}@{bin} -@{lib_dirs} = @{lib}/ /snap/{snapd,core}/@{int}@{lib} +@{bin_dirs} = @{bin}/ /snap/{snapd,core}/{,x}@{int}@{bin} +@{lib_dirs} = @{lib}/ /snap/{snapd,core}/{,x}@{int}@{lib} @{exec_path} = @{lib_dirs}/snapd/snapd profile snapd @{exec_path} { include include include - include - include + include + include include include include + include include include + include capability audit_write, capability chown, @@ -34,7 +36,6 @@ profile snapd @{exec_path} { capability setuid, capability sys_admin, capability sys_ptrace, - capability sys_resource, network inet stream, network inet6 stream, @@ -50,32 +51,32 @@ profile snapd @{exec_path} { ptrace read peer=@{p_systemd}, ptrace read peer=snap{,.*}, - signal send set=kill peer=journalctl, + signal send set=kill peer=snapd//journalctl, dbus send bus=system path=/org/freedesktop/ interface=org.freedesktop.login1.Manager member={SetWallMessage,ScheduleShutdown} - peer=(name=org.freedesktop.login1, label=systemd-logind), + peer=(name=org.freedesktop.login1, label="@{p_systemd_logind}"), dbus send bus=system path=/org/freedesktop/timedate1 interface=org.freedesktop.DBus.Properties member=Get - peer=(name=org.freedesktop.timedate1, label=unconfined), + peer=(name=org.freedesktop.timedate1), @{exec_path} mrix, @{sh_path} rix, - @{bin}/adduser rPx, - @{bin}/apparmor_parser rPx, + @{sbin}/adduser rPx, + @{sbin}/apparmor_parser rPx, @{bin}/cp rix, @{bin}/getent rix, - @{bin}/groupadd rPx, + @{sbin}/groupadd rPx, @{bin}/gzip rix, @{bin}/hostnamectl rPx, - @{bin}/journalctl rPx, + @{bin}/journalctl rCx -> journalctl, @{bin}/kmod rPx, @{bin}/mount rix, - @{bin}/runuser rCx -> runuser, + @{sbin}/runuser rCx -> runuser, @{bin}/ssh-keygen rPx, @{bin}/sync rix, @{bin}/systemctl rCx -> systemctl, @@ -85,7 +86,7 @@ profile snapd @{exec_path} { @{bin}/umount rix, @{bin}/unsquashfs rix, @{bin}/update-desktop-database rPx, - @{bin}/useradd rPx, + @{sbin}/useradd rPx, @{bin_dirs}/fc-cache-* mr, @{bin_dirs}/snap rPUx, @@ -98,18 +99,20 @@ profile snapd @{exec_path} { @{lib_dirs}/snapd/snap-update-ns rPx, /usr/share/bash-completion/{,**} r, - /usr/share/dbus-1/{system,session}.d/{,snapd*} rw, + /usr/share/dbus-1/{system,session}.d/ rw, + /usr/share/dbus-1/{system,session}.d/snapd* rw, /usr/share/dbus-1/services/*snap* r, - /usr/share/polkit-1/actions/{,**/} r, + /usr/share/polkit-1/actions/{,**} r, + /usr/share/polkit-1/actions/snap.*.policy* rw, @{etc_ro}/environment r, /etc/apparmor.d/*snapd.snap* r, /etc/dbus-1/system.d/{,**/} r, /etc/fstab r, - /etc/mime.types r, /etc/modprobe.d/{,**/} r, /etc/modules-load.d/{,**/} r, /etc/modules-load.d/*snap* rw, + /etc/polkit-1/rules.d/{,**/} r, /etc/systemd/system/{,**/} r, /etc/systemd/system/snap* rw, /etc/systemd/user/{,**/} rw, @@ -132,8 +135,8 @@ profile snapd @{exec_path} { /tmp/syscheck-mountpoint-@{int}/{,**} rw, /tmp/syscheck-squashfs-@{int} rw, - /boot/ r, - /boot/grub/grubenv r, + @{efi}/ r, + @{efi}/grub/grubenv r, / r, /home/ r, @@ -147,22 +150,23 @@ profile snapd @{exec_path} { @{run}/user/ r, @{run}/user/@{uid}/ r, + @{run}/user/@{uid}/snap.*/{,**} rw, @{run}/user/@{uid}/snapd-session-agent.socket rw, @{run}/user/snap.*/{,**} rw, + @{run}/mount/utab.act rk, @{run}/snapd*.socket rw, @{run}/snapd/{,**} rw, @{run}/snapd/lock/*.lock rwk, - @{run}/systemd/notify rw, @{run}/systemd/private rw, @{sys}/fs/cgroup/{,*/} r, - @{sys}/fs/cgroup/cgroup.controllers r, - @{sys}/fs/cgroup/system.slice/{,**/} r, - @{sys}/fs/cgroup/system.slice/snap*.service/cgroup.procs r, @{sys}/fs/cgroup/*.slice/ r, - @{sys}/fs/cgroup/*.slice/*.service/{,**/} r, - @{sys}/fs/cgroup/*.slice/*-@{uid}.slice/*@@{uid}.service/app.slice/snap*.service/cgroup.procs r, + @{sys}/fs/cgroup/*.slice/{,**/} r, + @{sys}/fs/cgroup/*.slice/**/cgroup.procs r, + @{sys}/fs/cgroup/cgroup.controllers r, + @{sys}/fs/cgroup/net_cls/*/ r, + @{sys}/fs/cgroup/system.slice/snapd.service/cpu.max r, @{sys}/kernel/kexec_loaded r, @{sys}/kernel/security/apparmor/.notify r, @{sys}/kernel/security/apparmor/features/{,**} r, @@ -189,21 +193,57 @@ profile snapd @{exec_path} { network netlink raw, + ptrace read peer=@{p_systemd}, + /etc/systemd/system/{,**/} r, /etc/systemd/system/snap* rw, /etc/systemd/user/{,**/} rw, /etc/systemd/user/**/*snap* rw, /etc/systemd/user/*snap* rw, - @{run}/systemd/notify rw, - include if exists } + profile journalctl { + include + include + + capability net_admin, + capability sys_resource, + + network netlink raw, + + signal receive set=kill peer=snapd, + + @{bin}/journalctl mr, + + /etc/machine-id r, + /var/lib/dbus/machine-id r, + + /{run,var}/log/journal/ r, + /{run,var}/log/journal/@{hex32}/{,*} r, + + include if exists + } + profile runuser { include + include + include + + capability audit_write, + capability setgid, + capability setuid, + + network netlink raw, + + @{sbin}/runuser mr, + + @{sh_path} ix, + @{bin}/gzip ix, + @{bin}/tar ix, - @{bin}/runuser mr, + owner @{HOME}/snap/*/{,**} r, include if exists } diff --git a/apparmor.d/groups/snap/snapd-aa-prompt-listener b/apparmor.d/groups/snap/snapd-aa-prompt-listener index 7b9adced79..37730ba6f8 100644 --- a/apparmor.d/groups/snap/snapd-aa-prompt-listener +++ b/apparmor.d/groups/snap/snapd-aa-prompt-listener @@ -6,7 +6,7 @@ abi , include -@{lib_dirs} = @{lib}/ /snap/{snapd,core}/@{int}@{lib} +@{lib_dirs} = @{lib}/ /snap/{snapd,core}/{,x}@{int}@{lib} @{exec_path} = @{lib_dirs}/snapd/snapd-aa-prompt-listener profile snapd-aa-prompt-listener @{exec_path} { diff --git a/apparmor.d/groups/snap/snapd-aa-prompt-ui b/apparmor.d/groups/snap/snapd-aa-prompt-ui index 0d26f42d3e..99dc98efe3 100644 --- a/apparmor.d/groups/snap/snapd-aa-prompt-ui +++ b/apparmor.d/groups/snap/snapd-aa-prompt-ui @@ -6,7 +6,7 @@ abi , include -@{lib_dirs} = @{lib}/ /snap/{snapd,core}/@{int}@{lib} +@{lib_dirs} = @{lib}/ /snap/{snapd,core}/{,x}@{int}@{lib} @{exec_path} = @{lib_dirs}/snapd/snapd-aa-prompt-ui profile snapd-aa-prompt-ui @{exec_path} { diff --git a/apparmor.d/groups/snap/snapd-apparmor b/apparmor.d/groups/snap/snapd-apparmor index 6d873982b6..652a0c265a 100644 --- a/apparmor.d/groups/snap/snapd-apparmor +++ b/apparmor.d/groups/snap/snapd-apparmor @@ -6,16 +6,18 @@ abi , include -@{lib_dirs} = @{lib}/ /snap/{snapd,core}/@{int}@{lib} +@{lib_dirs} = @{lib}/ /snap/{snapd,core}/{,x}@{int}@{lib} @{exec_path} = @{lib_dirs}/snapd/snapd-apparmor profile snapd-apparmor @{exec_path} { include + capability dac_read_search, + @{exec_path} mrix, @{bin}/systemd-detect-virt rPx, - @{bin}/apparmor_parser rPx, + @{sbin}/apparmor_parser rPx, @{lib_dirs}/** mr, @{lib_dirs}/snapd/apparmor_parser rPx -> apparmor_parser, @@ -23,6 +25,11 @@ profile snapd-apparmor @{exec_path} { /var/lib/snapd/apparmor/profiles/ r, + @{sys}/fs/cgroup/system.slice/snapd.apparmor.service/cpu.max r, + @{sys}/fs/cgroup/system.slice/snapd.service/cpu.max r, + + @{PROC}/@{pids}/cgroup r, + @{PROC}/@{pids}/mountinfo r, @{PROC}/cmdline r, include if exists diff --git a/apparmor.d/groups/ssh/ssh b/apparmor.d/groups/ssh/ssh index 43fbddc63c..e94fb6912c 100644 --- a/apparmor.d/groups/ssh/ssh +++ b/apparmor.d/groups/ssh/ssh @@ -8,12 +8,16 @@ abi , include @{exec_path} = @{bin}/ssh -profile ssh @{exec_path} { +profile ssh @{exec_path} flags=(attach_disconnected) { include include + include include + include include + capability dac_override, + network inet stream, network inet6 stream, network inet dgram, @@ -26,40 +30,40 @@ profile ssh @{exec_path} { @{exec_path} mrix, @{bin}/@{shells} rUx, + @{bin}/ssh.hmac r, @{lib}/{,ssh/}ssh-sk-helper rix, + @{lib}/ssh-askpass/x11-ssh-askpass PUx, @{etc_ro}/ssh/ssh_config r, @{etc_ro}/ssh/ssh_config.d/{,*} r, @{etc_ro}/ssh/sshd_config r, @{etc_ro}/ssh/sshd_config.d/{,*} r, /etc/machine-id r, + /etc/gss/mech.d/{,*} r, + + / r, - owner @{HOME}/@{XDG_SSH_DIR}/ r, - owner @{HOME}/@{XDG_SSH_DIR}/*_*{,.pub} r, - owner @{HOME}/@{XDG_SSH_DIR}/config r, + owner @{HOME}/@{XDG_SSH_DIR}/{,*} r, owner @{HOME}/@{XDG_SSH_DIR}/known_hosts{,.*} rwl, owner @{HOME}/@{XDG_SSH_DIR}/ssh_control_*_*_* wl, owner @{user_projects_dirs}/**/ssh/{,*} r, owner @{user_projects_dirs}/**/config r, - audit owner @{tmp}/ssh-*/{,agent.@{int}} rwkl, + owner @{tmp}/krb5cc_* rwk, - owner @{run}/user/@{uid}/gvfsd-sftp/@{hex} wl -> @{run}/user/@{uid}/gvfsd-sftp/@{hex}.@{rand}, - owner @{run}/user/@{uid}/gvfsd-sftp/@{hex}.@{rand} wl -> @{run}/user/@{uid}/gvfsd-sftp/@{hex}.@{rand}, + owner @{run}/user/@{uid}/gcr/ssh rw, # gcr-ssh-agent socket (i.e. Gnome only) + owner @{run}/user/@{uid}/gvfsd-sftp/@{hex} rwl -> @{run}/user/@{uid}/gvfsd-sftp/@{hex}.@{rand}, + owner @{run}/user/@{uid}/gvfsd-sftp/@{hex}.@{rand} rwl -> @{run}/user/@{uid}/gvfsd-sftp/@{hex}.@{rand}, owner @{run}/user/@{uid}/keyring/ssh rw, - - @{sys}/ r, - @{sys}/bus/ r, - @{sys}/class/ r, - @{sys}/class/hidraw/ r, - @{sys}/class/hidraw/hidraw@{int} r, + owner @{run}/user/@{uid}/openssh_agent rw, owner @{PROC}/@{pid}/loginuid r, owner @{PROC}/@{pid}/fd/ r, - /dev/hidraw@{int} rwk, + #aa:only test + owner @{tmp}/ssh-@{rand10}/{,agent.@{int}} rw, include if exists } diff --git a/apparmor.d/groups/ssh/ssh-agent b/apparmor.d/groups/ssh/ssh-agent index f6732b1cfe..b86c303571 100644 --- a/apparmor.d/groups/ssh/ssh-agent +++ b/apparmor.d/groups/ssh/ssh-agent @@ -13,6 +13,7 @@ profile ssh-agent @{exec_path} { include signal receive set=term peer=cockpit-bridge, + signal receive set=term peer=cockpit-session, signal receive set=term peer=gnome-keyring-daemon, @{exec_path} mr, @@ -23,6 +24,9 @@ profile ssh-agent @{exec_path} { owner @{HOME}/@{XDG_SSH_DIR}/ rw, owner @{HOME}/@{XDG_SSH_DIR}/* r, + owner @{HOME}/@{XDG_SSH_DIR}/agent/ rw, + owner @{HOME}/@{XDG_SSH_DIR}/agent/* rw, + owner @{HOME}/.xsession-errors w, owner @{user_projects_dirs}/**/ssh/{,*} r, @@ -32,9 +36,9 @@ profile ssh-agent @{exec_path} { owner @{run}/user/@{uid}/keyring/.ssh rw, owner @{run}/user/@{uid}/openssh_agent rw, owner @{run}/user/@{uid}/ssh-agent.@{rand6} w, - owner @{run}/user/@{uid}/gcr/.ssh w, + owner @{run}/user/@{uid}/gcr/.ssh rw, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, /dev/tty rw, include if exists diff --git a/apparmor.d/groups/ssh/ssh-agent-launch b/apparmor.d/groups/ssh/ssh-agent-launch index c9f0c63733..86bd0866f1 100644 --- a/apparmor.d/groups/ssh/ssh-agent-launch +++ b/apparmor.d/groups/ssh/ssh-agent-launch @@ -15,7 +15,7 @@ profile ssh-agent-launch @{exec_path} { @{sh_path} rix, @{bin}/dbus-update-activation-environment rCx -> dbus, @{bin}/getopt rix, - @{bin}/grep rix, + @{bin}/{,e}grep rix, @{bin}/ssh-agent rPx, /etc/X11/Xsession.options r, diff --git a/apparmor.d/groups/ssh/ssh-keygen b/apparmor.d/groups/ssh/ssh-keygen index 397ffdcd62..4d80641e9e 100644 --- a/apparmor.d/groups/ssh/ssh-keygen +++ b/apparmor.d/groups/ssh/ssh-keygen @@ -15,15 +15,18 @@ profile ssh-keygen @{exec_path} { @{exec_path} mr, + @{lib}/{,ssh/}ssh-sk-helper rPx -> ssh-sk-helper, + + /etc/ssh/moduli rw, /etc/ssh/ssh_host_*_key* rw, - owner @{HOME}/@{XDG_SSH_DIR}/ w, - owner @{HOME}/@{XDG_SSH_DIR}/*_*{,.pub} rw, + owner @{HOME}/@{XDG_SSH_DIR}/ rw, + owner @{HOME}/@{XDG_SSH_DIR}/* rwl -> @{HOME}/@{XDG_SSH_DIR}/*, - /tmp/snapd@{int}/*_*{,.pub} w, - /tmp/snapd@{int}/*.key{,.pub} w, + owner /tmp/snapd@{int}/*_*{,.pub} w, + owner /tmp/snapd@{int}/*.key{,.pub} w, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, /dev/ttyS@{int} rw, include if exists diff --git a/apparmor.d/groups/ssh/ssh-sk-helper b/apparmor.d/groups/ssh/ssh-sk-helper index ff9de97c32..4d374f18d8 100644 --- a/apparmor.d/groups/ssh/ssh-sk-helper +++ b/apparmor.d/groups/ssh/ssh-sk-helper @@ -1,5 +1,6 @@ # apparmor.d - Full set of apparmor profiles # Copyright (C) 2024 valoq +# Copyright (C) 2025 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only abi , @@ -9,17 +10,12 @@ include @{exec_path} = @{lib}/{,ssh/}ssh-sk-helper profile ssh-sk-helper flags=(complain) { include + include include @{exec_path} mr, - @{sys}/ r, - @{sys}/bus/ r, - @{sys}/class/ r, - @{sys}/class/hidraw/ r, - @{sys}/class/hidraw/hidraw@{int} r, - - /dev/hidraw@{int} rwk, + / r, include if exists } diff --git a/apparmor.d/groups/ssh/sshd b/apparmor.d/groups/ssh/sshd index a7d9a6699d..9d4364968c 100644 --- a/apparmor.d/groups/ssh/sshd +++ b/apparmor.d/groups/ssh/sshd @@ -15,7 +15,7 @@ abi , include -@{exec_path} = @{bin}/sshd +@{exec_path} = @{sbin}/sshd profile sshd @{exec_path} flags=(attach_disconnected) { include include @@ -25,12 +25,14 @@ profile sshd @{exec_path} flags=(attach_disconnected) { include include include + include #aa:only RBAC capability audit_write, capability chown, - capability dac_read_search, capability dac_override, + capability dac_read_search, capability fowner, + capability fsetid, capability kill, capability net_bind_service, capability setgid, @@ -49,26 +51,34 @@ profile sshd @{exec_path} flags=(attach_disconnected) { network inet6 dgram, network netlink raw, - signal (receive) set=(hup) peer=@{p_systemd}, + unix type=stream peer=(label=sshd-session), + + signal receive set=hup peer=@{p_systemd}, - ptrace (read,trace) peer=@{p_systemd}, + ptrace (read trace) peer=@{p_systemd}, dbus send bus=system path=/org/freedesktop/login1 interface=org.freedesktop.login1.Manager member={CreateSession,ReleaseSession,CreateSessionWithPIDFD} - peer=(name=org.freedesktop.login1, label=systemd-logind), + peer=(name=org.freedesktop.login1, label="@{p_systemd_logind}"), + + dbus send bus=system path=/org/freedesktop/home1 + interface=org.freedesktop.home1.Manager + member=GetUserRecordByName + peer=(name=org.freedesktop.home1, label="@{p_systemd_homed}"), @{exec_path} mrix, - @{bin}/@{shells} rUx, - @{bin}/false rix, - @{bin}/nologin rPx, - @{bin}/passwd rPx, - @{lib}/{openssh,ssh}/sftp-server rPx, - @{lib}/{openssh,ssh}/sshd-session rix, + @{sbin}/sshd.hmac r, + + @{bin}/@{shells} Ux, #aa:exclude RBAC + @{bin}/false ix, + @{sbin}/nologin Px, + @{bin}/passwd Px, + @{lib}/{openssh,ssh}/sftp-server Px, + @{lib}/{openssh,ssh}/sshd-auth Px, + @{lib}/{openssh,ssh}/sshd-session Px, - @{etc_ro}/environment r, - @{etc_ro}/security/limits.d/{,*.conf} r, @{etc_rw}/motd r, @{etc_rw}/motd.d/{,**} r, /etc/default/locale r, @@ -92,16 +102,15 @@ profile sshd @{exec_path} flags=(attach_disconnected) { owner @{user_download_dirs}/{,**} rwl, owner @{user_sync_dirs}/{,**} rwl, - @{HOME}/@{XDG_SSH_DIR}/authorized_keys{,.*} r, + @{HOME}/@{XDG_SSH_DIR}/authorized_keys* r, owner @{user_cache_dirs}/{,motd*} rw, - @{att}/@{run}/systemd/sessions/@{int}.ref rw, + @{att}@{run}/systemd/sessions/@{int}.ref rw, @{run}/faillock/@{user} rwk, @{run}/motd.d/{,*} r, @{run}/motd.dynamic rw, @{run}/motd.dynamic.new rw, - @{run}/systemd/notify w, owner @{run}/sshd{,.init}.pid wl, @{sys}/fs/cgroup/*/user/*/@{int}/ rw, @@ -118,7 +127,7 @@ profile sshd @{exec_path} flags=(attach_disconnected) { owner @{PROC}/@{pid}/uid_map r, /dev/ptmx rw, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, /dev/ttyS@{int} rw, include if exists diff --git a/apparmor.d/groups/ssh/sshd-auth b/apparmor.d/groups/ssh/sshd-auth new file mode 100644 index 0000000000..c964fcce96 --- /dev/null +++ b/apparmor.d/groups/ssh/sshd-auth @@ -0,0 +1,35 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/{openssh,ssh}/sshd-auth +profile sshd-auth @{exec_path} { + include + include + + capability dac_override, + capability setgid, + capability setuid, + capability sys_chroot, + + network inet dgram, + network inet stream, + network inet6 dgram, + network inet6 stream, + network netlink raw, + + unix type=stream peer=(label=sshd-session), + + @{exec_path} mr, + @{sbin}/sshd.hmac r, + + /etc/gss/mech.d/{,*} r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/ssh/sshd-session b/apparmor.d/groups/ssh/sshd-session new file mode 100644 index 0000000000..b5db3667d1 --- /dev/null +++ b/apparmor.d/groups/ssh/sshd-session @@ -0,0 +1,106 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/{openssh,ssh}/sshd-session +profile sshd-session @{exec_path} flags=(attach_disconnected) { + include + include + include + include + include + include + include + include #aa:only RBAC + + capability audit_write, + capability chown, + capability dac_override, + capability dac_read_search, + capability fowner, + capability fsetid, + capability kill, + capability setgid, + capability setuid, + capability sys_chroot, + capability sys_resource, + + # sshd doesn't require net_admin. libpam-systemd tries to + # use it if available to set the send/receive buffers size, + # but will fall back to a non-privileged version if it fails. + deny capability net_admin, + + network inet dgram, + network inet stream, + network inet6 dgram, + network inet6 stream, + network netlink raw, + + unix type=stream peer=(label=sshd), + unix type=stream peer=(label=sshd-auth), + + dbus send bus=system path=/org/freedesktop/login1 + interface=org.freedesktop.login1.Manager + member={CreateSession,ReleaseSession,CreateSessionWithPIDFD} + peer=(name=org.freedesktop.login1, label="@{p_systemd_logind}"), + + dbus send bus=system path=/org/freedesktop/home1 + interface=org.freedesktop.home1.Manager + member=GetUserRecordByName + peer=(name=org.freedesktop.home1, label="@{p_systemd_homed}"), + + @{exec_path} mr, + + @{bin}/@{shells} Ux, #aa:exclude RBAC + @{bin}/userdbctl Px, + @{lib}/{openssh,ssh}/sshd-auth Px, + + @{etc_rw}/motd r, + @{etc_rw}/motd.d/{,**} r, + /etc/legal r, + /etc/machine-id r, + /etc/motd r, + /etc/ssh/moduli r, + + /var/lib/lastlog/ r, + /var/lib/lastlog/lastlog2.db rwk, + /var/lib/lastlog/lastlog2.db-journal rw, + + /var/lib/wtmpdb/ w, + + /var/log/ r, + /var/log/wtmp.db rwk, + /var/log/wtmp.db-journal rw, + + owner @{HOME}/@{XDG_SSH_DIR}/authorized_keys{,.*} r, + + owner @{user_cache_dirs}/{,motd*} rw, + + @{att}@{run}/systemd/sessions/@{int}.ref w, + + @{run}/cockpit/active.issue r, + @{run}/faillock/@{user} rwk, + @{run}/motd.d/{,*} r, + @{run}/motd.dynamic rw, + @{run}/motd.dynamic.new rw, + @{run}/nologin r, + @{run}/systemd/io.systemd.Login rw, + + @{PROC}/1/limits r, + owner @{PROC}/@{pid}/loginuid rw, + owner @{PROC}/@{pid}/uid_map r, + + /dev/ptmx rw, + /dev/pts/@{u16} rw, + + #aa:only test + owner @{tmp}/ssh-@{rand10}/{,agent.@{int}} rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/ssh/sshfs b/apparmor.d/groups/ssh/sshfs index 12e7d89306..ee6a2f903a 100644 --- a/apparmor.d/groups/ssh/sshfs +++ b/apparmor.d/groups/ssh/sshfs @@ -18,7 +18,7 @@ profile sshfs @{exec_path} flags=(complain) { mount fstype=fuse.sshfs -> @{MOUNTS}/*/, mount fstype=fuse.sshfs -> @{MOUNTS}/*/*/, - unix (connect, send, receive) type=stream peer=(label="sshfs//fusermount",addr=none), + unix (connect, send, receive) type=stream peer=(label="sshfs//fusermount"), @{exec_path} mr, diff --git a/apparmor.d/groups/steam/steam b/apparmor.d/groups/steam/steam index 9cb5ac86bc..f9fcc05291 100644 --- a/apparmor.d/groups/steam/steam +++ b/apparmor.d/groups/steam/steam @@ -21,10 +21,12 @@ abi , include -@{runtime} = SteamLinuxRuntime_sniper +@{domain} = org.chromium.Chromium +@{runtime_name} = sniper soldier +@{runtime} = SteamLinuxRuntime_@{runtime_name} steam-runtime-steamrt @{share_dirs} = @{user_share_dirs}/Steam @{HOME}/.steam/debian-installation -@{lib_dirs} = @{share_dirs}/ubuntu@{int2}_{32,64} -@{runtime_dirs} = @{lib_dirs}/steam-runtime{,-sniper} +@{lib_dirs} = @{share_dirs}/ubuntu@{int2}_{32,64} steamrt64 +@{runtime_dirs} = @{lib_dirs}/steam-runtime{,-sniper} @{lib_dirs}/steam-runtime-steamrt @{app_dirs} = @{share_dirs}/steamapps/common/ @{exec_path} = @{share_dirs}/steam.sh @@ -39,6 +41,7 @@ profile steam @{exec_path} flags=(attach_disconnected,mediate_deleted) { include include include + include include capability sys_ptrace, @@ -67,19 +70,18 @@ profile steam @{exec_path} flags=(attach_disconnected,mediate_deleted) { @{open_path} rPx -> child-open, @{bin}/getopt rix, @{bin}/journalctl rPx -> systemctl, - @{bin}/ldconfig rix, + @{sbin}/ldconfig rix, @{bin}/ldd rix, @{bin}/lsb_release rPx -> lsb_release, @{bin}/lsof rix, @{bin}/lspci rCx -> lspci, @{bin}/tar rix, + @{ldd_path} rix, @{bin}/which{,.debianutils} rix, @{bin}/xdg-icon-resource rPx, @{bin}/xdg-user-dir rix, @{bin}/xz rix, @{bin}/zenity rix, - @{lib}/@{multiarch}/ld-*.so* rix, - @{lib}/ld-linux.so* rix, @{lib_dirs}/** mr, @{lib_dirs}/*driverquery rix, @@ -109,6 +111,7 @@ profile steam @{exec_path} flags=(attach_disconnected,mediate_deleted) { @{runtime_dirs}/@{lib}/steam-runtime-tools-@{int}/@{multiarch}-* rix, @{runtime_dirs}/@{lib}/steam-runtime-tools-@{int}/srt-logger rix, @{runtime_dirs}/pressure-vessel/@{bin}/pressure-vessel-* rix, + @{runtime_dirs}/pressure-vessel/@{bin}/pv-* rix, @{runtime_dirs}/pressure-vessel/@{lib}/steam-runtime-tools-@{int}/@{multiarch}-* rix, @{runtime_dirs}/pressure-vessel/@{lib}/steam-runtime-tools-@{int}/srt-bwrap rcx -> web, @{runtime_dirs}/run{,.sh} rix, @@ -174,6 +177,7 @@ profile steam @{exec_path} flags=(attach_disconnected,mediate_deleted) { owner @{tmp}/steam/** rwk, owner @{tmp}/steam@{rand6}/{,**} rw, owner @{tmp}/vdpau-drivers-@{rand6}/{,**} rw, + owner @{tmp}/steam@{rand6} rwk, owner @{att}/dev/shm/ValveIPCSHM_@{uid} rw, owner /dev/shm/fossilize-*-@{int}-@{int} rw, @@ -188,7 +192,7 @@ profile steam @{exec_path} flags=(attach_disconnected,mediate_deleted) { @{run}/udev/data/+pci:* r, # Identifies all PCI devices (CPU, GPU, Network, Disks, USB, etc.) @{run}/udev/data/c13:@{int} r, # for /dev/input/* - @{run}/udev/data/n@{int} r, + @{run}/udev/data/n@{int} r, # For network interfaces @{sys}/ r, @{sys}/bus/ r, @@ -241,14 +245,13 @@ profile steam @{exec_path} flags=(attach_disconnected,mediate_deleted) { owner @{PROC}/@{pid}/task/@{tid}/comm rw, /dev/input/ r, - /dev/uinput w, deny /opt/** r, profile web flags=(attach_disconnected,mediate_deleted,complain) { include include - include + include include include include @@ -275,7 +278,7 @@ profile steam @{exec_path} flags=(attach_disconnected,mediate_deleted) { @{bin}/getopt rix, @{bin}/gzip rix, - @{bin}/ldconfig rix, + @{sbin}/ldconfig rix, @{bin}/localedef rix, @{bin}/readlink rix, @{bin}/true rix, @@ -292,6 +295,8 @@ profile steam @{exec_path} flags=(attach_disconnected,mediate_deleted) { @{run}/host/@{lib}/** rix, @{share_dirs}/config/cefdata/WidevineCdm/**/linux_*/libwidevinecdm.so mr, + @{share_dirs}/config/htmlcache/WidevineCdm/**/linux_*/libwidevinecdm.so mr, + @{share_dirs}/linux{32,64}/steamclient.so mr, @{runtime_dirs}/var/tmp-@{rand6}/usr/.ref w, @@ -302,12 +307,15 @@ profile steam @{exec_path} flags=(attach_disconnected,mediate_deleted) { @{lib}/ r, /usr/local/lib/ r, /var/tmp/ r, + /home/ r, owner /bindfile@{rand6} rw, owner /var/cache/ldconfig/aux-cache* rw, owner /var/pressure-vessel/ldso/* rw, + owner @{HOME}/ r, + owner @{lib_dirs}/.cef-* wk, owner @{share_dirs}/{,**} r, @@ -344,10 +352,9 @@ profile steam @{exec_path} flags=(attach_disconnected,mediate_deleted) { @{sys}/devices/**/report_descriptor r, @{sys}/devices/**/uevent r, @{sys}/devices/@{pci}/usb@{int}/**/{idVendor,idProduct,interface} r, - @{sys}/devices/system/cpu/kernel_max r, - @{sys}/devices/virtual/tty/tty@{int}/active r, @{PROC}/ r, + @{PROC}/version r, @{PROC}/@{pid}/stat r, @{PROC}/sys/fs/inotify/max_user_watches r, @{PROC}/sys/kernel/yama/ptrace_scope r, @@ -363,16 +370,19 @@ profile steam @{exec_path} flags=(attach_disconnected,mediate_deleted) { /dev/hidraw@{int} rw, /dev/tty rw, + @{att}/dev/dri/renderD128 rw, + include if exists } profile check flags=(attach_disconnected,mediate_deleted,complain) { include - include + include include capability dac_override, capability dac_read_search, + capability sys_ptrace, unix receive type=stream, diff --git a/apparmor.d/groups/steam/steam-fossilize b/apparmor.d/groups/steam/steam-fossilize index e3e7f87e28..a2c999d90f 100644 --- a/apparmor.d/groups/steam/steam-fossilize +++ b/apparmor.d/groups/steam/steam-fossilize @@ -6,7 +6,7 @@ abi , include -@{runtime} = SteamLinuxRuntime_sniper +@{runtime} = SteamLinuxRuntime_{sniper,soldier} @{share_dirs} = @{user_share_dirs}/Steam @{HOME}/.steam/debian-installation @{lib_dirs} = @{share_dirs}/ubuntu@{int2}_{32,64} @{share_dirs}/linux{32,64} @{runtime_dirs} = @{lib_dirs}/steam-runtime{,-sniper} @@ -16,7 +16,7 @@ include profile steam-fossilize @{exec_path} flags=(attach_disconnected) { include include - include + include include signal receive peer=steam, @@ -39,11 +39,13 @@ profile steam-fossilize @{exec_path} flags=(attach_disconnected) { @{sys}/devices/system/node/node@{int}/cpumap r, - @{PROC}/@{pids}/statm r, + @{PROC}/@{pid}/statm r, @{PROC}/pressure/io r, owner @{PROC}/@{pid}/cmdline r, + owner @{PROC}/@{pid}/stat r, owner @{PROC}/@{pid}/task/@{tid}/comm rw, + deny network inet stream, deny owner @{user_share_dirs}/gvfs-metadata/{,*} r, include if exists diff --git a/apparmor.d/groups/steam/steam-game-native b/apparmor.d/groups/steam/steam-game-native index ca80801d76..ba06d56a41 100644 --- a/apparmor.d/groups/steam/steam-game-native +++ b/apparmor.d/groups/steam/steam-game-native @@ -6,7 +6,7 @@ abi , include -@{runtime} = SteamLinuxRuntime_sniper +@{runtime} = SteamLinuxRuntime_{sniper,soldier} @{share_dirs} = @{user_share_dirs}/Steam @{HOME}/.steam/debian-installation @{lib_dirs} = @{share_dirs}/ubuntu@{int2}_{32,64} @{share_dirs}/linux{32,64} @{runtime_dirs} = @{lib_dirs}/steam-runtime{,-sniper} diff --git a/apparmor.d/groups/steam/steam-game-proton b/apparmor.d/groups/steam/steam-game-proton index 3c4695e4fb..1ace879b95 100644 --- a/apparmor.d/groups/steam/steam-game-proton +++ b/apparmor.d/groups/steam/steam-game-proton @@ -6,7 +6,8 @@ abi , include -@{runtime} = SteamLinuxRuntime_sniper +@{runtime_name} = sniper soldier +@{runtime} = SteamLinuxRuntime_@{runtime_name} @{share_dirs} = @{user_share_dirs}/Steam @{HOME}/.steam/debian-installation @{lib_dirs} = @{share_dirs}/ubuntu@{int2}_{32,64} @{share_dirs}/linux{32,64} @{runtime_dirs} = @{lib_dirs}/steam-runtime{,-sniper} @@ -15,7 +16,7 @@ include @{exec_path} = @{app_dirs}/@{runtime}/pressure-vessel/@{lib}/steam-runtime-tools-@{int}/srt-bwrap profile steam-game-proton @{exec_path} flags=(attach_disconnected,complain) { include - include + include include include include @@ -35,18 +36,24 @@ profile steam-game-proton @{exec_path} flags=(attach_disconnected,complain) { @{exec_path} mr, @{bin}/bwrap mrix, + @{sh_path} rix, + @{bin}/cat rix, + @{bin}/env rix, @{bin}/chmod rix, @{bin}/fc-match rix, @{bin}/getopt rix, @{bin}/gzip rix, - @{bin}/ldconfig rix, + @{sbin}/ldconfig rix, + @{bin}/ln rix, @{bin}/localedef rix, - @{python_path} rix, + @{bin}/mkdir rix, @{bin}/readlink rix, + @{bin}/rm rix, @{bin}/steam-runtime-launcher-interface-@{int} rix, @{bin}/steam-runtime-system-info rix, @{bin}/steam-runtime-urlopen rix, @{bin}/true rix, + @{python_path} rix, @{open_path} rix, @{lib_dirs}/** mr, @@ -54,9 +61,17 @@ profile steam-game-proton @{exec_path} flags=(attach_disconnected,complain) { @{lib}/pressure-vessel/from-host/@{lib}/** rix, @{lib}/steam-runtime-tools-@{int}/@{multiarch}-* rix, + # TODO stack with steam ? rpx -> steam-game-proton&//steam, + @{runtime_dirs}/run.sh rix, + @{runtime_dirs}/@{arch}@{bin}/steam-runtime-identify-library-abi rix, + @{runtime_dirs}/@{arch}@{bin}/steam-runtime-launcher-interface-@{int} rix, + @{app_dirs}/SteamLinuxRuntime/var/steam-runtime/run.sh rix, + @{app_dirs}/SteamLinuxRuntime/var/steam-runtime/@{arch}@{bin}/steam-runtime-identify-library-abi rix, + @{app_dirs}/SteamLinuxRuntime/var/steam-runtime/@{arch}@{bin}/steam-runtime-launcher-interface-@{int} rix, + @{app_dirs}/** mrix, - @{run}/host/@{bin}/ldconfig rix, + @{run}/host/@{sbin}/ldconfig rix, @{run}/host/@{bin}/localedef rix, @{run}/host/@{lib}/** mr, @@ -72,6 +87,7 @@ profile steam-game-proton @{exec_path} flags=(attach_disconnected,complain) { owner "@{app_dirs}/Steamworks Shared/runasadmin.vdf" rw, owner @{app_dirs}/@{runtime}/var/tmp-@{rand6}/usr/.ref rwk, + owner @{app_dirs}/SteamLinuxRuntime/var/steam-runtime/* rw, owner @{app_dirs}/Proton*/** rwkl, owner @{share_dirs}/*.dll r, diff --git a/apparmor.d/groups/steam/steam-gameoverlayui b/apparmor.d/groups/steam/steam-gameoverlayui index 0cd8371356..278b47e981 100644 --- a/apparmor.d/groups/steam/steam-gameoverlayui +++ b/apparmor.d/groups/steam/steam-gameoverlayui @@ -6,7 +6,7 @@ abi , include -@{runtime} = SteamLinuxRuntime_sniper +@{runtime} = SteamLinuxRuntime_{sniper,soldier} @{share_dirs} = @{user_share_dirs}/Steam @{HOME}/.steam/debian-installation @{lib_dirs} = @{share_dirs}/ubuntu@{int2}_{32,64} @{share_dirs}/linux{32,64} @{runtime_dirs} = @{lib_dirs}/steam-runtime{,-sniper} @@ -49,6 +49,8 @@ profile steam-gameoverlayui @{exec_path} flags=(attach_disconnected) { owner @{share_dirs}/resource/{,**} rk, owner @{share_dirs}/userdata/@{int}/{,**} rk, + owner @{att}/dev/shm/ValveIPCSHM_@{uid} rw, + owner /dev/shm/u@{uid}-Shm_@{hex} rw, owner /dev/shm/u@{uid}-ValveIPCSharedObj-Steam rwk, owner /dev/shm/ValveIPCSHM_@{uid} rw, diff --git a/apparmor.d/groups/steam/steam-launch b/apparmor.d/groups/steam/steam-launch index 4929c1d569..321c9c9c5d 100644 --- a/apparmor.d/groups/steam/steam-launch +++ b/apparmor.d/groups/steam/steam-launch @@ -6,7 +6,7 @@ abi , include -@{runtime} = SteamLinuxRuntime_sniper +@{runtime} = SteamLinuxRuntime_{sniper,soldier} @{share_dirs} = @{user_share_dirs}/Steam @{HOME}/.steam/debian-installation @{lib_dirs} = @{share_dirs}/ubuntu@{int2}_{32,64} @{share_dirs}/linux{32,64} @{runtime_dirs} = @{lib_dirs}/steam-runtime{,-sniper} @@ -36,6 +36,8 @@ profile steam-launch @{exec_path} { @{lib}/steam/bin_steam.sh rix, @{share_dirs}/steam.sh rPx, + @{lib_dirs}/** mr, + @{runtime_dirs}/@{arch}/@{bin}/steam-runtime-steam-remote rPx, @{runtime_dirs}/@{lib}/steam-runtime-tools-@{int}/* r, @{runtime_dirs}/@{lib}/steam-runtime-tools-@{int}/srt-logger rix, @@ -44,7 +46,10 @@ profile steam-launch @{exec_path} { /usr/local/ r, owner @{share_dirs}/bootstrap.tar.xz rw, + owner @{share_dirs}/logs/ r, + owner @{share_dirs}/logs/* rwk, + owner @{run}/user/@{uid}/srt-fifo.@{rand6}/ rw, owner @{run}/user/@{uid}/srt-fifo.@{rand6}/fifo rw, owner @{PROC}/@{pid}/fd/@{int} rw, diff --git a/apparmor.d/groups/steam/steam-launcher b/apparmor.d/groups/steam/steam-launcher index 0bd8c67d3d..e73b30d1a0 100644 --- a/apparmor.d/groups/steam/steam-launcher +++ b/apparmor.d/groups/steam/steam-launcher @@ -6,7 +6,7 @@ abi , include -@{runtime} = SteamLinuxRuntime_sniper +@{runtime} = SteamLinuxRuntime_{sniper,soldier} @{share_dirs} = @{user_share_dirs}/Steam @{HOME}/.steam/debian-installation @{lib_dirs} = @{share_dirs}/ubuntu@{int2}_{32,64} @{share_dirs}/linux{32,64} @{runtime_dirs} = @{lib_dirs}/steam-runtime{,-sniper} diff --git a/apparmor.d/groups/steam/steam-runtime b/apparmor.d/groups/steam/steam-runtime deleted file mode 100644 index 2a3e839ffd..0000000000 --- a/apparmor.d/groups/steam/steam-runtime +++ /dev/null @@ -1,87 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - -abi , - -include - -@{runtime} = SteamLinuxRuntime_sniper -@{share_dirs} = @{user_share_dirs}/Steam @{HOME}/.steam/debian-installation -@{lib_dirs} = @{share_dirs}/ubuntu@{int2}_{32,64} @{share_dirs}/linux{32,64} -@{runtime_dirs} = @{lib_dirs}/steam-runtime{,-sniper} -@{app_dirs} = @{share_dirs}/steamapps/common/ - -@{exec_path} = @{lib_dirs}/reaper -profile steam-runtime @{exec_path} flags=(attach_disconnected) { - include - include - include - include - include - include - - network inet stream, - network inet6 stream, - network unix stream, - - @{exec_path} mr, - - @{sh_path} rix, - @{bin}/getopt rix, - @{bin}/readlink rix, - - @{lib_dirs}/** mr, - @{lib_dirs}/steam-launch-wrapper rix, - - # Native linux games (steam-game-native) - @{app_dirs}/[^S]*/** rpx -> steam-game-native, # Only for @{app_dirs}/@{runtime}/** - - # Proton games, sandboxed (steam-game-proton) - @{app_dirs}/@{runtime}/*entry-point rmix, - @{app_dirs}/@{runtime}/pressure-vessel/@{bin}/pressure-vessel-* rix, - @{app_dirs}/@{runtime}/pressure-vessel/@{lib}/** mr, - @{app_dirs}/@{runtime}/pressure-vessel/@{lib}/steam-runtime-tools-@{int}/@{multiarch}-* rix, - @{app_dirs}/@{runtime}/pressure-vessel/@{lib}/steam-runtime-tools-@{int}/srt-bwrap rpx -> steam-game-proton, - @{app_dirs}/@{runtime}/run rix, - @{bin}/bwrap rpx -> steam-game-proton, - - / r, - @{lib}/ r, - @{lib_dirs}/ r, - - owner @{HOME}/.steam/steam.pipe r, - - owner @{app_dirs}/*/ r, - owner @{app_dirs}/config/config.vdf{,.*} rw, - owner @{app_dirs}/@{runtime}/** r, - owner @{app_dirs}/@{runtime}/pressure-vessel/** rwk, - owner @{app_dirs}/@{runtime}/sniper_platform_*/** rwk, - owner @{app_dirs}/@{runtime}/var/** rwk, - owner link @{app_dirs}/@{runtime}/var/** -> @{app_dirs}/@{runtime}/pressure-vessel/**, - owner link @{app_dirs}/@{runtime}/var/** -> @{app_dirs}/@{runtime}/sniper_platform_*/**, - - owner @{share_dirs}/config/config.vdf{,.*} rw, - owner @{share_dirs}/steamapps/appmanifest_* rw, - - owner @{tmp}/ r, - owner @{tmp}/#@{int} rw, - owner @{tmp}/vdpau-drivers-@{rand6}/{,**} rw, - - owner @{run}/user/@{uid}/ r, - - owner /dev/shm/u@{uid}-Shm_@{hex6} rw, - owner /dev/shm/u@{uid}-Shm_@{hex6}@{h} rw, - owner /dev/shm/u@{uid}-Shm_@{hex8} rw, - owner /dev/shm/u@{uid}-ValveIPCSharedObj-Steam rwk, - - owner @{PROC}/@{pid}/cmdline r, - owner @{PROC}/@{pid}/comm r, - owner @{PROC}/@{pid}/fd/ r, - - /dev/tty rw, - - include if exists -} - -# vim:syntax=apparmor diff --git a/apparmor.d/groups/steam/steam-runtime-steam-remote b/apparmor.d/groups/steam/steam-runtime-steam-remote index 93a93e8925..b7d5f2b152 100644 --- a/apparmor.d/groups/steam/steam-runtime-steam-remote +++ b/apparmor.d/groups/steam/steam-runtime-steam-remote @@ -6,7 +6,7 @@ abi , include -@{runtime} = SteamLinuxRuntime_sniper +@{runtime} = SteamLinuxRuntime_{sniper,soldier} @{share_dirs} = @{user_share_dirs}/Steam @{HOME}/.steam/debian-installation @{lib_dirs} = @{share_dirs}/ubuntu@{int2}_{32,64} @{share_dirs}/linux{32,64} @{runtime_dirs} = @{lib_dirs}/steam-runtime{,-sniper} diff --git a/apparmor.d/groups/steam/steamerrorreporter b/apparmor.d/groups/steam/steamerrorreporter index 27fe69be90..d438c604d8 100644 --- a/apparmor.d/groups/steam/steamerrorreporter +++ b/apparmor.d/groups/steam/steamerrorreporter @@ -6,7 +6,7 @@ abi , include -@{runtime} = SteamLinuxRuntime_sniper +@{runtime} = SteamLinuxRuntime_{sniper,soldier} @{share_dirs} = @{user_share_dirs}/Steam @{HOME}/.steam/debian-installation @{lib_dirs} = @{share_dirs}/ubuntu@{int2}_{32,64} @{share_dirs}/linux{32,64} @{runtime_dirs} = @{lib_dirs}/steam-runtime{,-sniper} @@ -34,8 +34,6 @@ profile steamerrorreporter @{exec_path} flags=(attach_disconnected) { owner @{tmp}/dumps/ r, owner @{tmp}/dumps/*_log.txt rw, - owner @{PROC}/@{pid}/status r, - include if exists } diff --git a/apparmor.d/groups/systemd/systemd-generator-bless-boot b/apparmor.d/groups/systemd-generators/systemd-generator-bless-boot similarity index 76% rename from apparmor.d/groups/systemd/systemd-generator-bless-boot rename to apparmor.d/groups/systemd-generators/systemd-generator-bless-boot index 32e2aac65d..8a9d460250 100644 --- a/apparmor.d/groups/systemd/systemd-generator-bless-boot +++ b/apparmor.d/groups/systemd-generators/systemd-generator-bless-boot @@ -11,8 +11,13 @@ profile systemd-generator-bless-boot @{exec_path} flags=(attach_disconnected) { include include + ptrace read peer=@{p_systemd}, + @{exec_path} mr, + @{run}/systemd/generator.early/basic.target.wants/ w, + @{run}/systemd/generator.early/basic.target.wants/systemd-bless-boot.service w, + @{PROC}/@{pid}/cgroup r, include if exists diff --git a/apparmor.d/groups/systemd/systemd-generator-cloud-init b/apparmor.d/groups/systemd-generators/systemd-generator-cloud-init similarity index 92% rename from apparmor.d/groups/systemd/systemd-generator-cloud-init rename to apparmor.d/groups/systemd-generators/systemd-generator-cloud-init index 698a4fcb9d..31df5a3de9 100644 --- a/apparmor.d/groups/systemd/systemd-generator-cloud-init +++ b/apparmor.d/groups/systemd-generators/systemd-generator-cloud-init @@ -12,6 +12,10 @@ profile systemd-generator-cloud-init @{exec_path} flags=(attach_disconnected) { include include + capability sys_admin, # optional: no audit + + ptrace read peer=@{p_systemd}, + @{exec_path} mr, @{sh_path} rix, diff --git a/apparmor.d/groups/systemd/systemd-generator-cryptsetup b/apparmor.d/groups/systemd-generators/systemd-generator-cryptsetup similarity index 94% rename from apparmor.d/groups/systemd/systemd-generator-cryptsetup rename to apparmor.d/groups/systemd-generators/systemd-generator-cryptsetup index 1979dba1d0..beffa8e175 100644 --- a/apparmor.d/groups/systemd/systemd-generator-cryptsetup +++ b/apparmor.d/groups/systemd-generators/systemd-generator-cryptsetup @@ -12,6 +12,8 @@ profile systemd-generator-cryptsetup @{exec_path} flags=(attach_disconnected) { include include + ptrace read peer=@{p_systemd}, + @{exec_path} mr, /etc/crypttab r, diff --git a/apparmor.d/groups/systemd/systemd-generator-debug b/apparmor.d/groups/systemd-generators/systemd-generator-debug similarity index 76% rename from apparmor.d/groups/systemd/systemd-generator-debug rename to apparmor.d/groups/systemd-generators/systemd-generator-debug index 4ce9d2974e..a038e823e2 100644 --- a/apparmor.d/groups/systemd/systemd-generator-debug +++ b/apparmor.d/groups/systemd-generators/systemd-generator-debug @@ -11,8 +11,14 @@ profile systemd-generator-debug @{exec_path} flags=(attach_disconnected) { include include + ptrace read peer=@{p_systemd}, + @{exec_path} mr, + @{run}/credentials/@encrypted/ r, + @{run}/credentials/@system/ r, + @{run}/systemd/generator.early/systemd-repart.service w, + @{PROC}/@{pid}/cgroup r, include if exists diff --git a/apparmor.d/groups/systemd/systemd-generator-ds-identify b/apparmor.d/groups/systemd-generators/systemd-generator-ds-identify similarity index 70% rename from apparmor.d/groups/systemd/systemd-generator-ds-identify rename to apparmor.d/groups/systemd-generators/systemd-generator-ds-identify index d9a6639c10..9870ba9057 100644 --- a/apparmor.d/groups/systemd/systemd-generator-ds-identify +++ b/apparmor.d/groups/systemd-generators/systemd-generator-ds-identify @@ -11,28 +11,26 @@ profile systemd-generator-ds-identify @{exec_path} flags=(attach_disconnected) { include include include + include - ptrace (read) peer=@{p_systemd}, + ptrace read peer=@{p_systemd}, @{exec_path} mr, @{sh_path} rix, - @{bin}/blkid rPx, - @{bin}/grep rix, + @{bin}/{,e}grep rix, @{bin}/systemd-detect-virt rPx, @{bin}/tr rix, @{bin}/uname rix, + @{sbin}/blkid rPx, /etc/cloud/{,**} r, @{run}/cloud-init/{,.}ds-identify.* rw, @{run}/cloud-init/cloud.cfg rw, - @{sys}/devices/virtual/dmi/id/chassis_asset_tag r, - @{sys}/devices/virtual/dmi/id/product_name r, - @{sys}/devices/virtual/dmi/id/product_serial r, - @{sys}/devices/virtual/dmi/id/product_uuid r, - @{sys}/devices/virtual/dmi/id/sys_vendor r, + @{sys}/class/*/ r, + @{sys}/devices/**/name r, @{PROC}/cmdline r, @{PROC}/uptime r, diff --git a/apparmor.d/groups/systemd/systemd-generator-environment-arch b/apparmor.d/groups/systemd-generators/systemd-generator-environment-arch similarity index 94% rename from apparmor.d/groups/systemd/systemd-generator-environment-arch rename to apparmor.d/groups/systemd-generators/systemd-generator-environment-arch index 738144547e..aee9ee573c 100644 --- a/apparmor.d/groups/systemd/systemd-generator-environment-arch +++ b/apparmor.d/groups/systemd-generators/systemd-generator-environment-arch @@ -12,6 +12,8 @@ profile systemd-generator-environment-arch @{exec_path} { include include + ptrace read peer=@{p_systemd}, + @{exec_path} mr, @{sh_path} r, diff --git a/apparmor.d/groups/systemd/systemd-generator-environment-flatpak b/apparmor.d/groups/systemd-generators/systemd-generator-environment-flatpak similarity index 92% rename from apparmor.d/groups/systemd/systemd-generator-environment-flatpak rename to apparmor.d/groups/systemd-generators/systemd-generator-environment-flatpak index a4ba2afe10..cc67056d70 100644 --- a/apparmor.d/groups/systemd/systemd-generator-environment-flatpak +++ b/apparmor.d/groups/systemd-generators/systemd-generator-environment-flatpak @@ -11,6 +11,8 @@ profile systemd-generator-environment-flatpak @{exec_path} { include include + ptrace read peer=@{p_systemd}, + @{exec_path} mr, @{sh_path} rix, @@ -18,6 +20,8 @@ profile systemd-generator-environment-flatpak @{exec_path} { /usr/{local/,}share/gvfs/remote-volume-monitors/{,*} r, + /root/.cache/ w, + /dev/tty rw, include if exists diff --git a/apparmor.d/groups/systemd-generators/systemd-generator-environment-snapd b/apparmor.d/groups/systemd-generators/systemd-generator-environment-snapd new file mode 100644 index 0000000000..162be13037 --- /dev/null +++ b/apparmor.d/groups/systemd-generators/systemd-generator-environment-snapd @@ -0,0 +1,20 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/systemd/system-environment-generators/snapd-env-generator +profile systemd-generator-environment-snapd @{exec_path} flags=(attach_disconnected) { + include + + ptrace read peer=@{p_systemd}, + + @{exec_path} mr, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd-generators/systemd-generator-friendly-recovery b/apparmor.d/groups/systemd-generators/systemd-generator-friendly-recovery new file mode 100644 index 0000000000..ad49627122 --- /dev/null +++ b/apparmor.d/groups/systemd-generators/systemd-generator-friendly-recovery @@ -0,0 +1,26 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/systemd/system-generators/friendly-recovery +profile systemd-generator-friendly-recovery @{exec_path} flags=(attach_disconnected) { + include + + ptrace read peer=@{p_systemd}, + + @{exec_path} mr, + + @{sh_path} rix, + @{bin}/cat rix, + @{bin}/ln rix, + + @{PROC}/cmdline r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd/systemd-generator-fstab b/apparmor.d/groups/systemd-generators/systemd-generator-fstab similarity index 80% rename from apparmor.d/groups/systemd/systemd-generator-fstab rename to apparmor.d/groups/systemd-generators/systemd-generator-fstab index 193ff22af6..c2e86205ed 100644 --- a/apparmor.d/groups/systemd/systemd-generator-fstab +++ b/apparmor.d/groups/systemd-generators/systemd-generator-fstab @@ -7,7 +7,7 @@ abi , include @{exec_path} = @{lib}/systemd/system-generators/systemd-fstab-generator -profile systemd-generator-fstab @{exec_path} { +profile systemd-generator-fstab @{exec_path} flags=(attach_disconnected) { include include @@ -15,6 +15,8 @@ profile systemd-generator-fstab @{exec_path} { capability dac_read_search, capability mknod, + ptrace read peer=@{p_systemd}, + @{exec_path} mr, /etc/fstab r, @@ -23,6 +25,8 @@ profile systemd-generator-fstab @{exec_path} { @{PROC}/@{pid}/cgroup r, + priority=10 @{PROC}/1/environ r, + include if exists } diff --git a/apparmor.d/groups/systemd/systemd-generator-getty b/apparmor.d/groups/systemd-generators/systemd-generator-getty similarity index 77% rename from apparmor.d/groups/systemd/systemd-generator-getty rename to apparmor.d/groups/systemd-generators/systemd-generator-getty index 0eadabec8b..5169b3b62c 100644 --- a/apparmor.d/groups/systemd/systemd-generator-getty +++ b/apparmor.d/groups/systemd-generators/systemd-generator-getty @@ -12,17 +12,24 @@ profile systemd-generator-getty @{exec_path} flags=(attach_disconnected) { include include + ptrace read peer=@{p_systemd}, + @{exec_path} mr, @{run}/systemd/generator/getty.target.wants/ w, + @{run}/systemd/generator/getty.target.wants/serial-getty@hvc@{int}.service w, @{run}/systemd/generator/getty.target.wants/serial-getty@ttyS@{int}.service w, @{sys}/devices/virtual/tty/console/active r, + @{sys}/devices/virtual/tty/tty@{int}/active r, @{PROC}/@{pid}/cgroup r, + owner /dev/hvc@{int} rw, owner /dev/ttyS@{int} rw, + priority=10 @{PROC}/1/environ r, + include if exists } diff --git a/apparmor.d/groups/systemd-generators/systemd-generator-gpt-auto b/apparmor.d/groups/systemd-generators/systemd-generator-gpt-auto new file mode 100644 index 0000000000..00ee4ad979 --- /dev/null +++ b/apparmor.d/groups/systemd-generators/systemd-generator-gpt-auto @@ -0,0 +1,60 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2023-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/systemd/system-generators/systemd-gpt-auto-generator +profile systemd-generator-gpt-auto @{exec_path} flags=(attach_disconnected) { + include + include + include + + capability sys_admin, + + ptrace read peer=@{p_systemd}, + + @{exec_path} mr, + + / r, + @{efi}/ r, + /etc/fstab r, + /usr/ r, + /home/ r, + + @{run}/systemd/generator.late/*.mount.wants/ w, + @{run}/systemd/generator.late/*.mount.wants/systemd-growfs*.service w, + @{run}/systemd/generator.late/*.mount.wants/systemd-pcrfs*.service w, + @{run}/systemd/generator.late/*.mount.wants/systemd-validatefs@*.service w, + @{run}/systemd/generator.late/**.{,auto}mount w, + @{run}/systemd/generator.late/**.swap w, + @{run}/systemd/generator.late/cryptsetup.target.requires/ w, + @{run}/systemd/generator.late/cryptsetup.target.requires/systemd-cryptsetup@*.service w, + @{run}/systemd/generator.late/dev-disk-by*.device.wants/ w, + @{run}/systemd/generator.late/dev-disk-by*.device.wants/systemd-cryptsetup@*.service w, + @{run}/systemd/generator.late/dev-mapper-*.device.d/ w, + @{run}/systemd/generator.late/dev-mapper-*.device.d/.#*.conf@{hex16} rw, + @{run}/systemd/generator.late/dev-mapper-*.device.d/*.conf w, + @{run}/systemd/generator.late/dev-mapper-*.device.requires/ w, + @{run}/systemd/generator.late/dev-mapper-*.device.requires/systemd-cryptsetup@*.service w, + @{run}/systemd/generator.late/local-fs.target.d/ w, + @{run}/systemd/generator.late/local-fs.target.d/*.conf w, + @{run}/systemd/generator.late/local-fs.target.requires/ w, + @{run}/systemd/generator.late/local-fs.target.wants/ w, + @{run}/systemd/generator.late/swap.target.wants/ w, + @{run}/systemd/generator.late/systemd-cryptsetup@*.service w, + @{run}/systemd/generator/local-fs.target.wants/ w, + @{run}/systemd/generator/local-fs.target.wants/systemd-fsck*.service w, + + @{sys}/firmware@{efi}/efivars/LoaderTpm2ActivePcrBanks-@{uuid} r, + @{sys}/firmware@{efi}/efivars/StubPcrKernelImage-@{uuid} r, + @{sys}/firmware/efi/efivars/LoaderDevicePartUUID-@{uuid} r, + + @{PROC}/@{pid}/cgroup r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd/systemd-generator-hibernate-resume b/apparmor.d/groups/systemd-generators/systemd-generator-hibernate-resume similarity index 94% rename from apparmor.d/groups/systemd/systemd-generator-hibernate-resume rename to apparmor.d/groups/systemd-generators/systemd-generator-hibernate-resume index 7c5e9ec806..8979388dc9 100644 --- a/apparmor.d/groups/systemd/systemd-generator-hibernate-resume +++ b/apparmor.d/groups/systemd-generators/systemd-generator-hibernate-resume @@ -11,6 +11,8 @@ profile systemd-generator-hibernate-resume @{exec_path} flags=(attach_disconnect include include + ptrace read peer=@{p_systemd}, + @{exec_path} mr, @{PROC}/@{pid}/cgroup r, diff --git a/apparmor.d/groups/systemd-generators/systemd-generator-import b/apparmor.d/groups/systemd-generators/systemd-generator-import new file mode 100644 index 0000000000..de3753aaf5 --- /dev/null +++ b/apparmor.d/groups/systemd-generators/systemd-generator-import @@ -0,0 +1,31 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/systemd/system-generators/systemd-import-generator +profile systemd-generator-import @{exec_path} flags=(attach_disconnected) { + include + + capability sys_ptrace, + + ptrace read peer=@{p_systemd}, + + @{exec_path} mr, + + / r, + + @{PROC}/@{pid}/cgroup r, + @{PROC}/1/environ r, + @{PROC}/cmdline r, + @{PROC}/sys/kernel/osrelease r, + + /dev/kmsg w, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd/systemd-generator-integritysetup b/apparmor.d/groups/systemd-generators/systemd-generator-integritysetup similarity index 94% rename from apparmor.d/groups/systemd/systemd-generator-integritysetup rename to apparmor.d/groups/systemd-generators/systemd-generator-integritysetup index 72ef280612..5ac1ea004c 100644 --- a/apparmor.d/groups/systemd/systemd-generator-integritysetup +++ b/apparmor.d/groups/systemd-generators/systemd-generator-integritysetup @@ -11,6 +11,8 @@ profile systemd-generator-integritysetup @{exec_path} flags=(attach_disconnected include include + ptrace read peer=@{p_systemd}, + @{exec_path} mr, @{PROC}/@{pid}/cgroup r, diff --git a/apparmor.d/groups/systemd-generators/systemd-generator-openvpn b/apparmor.d/groups/systemd-generators/systemd-generator-openvpn new file mode 100644 index 0000000000..a9a5be11c6 --- /dev/null +++ b/apparmor.d/groups/systemd-generators/systemd-generator-openvpn @@ -0,0 +1,31 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/systemd/system-generators/openvpn-generator +profile systemd-generator-openvpn @{exec_path} flags=(attach_disconnected) { + include + + capability sys_admin, + + ptrace read peer=@{p_systemd}, + + @{exec_path} mr, + + @{sh_path} r, + @{bin}/ls ix, + @{bin}/mkdir ix, + + /etc/default/openvpn r, + /etc/openvpn/ r, + + @{run}/systemd/generator/openvpn.service.wants/{,**} w, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd/systemd-generator-ostree b/apparmor.d/groups/systemd-generators/systemd-generator-ostree similarity index 93% rename from apparmor.d/groups/systemd/systemd-generator-ostree rename to apparmor.d/groups/systemd-generators/systemd-generator-ostree index ce2ecaf439..9a3d610cbd 100644 --- a/apparmor.d/groups/systemd/systemd-generator-ostree +++ b/apparmor.d/groups/systemd-generators/systemd-generator-ostree @@ -10,6 +10,8 @@ include profile systemd-generator-ostree @{exec_path} flags=(attach_disconnected) { include + ptrace read peer=@{p_systemd}, + @{exec_path} mr, @{PROC}/cmdline r, diff --git a/apparmor.d/groups/systemd-generators/systemd-generator-rc-local b/apparmor.d/groups/systemd-generators/systemd-generator-rc-local new file mode 100644 index 0000000000..3e8bec6c53 --- /dev/null +++ b/apparmor.d/groups/systemd-generators/systemd-generator-rc-local @@ -0,0 +1,28 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/systemd/system-generators/systemd-rc-local-generator +profile systemd-generator-rc-local @{exec_path} flags=(attach_disconnected) { + include + + ptrace read peer=@{p_systemd}, + + @{exec_path} mr, + + @{PROC}/@{pid}/cgroup r, + @{PROC}/1/cgroup r, + @{PROC}/1/environ r, + @{PROC}/cmdline r, + @{PROC}/sys/kernel/osrelease r, + + /dev/kmsg w, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd/systemd-generator-run b/apparmor.d/groups/systemd-generators/systemd-generator-run similarity index 100% rename from apparmor.d/groups/systemd/systemd-generator-run rename to apparmor.d/groups/systemd-generators/systemd-generator-run diff --git a/apparmor.d/groups/systemd-generators/systemd-generator-snapd b/apparmor.d/groups/systemd-generators/systemd-generator-snapd new file mode 100644 index 0000000000..85ea9734cd --- /dev/null +++ b/apparmor.d/groups/systemd-generators/systemd-generator-snapd @@ -0,0 +1,22 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/systemd/system-generators/snapd-generator +profile systemd-generator-snapd @{exec_path} flags=(attach_disconnected) { + include + + ptrace read peer=@{p_systemd}, + + @{exec_path} mr, + + @{PROC}/1/mountinfo r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd-generators/systemd-generator-ssh b/apparmor.d/groups/systemd-generators/systemd-generator-ssh new file mode 100644 index 0000000000..e73b65fc7a --- /dev/null +++ b/apparmor.d/groups/systemd-generators/systemd-generator-ssh @@ -0,0 +1,50 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/systemd/system-generators/systemd-ssh-generator +profile systemd-generator-ssh @{exec_path} flags=(attach_disconnected) { + include + include + + capability net_admin, + + network vsock stream, + + ptrace read peer=@{p_systemd}, + + @{exec_path} mr, + + @{sbin}/sshd r, + + / r, + + @{run}/ r, + @{run}/systemd/ r, + @{run}/systemd/generator/ r, + @{run}/systemd/generator/sockets.target.wants/ rw, + @{run}/systemd/generator/sockets.target.wants/*.socket w, + @{run}/systemd/generator/sshd-*.service w, + @{run}/systemd/generator/sshd-*.socket rw, + @{run}/systemd/system/ r, + @{run}/systemd/transient/ r, + + @{sys}/firmware/dmi/entries/*/raw r, + + @{PROC}/@{pid}/cgroup r, + @{PROC}/1/cgroup r, + @{PROC}/1/environ r, + @{PROC}/cmdline r, + @{PROC}/sys/kernel/osrelease r, + + /dev/kmsg w, + /dev/vsock r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd-generators/systemd-generator-sshd-socket b/apparmor.d/groups/systemd-generators/systemd-generator-sshd-socket new file mode 100644 index 0000000000..8e90be300d --- /dev/null +++ b/apparmor.d/groups/systemd-generators/systemd-generator-sshd-socket @@ -0,0 +1,30 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/systemd/system-generators/sshd-socket-generator +profile systemd-generator-sshd-socket @{exec_path} { + include + include + + network inet dgram, + network inet6 dgram, + network netlink raw, + + ptrace read peer=@{p_systemd}, + + @{exec_path} mr, + + @{etc_ro}/ssh/sshd_config r, + @{etc_ro}/ssh/sshd_config.d/{,*} r, + + @{run}/systemd/generator/ssh.socket.d/{,*} rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd/systemd-generator-system-update b/apparmor.d/groups/systemd-generators/systemd-generator-system-update similarity index 85% rename from apparmor.d/groups/systemd/systemd-generator-system-update rename to apparmor.d/groups/systemd-generators/systemd-generator-system-update index 557e4ab6e8..84127551f6 100644 --- a/apparmor.d/groups/systemd/systemd-generator-system-update +++ b/apparmor.d/groups/systemd-generators/systemd-generator-system-update @@ -11,9 +11,12 @@ profile systemd-generator-system-update @{exec_path} flags=(attach_disconnected) include include + ptrace read peer=@{p_systemd}, + @{exec_path} mr, - @{PROC}/@{pid}/cgroup r, + @{PROC}/@{pids}/cgroup r, + @{PROC}/@{pids}/status r, include if exists } diff --git a/apparmor.d/groups/systemd-generators/systemd-generator-sysv b/apparmor.d/groups/systemd-generators/systemd-generator-sysv new file mode 100644 index 0000000000..952166615c --- /dev/null +++ b/apparmor.d/groups/systemd-generators/systemd-generator-sysv @@ -0,0 +1,34 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/systemd/system-generators/systemd-sysv-generator +profile systemd-generator-sysv @{exec_path} flags=(attach_disconnected) { + include + + capability mknod, # optional: no audit + + ptrace read peer=@{p_systemd}, + + @{exec_path} mr, + + /etc/init.d/{,**} r, + /etc/rc@{int}.d/{,**} r, + + @{run}/systemd/generator.late/** w, + + @{PROC}/@{pid}/cgroup r, + @{PROC}/1/environ r, + @{PROC}/cmdline r, + @{PROC}/sys/kernel/osrelease r, + + /dev/kmsg w, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd-generators/systemd-generator-tpm2 b/apparmor.d/groups/systemd-generators/systemd-generator-tpm2 new file mode 100644 index 0000000000..3d23784a53 --- /dev/null +++ b/apparmor.d/groups/systemd-generators/systemd-generator-tpm2 @@ -0,0 +1,32 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/systemd/system-generators/systemd-tpm2-generator +profile systemd-generator-tpm2 @{exec_path} flags=(attach_disconnected) { + include + + ptrace read peer=@{p_systemd}, + + @{exec_path} mr, + + @{sys}/class/tpmrm/ r, + @{sys}/devices/**/tpm/tpm@{int}/tpm_version_major r, + @{sys}/firmware@{efi}/efivars/LoaderTpm2ActivePcrBanks-@{uuid} r, + + @{PROC}/@{pid}/cgroup r, + @{PROC}/1/cgroup r, + @{PROC}/1/environ r, + @{PROC}/cmdline r, + @{PROC}/sys/kernel/osrelease r, + + /dev/kmsg w, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd/systemd-generator-user-autostart b/apparmor.d/groups/systemd-generators/systemd-generator-user-autostart similarity index 91% rename from apparmor.d/groups/systemd/systemd-generator-user-autostart rename to apparmor.d/groups/systemd-generators/systemd-generator-user-autostart index 8e3ebb6b3c..7e98e166ec 100644 --- a/apparmor.d/groups/systemd/systemd-generator-user-autostart +++ b/apparmor.d/groups/systemd-generators/systemd-generator-user-autostart @@ -10,13 +10,14 @@ include profile systemd-generator-user-autostart @{exec_path} flags=(attach_disconnected) { include include + include include capability net_admin, - @{exec_path} mr, + ptrace read peer=@{p_systemd}, - @{system_share_dirs}/applications/*.desktop r, + @{exec_path} mr, @{etc_ro}/xdg/autostart/{,*.desktop} r, diff --git a/apparmor.d/groups/systemd/systemd-generator-user-environment b/apparmor.d/groups/systemd-generators/systemd-generator-user-environment similarity index 86% rename from apparmor.d/groups/systemd/systemd-generator-user-environment rename to apparmor.d/groups/systemd-generators/systemd-generator-user-environment index 27db220782..2fbfc0c32a 100644 --- a/apparmor.d/groups/systemd/systemd-generator-user-environment +++ b/apparmor.d/groups/systemd-generators/systemd-generator-user-environment @@ -14,6 +14,8 @@ profile systemd-generator-user-environment @{exec_path} flags=(attach_disconnect capability net_admin, + ptrace read peer=@{p_systemd}, + @{exec_path} mr, @{sh_path} rix, @@ -26,6 +28,9 @@ profile systemd-generator-user-environment @{exec_path} flags=(attach_disconnect /snap/snapd/@{int}/usr/lib/environment.d/{,*.conf} r, + owner @{desktop_config_dirs}/environment.d/ r, + owner @{desktop_config_dirs}/environment.d/{,*.conf} r, + owner @{user_config_dirs}/environment.d/{,*.conf} r, /dev/tty rw, diff --git a/apparmor.d/groups/systemd/systemd-generator-veritysetup b/apparmor.d/groups/systemd-generators/systemd-generator-veritysetup similarity index 69% rename from apparmor.d/groups/systemd/systemd-generator-veritysetup rename to apparmor.d/groups/systemd-generators/systemd-generator-veritysetup index 97776312f6..cfada4595d 100644 --- a/apparmor.d/groups/systemd/systemd-generator-veritysetup +++ b/apparmor.d/groups/systemd-generators/systemd-generator-veritysetup @@ -11,10 +11,14 @@ profile systemd-generator-veritysetup @{exec_path} flags=(attach_disconnected) { include include - ptrace (read) peer=@{p_systemd}, + ptrace read peer=@{p_systemd}, @{exec_path} mr, + @{run}/systemd/generator/systemd-veritysetup@*.service w, + @{run}/systemd/generator/veritysetup.target.requires/ w, + @{run}/systemd/generator/veritysetup.target.requires/systemd-veritysetup@*.service w, + @{PROC}/@{pid}/cgroup r, include if exists diff --git a/apparmor.d/groups/systemd-service/cloud-init-hotplugd.service b/apparmor.d/groups/systemd-service/cloud-init-hotplugd.service new file mode 100644 index 0000000000..62af762896 --- /dev/null +++ b/apparmor.d/groups/systemd-service/cloud-init-hotplugd.service @@ -0,0 +1,26 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# systemd service: `cloud-init-hotplugd.service` +# +# ```sh +# /bin/bash -c 'read args <&3; echo "args=$args"; \ +# exec /usr/bin/cloud-init devel hotplug-hook $args; \ +# exit 0' +# ``` + +abi , + +include + +profile cloud-init-hotplugd.service { + include + + @{sh_path} ix, + @{bin}/cloud-init Px, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd-service/debug-shell.service b/apparmor.d/groups/systemd-service/debug-shell.service new file mode 100644 index 0000000000..20d2bbd20d --- /dev/null +++ b/apparmor.d/groups/systemd-service/debug-shell.service @@ -0,0 +1,25 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# systemd service: `debug-shell.service` +# +# ```sh +# /usr/bin/bash +# ``` +# +# On purpose, this profile allow everything. + +abi , + +include + +profile debug-shell.service { + include + + all, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd-service/dmesg.service b/apparmor.d/groups/systemd-service/dmesg.service new file mode 100644 index 0000000000..f4b2c0fc7d --- /dev/null +++ b/apparmor.d/groups/systemd-service/dmesg.service @@ -0,0 +1,68 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# systemd service: `dmesg.service` +# +# ```sh +# /usr/bin/savelog -m640 -q -p -n -c 5 /var/log/dmesg +# /bin/journalctl --boot 0 --dmesg --output short-monotonic --quiet --no-pager --no-hostname +# /bin/chgrp adm /var/log/dmesg +# /bin/chmod 0640 /var/log/dmesg +# ``` +# + +abi , + +include + +profile dmesg.service flags=(attach_disconnected) { + include + include + + capability chown, + capability fsetid, + capability sys_admin, + + ptrace read peer=@{p_systemd}, + + @{sh_path} r, + @{bin}/basename ix, + @{bin}/chgrp rix, + @{bin}/chmod rix, + @{bin}/chown ix, + @{bin}/date ix, + @{bin}/dirname ix, + @{bin}/gzip ix, + @{bin}/gzip ix, + @{bin}/journalctl r, + @{bin}/ln ix, + @{bin}/mv ix, + @{bin}/rm ix, + @{bin}/savelog rix, + @{bin}/touch ix, + + /etc/machine-id r, + + /var/log/ r, + /var/log/dmesg rw, + /var/log/dmesg.* rwl -> /var/log/dmesg, + + /{run,var}/log/journal/ r, + /{run,var}/log/journal/@{hex32}/ r, + /{run,var}/log/journal/@{hex32}/system.journal* r, + /{run,var}/log/journal/@{hex32}/system@@{hex}-@{hex}.journal* rw, + /{run,var}/log/journal/@{hex32}/system@@{hex32}-@{hex16}-@{hex16}.journal* rw, + /{run,var}/log/journal/@{hex32}/user-@{hex}.journal* rw, + /{run,var}/log/journal/@{hex32}/user-@{uid}@@{hex}-@{hex}.journal* rw, + /{run,var}/log/journal/@{hex32}/user-@{uid}@@{hex32}-@{hex16}-@{hex16}.journal* rw, + + @{PROC}/1/environ r, + @{PROC}/cmdline r, + @{PROC}/sys/kernel/osrelease r, + @{PROC}/sys/kernel/random/boot_id r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd-service/grub-common.service b/apparmor.d/groups/systemd-service/grub-common.service new file mode 100644 index 0000000000..eaa87f5321 --- /dev/null +++ b/apparmor.d/groups/systemd-service/grub-common.service @@ -0,0 +1,47 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# systemd service: `grub-common.service` +# +# ```sh +# /bin/sh -c '[ -s /boot/grub/grubenv ] || rm -f /boot/grub/grubenv; mkdir -p /boot/grub' +# grub-editenv /boot/grub/grubenv unset recordfail +# /bin/sh -c 'if grub-editenv /boot/grub/grubenv list | grep -q initrdless_boot_fallback_triggered=1; then echo "grub: GRUB_FORCE_PARTUUID set, initrdless boot paniced, fallback triggered."; fi' +# ``` + +abi , + +include + +profile grub-common.service { + include + + @{sh_path} rix, + @{bin}/{,e}grep ix, + @{bin}/grub-editenv rix, + @{bin}/mkdir ix, + @{bin}/plymouth Px, + @{bin}/rm ix, + @{bin}/systemctl Cx -> systemctl, + + /etc/init.d/grub-common r, + + @{efi}/grub/ w, + @{efi}/grub/grubenv rw, + + profile systemctl { + include + include + + capability net_admin, + + ptrace read peer=@{p_systemd}, + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd-service/ldconfig.service b/apparmor.d/groups/systemd-service/ldconfig.service new file mode 100644 index 0000000000..5781dcfa10 --- /dev/null +++ b/apparmor.d/groups/systemd-service/ldconfig.service @@ -0,0 +1,29 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# systemd service: `ldconfig.service` +# +# ```sh +# /sbin/ldconfig -X +# ``` +# +# FIXME: configure the systemd unit file to use the `ldconfig` profile. + +abi , + +include + +profile ldconfig.service { + include + + @{lib}/ r, + @{sbin}/ldconfig r, + + /var/cache/ldconfig/aux-cache rw, + /var/cache/ldconfig/aux-cache~ rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd-service/man-db.service b/apparmor.d/groups/systemd-service/man-db.service new file mode 100644 index 0000000000..cfd7433335 --- /dev/null +++ b/apparmor.d/groups/systemd-service/man-db.service @@ -0,0 +1,43 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# ExecStart=+/usr/bin/install -d -o man -g man -m 0755 /var/cache/man +# ExecStart=/usr/bin/find /var/cache/man -type f -name *.gz -atime +6 -delete +# ExecStart=/usr/bin/mandb --quiet + +abi , + +include + +profile man-db.service flags=(attach_disconnected) { + include + include + + capability dac_read_search, + + @{bin}/find ix, + @{bin}/install ix, + @{bin}/mandb r, + + /usr/{,local/}share/man/{,**} r, + + /etc/man_db.conf r, + /etc/manpath.config r, + + /usr/share/man/{,**} r, + /usr/local/man/{,**} r, + /usr/local/share/man/{,**} r, + + /usr/{,share/}man/{,**} r, + /usr/local/{,share/}man/{,**} r, + + /usr/share/**/man/man@{u8}/*.@{int}.gz r, + + owner /var/cache/man/ rw, + owner /var/cache/man/** rwk, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd-service/secureboot-db.service b/apparmor.d/groups/systemd-service/secureboot-db.service new file mode 100644 index 0000000000..f17a30acaa --- /dev/null +++ b/apparmor.d/groups/systemd-service/secureboot-db.service @@ -0,0 +1,36 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# systemd service: `secureboot-db.service` +# +# ```sh +# /usr/bin/chattr -i /sys/firmware/efi/efivars/KEK-@{uuid} +# /usr/bin/chattr -i /sys/firmware/efi/efivars/db-@{uuid} +# /usr/bin/chattr -i /sys/firmware/efi/efivars/dbx-@{uuid} +# /usr/bin/sbkeysync --no-default-keystores --keystore /usr/share/secureboot/updates --verbose +# ``` + +abi , + +include + +profile secureboot-db.service flags=(complain) { + include + + capability linux_immutable, + + @{bin}/chattr ix, + @{bin}/sbkeysync PUx, + + /usr/share/secureboot/updates/dbx/{,**} r, + + @{sys}/firmware@{efi}/efivars/PK-@{uuid} r, + @{sys}/firmware/efi/efivars/db-@{uuid} rw, + @{sys}/firmware/efi/efivars/dbx-@{uuid} rw, + @{sys}/firmware/efi/efivars/KEK-@{uuid} rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd-service/shadow.service b/apparmor.d/groups/systemd-service/shadow.service new file mode 100644 index 0000000000..f77ce67c7c --- /dev/null +++ b/apparmor.d/groups/systemd-service/shadow.service @@ -0,0 +1,32 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# systemd service: `shadow.service` +# +# ```sh +# /bin/sh -c '/usr/bin/pwck -qr || r=1; /usr/bin/grpck -r && exit $r' +# ``` + +abi , + +include + +profile shadow.service flags=(attach_disconnected) { + include + include + include + + @{sh_path} rix, + @{sbin}/grpck rPx -> shadow.service//&grpck, + @{sbin}/pwck rPx -> shadow.service//&pwck, + + /etc/gshadow r, + /etc/login.defs r, + /etc/machine-id r, + /etc/shadow r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd-service/snapd.system-shutdown.service b/apparmor.d/groups/systemd-service/snapd.system-shutdown.service new file mode 100644 index 0000000000..cea4d9218d --- /dev/null +++ b/apparmor.d/groups/systemd-service/snapd.system-shutdown.service @@ -0,0 +1,32 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# systemd service: `snapd.system-shutdown.service` +# +# ```sh +# /bin/mount /run -o remount,exec +# /bin/mkdir -p /run/initramfs +# /bin/cp /usr/lib/snapd/system-shutdown /run/initramfs/shutdown +# ``` + +abi , + +include + +profile snapd.system-shutdown.service { + include + + @{bin}/cp ix, + @{bin}/mkdir ix, + @{bin}/mount ix, + + @{lib}/snapd/system-shutdown r, + + @{run}/initramfs/ rw, + @{run}/initramfs/shutdown rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd-service/system-update-cleanup.service b/apparmor.d/groups/systemd-service/system-update-cleanup.service new file mode 100644 index 0000000000..0bce8c9336 --- /dev/null +++ b/apparmor.d/groups/systemd-service/system-update-cleanup.service @@ -0,0 +1,26 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# systemd service: `system-update-cleanup.service` +# +# ```sh +# rm -fv /system-update /etc/system-update +# ``` + +abi , + +include + +profile system-update-cleanup.service { + include + + @{bin}/rm ix, + + /etc/system-update w, + /system-update w, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd-service/usb_modeswitch.service b/apparmor.d/groups/systemd-service/usb_modeswitch.service new file mode 100644 index 0000000000..728f448882 --- /dev/null +++ b/apparmor.d/groups/systemd-service/usb_modeswitch.service @@ -0,0 +1,19 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# systemd service: `usb_modeswitch.service` + +abi , + +include + +profile usb_modeswitch.service { + include + + @{sbin}/usb_modeswitch_dispatcher ix, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd/bootctl b/apparmor.d/groups/systemd/bootctl index 28c2851fa6..dce710ae20 100644 --- a/apparmor.d/groups/systemd/bootctl +++ b/apparmor.d/groups/systemd/bootctl @@ -7,35 +7,35 @@ abi , include @{exec_path} = @{bin}/bootctl -profile bootctl @{exec_path} flags=(attach_disconnected) { +profile bootctl @{exec_path} flags=(attach_disconnected,mediate_deleted) { include include include include + include + capability linux_immutable, capability mknod, capability net_admin, + capability sys_rawio, + capability sys_resource, - signal (send) peer=child-pager, + signal send peer=child-pager, - ptrace (read) peer=unconfined, + ptrace read peer=unconfined, @{exec_path} mr, @{pager_path} rPx -> child-pager, - /{boot,efi}/ r, - /{boot,efi}/EFI/{,**} r, - /{boot,efi}/EFI/BOOT/.#BOOT*.EFI@{hex} rw, - /{boot,efi}/EFI/BOOT/BOOTX64.EFI w, - /{boot,efi}/EFI/systemd/.#systemd-boot*.efi@{hex} rw, - /{boot,efi}/EFI/systemd/systemd-boot*.efi w, - /{boot,efi}/loader/.#bootctlrandom-seed@{hex} rw, - /{boot,efi}/loader/.#entries.srel* w, - /{boot,efi}/loader/{,**} r, - /{boot,efi}/loader/entries.srel w, - /{boot,efi}/loader/random-seed w, + @{efi}/ r, + @{efi}/@{hex32}/ rw, + @{efi}/EFI/{,**} rwl, + @{efi}/loader/ rw, + @{efi}/loader/** rwl -> @{efi}/loader/#@{int}, + /etc/kernel/.#entry-token@{hex16} rw, + /etc/kernel/entry-token rw, /etc/machine-id r, /etc/machine-info r, @@ -44,14 +44,12 @@ profile bootctl @{exec_path} flags=(attach_disconnected) { @{sys}/class/tpmrm/ r, @{sys}/devices/pnp@{int}/**/tpm/tpm@{int}/tpm_version_major r, - @{sys}/devices/virtual/dmi/id/{board_vendor,bios_vendor} r, - @{sys}/devices/virtual/dmi/id/{sys_vendor,product_version,product_name} r, @{sys}/firmware/dmi/entries/*/raw r, @{sys}/firmware/efi/efivars/ r, @{sys}/firmware/efi/efivars/AuditMode-@{uuid} r, - @{sys}/firmware/efi/efivars/Boot@{hex}-@{uuid} r, - @{sys}/firmware/efi/efivars/BootOrder-@{uuid} r, + @{sys}/firmware/efi/efivars/Boot@{hex}-@{uuid} rw, + @{sys}/firmware/efi/efivars/BootOrder-@{uuid} rw, @{sys}/firmware/efi/efivars/DeployedMode-@{uuid} r, @{sys}/firmware/efi/efivars/LoaderDevicePartUUID-@{uuid} r, @{sys}/firmware/efi/efivars/LoaderEntries-@{uuid} r, @@ -61,8 +59,8 @@ profile bootctl @{exec_path} flags=(attach_disconnected) { @{sys}/firmware/efi/efivars/LoaderFirmwareType-@{uuid} r, @{sys}/firmware/efi/efivars/LoaderImageIdentifier-@{uuid} r, @{sys}/firmware/efi/efivars/LoaderInfo-@{uuid} r, - @{sys}/firmware/efi/efivars/LoaderSystemToken-@{uuid} r, - @{sys}/firmware/efi/efivars/OsIndications-@{uuid} r, + @{sys}/firmware/efi/efivars/LoaderSystemToken-@{uuid} rw, + @{sys}/firmware/efi/efivars/OsIndications-@{uuid} rw, @{sys}/firmware/efi/efivars/OsIndicationsSupported-@{uuid} r, @{sys}/firmware/efi/efivars/SecureBoot-@{uuid} r, @{sys}/firmware/efi/efivars/SetupMode-@{uuid} r, diff --git a/apparmor.d/groups/systemd/busctl b/apparmor.d/groups/systemd/busctl index 8b32b348fa..64a446d5b9 100644 --- a/apparmor.d/groups/systemd/busctl +++ b/apparmor.d/groups/systemd/busctl @@ -9,10 +9,9 @@ include @{exec_path} = @{bin}/busctl profile busctl @{exec_path} flags=(attach_disconnected) { include - include + include include include - include include include include @@ -34,6 +33,26 @@ profile busctl @{exec_path} flags=(attach_disconnected) { interface=org.freedesktop.DBus.Monitoring member=BecomeMonitor peer=(name=org.freedesktop.DBus, label="@{p_dbus_system}"), + dbus send bus=system path=/org/freedesktop/DBus + interface=org.freedesktop.DBus + member={GetConnectionCredentials,ListNames,ListActivatableNames} + peer=(name=org.freedesktop.DBus, label="@{p_dbus_system}"), + + dbus send bus=session path=/org/freedesktop/DBus + interface=org.freedesktop.DBus.Monitoring + member=BecomeMonitor + peer=(name=org.freedesktop.DBus, label="@{p_dbus_session}"), + dbus send bus=session path=/org/freedesktop/DBus + interface=org.freedesktop.DBus + member={GetConnectionCredentials,ListNames,ListActivatableNames} + peer=(name=org.freedesktop.DBus, label="@{p_dbus_session}"), + + dbus send bus=system + interface=org.freedesktop.DBus.Introspectable + member=Introspect, + dbus send bus=system + interface=org.freedesktop.DBus.Properties + member={GetAll,Get}, @{exec_path} mr, @@ -47,6 +66,8 @@ profile busctl @{exec_path} flags=(attach_disconnected) { @{PROC}/@{pid}/loginuid r, @{PROC}/@{pid}/sessionid r, @{PROC}/@{pid}/stat r, + @{PROC}/1/status r, + @{PROC}/sys/fs/nr_open r, include if exists } diff --git a/apparmor.d/groups/systemd/coredumpctl b/apparmor.d/groups/systemd/coredumpctl index e77f326fe3..df3c1dc1f7 100644 --- a/apparmor.d/groups/systemd/coredumpctl +++ b/apparmor.d/groups/systemd/coredumpctl @@ -8,17 +8,18 @@ abi , include @{exec_path} = @{bin}/coredumpctl -profile coredumpctl @{exec_path} flags=(complain) { +profile coredumpctl @{exec_path} { include - include include + include + include include capability dac_read_search, capability net_admin, capability sys_resource, - signal (send) peer=child-pager, + signal send peer=child-pager, @{exec_path} mr, @@ -29,7 +30,7 @@ profile coredumpctl @{exec_path} flags=(complain) { /var/lib/dbus/machine-id r, /etc/machine-id r, - /var/lib/systemd/coredump/core.*.@{int}.@{hex}.@{int}.@{int}.zst r, + /var/lib/systemd/coredump/{,**} r, /{run,var}/log/journal/ r, /{run,var}/log/journal/@{hex32}/ r, @@ -45,29 +46,38 @@ profile coredumpctl @{exec_path} flags=(complain) { profile gdb { include + include include - ptrace (trace), + ptrace trace, + + signal receive peer=coredumpctl, @{bin}/gdb mr, @{bin}/iconv rix, @{bin}/* r, + @{lib}/sysimage/rpm/*.db rk, + /usr/share/gcc-[0-9]*/python/{,**} r, /usr/share/gcc/** r, /usr/share/gdb/{,**} r, + /usr/share/gdb/python/{,**/}__pycache__/ w, + /usr/share/gdb/python/{,**/}__pycache__/**.pyc w, + /usr/share/gdb/python/{,**/}__pycache__/**.pyc.@{u64} w, /usr/share/glib-2.0/gdb/{,**} r, /usr/share/terminfo/** r, - /etc/inputrc r, /etc/gdb/** r, + /etc/gdbinit r, + /etc/inputrc r, owner /var/tmp/coredump-* rw, @{PROC}/@{pids}/fd/ r, - include if exists + include if exists } include if exists diff --git a/apparmor.d/groups/systemd/homectl b/apparmor.d/groups/systemd/homectl index aaae97d643..34cfa1ea79 100644 --- a/apparmor.d/groups/systemd/homectl +++ b/apparmor.d/groups/systemd/homectl @@ -7,7 +7,7 @@ abi , include @{exec_path} = @{bin}/homectl -profile homectl @{exec_path} { +profile homectl @{exec_path} flags=(attach_disconnected) { include include include @@ -19,7 +19,7 @@ profile homectl @{exec_path} { signal send peer=child-pager, - #aa:dbus talk bus=system name=org.freedesktop.home1 label=systemd-homed + #aa:dbus talk bus=system name=org.freedesktop.home1 label="@{p_systemd_homed}" @{exec_path} mr, @@ -28,6 +28,8 @@ profile homectl @{exec_path} { @{pager_path} rPx -> child-pager, /etc/machine-id r, + /etc/security/pwquality.conf r, + /etc/security/pwquality.conf.d/{,*.conf} r, owner @{PROC}/@{pids}/cgroup r, diff --git a/apparmor.d/groups/systemd/hostnamectl b/apparmor.d/groups/systemd/hostnamectl index dcbe9a46f3..4016ecf0ed 100644 --- a/apparmor.d/groups/systemd/hostnamectl +++ b/apparmor.d/groups/systemd/hostnamectl @@ -10,16 +10,13 @@ include profile hostnamectl @{exec_path} { include include - include + include + include include capability net_admin, - #aa:dbus talk bus=system name=org.freedesktop.hostname1 label=systemd-hostnamed - dbus send bus=system path=/org/freedesktop/hostname1 - interface=org.freedesktop.DBus.Properties - member=GetAll - peer=(name=org.freedesktop.hostname1), + #aa:dbus talk bus=system name=org.freedesktop.hostname1 label="@{p_systemd_hostnamed}" @{exec_path} mr, diff --git a/apparmor.d/groups/systemd/journalctl b/apparmor.d/groups/systemd/journalctl index 36fbd9e756..f17da0e624 100644 --- a/apparmor.d/groups/systemd/journalctl +++ b/apparmor.d/groups/systemd/journalctl @@ -20,18 +20,27 @@ profile journalctl @{exec_path} flags=(attach_disconnected) { capability net_admin, capability sys_resource, - signal (receive) set=(term) peer=cockpit-bridge, - signal (send) peer=child-pager, + network netlink raw, + + signal receive set=kill peer=snapd, + signal receive set=term peer=cockpit-bridge, + signal send peer=child-pager, + + ptrace read peer=@{p_systemd}, @{exec_path} mr, @{pager_path} rPx -> child-pager, + @{bin}/* r, + @{sbin}/* r, + /var/lib/dbus/machine-id r, /etc/machine-id r, - /var/lib/systemd/catalog/database rw, + /var/lib/systemd/catalog/ w, /var/lib/systemd/catalog/.#database* rw, + /var/lib/systemd/catalog/database rw, /var/log/dmesg w, diff --git a/apparmor.d/groups/systemd/localectl b/apparmor.d/groups/systemd/localectl index db8e7b21be..9792fb75f9 100644 --- a/apparmor.d/groups/systemd/localectl +++ b/apparmor.d/groups/systemd/localectl @@ -7,12 +7,21 @@ abi , include @{exec_path} = @{bin}/localectl -profile localectl @{exec_path} { +profile localectl @{exec_path} flags=(attach_disconnected) { include include + include capability net_admin, + signal send set=cont peer=child-pager, + + #aa:dbus talk bus=system name=org.freedesktop.locale1 label="@{p_systemd_localed}" + dbus send bus=system path=/org/freedesktop/locale1 + interface=org.freedesktop.DBus.Properties + member=GetAll + peer=(name=org.freedesktop.locale1), + @{exec_path} mr, @{pager_path} rPx -> child-pager, @@ -20,6 +29,8 @@ profile localectl @{exec_path} { /usr/share/kbd/keymaps/{,**} r, + owner @{PROC}/@{pid}/cgroup r, + include if exists } diff --git a/apparmor.d/groups/systemd/loginctl b/apparmor.d/groups/systemd/loginctl index ca43277aa5..2ae4440f7e 100644 --- a/apparmor.d/groups/systemd/loginctl +++ b/apparmor.d/groups/systemd/loginctl @@ -9,22 +9,41 @@ include @{exec_path} = @{bin}/loginctl profile loginctl @{exec_path} flags=(attach_disconnected) { include - include include + include include + include + include capability net_admin, capability sys_resource, signal send set=cont peer=child-pager, - #aa:dbus talk bus=system name=org.freedesktop.login1 label=systemd-logind + #aa:dbus talk bus=system name=org.freedesktop.login1 label="@{p_systemd_logind}" @{exec_path} mr, @{pager_path} rPx -> child-pager, @{bin}/ssh rPx, + /etc/machine-id r, + + @{run}/log/journal/ r, + + owner @{tmp}/xauth_@{rand6} r, + + /var/lib/systemd/catalog/database r, + + /{run,var}/log/journal/ r, + /{run,var}/log/journal/@{hex32}/ r, + /{run,var}/log/journal/@{hex32}/system.journal* r, + /{run,var}/log/journal/@{hex32}/system@@{hex}-@{hex}.journal* r, + /{run,var}/log/journal/@{hex32}/system@@{hex32}-@{hex16}-@{hex16}.journal* r, + /{run,var}/log/journal/@{hex32}/user-@{hex}.journal* r, + /{run,var}/log/journal/@{hex32}/user-@{uid}@@{hex}-@{hex}.journal* r, + /{run,var}/log/journal/@{hex32}/user-@{uid}@@{hex32}-@{hex16}-@{hex16}.journal* r, + @{PROC}/sys/fs/nr_open r, owner @{PROC}/@{pid}/cgroup r, diff --git a/apparmor.d/groups/systemd/machinectl b/apparmor.d/groups/systemd/machinectl new file mode 100644 index 0000000000..6f26a8cea0 --- /dev/null +++ b/apparmor.d/groups/systemd/machinectl @@ -0,0 +1,51 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2021 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/machinectl +profile machinectl @{exec_path} flags=(attach_disconnected) { + include + include + include + include + include + + capability net_admin, + capability sys_ptrace, + capability sys_resource, + + signal send set=(cont term winch) peer=child-pager, + signal send set=(cont term winch) peer=pkttyagent, + signal send set=(cont term winch) peer=systemd-tty-ask-password-agent, + + #aa:dbus talk bus=system name=org.freedesktop.machine1 label=systemd-machined + dbus send bus=system path=/org/freedesktop/machine1 + interface=org.freedesktop.machine1.Manager + peer=(name=org.freedesktop.machine1), + + @{exec_path} mr, + + @{bin}/pkttyagent Px, + @{bin}/systemd-tty-ask-password-agent Px, + @{pager_path} Px -> child-pager, + + /{run,var}/log/journal/ r, + /{run,var}/log/journal/@{hex32}/{,*} r, + + @{run}/systemd/machines/{,**} r, + + @{PROC}/@{pid}/comm r, + + @{PROC}/sys/fs/nr_open r, + owner @{PROC}/@{pid}/cgroup r, + + /dev/pts/ptmx rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd/networkctl b/apparmor.d/groups/systemd/networkctl index 0163f22588..d09f2a1eb5 100644 --- a/apparmor.d/groups/systemd/networkctl +++ b/apparmor.d/groups/systemd/networkctl @@ -11,6 +11,7 @@ include profile networkctl @{exec_path} flags=(attach_disconnected) { include include + include capability net_admin, capability sys_module, @@ -26,7 +27,7 @@ profile networkctl @{exec_path} flags=(attach_disconnected) { unix (bind) type=stream addr=@@{udbus}/bus/networkctl/system, - #aa:dbus talk bus=system name=org.freedesktop.network1 label=systemd-networkd + #aa:dbus talk bus=system name=org.freedesktop.network1 label="@{p_systemd_networkd}" dbus send bus=system path=/org/freedesktop/network1{,/**} interface=org.freedesktop.DBus.Properties member=Get @@ -50,19 +51,21 @@ profile networkctl @{exec_path} flags=(attach_disconnected) { /{run,var}/log/journal/@{hex32}/system.journal* r, /{run,var}/log/journal/@{hex32}/system@@{hex}.journal* r, - @{att}/@{run}/systemd/netif/io.systemd.Network rw, + @{run}/systemd/netif/io.systemd.Network rw, + @{att}@{run}/systemd/netif/io.systemd.Network rw, + @{run}/systemd/netif/links/ r, @{run}/systemd/netif/leases/@{int} r, @{run}/systemd/netif/links/@{int} r, @{run}/systemd/netif/state r, - @{run}/systemd/notify w, - @{run}/udev/data/n@{int} r, + @{run}/udev/data/n@{int} r, # For network interfaces @{sys}/devices/**/net/**/uevent r, @{PROC}/1/cgroup r, @{PROC}/cmdline r, + @{PROC}/sys/fs/nr_open r, @{PROC}/sys/kernel/osrelease r, @{PROC}/sys/kernel/random/boot_id r, owner @{PROC}/@{pid}/cgroup r, diff --git a/apparmor.d/groups/systemd/oomctl b/apparmor.d/groups/systemd/oomctl new file mode 100644 index 0000000000..473cacc948 --- /dev/null +++ b/apparmor.d/groups/systemd/oomctl @@ -0,0 +1,28 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2021 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/oomctl +profile oomctl @{exec_path} { + include + include + include + + signal send set=cont peer=child-pager, + + #aa:dbus talk bus=system name=org.freedesktop.oom1 label="@{p_systemd_oomd}" + + @{exec_path} mr, + + @{pager_path} rPx -> child-pager, + + owner @{PROC}/@{pid}/cgroup r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd/resolvectl b/apparmor.d/groups/systemd/resolvectl index dc3090c5a1..51d26559cf 100644 --- a/apparmor.d/groups/systemd/resolvectl +++ b/apparmor.d/groups/systemd/resolvectl @@ -7,13 +7,30 @@ abi , include @{exec_path} = @{bin}/resolvectl -profile resolvectl @{exec_path} { +profile resolvectl @{exec_path} flags=(attach_disconnected) { include - include include include + include + + capability net_admin, + + network inet raw, + network inet stream, + network inet6 raw, + network inet6 stream, + network netlink raw, + + signal send set=cont peer=child-pager, + + unix bind type=stream addr=@@{udbus}/bus/resolvconf/system, + + #aa:dbus talk bus=system name=org.freedesktop.resolve1 label="@{p_systemd_resolved}" - #aa:dbus talk bus=system name=org.freedesktop.resolve1 label=systemd-resolved + #aa:dbus talk bus=system name=org.freedesktop.network1 label="@{p_systemd_networkd}" + dbus send bus=system path=/org/freedesktop/network1 + interface=org.freedesktop.network1.Manager + peer=(name=org.freedesktop.network1), @{exec_path} mr, diff --git a/apparmor.d/groups/systemd/systemd-ac-power b/apparmor.d/groups/systemd/systemd-ac-power index 1353547f00..90b9e66db5 100644 --- a/apparmor.d/groups/systemd/systemd-ac-power +++ b/apparmor.d/groups/systemd/systemd-ac-power @@ -10,16 +10,12 @@ include @{exec_path} = @{lib}/systemd/systemd-ac-power profile systemd-ac-power @{exec_path} { include + include @{exec_path} mr, owner @{PROC}/@{pid}/stat r, - @{sys}/class/power_supply/ r, - - @{sys}/devices/**/power_supply/{AC,BAT@{int}}/ r, - @{sys}/devices/**/power_supply/{AC,BAT@{int}}/{type,online} r, - include if exists } diff --git a/apparmor.d/groups/systemd/systemd-analyze b/apparmor.d/groups/systemd/systemd-analyze index 7310586e87..8cda520548 100644 --- a/apparmor.d/groups/systemd/systemd-analyze +++ b/apparmor.d/groups/systemd/systemd-analyze @@ -8,11 +8,12 @@ abi , include @{exec_path} = @{bin}/systemd-analyze -profile systemd-analyze @{exec_path} { +profile systemd-analyze @{exec_path} flags=(attach_disconnected) { include include - include + include include + include capability sys_resource, capability net_admin, @@ -22,6 +23,7 @@ profile systemd-analyze @{exec_path} { signal (send) peer=child-pager, + unix bind type=stream addr=@@{udbus}/bus/systemd-analyze/, unix bind type=stream addr=@@{udbus}/bus/systemd-analyze/system, #aa:dbus talk bus=system name=org.freedesktop.systemd1 label="@{p_systemd}" @@ -42,12 +44,15 @@ profile systemd-analyze @{exec_path} { owner @{tmp}/systemd-temporary-*/ rw, + @{att}@{run}/systemd/private rw, + @{run}/systemd/generator/ r, @{run}/systemd/private rw, @{run}/systemd/system/ r, @{run}/systemd/transient/ r, @{run}/systemd/userdb/io.systemd.DynamicUser w, - @{run}/udev/data/* r, + @{run}/udev/data/+*:* r, # Identifies all subsystems + @{run}/udev/data/c@{int}:@{int} r, # Identifies all character devices @{run}/udev/tags/systemd/ r, @{sys}/devices/**/uevent r, diff --git a/apparmor.d/groups/systemd/systemd-backlight b/apparmor.d/groups/systemd/systemd-backlight index 374e9c4ae0..8e4b96f23a 100644 --- a/apparmor.d/groups/systemd/systemd-backlight +++ b/apparmor.d/groups/systemd/systemd-backlight @@ -10,37 +10,24 @@ include @{exec_path} = @{lib}/systemd/systemd-backlight profile systemd-backlight @{exec_path} flags=(attach_disconnected) { include + include include + ptrace read peer=@{p_systemd}, + capability net_admin, @{exec_path} mr, /var/lib/systemd/backlight/*backlight* rw, - @{run}/udev/data/+backlight:* r, - @{run}/udev/data/+leds:*backlight* r, @{run}/udev/data/+pci:* r, # Identifies all PCI devices (CPU, GPU, Network, Disks, USB, etc.) @{sys}/bus/ r, @{sys}/bus/pci/devices/ r, - @{sys}/class/ r, - @{sys}/class/backlight/ r, @{sys}/devices/@{pci}/ r, - @{sys}/devices/@{pci}/*_backlight/{,max_,actual_}brightness rw, - @{sys}/devices/@{pci}/*_backlight/{uevent,type,enabled} r, - @{sys}/devices/@{pci}/backlight/**/{,max_,actual_}brightness rw, - @{sys}/devices/@{pci}/backlight/**/{uevent,type,enabled} r, - @{sys}/devices/@{pci}/backlight/**/brightness rw, @{sys}/devices/@{pci}/class r, - @{sys}/devices/@{pci}/drm/card@{int}/**/{,max_,actual_}brightness rw, - @{sys}/devices/@{pci}/drm/card@{int}/**/{uevent,type,enabled} r, - @{sys}/devices/@{pci}/drm/card@{int}/**/brightness rw, - @{sys}/devices/@{pci}/uevent r, - @{sys}/devices/**/leds/**/{,max_,actual_}brightness rw, - @{sys}/devices/**/leds/**/{uevent,type,enabled} r, - @{sys}/devices/**/leds/**/brightness_hw_changed r, include if exists } diff --git a/apparmor.d/groups/systemd/systemd-binfmt b/apparmor.d/groups/systemd/systemd-binfmt index d34bbe4cb0..bceba07260 100644 --- a/apparmor.d/groups/systemd/systemd-binfmt +++ b/apparmor.d/groups/systemd/systemd-binfmt @@ -13,20 +13,23 @@ profile systemd-binfmt @{exec_path} flags=(attach_disconnected) { capability net_admin, + ptrace read peer=@{p_systemd}, + @{exec_path} mr, @{bin}/* r, + @{sbin}/* r, # Config file locations /etc/binfmt.d/{,*.conf} r, @{run}/binfmt.d/{,*.conf} r, - /usr/lib/binfmt.d/{,*.conf} r, + @{lib}/binfmt.d/{,*.conf} r, @{PROC}/sys/fs/binfmt_misc/register w, @{PROC}/sys/fs/binfmt_misc/status w, - /dev/tty@{int} rw, - /dev/pts/@{int} rw, + /dev/tty@{u8} rw, + /dev/pts/@{u16} rw, include if exists } diff --git a/apparmor.d/groups/systemd/systemd-bless-boot b/apparmor.d/groups/systemd/systemd-bless-boot new file mode 100644 index 0000000000..30783c8982 --- /dev/null +++ b/apparmor.d/groups/systemd/systemd-bless-boot @@ -0,0 +1,28 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/systemd/systemd-bless-boot +profile systemd-bless-boot @{exec_path} flags=(attach_disconnected) { + include + include + include + + capability net_admin, + + @{exec_path} mr, + + @{efi}/ r, + @{efi}/EFI/Linux/ r, + @{efi}/EFI/Linux/*.efi rw, + + @{sys}/firmware@{efi}/efivars/LoaderBootCountPath-@{uuid} r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd/systemd-cat b/apparmor.d/groups/systemd/systemd-cat index fd202c1814..14ba03d6d3 100644 --- a/apparmor.d/groups/systemd/systemd-cat +++ b/apparmor.d/groups/systemd/systemd-cat @@ -7,7 +7,7 @@ abi , include @{exec_path} = @{bin}/systemd-cat -profile systemd-cat @{exec_path} { +profile systemd-cat @{exec_path} flags=(attach_disconnected) { include include include @@ -16,6 +16,8 @@ profile systemd-cat @{exec_path} { @{exec_path} mr, + @{bin}/echo ix, + include if exists } diff --git a/apparmor.d/groups/systemd/systemd-cgls b/apparmor.d/groups/systemd/systemd-cgls index 33191171eb..92ebb580a3 100644 --- a/apparmor.d/groups/systemd/systemd-cgls +++ b/apparmor.d/groups/systemd/systemd-cgls @@ -10,7 +10,7 @@ include profile systemd-cgls @{exec_path} { include include - include + include include capability sys_ptrace, diff --git a/apparmor.d/groups/systemd/systemd-coredump b/apparmor.d/groups/systemd/systemd-coredump index 52efea3dba..3c79ad324e 100644 --- a/apparmor.d/groups/systemd/systemd-coredump +++ b/apparmor.d/groups/systemd/systemd-coredump @@ -7,16 +7,18 @@ abi , include -@{exec_path} = @{lib}/systemd/systemd-coredump +@{exec_path} = @{lib}/systemd/systemd-coredump profile systemd-coredump @{exec_path} flags=(attach_disconnected,mediate_deleted) { include - include + include include + include userns, capability dac_override, capability dac_read_search, + capability kill, capability net_admin, capability setgid, capability setpcap, @@ -33,29 +35,43 @@ profile systemd-coredump @{exec_path} flags=(attach_disconnected,mediate_deleted @{lib}/** r, / r, @{bin}/* r, + @{sbin}/* r, /opt/** r, + /usr/share/*/** r, @{user_lib_dirs}/** r, + /snap/*/@{int}/bin/** r, + /snap/*/@{int}/opt/** r, + /snap/*/@{int}/usr/** r, + @{att}/ r, /etc/systemd/coredump.conf r, /etc/systemd/coredump.conf.d/{,**} r, - owner @{HOME}/**.so r, + owner @{HOME}/**.so* r, + owner @{HOME}/.var/app/*/** r, # Crash from flatpak apps /var/lib/systemd/coredump/{,**} rwl, - @{att}/@{run}/systemd/coredump rw, - @{run}/systemd/coredump rw, + owner @{run}/user/@{uid}/snap.*/.org.chromium.Chromium.@{rand6} r, + + @{run}/systemd/coredump rw, + @{att}@{run}/systemd/coredump rw, + @{PROC}/@{pids}/auxv r, @{PROC}/@{pids}/cgroup r, @{PROC}/@{pids}/cmdline r, @{PROC}/@{pids}/comm r, @{PROC}/@{pids}/environ r, @{PROC}/@{pids}/fd/ r, @{PROC}/@{pids}/fdinfo/@{int} r, + @{PROC}/@{pids}/gid_map r, @{PROC}/@{pids}/limits r, + @{PROC}/@{pids}/maps r, @{PROC}/@{pids}/mountinfo r, @{PROC}/@{pids}/ns/ r, @{PROC}/@{pids}/stat r, + @{PROC}/@{pids}/status r, + @{PROC}/sys/kernel/core_pattern w, owner @{PROC}/@{pid}/setgroups r, include if exists diff --git a/apparmor.d/groups/systemd/systemd-cryptsetup b/apparmor.d/groups/systemd/systemd-cryptsetup index fdddebe03f..790cd10bb6 100644 --- a/apparmor.d/groups/systemd/systemd-cryptsetup +++ b/apparmor.d/groups/systemd/systemd-cryptsetup @@ -10,13 +10,17 @@ include profile systemd-cryptsetup @{exec_path} flags=(attach_disconnected) { include include + include include + include capability dac_read_search, capability ipc_lock, capability net_admin, capability sys_admin, + ptrace read peer=@{p_systemd}, + @{exec_path} mr, /etc/fstab r, @@ -32,6 +36,9 @@ profile systemd-cryptsetup @{exec_path} flags=(attach_disconnected) { @{sys}/fs/ r, @{run}/systemd/ask-password/ r, + @{run}/systemd/tpm2-pcr-signature.json r, + + @{sys}/firmware@{efi}/efivars/LoaderTpm2ActivePcrBanks-@{uuid} r, @{PROC}/devices r, owner @{PROC}/@{pid}/mountinfo r, diff --git a/apparmor.d/groups/systemd/systemd-delta b/apparmor.d/groups/systemd/systemd-delta index 7cf546a563..311636d955 100644 --- a/apparmor.d/groups/systemd/systemd-delta +++ b/apparmor.d/groups/systemd/systemd-delta @@ -10,11 +10,11 @@ include profile systemd-delta @{exec_path} { include - signal (send) peer=child-pager, + signal send peer=child-pager, @{exec_path} mr, - @{bin}/less rPx -> child-pager, + @{pager_path} rPx -> child-pager, /etc/binfmt.d/{,**} r, /etc/modprobe.d/{,**} r, diff --git a/apparmor.d/groups/systemd/systemd-detect-virt b/apparmor.d/groups/systemd/systemd-detect-virt index 35f4afbc44..42a5918880 100644 --- a/apparmor.d/groups/systemd/systemd-detect-virt +++ b/apparmor.d/groups/systemd/systemd-detect-virt @@ -11,24 +11,37 @@ include profile systemd-detect-virt @{exec_path} flags=(attach_disconnected) { include include - include + include - capability net_admin, + capability sys_ptrace, - network netlink raw, + ptrace read peer=@{p_systemd}, @{exec_path} mr, @{run}/cloud-init/ds-identify.log w, @{run}/host/container-manager r, - @{run}/systemd/notify w, + @{run}/systemd/container r, - @{sys}/devices/virtual/dmi/id/bios_vendor r, - @{sys}/devices/virtual/dmi/id/board_vendor r, - @{sys}/devices/virtual/dmi/id/product_name r, @{sys}/devices/virtual/dmi/id/product_version r, - @{sys}/devices/virtual/dmi/id/sys_vendor r, @{sys}/firmware/dmi/entries/*/raw r, + @{sys}/firmware/uv/prot_virt_guest r, + @{sys}/hypervisor/properties/features r, + @{sys}/hypervisor/type r, + + @{PROC}/1/environ r, + @{PROC}/device-tree/ r, + @{PROC}/device-tree/compatible r, + @{PROC}/device-tree/hypervisor/compatible r, + @{PROC}/sys/kernel/osrelease r, + @{PROC}/sysinfo r, + @{PROC}/xen/capabilities r, + + /dev/cpu/@{int}/msr r, + + deny capability net_admin, + deny capability perfmon, + deny network (send receive) netlink raw, include if exists } diff --git a/apparmor.d/groups/systemd/systemd-dissect b/apparmor.d/groups/systemd/systemd-dissect index 7dc10fd46b..b152a5c543 100644 --- a/apparmor.d/groups/systemd/systemd-dissect +++ b/apparmor.d/groups/systemd/systemd-dissect @@ -19,19 +19,19 @@ profile systemd-dissect @{exec_path} flags=(attach_disconnected) { mount -> /tmp/dissect-@{rand6}/, mount fstype=tmpfs options=(rw nodev) rootfs -> @{run}/systemd/dissect-root/, - mount options=(ro nodev) /dev/loop* -> @{run}/systemd/dissect-root/{,**/}, + mount options=(ro nodev) @{att}/dev/loop* -> @{run}/systemd/dissect-root/{,**/}, mount options=(rw nodev) -> /mnt/*/, - mount options=(rw rshared rslave) -> /, + mount options=(rw rshared make-rslave) /, umount @{run}/systemd/dissect-root/, signal send set=cont peer=child-pager, - ptrace read peer=unconfined, + ptrace read peer=@{p_systemd}, @{exec_path} mr, - @{bin}/fsck rPx, + @{sbin}/fsck rPx, @{pager_path} rPx -> child-pager, # Location of file system OS images @@ -51,9 +51,11 @@ profile systemd-dissect @{exec_path} flags=(attach_disconnected) { @{PROC}/@{pid}/cgroup r, @{PROC}/@{pid}/mountinfo r, + /dev/loop* rwk, + @{att}/dev/loop* wk, + /dev/btrfs-control rw, /dev/loop-control rwk, - /dev/loop* rwk, /dev/mapper/control w, include if exists diff --git a/apparmor.d/groups/systemd/systemd-fsck b/apparmor.d/groups/systemd/systemd-fsck index 0680e0be8e..6f35db3aca 100644 --- a/apparmor.d/groups/systemd/systemd-fsck +++ b/apparmor.d/groups/systemd/systemd-fsck @@ -17,11 +17,13 @@ profile systemd-fsck @{exec_path} flags=(attach_disconnected) { capability net_admin, capability sys_resource, + ptrace read peer=@{p_systemd}, + @{exec_path} mr, - @{bin}/e2fsck rPx, - @{bin}/fsck rPx, - @{bin}/fsck.* rPx, + @{sbin}/e2fsck rPx, + @{sbin}/fsck rPx, + @{sbin}/fsck.* rPx, owner @{run}/systemd/quotacheck w, owner @{run}/systemd/fsck.progress rw, diff --git a/apparmor.d/groups/systemd/systemd-fsckd b/apparmor.d/groups/systemd/systemd-fsckd index 33a433a09c..ea7170b6b5 100644 --- a/apparmor.d/groups/systemd/systemd-fsckd +++ b/apparmor.d/groups/systemd/systemd-fsckd @@ -8,7 +8,7 @@ abi , include @{exec_path} = @{lib}/systemd/systemd-fsckd -profile systemd-fsckd @{exec_path} { +profile systemd-fsckd @{exec_path} flags=(attach_disconnected) { include include include @@ -16,6 +16,8 @@ profile systemd-fsckd @{exec_path} { capability net_admin, capability sys_tty_config, + unix type=stream peer=(addr=@/org/freedesktop/plymouthd), + @{exec_path} mr, @{run}/systemd/fsck.progress rw, diff --git a/apparmor.d/groups/systemd/systemd-generator-gpt-auto b/apparmor.d/groups/systemd/systemd-generator-gpt-auto deleted file mode 100644 index 0d6c09c6b2..0000000000 --- a/apparmor.d/groups/systemd/systemd-generator-gpt-auto +++ /dev/null @@ -1,35 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - -abi , - -include - -@{exec_path} = @{lib}/systemd/system-generators/systemd-gpt-auto-generator -profile systemd-generator-gpt-auto @{exec_path} flags=(attach_disconnected) { - include - include - include - - capability sys_admin, - - @{exec_path} mr, - - / r, - /boot/ r, - /efi/ r, - /etc/fstab r, - /usr/ r, - - @{run}/systemd/generator.late/**.{,auto}mount w, - @{run}/systemd/generator.late/local-fs.target.wants/ w, - - @{sys}/firmware/efi/efivars/LoaderDevicePartUUID-@{uuid} r, - - @{PROC}/@{pid}/cgroup r, - - include if exists -} - -# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd/systemd-homed b/apparmor.d/groups/systemd/systemd-homed index a248581253..8dca66adce 100644 --- a/apparmor.d/groups/systemd/systemd-homed +++ b/apparmor.d/groups/systemd/systemd-homed @@ -14,6 +14,8 @@ profile systemd-homed @{exec_path} flags=(attach_disconnected) { include include + userns, + capability chown, capability dac_override, capability dac_read_search, @@ -24,6 +26,7 @@ profile systemd-homed @{exec_path} flags=(attach_disconnected) { capability setpcap, capability setuid, capability sys_admin, + capability sys_ptrace, capability sys_resource, network inet dgram, @@ -32,58 +35,95 @@ profile systemd-homed @{exec_path} flags=(attach_disconnected) { network inet6 raw, network netlink raw, - mount options=(rw, rslave) -> @{run}/, - mount /dev/dm-@{int} -> @{run}/systemd/user-home-mount/, + mount -> @{run}/systemd/user-home-mount/, + mount options=(rw bind) @{run}/systemd/user-home-mount/@{user}/ -> @{HOME}/, + mount options=(rw make-rslave) @{run}/, + mount options=(rw move) -> @{run}/systemd/user-home-mount/@{user}/, + mount options=(rw private) -> @{run}/systemd/user-home-mount/, + + umount @{HOME}/, + umount @{run}/systemd/user-home-mount/, + umount @{run}/systemd/user-home-mount/@{user}/, + + signal (send receive) set=kill peer=systemd-homed//&systemd-homework, + + ptrace read peer=systemd-homed//&systemd-homework, + unix bind type=dgram addr=@@{udbus}, unix bind type=stream addr=@@{udbus}/bus/systemd-homed/system, + unix receive type=dgram addr=@@{int}@{int} peer=(label=systemd-homework), #aa:dbus own bus=system name=org.freedesktop.home1 + #aa:dbus talk bus=system name=org.freedesktop.PolicyKit1 label=polkitd @{exec_path} mr, - @{lib}/systemd/systemd-homework rPx -> systemd-homed//&systemd-homework, - @{bin}/mkfs.btrfs rPx, - @{bin}/mkfs.fat rPx, - @{bin}/mke2fs rPx, + @{lib}/systemd/systemd-homework Px -> systemd-homed//&systemd-homework, + @{sbin}/mkfs.fat Px, + @{sbin}/mke2fs Px, + # nnp + @{sbin}/fsck ix, + @{sbin}/fsck.* rix, + @{bin}/mkfs.* ix, + + /etc/fstab r, /etc/machine-id r, - /etc/systemd/homed.conf r, + /etc/security/pwquality.conf r, + /etc/security/pwquality.conf.d/{,**} r, /etc/skel/{,**} r, + /etc/systemd/homed.conf r, /var/cache/systemd/home/{,**} rw, /var/lib/systemd/home/{,**} rw, + @{att}/ r, + @{att}/@{HOMEDIRS}/@{user}.home rw, + / r, @{HOMEDIRS}/ r, @{HOMEDIRS}/* rw, @{HOMEDIRS}/*.homedir/ rw, + @{HOMEDIRS}/@{user}.home k, + + @{HOME}/ rw, + @{HOME}/.#.identity-blob@{hex16}/ rw, + @{HOME}/.#.identity@{hex16} rw, + @{HOME}/.identity rw, + @{HOME}/.identity-blob/ w, @{run}/ r, @{run}/cryptsetup/{,*} rwk, @{run}/systemd/home/{,**} rw, @{run}/systemd/userdb/io.systemd.home r, @{run}/systemd/user-home-mount/{,**} rw, - @{run}/systemd/notify w, @{sys}/bus/ r, - @{sys}/fs/ r, @{sys}/class/ r, - @{sys}/kernel/uevent_seqnum r, @{sys}/devices/**/read_ahead_kb r, + @{sys}/devices/**/uevent r, + @{sys}/fs/ r, + @{sys}/kernel/uevent_seqnum r, @{PROC}/@{pid}/cgroup r, + @{PROC}/@{pid}/setgroups w, @{PROC}/devices r, @{PROC}/pressure/* r, + @{PROC}/swaps r, + @{PROC}/sys/fs/nr_open r, @{PROC}/sysvipc/{shm,sem,msg} r, owner @{PROC}/@{pid}/gid_map w, owner @{PROC}/@{pid}/mountinfo r, + owner @{PROC}/@{pid}/mounts r, owner @{PROC}/@{pid}/uid_map w, + @{att}/dev/loop@{int} rw, + /dev/btrfs-control rw, /dev/loop-control rwk, - /dev/loop@{int} rw, /dev/mapper/control rw, /dev/mqueue/ r, /dev/shm/ r, + /dev/tty rw, include if exists } diff --git a/apparmor.d/groups/systemd/systemd-homework b/apparmor.d/groups/systemd/systemd-homework index f0fe98a168..d8bbdc6526 100644 --- a/apparmor.d/groups/systemd/systemd-homework +++ b/apparmor.d/groups/systemd/systemd-homework @@ -7,14 +7,83 @@ abi , include @{exec_path} = @{lib}/systemd/systemd-homework -profile systemd-homework @{exec_path} { +profile systemd-homework @{exec_path} flags=(attach_disconnected) { include - include include + include + include + + userns, + + capability chown, + capability dac_read_search, + capability fowner, + capability fsetid, + capability setfcap, + capability setgid, + capability setuid, + capability sys_admin, + capability sys_ptrace, + capability sys_resource, + + network netlink raw, + + mount -> @{run}/systemd/user-home-mount/, + mount options=(rw bind) @{run}/systemd/user-home-mount/@{user}/ -> @{HOME}/, + mount options=(rw make-rslave) @{run}/, + mount options=(rw move) -> @{run}/systemd/user-home-mount/@{user}/, + + umount @{run}/systemd/user-home-mount/, + umount @{run}/systemd/user-home-mount/@{user}/, + + unix send type=dgram peer=(label=systemd-homed), + + signal (send receive) set=kill peer=systemd-homed//&systemd-homework, + + ptrace read peer=systemd-homed//&systemd-homework, @{exec_path} mr, + @{sbin}/fsck rix, # no new privs + @{sbin}/fsck.* rix, + @{sbin}/mke2fs rPx, + @{sbin}/mkfs.btrfs rPx, + @{sbin}/mkfs.fat rPx, + /etc/machine-id r, + /etc/skel/{,**} r, + /etc/fstab r, + + /var/cache/systemd/home/{,**} rw, + + @{HOMEDIRS}/ r, + @{HOMEDIRS}/.#homework@{user}.* rw, + @{HOMEDIRS}/@{user}.home rwk, + + @{HOME}/ r, + @{HOME}/.identity r, + + @{run}/ r, + @{run}/cryptsetup/ r, + @{run}/cryptsetup/* rwk, + @{run}/systemd/user-home-mount/ rw, + @{run}/systemd/user-home-mount/@{user}/{,**} rw, + + @{sys}/fs/ r, + @{sys}/devices/**/read_ahead_kb r, + + @{PROC}/@{pid}/setgroups w, + @{PROC}/devices r, + @{PROC}/swaps r, + @{PROC}/sys/fs/nr_open r, + owner @{PROC}/@{pid}/gid_map w, + owner @{PROC}/@{pid}/mountinfo r, + owner @{PROC}/@{pid}/mounts r, + owner @{PROC}/@{pid}/uid_map w, + + /dev/loop-control rwk, + /dev/loop@{int} rw, + /dev/mapper/control rw, include if exists } diff --git a/apparmor.d/groups/systemd/systemd-hostnamed b/apparmor.d/groups/systemd/systemd-hostnamed index 01d04989b8..4675b2f7d2 100644 --- a/apparmor.d/groups/systemd/systemd-hostnamed +++ b/apparmor.d/groups/systemd/systemd-hostnamed @@ -11,8 +11,9 @@ include profile systemd-hostnamed @{exec_path} flags=(attach_disconnected) { include include - include + include include + include capability sys_admin, # To set a hostname @@ -32,20 +33,9 @@ profile systemd-hostnamed @{exec_path} flags=(attach_disconnected) { /etc/machine-info rw, /etc/os-release r, - @{att}/@{run}/systemd/notify rw, - @{run}/systemd/default-hostname rw, @{run}/udev/data/+dmi:* r, # for motherboard info - @{sys}/devices/virtual/dmi/id/ r, - @{sys}/devices/virtual/dmi/id/bios_date r, - @{sys}/devices/virtual/dmi/id/bios_vendor r, - @{sys}/devices/virtual/dmi/id/bios_version r, - @{sys}/devices/virtual/dmi/id/board_vendor r, - @{sys}/devices/virtual/dmi/id/chassis_type r, - @{sys}/devices/virtual/dmi/id/product_name r, - @{sys}/devices/virtual/dmi/id/product_version r, - @{sys}/devices/virtual/dmi/id/sys_vendor r, @{sys}/devices/virtual/dmi/id/uevent r, @{sys}/firmware/acpi/pm_profile r, @{sys}/firmware/dmi/entries/*/raw r, diff --git a/apparmor.d/groups/systemd/systemd-hwdb b/apparmor.d/groups/systemd/systemd-hwdb index ae64274c6e..a0a48869a0 100644 --- a/apparmor.d/groups/systemd/systemd-hwdb +++ b/apparmor.d/groups/systemd/systemd-hwdb @@ -12,17 +12,20 @@ profile systemd-hwdb @{exec_path} flags=(attach_disconnected,mediate_deleted) { include capability dac_override, + capability net_admin, @{exec_path} mr, @{lib}/udev/#@{int} rwl, @{lib}/udev/.#hwdb.bin{@{hex16},@{rand6}} wl -> @{lib}/udev/#@{int}, - @{lib}/udev/hwdb.bin w, + @{lib}/udev/hwdb.bin wl -> @{lib}/udev/#@{int}, /etc/udev/.#hwdb.bin{@{hex16},@{rand6}} wl -> /etc/udev/#@{int}, - /etc/udev/hwdb.bin w, + /etc/udev/hwdb.bin wl -> @{lib}/udev/#@{int}, /etc/udev/hwdb.d/{,*} r, + / r, + owner @{PROC}/@{pid}/stat r, include if exists diff --git a/apparmor.d/groups/systemd/systemd-importd b/apparmor.d/groups/systemd/systemd-importd new file mode 100644 index 0000000000..d8bc412a1c --- /dev/null +++ b/apparmor.d/groups/systemd/systemd-importd @@ -0,0 +1,75 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/systemd/systemd-importd +profile systemd-importd @{exec_path} flags=(attach_disconnected) { + include + include + include + include + + capability chown, + capability fowner, + capability fsetid, + capability mknod, + capability setfcap, + capability sys_admin, + capability setpcap, + capability dac_override, + capability linux_immutable, + + network inet stream, + network inet6 stream, + network inet dgram, + network inet6 dgram, + network netlink raw, + + #aa:dbus own bus=system name=org.freedesktop.import1 + + @{exec_path} mr, + + @{bin}/gpg ix, + @{bin}/tar ix, + @{lib}/systemd/systemd-import ix, + @{lib}/systemd/systemd-pull ix, + + @{lib}/systemd/import-pubring.gpg r, + /etc/systemd/import-pubring.gpg r, + + /var/lib/ r, + /var/lib/confexts/ rw, + /var/lib/confexts/** rwlk -> /var/lib/confexts/**, + /var/lib/extensions/ rw, + /var/lib/extensions/** rwlk -> /var/lib/extensions/**, + /var/lib/machines/ rw, + /var/lib/machines/** rwlk -> /var/lib/machines/**, + /var/lib/portables/ rw, + /var/lib/portables/** rwlk -> /var/lib/portables/**, + + owner @{run}/systemd/import/ w, + owner @{run}/systemd/import/notify w, + + /tmp/gpghome@{rand6}/ rw, + /tmp/sig@{rand6} rw, + + @{run}/dbus/system_bus_socket rw, + @{run}/systemd/import/notify r, + + @{sys}/fs/cgroup/system.slice/systemd-importd.service/memory.pressure rw, + + @{PROC}/@{pid}/fd/ r, + @{PROC}/@{pid}/fdinfo/@{int} r, + @{PROC}/1/environ r, + @{PROC}/cmdline r, + @{PROC}/sys/kernel/osrelease r, + @{PROC}/sys/kernel/random/boot_id r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd/systemd-inhibit b/apparmor.d/groups/systemd/systemd-inhibit index 2be38e6ba3..d5b12d462a 100644 --- a/apparmor.d/groups/systemd/systemd-inhibit +++ b/apparmor.d/groups/systemd/systemd-inhibit @@ -14,13 +14,13 @@ profile systemd-inhibit @{exec_path} flags=(attach_disconnected) { capability net_admin, capability sys_resource, - signal receive set=term peer=packagekitd, + signal receive set=term peer=@{p_packagekitd}, @{exec_path} mr, @{bin}/cat rix, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, include if exists } diff --git a/apparmor.d/groups/systemd/systemd-initctl b/apparmor.d/groups/systemd/systemd-initctl new file mode 100644 index 0000000000..035d3d6df4 --- /dev/null +++ b/apparmor.d/groups/systemd/systemd-initctl @@ -0,0 +1,26 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/systemd/systemd-initctl +profile systemd-initctl @{exec_path} flags=(attach_disconnected) { + include + include + include + + capability net_admin, + + unix type=stream addr=@@{udbus}/bus/systemd-initctl/, + + @{exec_path} mr, + + @{run}/initctl rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd/systemd-journald b/apparmor.d/groups/systemd/systemd-journald index b0a646f668..8ef89886a1 100644 --- a/apparmor.d/groups/systemd/systemd-journald +++ b/apparmor.d/groups/systemd/systemd-journald @@ -28,42 +28,46 @@ profile systemd-journald @{exec_path} flags=(attach_disconnected,mediate_deleted network netlink raw, - ptrace (read), + ptrace read, @{exec_path} mr, /etc/systemd/journald.conf r, /etc/systemd/journald.conf.d/{,**} r, - @{run}/log/ rw, + /{run,var}/log/ w, /{run,var}/log/journal/ rw, /{run,var}/log/journal/@{hex32}/ rw, /{run,var}/log/journal/@{hex32}/* rwl -> /{run,var}/log/journal/@{hex32}/#@{int}, owner @{run}/systemd/journal/{,**} rw, - owner @{run}/systemd/notify rw, @{run}/host/container-manager r, + @{run}/systemd/units/log-*.service r, @{run}/utmp rk, - @{run}/udev/data/+acpi:* r, - @{run}/udev/data/+bluetooth:* r, - @{run}/udev/data/+hid:* r, # for HID-Compliant Keyboard - @{run}/udev/data/+ieee80211:* r, + @{run}/udev/data/+acpi:* r, # Exposes ACPI objects (power buttons, batteries, thermal) + @{run}/udev/data/+bluetooth:* r, # For bluetooth adapters, controllers, and active connections. + @{run}/udev/data/+hdaudio:* r, # For High Definition Audio devices, such as sound cards and audio interfaces. + @{run}/udev/data/+hid:* r, # For Human Interface Device (mice, controllers, drawing tablets, scanners) + @{run}/udev/data/+i2c:* r, # For Inter-Integrated Circuit, low-speed peripherals (sensors, EEPROMs, etc.) + @{run}/udev/data/+ieee80211:* r, # For Wi-Fi devices, such as wireless network cards and access points. @{run}/udev/data/+input:input@{int} r, # for mouse, keyboard, touchpad - @{run}/udev/data/+mdio_bus:* r, - @{run}/udev/data/+pci:* r, - @{run}/udev/data/+platform:* r, - @{run}/udev/data/+scsi:* r, - @{run}/udev/data/+sdio:* r, - @{run}/udev/data/+thunderbolt:* r, - @{run}/udev/data/+usb-serial:* r, - @{run}/udev/data/+usb:* r, - @{run}/udev/data/+virtio:* r, + @{run}/udev/data/+mdio_bus:* r, # For Management Data Input/Output (Ethernet PHY (physical layer) devices) + @{run}/udev/data/+pci:* r, # Identifies all PCI devices (CPU, GPU, Network, Disks, USB, etc.) + @{run}/udev/data/+platform:* r, # Identifies onboard devices (laptop/board model, power controllers, thermal sensors) + @{run}/udev/data/+scsi:* r, # For SCSI devices. Block-storage for SATA, SAS, USB, iSCSI + @{run}/udev/data/+sdio:* r, # For Secure Digital Input Output devices, such as Wi-Fi, Bluetooth cards, GPS and NFC modules. + @{run}/udev/data/+thunderbolt:* r, # For Thunderbolt devices, such as docks, external GPUs, and storage devices. + @{run}/udev/data/+usb-serial:* r, # For USB to serial adapters + @{run}/udev/data/+usb:* r, # Identifies all USB devices + @{run}/udev/data/+virtio:* r, # For paravirtualized devices (network interfaces, block devices, console) + @{run}/udev/data/b43:@{int} r, # for /dev/nbd* @{run}/udev/data/b254:@{int} r, # for /dev/zram* @{run}/udev/data/b259:@{int} r, # Block Extended Major @{run}/udev/data/c1:@{int} r, # For RAM disk @{run}/udev/data/c4:@{int} r, # For TTY devices + @{run}/udev/data/c7:@{int} r, # For Virtual console capture devices @{run}/udev/data/b8:@{int} r, # for /dev/sd* @{run}/udev/data/c10:@{int} r, # For non-serial mice, misc features @{run}/udev/data/c108:@{int} r, # For /dev/ppp @@ -82,6 +86,7 @@ profile systemd-journald @{exec_path} flags=(attach_disconnected,mediate_deleted @{PROC}/@{pids}/comm r, @{PROC}/@{pids}/loginuid r, @{PROC}/@{pids}/sessionid r, + @{PROC}/@{pids}/status r, @{PROC}/pressure/* r, @{PROC}/sys/kernel/hostname r, diff --git a/apparmor.d/groups/systemd/systemd-localed b/apparmor.d/groups/systemd/systemd-localed index 205d8a55fc..640d61c254 100644 --- a/apparmor.d/groups/systemd/systemd-localed +++ b/apparmor.d/groups/systemd/systemd-localed @@ -14,29 +14,45 @@ profile systemd-localed @{exec_path} flags=(attach_disconnected) { include include - unix (bind) type=stream addr=@@{udbus}/bus/systemd-localed/system, + unix bind type=stream addr=@@{udbus}/bus/systemd-localed/system, #aa:dbus own bus=system name=org.freedesktop.locale1 + dbus send bus=system path=/org/freedesktop/systemd1 + interface=org.freedesktop.systemd1.Manager + member={Reload,RestartUnit} + peer=(name=org.freedesktop.systemd1, label="@{p_systemd}"), @{exec_path} mr, + @{bin}/cat ix, + @{bin}/gzip ix, + @{bin}/localedef ix, + @{bin}/rm ix, + @{bin}/sort ix, + @{sbin}/locale-gen Px -> systemd-localed//&locale-gen, + + /usr/share/i18n/{,**} r, /usr/share/kbd/keymaps/{,**} r, /usr/share/systemd/*-map r, /usr/share/X11/xkb/{,**} r, + /usr/share/xkeyboard-config-2/{,**} r, + /etc/ r, /etc/.#locale.conf@{hex16} rw, + /etc/.#locale.gen@{hex16} rw, /etc/.#vconsole.conf* rw, /etc/default/.#locale* rw, /etc/default/keyboard r, /etc/default/locale rw, /etc/locale.conf rw, + /etc/locale.gen rw, + /etc/nsswitch.conf r, + /etc/passwd r, /etc/vconsole.conf rw, - /etc/X11/xorg.conf.d/ r, - /etc/X11/xorg.conf.d/.#*.confd* rw, + /etc/X11/xorg.conf.d/ rw, + /etc/X11/xorg.conf.d/.#*.conf@{hex} rw, /etc/X11/xorg.conf.d/*.conf rw, - @{att}/@{run}/systemd/notify rw, - include if exists } diff --git a/apparmor.d/groups/systemd/systemd-logind b/apparmor.d/groups/systemd/systemd-logind index a879d02ec3..66ccec0ac1 100644 --- a/apparmor.d/groups/systemd/systemd-logind +++ b/apparmor.d/groups/systemd/systemd-logind @@ -8,15 +8,15 @@ abi , include @{exec_path} = @{lib}/systemd/systemd-logind -profile systemd-logind @{exec_path} flags=(attach_disconnected) { +profile systemd-logind @{exec_path} flags=(attach_disconnected,mediate_deleted) { include include - include + include + include include include include include - include capability chown, capability dac_override, @@ -30,7 +30,7 @@ profile systemd-logind @{exec_path} flags=(attach_disconnected) { mqueue getattr type=posix /, mqueue r type=posix /, - unix (bind) type=stream addr=@@{udbus}/bus/systemd-logind/system, + unix bind type=stream addr=@@{udbus}/bus/systemd-logind/system, #aa:dbus own bus=system name=org.freedesktop.login1 @@ -50,13 +50,12 @@ profile systemd-logind @{exec_path} flags=(attach_disconnected) { /etc/systemd/sleep.conf.d/{,**} r, / r, - /boot/{,**} r, - /efi/{,**} r, + @{efi}/{,**} r, /swap.img r, /swap/swapfile r, /swapfile r, - /var/lib/systemd/linger/ r, + /var/lib/systemd/linger/{,@{user}} rw, @{run}/.#nologin* rw, @{run}/credentials/getty@tty@{int}.service/ r, @@ -64,21 +63,25 @@ profile systemd-logind @{exec_path} flags=(attach_disconnected) { @{run}/nologin rw, @{run}/utmp rk, + @{run}/udev/static_node-tags/uaccess/ r, @{run}/udev/tags/master-of-seat/ r, @{run}/udev/tags/power-switch/ r, @{run}/udev/tags/uaccess/ r, - @{run}/udev/static_node-tags/uaccess/ r, + @{run}/udev/tags/xaccess-render/ r, - @{run}/udev/data/+backlight:* r, - @{run}/udev/data/+drivers:* r, + @{run}/udev/data/+backlight:* r, # For display backlights on laptops, monitors, and other screens. + @{run}/udev/data/+drivers:* r, # For drivers loaded in the system @{run}/udev/data/+drm:card@{int}-* r, # For screen outputs - @{run}/udev/data/+hid:* r, - @{run}/udev/data/+i2c:* r, + @{run}/udev/data/+hid:* r, # For Human Interface Device (mice, controllers, drawing tablets, scanners) + @{run}/udev/data/+i2c:* r, # For Inter-Integrated Circuit, low-speed peripherals (sensors, EEPROMs, etc.) @{run}/udev/data/+input:input@{int} r, # for mouse, keyboard, touchpad - @{run}/udev/data/+leds:* r, + @{run}/udev/data/+leds:* r, # Identifies all LEDs (keyboard, mouse, etc.) @{run}/udev/data/+pci:* r, # Identifies all PCI devices (CPU, GPU, Network, Disks, USB, etc.) - @{run}/udev/data/+wakeup:* r, + @{run}/udev/data/+wakeup:* r, # For wakeup events (e.g., from sleep or hibernation) @{run}/udev/data/c1:@{int} r, # For RAM disk + @{run}/udev/data/c4:@{int} r, # For TTY devices + @{run}/udev/data/c5:@{int} r, # for /dev/tty, /dev/console, /dev/ptmx + @{run}/udev/data/c7:@{int} r, # For Virtual console capture devices @{run}/udev/data/c10:@{int} r, # For non-serial mice, misc features @{run}/udev/data/c13:@{int} r, # For /dev/input/* @{run}/udev/data/c14:@{int} r, # Open Sound System (OSS) @@ -87,32 +90,31 @@ profile systemd-logind @{exec_path} flags=(attach_disconnected) { @{run}/udev/data/c81:@{int} r, # For video4linux @{run}/udev/data/c89:@{int} r, # For I2C bus interface @{run}/udev/data/c116:@{int} r, # For ALSA - @{run}/udev/data/c226:@{int} r, # For /dev/dri/card* + @{run}/udev/data/c202:@{int} r, # CPU model-specific registers + @{run}/udev/data/c203:@{int} r, # CPU CPUID information + @{run}/udev/data/c226:@{int} r, # For DRI card /dev/dri/card@{int} @{run}/udev/data/c@{dynamic}:@{int} r, # For dynamic assignment range 234 to 254, 384 to 511 - @{att}/@{run}/systemd/notify w, - @{att}/@{run}/systemd/userdb/io.systemd.DynamicUser rw, - @{att}/@{run}/systemd/userdb/io.systemd.Multiplexer rw, + @{att}@{run}/systemd/userdb/io.systemd.DynamicUser rw, + @{att}@{run}/systemd/userdb/io.systemd.Multiplexer rw, @{run}/systemd/inhibit/ rw, - @{run}/systemd/inhibit/.#* rw, - @{run}/systemd/inhibit/@{int}{,.ref} rw, + @{run}/systemd/inhibit/* rwlk, @{run}/systemd/seats/ rw, - @{run}/systemd/seats/.#seat* rw, - @{run}/systemd/seats/seat@{int} rw, - @{run}/systemd/sessions/{,*} rw, - @{run}/systemd/sessions/*.ref rw, - @{run}/systemd/shutdown/.#scheduled* rw, - @{run}/systemd/shutdown/scheduled rw, + @{run}/systemd/seats/* rwlk, + @{run}/systemd/sessions/ rw, + @{run}/systemd/sessions/* rwlk, + @{run}/systemd/shutdown/ rw, + @{run}/systemd/shutdown/* rwlk, @{run}/systemd/users/ rw, - @{run}/systemd/users/.#* rw, - @{run}/systemd/users/@{uid} rw, + @{run}/systemd/users/* rwlk, @{sys}/bus/serial-base/drivers/port/uevent r, @{sys}/class/drm/ r, @{sys}/class/power_supply/ r, @{sys}/devices/** r, @{sys}/devices/**/brightness rw, + @{sys}/devices/**/uevent rw, @{sys}/devices/virtual/tty/tty@{int}/active r, @{sys}/firmware/efi/efivars/LoaderEntries-@{uuid} r, @{sys}/firmware/efi/efivars/LoaderFeatures-@{uuid} r, @@ -122,15 +124,17 @@ profile systemd-logind @{exec_path} flags=(attach_disconnected) { @{sys}/fs/cgroup/memory.max r, @{sys}/fs/cgroup/memory/memory.limit_in_bytes r, @{sys}/kernel/kexec_loaded r, + @{sys}/kernel/kexec/loaded r, @{sys}/module/vt/parameters/default_utf8 r, @{sys}/power/{state,resume_offset,resume,disk} r, - @{PROC}/@{pid}/cgroup r, - @{PROC}/@{pid}/comm r, - @{PROC}/@{pid}/fd/ r, - @{PROC}/@{pid}/mountinfo r, - @{PROC}/@{pid}/sessionid r, - @{PROC}/@{pid}/stat r, + @{PROC}/@{pids}/cgroup r, + @{PROC}/@{pids}/comm r, + @{PROC}/@{pids}/fd/ r, + @{PROC}/@{pids}/mountinfo r, + @{PROC}/@{pids}/sessionid r, + @{PROC}/@{pids}/stat r, + @{PROC}/@{pids}/status r, @{PROC}/1/cmdline r, @{PROC}/pressure/* r, @{PROC}/swaps r, @@ -138,11 +142,13 @@ profile systemd-logind @{exec_path} flags=(attach_disconnected) { owner @{PROC}/@{pid}/fdinfo/@{int} r, /dev/dri/card@{int} rw, - /dev/input/event@{int} rw, # Input devices (keyboard, mouse, etc) - /dev/mqueue/ r, - /dev/tty@{int} rw, - owner @{att}/dev/tty@{int} rw, - owner /dev/shm/{,**/} rw, + @{att}/dev/dri/card@{int} rw, + + /dev/input/event@{int} rw, # Input devices (keyboard, mouse, etc) + /dev/mqueue/ r, + /dev/tty@{u8} rw, + /dev/pts/@{u8} w, + /dev/shm/{,**} rw, include if exists } diff --git a/apparmor.d/groups/systemd/systemd-machine-id-setup b/apparmor.d/groups/systemd/systemd-machine-id-setup index f3f27b5236..0de6c4d603 100644 --- a/apparmor.d/groups/systemd/systemd-machine-id-setup +++ b/apparmor.d/groups/systemd/systemd-machine-id-setup @@ -12,15 +12,16 @@ profile systemd-machine-id-setup @{exec_path} flags=(attach_disconnected) { include capability dac_override, + capability net_admin, capability setgid, capability setuid, capability sys_admin, capability sys_chroot, - ptrace (read), + ptrace read, - mount options=(rw rshared) -> /, - mount options=(rw rslave) -> /, + mount options=(rw make-rshared) /, + mount options=(rw make-rslave) /, umount /etc/machine-id, @{exec_path} mr, @@ -31,12 +32,16 @@ profile systemd-machine-id-setup @{exec_path} flags=(attach_disconnected) { /etc/machine-id rw, /var/ r, + @{PROC}/@{pid}/fdinfo/@{int} r, @{PROC}/1/environ r, @{PROC}/cmdline r, @{PROC}/sys/kernel/osrelease r, owner @{PROC}/@{pid}/setgroups r, owner @{PROC}/@{pid}/stat r, + #aa:only test + /tmp/c_busybox.@{rand8}/{,**} rw, + include if exists } diff --git a/apparmor.d/groups/systemd/systemd-machined b/apparmor.d/groups/systemd/systemd-machined index b37f2300bf..0648cf56a4 100644 --- a/apparmor.d/groups/systemd/systemd-machined +++ b/apparmor.d/groups/systemd/systemd-machined @@ -7,11 +7,13 @@ abi , include @{exec_path} = @{lib}/systemd/systemd-machined -profile systemd-machined @{exec_path} flags=(attach_disconnected) { +profile systemd-machined @{exec_path} flags=(attach_disconnected,mediate_deleted) { include + include include - include include + include + include capability chown, capability dac_override, @@ -21,6 +23,7 @@ profile systemd-machined @{exec_path} flags=(attach_disconnected) { capability kill, capability mknod, capability setgid, + capability setuid, capability sys_admin, capability sys_chroot, capability sys_ptrace, @@ -31,26 +34,55 @@ profile systemd-machined @{exec_path} flags=(attach_disconnected) { network inet6 dgram, network netlink raw, + signal send set=rtmin+6 peer=systemd-nspawn, + + ptrace read peer=@{p_systemd}, + ptrace read peer=libvirtd, + ptrace read peer=mkosi, + ptrace read peer=systemd-nspawn, + + unix type=stream addr=@@{udbus}/bus/systemd-machine/system, + unix type=stream addr=@@{udbus}/bus/systemd-machine/user, + #aa:dbus own bus=system name=org.freedesktop.machine1 #aa:dbus talk bus=system name=org.freedesktop.systemd1 label="@{p_systemd}" @{exec_path} mr, - /var/lib/machines/{,**} rw, - /etc/machine-id r, + / r, + @{att}/ r, + + owner /var/lib/machines/ rw, + owner /var/lib/machines/** rwk, + + owner @{run}/systemd/nspawn/ w, + owner @{run}/systemd/nspawn/locks/ w, + owner @{run}/systemd/nspawn/locks/** rwk, + + owner @{run}/user/@{uid}/systemd/machines/{,**} rwl, + owner @{run}/user/@{uid}/systemd/notify w, + + @{run}/systemd/machine/{,**} rwl, + @{run}/systemd/machines/{,**} rwl, + @{run}/systemd/resolve.hook/{,**} rwl, - @{run}/systemd/machine/{,**} rw, - @{run}/systemd/machines/{,**} rw, - @{run}/systemd/notify w, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/systemd-machined.service/memory.pressure rw, @{PROC}/@{pid}/cgroup r, + @{PROC}/@{pid}/fdinfo/@{int} r, + @{PROC}/@{pid}/gid_map r, + @{PROC}/@{pid}/setgroups r, + @{PROC}/@{pid}/stat r, + @{PROC}/@{pid}/uid_map r, @{PROC}/pressure/cpu r, @{PROC}/pressure/io r, @{PROC}/pressure/memory r, /dev/ptmx rw, - /dev/pts/@{int} rw, + /dev/pts/@{u16} rw, + /dev/pts/ptmx rw, + /dev/vsock r, include if exists } diff --git a/apparmor.d/groups/systemd/systemd-makefs b/apparmor.d/groups/systemd/systemd-makefs index 8556e51d77..9bbc2a4bd3 100644 --- a/apparmor.d/groups/systemd/systemd-makefs +++ b/apparmor.d/groups/systemd/systemd-makefs @@ -7,7 +7,7 @@ abi , include @{exec_path} = @{lib}/systemd/systemd-makefs -profile systemd-makefs @{exec_path} { +profile systemd-makefs @{exec_path} flags=(attach_disconnected) { include include include @@ -17,8 +17,11 @@ profile systemd-makefs @{exec_path} { @{exec_path} mr, - @{bin}/mkfs.* rPx, - @{bin}/mkswap rPx, + @{sbin}/mke2fs rPx, + @{sbin}/mkfs.* rPx, + @{sbin}/mkswap rPx, + + @{PROC}/sys/fs/nr_open r, include if exists } diff --git a/apparmor.d/groups/systemd/systemd-modules-load b/apparmor.d/groups/systemd/systemd-modules-load index 3f778244b3..ec4fac6054 100644 --- a/apparmor.d/groups/systemd/systemd-modules-load +++ b/apparmor.d/groups/systemd/systemd-modules-load @@ -16,6 +16,8 @@ profile systemd-modules-load @{exec_path} flags=(attach_disconnected) { capability perfmon, capability sys_module, + ptrace read peer=@{p_systemd}, + @{exec_path} mr, /etc/modprobe.d/ r, diff --git a/apparmor.d/groups/systemd/systemd-network-generator b/apparmor.d/groups/systemd/systemd-network-generator index e22d89629e..ceebbc5c2d 100644 --- a/apparmor.d/groups/systemd/systemd-network-generator +++ b/apparmor.d/groups/systemd/systemd-network-generator @@ -7,7 +7,7 @@ abi , include @{exec_path} = @{lib}/systemd/systemd-network-generator -profile systemd-network-generator @{exec_path} { +profile systemd-network-generator @{exec_path} flags=(attach_disconnected) { include include diff --git a/apparmor.d/groups/systemd/systemd-networkd b/apparmor.d/groups/systemd/systemd-networkd index ca54508263..ea4ff38af4 100644 --- a/apparmor.d/groups/systemd/systemd-networkd +++ b/apparmor.d/groups/systemd/systemd-networkd @@ -11,14 +11,19 @@ include profile systemd-networkd @{exec_path} flags=(attach_disconnected) { include include - include + include include + include + include capability bpf, capability net_admin, capability net_bind_service, capability net_broadcast, capability net_raw, + capability setgid, # FIXME: setgid, setpcap setuid are not needed when used as systemd service + capability setpcap, + capability setuid, capability sys_admin, network inet dgram, @@ -31,6 +36,8 @@ profile systemd-networkd @{exec_path} flags=(attach_disconnected) { unix bind type=stream addr=@@{udbus}/bus/systemd-network/bus-api-network, + signal receive set=usr2 peer=@{p_systemd}, + #aa:dbus own bus=system name=org.freedesktop.network1 dbus send bus=system path=/org/freedesktop/hostname1 @@ -40,43 +47,57 @@ profile systemd-networkd @{exec_path} flags=(attach_disconnected) { dbus send bus=system path=/org/freedesktop/hostname1 interface=org.freedesktop.hostname1 member=SetHostname - peer=(name=org.freedesktop.hostname1, label=systemd-hostnamed), + peer=(name=org.freedesktop.hostname1, label="@{p_systemd_hostnamed}"), @{exec_path} mr, /var/lib/dbus/machine-id r, /etc/machine-id r, - /etc/systemd/networkd.conf r, + /etc/systemd/network.conf r, /etc/systemd/network/{,**} r, + /etc/systemd/networkd.conf r, + /etc/systemd/networkd.conf.d/{,**} r, /etc/networkd-dispatcher/carrier.d/{,*} r, @{att}/ r, - @{att}/@{run}/systemd/notify rw, + + @{run}/mount/utab r, + @{run}/systemd/network/{,**} r, + @{run}/systemd/resolve/resolv.conf r, owner @{att}/var/lib/systemd/network/ r, + /var/lib/systemd/network/ r, + owner /var/lib/systemd/network/ rw, + owner /var/lib/systemd/network/** rwk, + @{run}/systemd/network/ r, @{run}/systemd/network/*.network r, owner @{run}/systemd/netif/** rw, - @{run}/udev/data/n@{int} r, + @{run}/udev/data/n@{int} r, # For network interfaces @{sys}/devices/@{pci}/ r, @{sys}/devices/@{pci}/rfkill@{int}/* r, - @{sys}/devices/**/net/** r, - @{sys}/devices/virtual/dmi/id/{sys,board,bios}_vendor r, - @{sys}/devices/virtual/dmi/id/product_name r, - @{sys}/devices/virtual/dmi/id/product_version r, + @{sys}/devices/**/@{pci}/ r, + @{sys}/devices/**/infiniband/ r, + @{sys}/devices/**/msi_irqs/ r, + @{sys}/devices/**/net/{,**} r, + @{sys}/devices/**/phy@{int}/** r, + @{sys}/devices/**/uevent r, @{sys}/fs/cgroup/ r, + @{sys}/fs/cgroup/system.slice/networkd-*.service/ r, @{sys}/kernel/btf/vmlinux r, @{PROC}/@{pid}/cgroup r, + @{PROC}/@{pid}/mountinfo r, + @{PROC}/@{pid}/setgroups r, @{PROC}/pressure/* r, @{PROC}/sys/net/ipv{4,6}/** rw, + @{PROC}/version_signature r, owner @{PROC}/@{pid}/fdinfo/@{int} r, - owner @{PROC}/@{pid}/mountinfo r, include if exists } diff --git a/apparmor.d/groups/systemd/systemd-networkd-wait-online b/apparmor.d/groups/systemd/systemd-networkd-wait-online index 0d5e407304..c3df19eb8e 100644 --- a/apparmor.d/groups/systemd/systemd-networkd-wait-online +++ b/apparmor.d/groups/systemd/systemd-networkd-wait-online @@ -8,7 +8,7 @@ abi , include @{exec_path} = @{lib}/systemd/systemd-networkd-wait-online -profile systemd-networkd-wait-online @{exec_path} flags=(complain) { +profile systemd-networkd-wait-online @{exec_path} flags=(attach_disconnected) { include include @@ -16,9 +16,12 @@ profile systemd-networkd-wait-online @{exec_path} flags=(complain) { network netlink raw, + ptrace read peer=@{p_systemd}, + @{exec_path} mr, @{run}/systemd/netif/links/@{int} r, + @{run}/systemd/resolve/io.systemd.Resolve.Monitor rw, include if exists } diff --git a/apparmor.d/groups/systemd/systemd-notify b/apparmor.d/groups/systemd/systemd-notify index f62599d287..973f8bdc8e 100644 --- a/apparmor.d/groups/systemd/systemd-notify +++ b/apparmor.d/groups/systemd/systemd-notify @@ -7,7 +7,7 @@ abi , include @{exec_path} = @{bin}/systemd-notify -profile systemd-notify @{exec_path} { +profile systemd-notify @{exec_path} flags=(attach_disconnected) { include include diff --git a/apparmor.d/groups/systemd/systemd-nsresourced b/apparmor.d/groups/systemd/systemd-nsresourced new file mode 100644 index 0000000000..b11ab12b53 --- /dev/null +++ b/apparmor.d/groups/systemd/systemd-nsresourced @@ -0,0 +1,42 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/systemd/systemd-nsresourced +profile systemd-nsresourced @{exec_path} flags=(attach_disconnected) { + include + include + + capability bpf, + capability net_admin, + capability perfmon, + capability sys_resource, + + signal receive set=usr2 peer=systemd-nsresourced//&systemd-nsresourcework, + + @{exec_path} mr, + + @{lib}/systemd/systemd-nsresourcework ix, # no new privs + + @{run}/systemd/nsresource/ rw, + @{run}/systemd/nsresource/** rw, + + @{sys}/devices/kprobe/type r, + @{sys}/fs/bpf/ r, + @{sys}/fs/bpf/systemd/ rw, + @{sys}/fs/bpf/systemd/userns-restrict/{,**} rw, + @{sys}/fs/cgroup/system.slice/systemd-nsresourced.service/memory.pressure rw, + @{sys}/kernel/btf/vmlinux r, + @{sys}/kernel/security/lsm r, + + @{PROC}/@{pid}/cgroup r, + @{PROC}/pressure/* r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd/systemd-nsresourcework b/apparmor.d/groups/systemd/systemd-nsresourcework new file mode 100644 index 0000000000..9c271d9163 --- /dev/null +++ b/apparmor.d/groups/systemd/systemd-nsresourcework @@ -0,0 +1,25 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/systemd/systemd-nsresourcework +profile systemd-nsresourcework @{exec_path} flags=(attach_disconnected) { + include + + capability net_admin, + capability sys_resource, + + signal send set=usr2 peer=systemd-nsresourced, + + @{exec_path} mr, + + @{run}/systemd/nsresource/registry/ r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd/systemd-oomd b/apparmor.d/groups/systemd/systemd-oomd index ce61dba23e..0d8b68be29 100644 --- a/apparmor.d/groups/systemd/systemd-oomd +++ b/apparmor.d/groups/systemd/systemd-oomd @@ -24,8 +24,7 @@ profile systemd-oomd @{exec_path} flags=(attach_disconnected) { /etc/systemd/oomd.conf r, /etc/systemd/oomd.conf.d/{,**} r, - @{att}/@{run}/systemd/notify w, - @{att}/@{run}/systemd/io.systemd.ManagedOOM rw, + @{att}@{run}/systemd/io.systemd.ManagedOOM rw, @{run}/systemd/io.system.ManagedOOM rw, @{run}/systemd/io.systemd.ManagedOOM rw, diff --git a/apparmor.d/groups/systemd/systemd-path b/apparmor.d/groups/systemd/systemd-path index 747527776e..5463048317 100644 --- a/apparmor.d/groups/systemd/systemd-path +++ b/apparmor.d/groups/systemd/systemd-path @@ -10,10 +10,16 @@ include profile systemd-path @{exec_path} { include include + include + + signal send peer=child-pager, @{exec_path} mr, - owner @{user_config_dirs}/user-dirs.dirs r, + @{pager_path} rPx -> child-pager, + + @{PROC}/1/cgroup r, + owner @{PROC}/@{pid}/cgroup r, include if exists } diff --git a/apparmor.d/groups/systemd/systemd-random-seed b/apparmor.d/groups/systemd/systemd-random-seed index 86ea02a0d0..400de0c9c1 100644 --- a/apparmor.d/groups/systemd/systemd-random-seed +++ b/apparmor.d/groups/systemd/systemd-random-seed @@ -13,11 +13,14 @@ profile systemd-random-seed @{exec_path} flags=(attach_disconnected) { capability net_admin, + ptrace read peer=@{p_systemd}, + @{exec_path} mr, /etc/machine-id r, - /var/lib/systemd/ r, + /var/lib/ w, + /var/lib/systemd/ rw, /var/lib/systemd/random-seed rw, @{PROC}/sys/kernel/random/poolsize r, diff --git a/apparmor.d/groups/systemd/systemd-remount-fs b/apparmor.d/groups/systemd/systemd-remount-fs index 750f7e18bd..591f5fa26c 100644 --- a/apparmor.d/groups/systemd/systemd-remount-fs +++ b/apparmor.d/groups/systemd/systemd-remount-fs @@ -19,22 +19,25 @@ profile systemd-remount-fs @{exec_path} flags=(attach_disconnected) { mount options=(rw, remount) -> /, mount options=(rw, remount) -> @{PROC}/, + ptrace read peer=@{p_systemd}, + @{exec_path} mr, @{bin}/mount rix, - /etc/blkid.conf r, + @{etc_ro}/blkid.conf r, + @{etc_ro}/blkid.conf.d/{,**} r, /etc/fstab r, @{run}/host/container-manager r, @{run}/mount/utab rw, - @{run}/mount/utab.@{rand6} rw, - @{run}/mount/utab.lock rwk, + @{run}/mount/utab.* rwk, @{sys}/devices/virtual/block/dm-@{int}/dm/name r, @{PROC}/ r, @{PROC}/1/cmdline r, + @{PROC}/sys/fs/nr_open r, include if exists } diff --git a/apparmor.d/groups/systemd/systemd-resolve b/apparmor.d/groups/systemd/systemd-resolve deleted file mode 100644 index f716aa3afe..0000000000 --- a/apparmor.d/groups/systemd/systemd-resolve +++ /dev/null @@ -1,27 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2021-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - -abi , - -include - -@{exec_path} = @{bin}/resolvectl -@{exec_path} += @{bin}/systemd-resolve -profile systemd-resolve @{exec_path} { - include - - capability mknod, - capability net_admin, - - network netlink raw, - - @{exec_path} mr, - - @{PROC}/ r, - owner @{PROC}/@{pids}/fd/ r, - - include if exists -} - -# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd/systemd-resolved b/apparmor.d/groups/systemd/systemd-resolved index 8f4b5bc579..79ef0a85ee 100644 --- a/apparmor.d/groups/systemd/systemd-resolved +++ b/apparmor.d/groups/systemd/systemd-resolved @@ -10,11 +10,11 @@ include profile systemd-resolved @{exec_path} flags=(attach_disconnected) { include include - include + include + include include include include - include capability net_bind_service, capability net_raw, @@ -36,9 +36,12 @@ profile systemd-resolved @{exec_path} flags=(attach_disconnected) { /etc/systemd/resolved.conf r, /etc/systemd/resolved.conf.d/{,*} r, - @{att}/@{run}/systemd/notify w, + @{run}/systemd/netif/io.systemd.Network rw, + @{att}@{run}/systemd/netif/io.systemd.Network rw, + @{att}@{run}/systemd/resolve.hook/io.systemd.Network rw, @{run}/systemd/netif/links/* r, + @{run}/systemd/resolve.hook/{,**} rw, @{run}/systemd/resolve/{,**} rw, @{PROC}/@{pid}/cgroup r, diff --git a/apparmor.d/groups/systemd/systemd-rfkill b/apparmor.d/groups/systemd/systemd-rfkill index 552bd9996a..dd53b136c1 100644 --- a/apparmor.d/groups/systemd/systemd-rfkill +++ b/apparmor.d/groups/systemd/systemd-rfkill @@ -13,18 +13,21 @@ profile systemd-rfkill @{exec_path} flags=(attach_disconnected) { include capability net_admin, + capability sys_admin, capability sys_ptrace, network netlink raw, + ptrace read peer=@{p_systemd}, + @{exec_path} mr, /var/lib/systemd/rfkill/* rw, - @{run}/systemd/notify rw, - @{run}/udev/data/+rfkill:* r, + @{run}/udev/data/+rfkill:* r, # Kill switch for wireless devices (Wi-Fi, Bluetooth, NFC) to save power @{sys}/devices/**/rfkill@{int}/{uevent,name} r, + @{sys}/devices/@{pci}/usb@{int}/** r, /dev/rfkill rw, diff --git a/apparmor.d/groups/systemd/systemd-shutdown b/apparmor.d/groups/systemd/systemd-shutdown index e9887c0cb4..60a87500cb 100644 --- a/apparmor.d/groups/systemd/systemd-shutdown +++ b/apparmor.d/groups/systemd/systemd-shutdown @@ -8,27 +8,40 @@ abi , include @{exec_path} = @{lib}/systemd/systemd-shutdown -profile systemd-shutdown @{exec_path} { +profile systemd-shutdown @{exec_path} flags=(attach_disconnected) { include include + capability ipc_lock, capability kill, + capability sys_admin, capability sys_boot, capability sys_ptrace, capability sys_resource, - mount options=(rw rprivate) -> /, + mount options=(rw make-rprivate) /, + + umount, + + ptrace read, signal (send) set=(stop, cont, term, kill), signal (receive) set=(rtmin+23) peer=plymouthd, @{exec_path} mr, + @{run}/initramfs/{,**} r, + @{PROC}/ r, - @{PROC}/@{pid}/fd/ r, - @{PROC}/@{pid}/fdinfo/@{int} r, + @{PROC}/@{pids}/cgroup r, @{PROC}/@{pids}/cmdline r, + @{PROC}/@{pids}/fd/ r, + @{PROC}/@{pids}/fdinfo/@{int} r, + @{PROC}/@{pids}/stat r, + @{PROC}/@{pids}/status r, owner @{PROC}/@{pid}/comm r, + owner @{PROC}/@{pid}/mountinfo r, + owner @{PROC}/@{pid}/mounts r, owner @{PROC}/sys/kernel/core_pattern w, owner @{PROC}/sys/kernel/printk rw, diff --git a/apparmor.d/groups/systemd/systemd-sleep b/apparmor.d/groups/systemd/systemd-sleep index d7c61e336b..3e83a87e2f 100644 --- a/apparmor.d/groups/systemd/systemd-sleep +++ b/apparmor.d/groups/systemd/systemd-sleep @@ -12,13 +12,22 @@ profile systemd-sleep @{exec_path} flags=(attach_disconnected) { include include include + include capability net_admin, capability sys_admin, capability sys_resource, + capability perfmon, + + unix bind type=stream addr=@@{udbus}/bus/systemd-sleep/, + unix bind type=stream addr=@@{udbus}/bus/systemd-sleep/system, @{exec_path} mr, + @{sh_path} mr, + + /var/tmp/#@{int} rw, + @{lib}/systemd/system-sleep/grub2.sleep rPx, @{lib}/systemd/system-sleep/hdparm rPx, @{lib}/systemd/system-sleep/nvidia rPx, @@ -28,8 +37,20 @@ profile systemd-sleep @{exec_path} flags=(attach_disconnected) { /etc/systemd/sleep.conf r, /etc/systemd/sleep.conf.d/{,*} r, + /etc/os-release r, + + /swap/* r, + + @{run}/systemd/private rw, @{sys}/power/state rw, + @{sys}/power/disk w, + @{sys}/power/resume rw, + @{sys}/power/resume_offset rw, + @{sys}/firmware@{efi}/efivars/HibernateLocation-@{uuid} w, + + @{PROC}/sys/fs/nr_open r, + @{PROC}/swaps r, include if exists } diff --git a/apparmor.d/groups/systemd/systemd-sleep-grub b/apparmor.d/groups/systemd/systemd-sleep-grub index b2b42bf44f..38be5772ff 100644 --- a/apparmor.d/groups/systemd/systemd-sleep-grub +++ b/apparmor.d/groups/systemd/systemd-sleep-grub @@ -14,7 +14,7 @@ profile systemd-sleep-grub @{exec_path} { @{exec_path} mr, @{sh_path} rix, - @{bin}/grep rix, + @{bin}/{,e}grep rix, @{bin}/uname rix, /etc/sysconfig/bootloader r, diff --git a/apparmor.d/groups/systemd/systemd-sleep-hdparm b/apparmor.d/groups/systemd/systemd-sleep-hdparm index 71008c96d4..d838962237 100644 --- a/apparmor.d/groups/systemd/systemd-sleep-hdparm +++ b/apparmor.d/groups/systemd/systemd-sleep-hdparm @@ -11,6 +11,25 @@ profile systemd-sleep-hdparm @{exec_path} { include @{exec_path} mr, + @{sh_path} r, + + @{bin}/{,e,f}grep rix, + @{bin}/sed rix, + @{bin}/udevadm Cx -> udevadm, + @{lib}/pm-utils/power.d/*hdparm-apm ix, + + /etc/hdparm.conf r, + + @{PROC}/cmdline r, + + /dev/ r, + + profile udevadm { + include + include + + include if exists + } include if exists } diff --git a/apparmor.d/groups/systemd/systemd-sleep-nvidia b/apparmor.d/groups/systemd/systemd-sleep-nvidia index 2ca5d74743..4950bd0389 100644 --- a/apparmor.d/groups/systemd/systemd-sleep-nvidia +++ b/apparmor.d/groups/systemd/systemd-sleep-nvidia @@ -28,7 +28,7 @@ profile systemd-sleep-nvidia @{exec_path} { @{PROC}/driver/nvidia/suspend w, /dev/tty rw, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/systemd/systemd-sleep-sysstat b/apparmor.d/groups/systemd/systemd-sleep-sysstat index 94e2e8daf7..83ecc284a0 100644 --- a/apparmor.d/groups/systemd/systemd-sleep-sysstat +++ b/apparmor.d/groups/systemd/systemd-sleep-sysstat @@ -11,6 +11,10 @@ profile systemd-sleep-sysstat @{exec_path} { include @{exec_path} mr, + @{sh_path} r, + + @{lib}/sysstat/sa{1,2} Px, + @{lib}/sysstat/debian-sa{1,2} Px, include if exists } diff --git a/apparmor.d/groups/systemd/systemd-sleep-tlp b/apparmor.d/groups/systemd/systemd-sleep-tlp index 60a28d4af2..fc9a510674 100644 --- a/apparmor.d/groups/systemd/systemd-sleep-tlp +++ b/apparmor.d/groups/systemd/systemd-sleep-tlp @@ -13,7 +13,7 @@ profile systemd-sleep-tlp @{exec_path} { @{exec_path} mr, @{sh_path} rix, - @{bin}/tlp rPUx, + @{sbin}/tlp rPUx, include if exists } diff --git a/apparmor.d/groups/systemd/systemd-sleep-upgrades b/apparmor.d/groups/systemd/systemd-sleep-upgrades index 4f2cce637d..c2c107b1f9 100644 --- a/apparmor.d/groups/systemd/systemd-sleep-upgrades +++ b/apparmor.d/groups/systemd/systemd-sleep-upgrades @@ -11,6 +11,7 @@ profile systemd-sleep-upgrades @{exec_path} { include @{exec_path} mr, + @{sh_path} r, include if exists } diff --git a/apparmor.d/groups/systemd/systemd-stdio-bridge b/apparmor.d/groups/systemd/systemd-stdio-bridge new file mode 100644 index 0000000000..93421eb8ad --- /dev/null +++ b/apparmor.d/groups/systemd/systemd-stdio-bridge @@ -0,0 +1,29 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/systemd-stdio-bridge +profile systemd-stdio-bridge @{exec_path} flags=(attach_disconnected) { + include + include + include + include + include + + signal send set=term peer=@{p_systemd}, + + unix bind type=stream addr=@@{udbus}/bus/systemd-stdio-b/, + unix bind type=stream addr=@@{udbus}/bus/systemd-stdio-b/session, + + unix type=stream peer=(label=do-release-upgrade//upgrader), + + @{exec_path} mr, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd/systemd-sulogin-shell b/apparmor.d/groups/systemd/systemd-sulogin-shell index d28531e563..5ccf332198 100644 --- a/apparmor.d/groups/systemd/systemd-sulogin-shell +++ b/apparmor.d/groups/systemd/systemd-sulogin-shell @@ -18,7 +18,7 @@ profile systemd-sulogin-shell @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, - @{bin}/sulogin rPx, + @{sbin}/sulogin rPx, include if exists } diff --git a/apparmor.d/groups/systemd/systemd-sysctl b/apparmor.d/groups/systemd/systemd-sysctl index 4541050113..0938d31ce7 100644 --- a/apparmor.d/groups/systemd/systemd-sysctl +++ b/apparmor.d/groups/systemd/systemd-sysctl @@ -18,6 +18,9 @@ profile systemd-sysctl @{exec_path} flags=(attach_disconnected) { capability sys_admin, capability sys_ptrace, capability sys_rawio, + capability mac_admin, # Required by the apparmor package to control user namespaces + + ptrace read peer=@{p_systemd}, @{exec_path} mr, @@ -25,10 +28,13 @@ profile systemd-sysctl @{exec_path} flags=(attach_disconnected) { @{run}/sysctl.d/{,*.conf} r, /etc/sysctl.conf r, /etc/sysctl.d/{,*.conf} r, - /usr/lib/sysctl.d/{,*.conf} r, + @{lib}/sysctl.d/{,*.conf} r, @{PROC}/sys/** rw, + @{PROC}/1/environ r, + @{PROC}/cmdline r, + include if exists } diff --git a/apparmor.d/groups/systemd/systemd-sysext b/apparmor.d/groups/systemd/systemd-sysext new file mode 100644 index 0000000000..65659e2076 --- /dev/null +++ b/apparmor.d/groups/systemd/systemd-sysext @@ -0,0 +1,77 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2021 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/systemd-sysext @{bin}/systemd-confext +profile systemd-sysext @{exec_path} flags=(attach_disconnected,mediate_deleted) { + include + + capability chown, + capability dac_override, + capability dac_read_search, + capability fsetid, + capability net_admin, + capability sys_admin, + capability sys_resource, + + mount options=(rw bind) @{lib}/confexts/core-config/ -> @{run}/systemd/sysext/confexts/core-config/, + mount options=(rw bind) @{run}/systemd/sysext/overlay/etc/.systemd-confext/ -> @{run}/systemd/sysext/overlay/etc/.systemd-confext/, + mount options=(rw make-rslave) @{run}/, + mount options=(rw rbind) @{run}/systemd/sysext/overlay/etc/ -> /etc/, + mount fstype=overlay options=(ro nodev noexec nosuid) confext -> @{run}/systemd/sysext/overlay/etc/, + mount fstype=overlay options=(rw noatime nodev noexec nosuid) confext -> @{run}/systemd/sysext/overlay/etc/, + mount fstype=tmpfs confext -> @{run}/systemd/sysext/, + + umount /etc/, + umount /etc/.systemd-confext/, + + ptrace read peer=@{p_systemd}, + + signal send set=(cont term winch) peer=child-pager, + + @{exec_path} mr, + + @{pager_path} Px -> child-pager, + + @{att}/etc/ r, + @{att}/lib/confexts/{,**} r, + @{att}/meta/etc/ r, + @{att}/meta/etc/.systemd-confext/* r, + @{att}/var/lib/extensions.mutable/{,**} rw, + + /etc/ r, + /etc/.systemd-confext/confexts r, + /etc/.systemd-confext/dev r, + /etc/extension-release.d/extension-release.* r, + + @{run}/systemd/ r, + @{run}/systemd/nspawn/ r, + @{run}/systemd/nspawn/locks/* rwk, + @{run}/systemd/sysext/confexts/ rw, + @{run}/systemd/sysext/confexts/{,**/} rw, + @{run}/systemd/sysext/meta/ w, + @{run}/systemd/sysext/meta/etc/ rw, + @{run}/systemd/sysext/meta/etc/.systemd-confext/ rw, + @{run}/systemd/sysext/meta/etc/.systemd-confext/* w, + @{run}/systemd/sysext/overlay/{,**/} w, + + # /usr/lib/confexts/{,**} r, + # /usr/local/lib/confexts/{,**} r, + # /var/lib/confexts/{,**} r, + # @{run}/confexts/{,**} r, + + @{PROC}/@{pid}/mountinfo r, + @{PROC}/1/cgroup r, + @{PROC}/1/environ r, + @{PROC}/cmdline r, + @{PROC}/sys/kernel/osrelease r, + owner @{PROC}/@{pid}/cgroup r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd/systemd-sysupdate b/apparmor.d/groups/systemd/systemd-sysupdate new file mode 100644 index 0000000000..488e06e2e1 --- /dev/null +++ b/apparmor.d/groups/systemd/systemd-sysupdate @@ -0,0 +1,57 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/systemd/systemd-sysupdate +profile systemd-sysupdate @{exec_path} flags=(attach_disconnected) { + include + include + include + + capability chown, + capability dac_override, + capability fowner, + capability fsetid, + capability linux_immutable, + capability mknod, + capability setfcap, + capability setpcap, + capability sys_admin, + + network inet dgram, + network inet6 dgram, + network inet stream, + network inet6 stream, + network netlink raw, + + unix send type=dgram peer=(label=unconfined, addr=@@{int}@{int}), + + @{exec_path} mr, + + @{bin}/gpg{,2} ix, + @{lib}/systemd/systemd-pull ix, + + @{etc_rw}/sysupdate.d/{,**} r, + + @{efi}/EFI/Linux/ r, + @{lib}/ r, + @{run}/ r, + /etc/ r, + /usr/ r, + /usr/local/lib/ r, + + /tmp/gpghome@{rand6}/ w, + /tmp/sig@{rand6} rw, + + @{PROC}/1/environ r, + @{PROC}/cmdline r, + @{PROC}/sys/kernel/osrelease r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd/systemd-sysusers b/apparmor.d/groups/systemd/systemd-sysusers index 254faeca0a..ac0f28d5fc 100644 --- a/apparmor.d/groups/systemd/systemd-sysusers +++ b/apparmor.d/groups/systemd/systemd-sysusers @@ -12,10 +12,15 @@ profile systemd-sysusers @{exec_path} flags=(attach_disconnected) { include include + capability audit_write, capability chown, capability fsetid, capability net_admin, + network netlink raw, + + ptrace read peer=@{p_systemd}, + signal send set=cont peer=child-pager, @{exec_path} mr, @@ -25,7 +30,7 @@ profile systemd-sysusers @{exec_path} flags=(attach_disconnected) { # Config file locations /etc/sysusers.d/{,*.conf} r, @{run}/sysusers.d/{,*.conf} r, - /usr/lib/sysusers.d/{,*.conf} r, + @{lib}/sysusers.d/{,*.conf} r, # Where the users can be created, /home/{,*} rw, @@ -46,8 +51,8 @@ profile systemd-sysusers @{exec_path} flags=(attach_disconnected) { owner @{PROC}/@{pid}/cgroup r, - /dev/tty@{int} rw, - owner /dev/pts/@{int} rw, + /dev/tty@{u8} rw, + owner /dev/pts/@{u16} rw, # Inherit Silencer deny network inet6 stream, diff --git a/apparmor.d/groups/systemd/systemd-timedated b/apparmor.d/groups/systemd/systemd-timedated index e070afe4e7..76a09c3dd9 100644 --- a/apparmor.d/groups/systemd/systemd-timedated +++ b/apparmor.d/groups/systemd/systemd-timedated @@ -11,19 +11,16 @@ include profile systemd-timedated @{exec_path} flags=(attach_disconnected) { include include + include + include include capability sys_time, - unix (bind) type=stream addr=@@{udbus}/bus/systemd-timedat/system, + unix bind type=stream addr=@@{udbus}/bus/systemd-timedat/system, #aa:dbus own bus=system name=org.freedesktop.timedate1 - dbus send bus=system path=/org/freedesktop/systemd1/unit/* - interface=org.freedesktop.DBus.Properties - member=GetAll - peer=(name=org.freedesktop.systemd1, label="@{p_systemd}"), - @{exec_path} mr, @{etc_rw}/.#adjtime* rw, @@ -35,8 +32,6 @@ profile systemd-timedated @{exec_path} flags=(attach_disconnected) { /etc/.#timezone* rw, /etc/timezone rw, - @{att}/@{run}/systemd/notify rw, - /dev/rtc@{int} r, include if exists diff --git a/apparmor.d/groups/systemd/systemd-timesyncd b/apparmor.d/groups/systemd/systemd-timesyncd index b603b24113..8ae122919d 100644 --- a/apparmor.d/groups/systemd/systemd-timesyncd +++ b/apparmor.d/groups/systemd/systemd-timesyncd @@ -22,7 +22,7 @@ profile systemd-timesyncd @{exec_path} flags=(attach_disconnected) { network inet6 stream, unix (bind) type=stream addr=@@{udbus}/bus/systemd-timesyn/bus-api-timesync, - unix (send, receive) type=dgram addr=none peer=(label=@{p_systemd}, addr=none), + unix (send, receive) type=dgram addr=none peer=(label=@{p_sd}, addr=none), #aa:dbus own bus=system name=org.freedesktop.timesync1 @@ -34,7 +34,8 @@ profile systemd-timesyncd @{exec_path} flags=(attach_disconnected) { owner /var/lib/systemd/timesync/clock rw, - @{att}/@{run}/systemd/notify rw, + @{run}/systemd/resolve/io.systemd.Resolve rw, + @{att}@{run}/systemd/resolve/io.systemd.Resolve rw, @{run}/resolvconf/*.conf r, @{run}/systemd/netif/state r, diff --git a/apparmor.d/groups/systemd/systemd-tmpfiles b/apparmor.d/groups/systemd/systemd-tmpfiles index e37073f470..5903614b45 100644 --- a/apparmor.d/groups/systemd/systemd-tmpfiles +++ b/apparmor.d/groups/systemd/systemd-tmpfiles @@ -22,6 +22,8 @@ profile systemd-tmpfiles @{exec_path} flags=(attach_disconnected) { capability sys_resource, capability syslog, + ptrace read peer=@{p_systemd}, + @{exec_path} mr, /etc/machine-id r, @@ -30,19 +32,20 @@ profile systemd-tmpfiles @{exec_path} flags=(attach_disconnected) { # Config file locations /etc/tmpfiles.d/{,*.conf} r, @{run}/tmpfiles.d/{,*.conf} r, - /usr/lib/tmpfiles.d/{,*.conf} r, + @{lib}/tmpfiles.d/{,*.conf} r, @{user_config_dirs}/user-tmpfiles.d/{,*.conf} r, @{run}/user/@{uid}/user-tmpfiles.d/{,*.conf} r, @{user_share_dirs}/user-tmpfiles.d/{,*.conf} r, /usr/share/user-tmpfiles.d/{,*.conf} r, + #aa:lint ignore=too-wide # Where the tmpfiles can be created, /{,*} rw, /dev/{,**} rw, /etc/{,**} rw, /home/ rw, /opt/{,**} rw, - /run/{,**} rw, + @{run}/{,**} rw, /srv/{,**} rw, /tmp/{,**} rwk, /usr/{,**} rw, @@ -52,13 +55,13 @@ profile systemd-tmpfiles @{exec_path} flags=(attach_disconnected) { @{sys}/class/net/ r, @{sys}/devices/system/cpu/cpufreq/ r, - @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_governor w, - @{sys}/devices/system/cpu/microcode/reload w, - @{sys}/module/pcie_aspm/parameters/policy w, + + # Tmpfiles file can also be set in /sys and /proc + @{sys}/** w, + @{PROC}/** w, @{PROC}/@{pid}/net/unix r, @{PROC}/1/cmdline r, - @{PROC}/sched_debug w, include if exists } diff --git a/apparmor.d/groups/systemd/systemd-tty-ask-password-agent b/apparmor.d/groups/systemd/systemd-tty-ask-password-agent index a9575dd892..3dd8af829e 100644 --- a/apparmor.d/groups/systemd/systemd-tty-ask-password-agent +++ b/apparmor.d/groups/systemd/systemd-tty-ask-password-agent @@ -7,23 +7,28 @@ abi , include @{exec_path} = @{bin}/systemd-tty-ask-password-agent -profile systemd-tty-ask-password-agent @{exec_path} { +profile systemd-tty-ask-password-agent @{exec_path} flags=(attach_disconnected) { include include - include capability dac_override, capability dac_read_search, capability net_admin, capability sys_resource, + capability sys_tty_config, - signal receive set=(term cont) peer=*//systemctl, - signal receive set=(term cont) peer=deb-systemd-invoke, - signal receive set=(term cont) peer=default, - signal receive set=(term cont) peer=logrotate, - signal receive set=(term cont) peer=makepkg//sudo, - signal receive set=(term cont) peer=role_*, - signal receive set=(term cont) peer=rpm, + ptrace read peer=@{p_systemd}, + ptrace read peer=systemd-cryptsetup, + + signal receive set=(term cont winch) peer=@{p_logrotate}, + signal receive set=(term cont winch) peer=*//root, + signal receive set=(term cont winch) peer=*//sudo, + signal receive set=(term cont winch) peer=*//systemctl, + signal receive set=(term cont winch) peer=deb-systemd-invoke, + signal receive set=(term cont winch) peer=machinectl, + signal receive set=(term cont winch) peer=role_*, + signal receive set=(term cont winch) peer=rpm, + signal receive set=(term cont winch) peer=systemd-run, @{exec_path} mrix, @@ -36,12 +41,23 @@ profile systemd-tty-ask-password-agent @{exec_path} { @{run}/utmp rk, - @{PROC}/@{pids}/stat r, + @{run}/systemd/sessions/ r, + @{run}/systemd/sessions/@{int} r, + @{run}/systemd/sessions/c@{int} r, @{sys}/devices/virtual/tty/console/active r, @{sys}/devices/virtual/tty/tty@{int}/active r, + @{sys}/module/vt/parameters/default_utf8 r, + + @{PROC}/@{pids}/stat r, + @{PROC}/1/environ r, + @{PROC}/cmdline r, + @{PROC}/sys/kernel/osrelease r, - /dev/tty@{int} rw, + /dev/console k, + /dev/hvc@{int} rw, + /dev/tty@{u8} rw, + /dev/ttyS@{int} rw, include if exists } diff --git a/apparmor.d/groups/systemd/systemd-udevd b/apparmor.d/groups/systemd/systemd-udevd index 29b40cb484..32a3fdde5e 100644 --- a/apparmor.d/groups/systemd/systemd-udevd +++ b/apparmor.d/groups/systemd/systemd-udevd @@ -8,7 +8,7 @@ abi , include @{exec_path} = @{bin}/udevadm @{lib}/systemd/systemd-udevd -profile systemd-udevd @{exec_path} flags=(attach_disconnected,complain) { +profile systemd-udevd @{exec_path} flags=(attach_disconnected) { include include include @@ -35,45 +35,58 @@ profile systemd-udevd @{exec_path} flags=(attach_disconnected,complain) { network inet6 dgram, network netlink raw, + unix bind type=dgram addr=@@{udbus}, + unix bind type=stream addr=@@{udbus}/bus/udevadm/, + @{exec_path} mrix, - @{sh_path} rix, - @{coreutils_path} rix, - @{pager_path} rPx -> child-pager, - @{bin}/*-print-pci-ids rix, - @{bin}/alsactl rPUx, - @{bin}/ddcutil rPx, - @{bin}/dmsetup rPx, - @{bin}/ethtool rix, - @{bin}/issue-generator rPx, - @{bin}/kmod rPx, - @{bin}/logger rix, - @{bin}/ls rix, - @{bin}/lvm rPx, - @{bin}/mknod rix, - @{bin}/multipath rPx, - @{bin}/nfsrahead rix, - @{bin}/nvidia-modprobe rPx -> child-modprobe-nvidia, - @{bin}/setfacl rix, - @{bin}/sg_inq rix, - @{bin}/snap rPx, - @{bin}/systemctl rCx -> systemctl, - @{bin}/systemd-run rix, - @{bin}/unshare rix, - @{bin}/vmmouse_detect rPUx, - - @{lib}/crda/* rPUx, - @{lib}/gdm-runtime-config rPx, - @{lib}/nfsrahead rPUx, - @{lib}/open-iscsi/net-interface-handler rPUx, - @{lib}/pm-utils/power.d/* rPUx, - @{lib}/snapd/snap-device-helper rPx, - @{lib}/systemd/systemd-* rPx, - @{lib}/udev/* rPUx, - /usr/share/hplip/config_usb_printer.py rPUx, - - /etc/console-setup/*.sh rPUx, - /etc/network/cloud-ifupdown-helper rPUx, + @{sh_path} rix, + @{coreutils_path} rix, + @{bin}/logger rix, + @{bin}/ls rix, + @{bin}/mknod rix, + @{bin}/nfsrahead rix, + @{sbin}/partx rix, + @{bin}/setfacl rix, + @{bin}/sg_inq rix, + @{bin}/systemd-run Cx -> run, + @{bin}/unshare rix, + @{sbin}/ethtool rix, + @{sbin}/kpartx rix, + + @{bin}/ddcutil Px, + @{bin}/input-remapper-control PUx, + @{bin}/pktsetup PUx, + @{bin}/kmod Cx -> kmod, + @{bin}/nvidia-modprobe Px -> child-modprobe-nvidia, + @{bin}/set-wireless-regdom PUx, + @{bin}/snap Px, + @{bin}/systemctl Cx -> systemctl, + @{bin}/vmmouse_detect PUx, + @{pager_path} Px -> child-pager, + @{sbin}/alsactl Px, + @{sbin}/dmsetup Px, + @{sbin}/issue-generator Px, + @{sbin}/kdump-config Px, + @{sbin}/lvm Px, + @{sbin}/multipath Px, + @{sbin}/sysctl Px, + @{sbin}/tlp Px, + @{sbin}/u-d-c-print-pci-ids Px, + + @{lib}/crda/* PUx, + @{lib}/gdm-runtime-config Px, + @{lib}/nfsrahead PUx, + @{lib}/open-iscsi/net-interface-handler Px, + @{lib}/pm-utils/power.d/* PUx, + @{lib}/snapd/snap-device-helper Px, + @{lib}/switcheroo-control-check-discrete-amdgpu PUx, + @{lib}/systemd/systemd-* Px, + @{lib}/udev/* PUx, + /usr/share/hplip/config_usb_printer.py PUx, + + /etc/console-setup/*.sh PUx, + /etc/network/cloud-ifupdown-helper PUx, /etc/default/* r, /etc/machine-id r, @@ -89,15 +102,19 @@ profile systemd-udevd @{exec_path} flags=(attach_disconnected,complain) { /etc/systemd/network/ r, /etc/systemd/network/@{int2}-*.link r, + / r, + /usr/ r, + @{run}/credentials/systemd-udev-load-credentials.service/ r, @{run}/modprobe.d/ r, @{run}/systemd/network/ r, @{run}/systemd/network/*.link rw, - @{run}/systemd/notify rw, + @{run}/systemd/private rw, @{run}/systemd/seats/seat@{int} r, + @{run}/systemd/sessions/{,*} r, + @{run}/u-d-c-card@{int}-is-simpledrm w, - @{att}/@{run}/systemd/notify w, - @{att}/@{run}/udev/control rw, + @{att}@{run}/udev/control rw, @{run}/udev/ rw, @{run}/udev/** rwk, @@ -106,12 +123,14 @@ profile systemd-udevd @{exec_path} flags=(attach_disconnected,complain) { @{PROC}/@{pid}/mountinfo r, @{PROC}/@{pids}/cgroup r, + @{PROC}/asound/cards r, @{PROC}/devices r, @{PROC}/driver/nvidia/gpus/ r, @{PROC}/driver/nvidia/gpus/*/information r, @{PROC}/driver/nvidia/params r, @{PROC}/pressure/* r, @{PROC}/sys/fs/nr_open r, + @{PROC}/sys/vm/swappiness rw, owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/loginuid r, owner @{PROC}/@{pid}/oom_score_adj rw, @@ -119,6 +138,21 @@ profile systemd-udevd @{exec_path} flags=(attach_disconnected,complain) { /dev/ rw, /dev/** rwk, + profile kmod flags=(attach_disconnected,complain) { + include + include + + capability sys_module, + + @{sh_path} rix, + @{bin}/kmod ix, + + @{sys}/module/*/initstate r, + @{sys}/module/compression r, + + include if exists + } + profile systemctl flags=(attach_disconnected,complain) { include include @@ -126,11 +160,32 @@ profile systemd-udevd @{exec_path} flags=(attach_disconnected,complain) { capability net_admin, capability sys_ptrace, - # / r, + ptrace read peer=@{p_systemd}, include if exists } + profile run flags=(attach_disconnected,complain) { + include + include + + capability net_admin, + capability sys_ptrace, + + ptrace read peer=@{p_systemd}, + + unix bind type=stream addr=@@{udbus}/bus/systemd-run/, + + @{bin}/systemd-run mr, + @{sbin}/lvm r, + + @{att}@{run}/systemd/private rw, + + @{PROC}/@{pid}/stat r, + + include if exists + } + include if exists } diff --git a/apparmor.d/groups/systemd/systemd-update-done b/apparmor.d/groups/systemd/systemd-update-done index e7a44d01d4..867eea5a41 100644 --- a/apparmor.d/groups/systemd/systemd-update-done +++ b/apparmor.d/groups/systemd/systemd-update-done @@ -16,11 +16,16 @@ profile systemd-update-done @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, + /etc/ r, /etc/.#.updated@{hex} rw, /etc/.updated w, + + /var/ r, /var/.#.updated@{hex} rw, /var/.updated w, + / r, + @{run}/host/container-manager r, @{PROC}/1/cmdline r, diff --git a/apparmor.d/groups/systemd/systemd-update-utmp b/apparmor.d/groups/systemd/systemd-update-utmp index 82025859bf..119f18cf2f 100644 --- a/apparmor.d/groups/systemd/systemd-update-utmp +++ b/apparmor.d/groups/systemd/systemd-update-utmp @@ -17,6 +17,8 @@ profile systemd-update-utmp @{exec_path} flags=(attach_disconnected) { network netlink raw, + ptrace read peer=@{p_systemd}, + unix bind type=stream addr=@@{udbus}/bus/systemd-update-/, @{exec_path} mr, diff --git a/apparmor.d/groups/systemd/systemd-user-runtime-dir b/apparmor.d/groups/systemd/systemd-user-runtime-dir index 363b9a32d9..dc24850ba1 100644 --- a/apparmor.d/groups/systemd/systemd-user-runtime-dir +++ b/apparmor.d/groups/systemd/systemd-user-runtime-dir @@ -10,7 +10,7 @@ include profile systemd-user-runtime-dir @{exec_path} flags=(attach_disconnected) { include include - include + include include include @@ -25,12 +25,19 @@ profile systemd-user-runtime-dir @{exec_path} flags=(attach_disconnected) { mount fstype=tmpfs options=(rw,nosuid,nodev) -> @{run}/user/@{uid}/, umount @{run}/user/@{uid}/, + ptrace read peer=@{p_systemd}, + unix (bind) type=stream addr=@@{udbus}/bus/systemd-user-ru/system, @{exec_path} mr, /etc/machine-id r, + /dev/shm/ r, + /tmp/ r, + /var/tmp/ r, + + #aa:lint ignore=too-wide @{run}/user/@{uid}/{,**} rw, include if exists diff --git a/apparmor.d/groups/systemd/systemd-user-sessions b/apparmor.d/groups/systemd/systemd-user-sessions index 8de32dfe24..8b44704728 100644 --- a/apparmor.d/groups/systemd/systemd-user-sessions +++ b/apparmor.d/groups/systemd/systemd-user-sessions @@ -13,6 +13,8 @@ profile systemd-user-sessions @{exec_path} flags=(attach_disconnected) { capability net_admin, + ptrace read peer=@{p_systemd}, + @{exec_path} mr, owner @{run}/.#nologin* rw, diff --git a/apparmor.d/groups/systemd/systemd-userdbd b/apparmor.d/groups/systemd/systemd-userdbd index 20e940b1db..8cb603ec78 100644 --- a/apparmor.d/groups/systemd/systemd-userdbd +++ b/apparmor.d/groups/systemd/systemd-userdbd @@ -29,12 +29,16 @@ profile systemd-userdbd @{exec_path} flags=(attach_disconnected,mediate_deleted) /etc/shadow r, /etc/machine-id r, + /etc/userdb/{,**} r, - @{att}/@{run}/systemd/notify w, - @{att}/@{run}/systemd/userdb/io.systemd.DynamicUser rw, - @{att}/@{run}/systemd/userdb/io.systemd.Home rw, + / r, + + @{att}@{run}/systemd/userdb/io.systemd.DynamicUser rw, + @{att}@{run}/systemd/userdb/io.systemd.Home rw, + @{att}@{run}/systemd/userdb/io.systemd.Machine rw, @{run}/systemd/userdb/{,**} rw, + @{run}/userdb/{,**} rw, @{PROC}/@{pid}/cgroup r, @{PROC}/pressure/cpu r, diff --git a/apparmor.d/groups/systemd/systemd-userwork b/apparmor.d/groups/systemd/systemd-userwork index 29641fd748..ed75125c96 100644 --- a/apparmor.d/groups/systemd/systemd-userwork +++ b/apparmor.d/groups/systemd/systemd-userwork @@ -18,8 +18,12 @@ profile systemd-userwork @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, + /etc/gshadow r, /etc/machine-id r, /etc/shadow r, + /etc/userdb/ r, + + @{run}/userdb/ r, include if exists } diff --git a/apparmor.d/groups/systemd/systemd-vconsole-setup b/apparmor.d/groups/systemd/systemd-vconsole-setup index 8c99d606c7..7929be288b 100644 --- a/apparmor.d/groups/systemd/systemd-vconsole-setup +++ b/apparmor.d/groups/systemd/systemd-vconsole-setup @@ -19,6 +19,8 @@ profile systemd-vconsole-setup @{exec_path} flags=(attach_disconnected) { capability sys_resource, capability sys_tty_config, + ptrace read peer=@{p_systemd}, + @{exec_path} mr, @{sh_path} rix, @@ -34,8 +36,10 @@ profile systemd-vconsole-setup @{exec_path} flags=(attach_disconnected) { @{sys}/module/vt/parameters/default_utf8 w, + @{PROC}/sys/fs/nr_open r, + /dev/console k, - /dev/tty@{int} rwk, + /dev/tty@{u8} rwk, include if exists } diff --git a/apparmor.d/groups/systemd/timedatectl b/apparmor.d/groups/systemd/timedatectl new file mode 100644 index 0000000000..eec048c53b --- /dev/null +++ b/apparmor.d/groups/systemd/timedatectl @@ -0,0 +1,29 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/timedatectl +profile timedatectl @{exec_path} { + include + include + include + + capability net_admin, + + signal send set=cont peer=child-pager, + + #aa:dbus talk bus=system name=org.freedesktop.timedate1 label="@{p_systemd_timedated}" + #aa:dbus talk bus=system name=org.freedesktop.timesync1 label=systemd-timesyncd + + @{exec_path} mr, + + @{pager_path} rPx -> child-pager, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd/updatectl b/apparmor.d/groups/systemd/updatectl new file mode 100644 index 0000000000..7d2ba69648 --- /dev/null +++ b/apparmor.d/groups/systemd/updatectl @@ -0,0 +1,32 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/updatectl +profile updatectl @{exec_path} flags=(attach_disconnected) { + include + include + include + + signal send set=(cont term winch) peer=child-pager, + signal send set=(cont term winch) peer=pkttyagent, + + #aa:dbus talk bus=system name=org.freedesktop.sysupdate1 label=systemd-sysupdated + + @{exec_path} mr, + + @{bin}/pkttyagent rPx, + + @{PROC}/1/cgroup r, + @{PROC}/sys/kernel/random/boot_id r, + owner @{PROC}/@{pid}/cgroup r, + owner @{PROC}/@{pid}/stat r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/systemd/userdbctl b/apparmor.d/groups/systemd/userdbctl index 97625db38d..c07479a897 100644 --- a/apparmor.d/groups/systemd/userdbctl +++ b/apparmor.d/groups/systemd/userdbctl @@ -7,11 +7,13 @@ abi , include @{exec_path} = @{bin}/userdbctl -profile userdbctl @{exec_path} { +profile userdbctl @{exec_path} flags=(attach_disconnected) { include + include include include + capability net_admin, capability dac_read_search, capability sys_resource, @@ -23,12 +25,16 @@ profile userdbctl @{exec_path} { /etc/gshadow r, /etc/shadow r, + /etc/userdb/ rw, /etc/machine-id r, - @{PROC}/1/cgroup r, + @{run}/userdb/ rw, + @{run}/credentials/systemd-userdb-load-credentials.service/ r, + owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/gid_map r, + owner @{PROC}/@{pid}/setgroups r, owner @{PROC}/@{pid}/uid_map r, include if exists diff --git a/apparmor.d/groups/systemd/zram-generator b/apparmor.d/groups/systemd/zram-generator index d156d88a4a..56d6b96fe2 100644 --- a/apparmor.d/groups/systemd/zram-generator +++ b/apparmor.d/groups/systemd/zram-generator @@ -11,16 +11,13 @@ profile zram-generator @{exec_path} flags=(attach_disconnected) { include include - capability sys_module, - @{exec_path} mr, - @{bin}/kmod rix, + @{bin}/kmod rCx -> kmod, @{bin}/systemd-detect-virt rPx, @{lib}/systemd/systemd-makefs rPx, /etc/systemd/zram-generator.conf r, - /etc/modprobe.d/{,**} r, owner @{run}/systemd/generator/{,*/}var-cache-makepkg.mount rw, owner @{run}/systemd/generator/dev-zram@{int}.swap rw, @@ -29,11 +26,22 @@ profile zram-generator @{exec_path} flags=(attach_disconnected) { @{sys}/block/zram@{int}/* rw, @{sys}/devices/virtual/block/zram@{int}/* rw, - @{sys}/module/compression r, @{PROC}/crypto r, - owner /dev/pts/@{int} rw, + owner /dev/pts/@{u16} rw, + + profile kmod flags=(attach_disconnected) { + include + include + + capability sys_module, + + @{sys}/module/compression r, + @{sys}/module/lz4_compress/initstate r, + + include if exists + } include if exists } diff --git a/apparmor.d/groups/ubuntu/apport b/apparmor.d/groups/ubuntu/apport index 8219ef1853..4216296727 100644 --- a/apparmor.d/groups/ubuntu/apport +++ b/apparmor.d/groups/ubuntu/apport @@ -9,11 +9,12 @@ include @{exec_path} = /usr/share/apport/apport profile apport @{exec_path} flags=(attach_disconnected) { include - include + include + include include - include include include + include capability chown, capability dac_read_search, @@ -28,31 +29,56 @@ profile apport @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, @{bin}/{,e,f}grep rix, - @{bin}/dpkg rPx -> child-dpkg, - @{bin}/dpkg-divert rPx -> child-dpkg-divert, + @{bin}/* r, + @{bin}/dpkg rPx -> apport//&child-dpkg, + @{bin}/dpkg-divert rPx -> apport//&child-dpkg-divert, @{bin}/gdbus rix, @{bin}/md5sum rix, - /usr/share/apport/{,**} r, - @{etc_ro}/login.defs r, - /etc/apport/report-ignore/{,**} r, + /etc/apport/{,**} r, + /etc/dpkg/dpkg.cfg r, + /etc/dpkg/dpkg.cfg.d/{,**} r, + + # Apport needs access to all install path of packages to report problems. + /usr/{,**} r, + /opt/{,**} r, /var/lib/dpkg/info/ r, /var/lib/dpkg/info/*.list r, /var/lib/dpkg/info/*.md5sums r, + /var/lib/dpkg/diversions r, + /var/lib/dpkg/triggers/* r, + /var/lib/dpkg/updates/{,*} r, + + /var/lib/apport/{,**} r, + /var/lib/ispell/{,**} r, + /var/lib/systemd/coredump/{,**} r, /var/crash/ rw, /var/crash/*.@{uid}.crash rw, owner /var/cache/apt/pkgcache.bin.@{rand6} rw, owner /var/log/apport.log rw, + /{run,var}/log/journal/ r, + /{run,var}/log/journal/@{hex32}/ r, + /{run,var}/log/journal/@{hex32}/system.journal* r, + /{run,var}/log/journal/@{hex32}/system@@{hex}-@{hex}.journal* r, + /{run,var}/log/journal/@{hex32}/system@@{hex32}-@{hex16}-@{hex16}.journal* r, + /{run,var}/log/journal/@{hex32}/user-@{hex}.journal* r, + /{run,var}/log/journal/@{hex32}/user-@{uid}@@{hex}-@{hex}.journal* r, + /{run,var}/log/journal/@{hex32}/user-@{uid}@@{hex32}-@{hex16}-@{hex16}.journal* r, + @{run}/apport.lock rwk, + @{run}/log/journal/ r, - @{PROC}/@{pid}/cgroup r, - @{PROC}/@{pid}/environ r, - @{PROC}/@{pid}/fd/ r, - @{PROC}/@{pid}/stat r, + @{PROC}/@{pids}/cgroup r, + @{PROC}/@{pids}/environ r, + @{PROC}/@{pids}/fd/ r, + @{PROC}/@{pids}/fdinfo/@{int} r, + @{PROC}/@{pids}/maps r, + @{PROC}/@{pids}/stat r, + @{PROC}/@{pids}/status r, @{PROC}/sys/fs/suid_dumpable w, @{PROC}/sys/kernel/core_pattern w, @{PROC}/sys/kernel/core_pipe_limit w, diff --git a/apparmor.d/groups/ubuntu/apport-gtk b/apparmor.d/groups/ubuntu/apport-gtk index 0121dd46db..cdd616f5e8 100644 --- a/apparmor.d/groups/ubuntu/apport-gtk +++ b/apparmor.d/groups/ubuntu/apport-gtk @@ -9,14 +9,11 @@ include @{exec_path} = /usr/share/apport/apport-gtk profile apport-gtk @{exec_path} { include + include include - include - include - include - include - include include include + include include include include @@ -29,10 +26,12 @@ profile apport-gtk @{exec_path} { network inet6 stream, network inet dgram, network inet6 dgram, + network netlink raw, @{exec_path} mr, @{sh_path} rix, + @{python_path} rix, @{bin}/{f,}grep rix, @{bin}/apt-cache rPx, @{bin}/cut rix, @@ -41,22 +40,26 @@ profile apport-gtk @{exec_path} { @{bin}/dpkg-query rpx, @{bin}/gdb rCx -> gdb, @{bin}/gsettings rPx, - @{bin}/ischroot rix, + @{bin}/ischroot rPx, @{bin}/journalctl rPx, - @{bin}/killall5 rix, @{bin}/kmod rPx, @{bin}/ldd rix, - @{bin}/lsb_release rPx -> lsb_release, + @{bin}/lsb_release rPx, @{bin}/md5sum rix, @{bin}/pkexec rCx -> pkexec, + @{bin}/readlink rix, @{bin}/systemctl rCx -> systemctl, @{bin}/systemd-detect-virt rPx, @{bin}/uname rix, @{bin}/which{,.debianutils} rix, + @{sbin}/killall5 rix, @{lib}/{,colord/}colord-sane rPx, @{lib}/@{multiarch}/ld*.so* rix, /usr/share/apport/root_info_wrapper rix, + @{bin}/* r, + @{sbin}/* r, + /usr/share/apport/{,**} r, /usr/share/apport/general-hooks/*.py r, @@ -79,9 +82,10 @@ profile apport-gtk @{exec_path} { /var/crash/ rw, owner /var/crash/*.@{uid}.{crash,upload} rw, + @{run}/cloud-init/cloud.cfg r, @{run}/snapd.socket rw, - owner @{tmp}/@{rand8} rw, + owner @{tmp}/@{word8} rw, owner @{tmp}/apport_core_@{rand8} rw, owner @{tmp}/launchpadlib.cache.@{rand8}/ rw, owner @{tmp}/tmp@{rand8}/{,**} rw, @@ -110,7 +114,6 @@ profile apport-gtk @{exec_path} { /usr/share/gdb/python/{,**/}__pycache__/{,**} rw, /usr/share/gdb/{,**} r, - /usr/share/glib-2.0/schemas/gschemas.compiled r, /usr/share/gnome-shell/{,**} r, /usr/share/terminfo/** r, /usr/share/themes/{,**} r, @@ -135,6 +138,15 @@ profile apport-gtk @{exec_path} { include include + dbus send bus=system path=/org/freedesktop/systemd1 + interface=org.freedesktop.DBus.Properties + member=Get + peer=(name=org.freedesktop.systemd1, label=unconfined), + dbus send bus=system path=/org/freedesktop/systemd1 + interface=org.freedesktop.systemd1.Manager + member=GetUnitFileState + peer=(name=org.freedesktop.systemd1, label=unconfined), + include if exists } diff --git a/apparmor.d/groups/ubuntu/apt-esm-hook b/apparmor.d/groups/ubuntu/apt-esm-hook index a04fc771d4..2555d03731 100644 --- a/apparmor.d/groups/ubuntu/apt-esm-hook +++ b/apparmor.d/groups/ubuntu/apt-esm-hook @@ -9,7 +9,7 @@ include @{exec_path} = @{lib}/ubuntu-advantage/apt-esm-hook profile apt-esm-hook @{exec_path} { include - include + include include @{exec_path} mr, diff --git a/apparmor.d/groups/ubuntu/apt-esm-json-hook b/apparmor.d/groups/ubuntu/apt-esm-json-hook index 2edc099700..e8f03807d4 100644 --- a/apparmor.d/groups/ubuntu/apt-esm-json-hook +++ b/apparmor.d/groups/ubuntu/apt-esm-json-hook @@ -9,7 +9,7 @@ include @{exec_path} = @{lib}/ubuntu-advantage/apt-esm-json-hook profile apt-esm-json-hook @{exec_path} { include - include + include include unix (receive, send) type=stream peer=(label=apt), diff --git a/apparmor.d/groups/ubuntu/apt_news b/apparmor.d/groups/ubuntu/apt_news new file mode 100644 index 0000000000..91c8b29cc2 --- /dev/null +++ b/apparmor.d/groups/ubuntu/apt_news @@ -0,0 +1,40 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/ubuntu-advantage/apt_news.py +profile apt_news @{exec_path} flags=(attach_disconnected) { + include + include + include + include + + capability chown, + capability fowner, + capability kill, + capability setgid, + capability setuid, + + signal send set=int peer=apt-methods-*, + + @{exec_path} mr, + + @{lib}/apt/methods/* Px, + + /etc/ubuntu-advantage/uaclient.conf r, + + @{run}/ubuntu-advantage/ rw, + @{run}/ubuntu-advantage/apt-news/{,**} rw, + + owner @{run}/ubuntu-advantage/apt-news/** rw, + + @{PROC}/@{pid}/fd/ r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/ubuntu/check-new-release-gtk b/apparmor.d/groups/ubuntu/check-new-release-gtk index 1ff6df2ae4..792bab11f4 100644 --- a/apparmor.d/groups/ubuntu/check-new-release-gtk +++ b/apparmor.d/groups/ubuntu/check-new-release-gtk @@ -9,11 +9,8 @@ include @{exec_path} = @{lib}/ubuntu-release-upgrader/check-new-release-gtk profile check-new-release-gtk @{exec_path} { include - include - include - include - include - include + include + include include include include @@ -29,8 +26,8 @@ profile check-new-release-gtk @{exec_path} { @{exec_path} mr, @{bin}/dpkg rPx, - @{bin}/ischroot rix, - @{bin}/lsb_release rPx -> lsb_release, + @{bin}/ischroot rPx, + @{bin}/lsb_release rPx, @{lib}/@{python_name}/dist-packages/UpdateManager/**/__pycache__/*.cpython-@{int}.pyc.@{int} w, @{lib}/@{python_name}/dist-packages/gi/**/__pycache__/*.cpython-@{int}.pyc.@{int} w, @@ -38,7 +35,6 @@ profile check-new-release-gtk @{exec_path} { /usr/share/distro-info/{,**} r, /usr/share/ubuntu-release-upgrader/{,**} r, /usr/share/update-manager/{,**} r, - /usr/share/dconf/profile/gdm r, /etc/update-manager/{,**} r, @@ -46,7 +42,6 @@ profile check-new-release-gtk @{exec_path} { /var/cache/apt/ rw, - owner @{DESKTOP_HOME}/greeter-dconf-defaults r, owner @{desktop_cache_dirs}/update-manager-core/ rwk, owner @{desktop_cache_dirs}/update-manager-core/meta-release-lts rw, diff --git a/apparmor.d/groups/ubuntu/cron-ubuntu-fan b/apparmor.d/groups/ubuntu/cron-ubuntu-fan index c5c31edd34..a80a4f7293 100644 --- a/apparmor.d/groups/ubuntu/cron-ubuntu-fan +++ b/apparmor.d/groups/ubuntu/cron-ubuntu-fan @@ -15,20 +15,14 @@ profile cron-ubuntu-fan @{exec_path} { @{exec_path} mr, @{sh_path} rix, - @{bin}/fanctl rix, - @{bin}/flock rix, - @{bin}/grep rix, - @{bin}/id rix, + @{sbin}/fanctl rPx, + @{bin}/{,e}grep rix, @{bin}/ip rix, @{bin}/mkdir rix, @{bin}/sed rix, - @{bin}/touch rix, /etc/network/fan r, - @{run}/ubuntu-fan/ rw, - @{run}/ubuntu-fan/.lock rwk, - include if exists } diff --git a/apparmor.d/groups/ubuntu/do-release-upgrade b/apparmor.d/groups/ubuntu/do-release-upgrade index 86c211f24c..804f21133a 100644 --- a/apparmor.d/groups/ubuntu/do-release-upgrade +++ b/apparmor.d/groups/ubuntu/do-release-upgrade @@ -7,15 +7,22 @@ abi , include @{exec_path} = @{bin}/do-release-upgrade -profile do-release-upgrade @{exec_path} { +profile do-release-upgrade @{exec_path} flags=(attach_disconnected) { include - include + include include include include include + capability chown, + capability dac_override, + capability dac_read_search, + capability fowner, + capability fsetid, capability net_admin, + capability setgid, + capability setuid, network inet dgram, network inet6 dgram, @@ -26,8 +33,10 @@ profile do-release-upgrade @{exec_path} { @{exec_path} mr, @{bin}/dpkg rPx -> child-dpkg, - @{bin}/ischroot rix, - @{bin}/lsb_release rPx -> lsb_release, + @{bin}/ischroot rPx, + @{bin}/lsb_release rPx, + @{bin}/gpg rPx, + @{lib}/apt/methods/http{,s} rPx, /usr/share/distro-info/*.csv r, /usr/share/ubuntu-release-upgrader/{,**} r, @@ -44,9 +53,24 @@ profile do-release-upgrade @{exec_path} { /var/cache/apt/srcpkgcache.bin rw, /var/cache/apt/srcpkgcache.bin.@{rand6} rw, + /tmp/ubuntu-release-upgrader-@{rand8}/ rw, + /tmp/ubuntu-release-upgrader-@{rand8}/** rwlk, + /tmp/ubuntu-release-upgrader-@{rand8}/* Cx -> upgrader, + /tmp/@{rand8} rw, + @{PROC}/@{pids}/mountinfo r, owner @{PROC}/@{pid}/fd/ r, + profile upgrader flags=(attach_disconnected) { + include + + # The upgrader process is not confined on purpose. We explicitly allow + # everything to avoid transitioning to any other profile. + all, + + include if exists + } + include if exists } diff --git a/apparmor.d/groups/ubuntu/esm_cache b/apparmor.d/groups/ubuntu/esm_cache new file mode 100644 index 0000000000..53238564aa --- /dev/null +++ b/apparmor.d/groups/ubuntu/esm_cache @@ -0,0 +1,19 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/ubuntu-advantage/esm_cache.py +profile esm_cache @{exec_path} { + include + include + + @{exec_path} mr, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/ubuntu/fanctl b/apparmor.d/groups/ubuntu/fanctl new file mode 100644 index 0000000000..6f08358ee5 --- /dev/null +++ b/apparmor.d/groups/ubuntu/fanctl @@ -0,0 +1,35 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{sbin}/fanctl +profile fanctl @{exec_path} flags=(attach_disconnected) { + include + + capability sys_admin, # optional: no audit + + network netlink raw, + + @{exec_path} mr, + + @{sh_path} rix, + @{bin}/flock ix, + @{bin}/id ix, + @{bin}/touch ix, + @{bin}/mkdir ix, + @{bin}/ip ix, + @{bin}/sed ix, + + /etc/network/fan r, + + @{run}/ubuntu-fan/ rw, + @{run}/ubuntu-fan/.lock rwk, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/ubuntu/hwe-support-status b/apparmor.d/groups/ubuntu/hwe-support-status index 3b4280e33c..c85fb9966b 100644 --- a/apparmor.d/groups/ubuntu/hwe-support-status +++ b/apparmor.d/groups/ubuntu/hwe-support-status @@ -9,13 +9,13 @@ include @{exec_path} = @{bin}/hwe-support-status profile hwe-support-status @{exec_path} { include - include + include include @{exec_path} mr, @{bin}/dpkg rPx, - @{bin}/lsb_release rPx -> lsb_release, + @{bin}/lsb_release rPx, /usr/share/distro-info/{,**} r, diff --git a/apparmor.d/groups/ubuntu/list-oem-metapackages b/apparmor.d/groups/ubuntu/list-oem-metapackages index 75e4279f21..5e4b09ce31 100644 --- a/apparmor.d/groups/ubuntu/list-oem-metapackages +++ b/apparmor.d/groups/ubuntu/list-oem-metapackages @@ -9,13 +9,13 @@ include @{exec_path} = @{lib}/update-notifier/list-oem-metapackages profile list-oem-metapackages @{exec_path} { include + include include - include @{exec_path} mr, @{bin}/dpkg rPx -> child-dpkg, - @{bin}/ischroot rix, + @{bin}/ischroot rPx, @{lib}/@{python_name}/dist-packages/UbuntuDrivers/__pycache__/*.cpython-@{int}.pyc.@{int} rw, diff --git a/apparmor.d/groups/ubuntu/livepatch-notification b/apparmor.d/groups/ubuntu/livepatch-notification index 4d5ecb46a0..ef516e8d6a 100644 --- a/apparmor.d/groups/ubuntu/livepatch-notification +++ b/apparmor.d/groups/ubuntu/livepatch-notification @@ -9,10 +9,6 @@ include @{exec_path} = @{lib}/update-notifier/livepatch-notification profile livepatch-notification @{exec_path} { include - include - include - include - include include include diff --git a/apparmor.d/groups/ubuntu/package-data-downloader b/apparmor.d/groups/ubuntu/package-data-downloader index c193bbe0c6..1703d27cda 100644 --- a/apparmor.d/groups/ubuntu/package-data-downloader +++ b/apparmor.d/groups/ubuntu/package-data-downloader @@ -9,11 +9,13 @@ include @{exec_path} = @{lib}/update-notifier/package-data-downloader profile package-data-downloader @{exec_path} { include - include + include include include include + capability dac_read_search, + @{exec_path} mr, /var/lib/update-notifier/package-data-downloads/{,**} rw, diff --git a/apparmor.d/groups/ubuntu/package-system-locked b/apparmor.d/groups/ubuntu/package-system-locked index 7398fc4044..8cf3ed885a 100644 --- a/apparmor.d/groups/ubuntu/package-system-locked +++ b/apparmor.d/groups/ubuntu/package-system-locked @@ -17,7 +17,7 @@ profile package-system-locked @{exec_path} flags=(attach_disconnected) { network inet dgram, network inet6 dgram, - mqueue r type=posix /, + mqueue (read,getattr) type=posix /, ptrace (read), diff --git a/apparmor.d/groups/ubuntu/release-upgrade-motd b/apparmor.d/groups/ubuntu/release-upgrade-motd index b5d7d2885c..f6d678f7be 100644 --- a/apparmor.d/groups/ubuntu/release-upgrade-motd +++ b/apparmor.d/groups/ubuntu/release-upgrade-motd @@ -10,6 +10,10 @@ include profile release-upgrade-motd @{exec_path} { include + capability dac_read_search, + + mqueue getattr type=posix, + @{exec_path} mr, @{sh_path} rix, @@ -24,7 +28,9 @@ profile release-upgrade-motd @{exec_path} { @{run}/motd.dynamic.new w, - /dev/tty@{int} rw, + @{PROC}/@{pid}/mountinfo r, + + /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/ubuntu/software-properties-dbus b/apparmor.d/groups/ubuntu/software-properties-dbus index c4c7956496..9e461b269d 100644 --- a/apparmor.d/groups/ubuntu/software-properties-dbus +++ b/apparmor.d/groups/ubuntu/software-properties-dbus @@ -9,30 +9,32 @@ include @{exec_path} = @{lib}/software-properties/software-properties-dbus profile software-properties-dbus @{exec_path} { include - include + include include + include include include - #aa:dbus own bus=system name=com.ubuntu.SoftwareProperties + #aa:dbus own bus=system name=com.ubuntu.SoftwareProperties path=/ dbus receive bus=session interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), dbus receive bus=system interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=software-properties-gtk), + peer=(name=@{busname}, label=software-properties-gtk), @{exec_path} mr, @{python_path} rix, @{bin}/env rix, @{bin}/apt-key rPx, # Changing trusted keys - @{bin}/lsb_release rPx -> lsb_release, + @{bin}/lsb_release rPx, /etc/apt/apt.conf.d/10periodic w, + /etc/apt/sources.list.d/{,*} rw, /etc/apt/sources.list{,.save} rw, /usr/share/python-apt/{,**} r, diff --git a/apparmor.d/groups/ubuntu/software-properties-gtk b/apparmor.d/groups/ubuntu/software-properties-gtk index e2bb2dc988..229e8d577b 100644 --- a/apparmor.d/groups/ubuntu/software-properties-gtk +++ b/apparmor.d/groups/ubuntu/software-properties-gtk @@ -7,21 +7,20 @@ abi , include @{exec_path} = @{bin}/software-properties-gtk -profile software-properties-gtk @{exec_path} { +profile software-properties-gtk @{exec_path} flags=(attach_disconnected) { include - include - include - include - include - include - include + include + include include include include include #aa:dbus own bus=session name=com.ubuntu.SoftwareProperties + #aa:dbus talk bus=system name=com.canonical.UbuntuAdvantage label=ubuntu-advantage-desktop-daemon + #aa:dbus talk bus=system name=com.ubuntu.SoftwareProperties path=/ label=software-properties-dbus + #aa:dbus talk bus=system name=org.freedesktop.PackageKit path=/** label=packagekitd @{exec_path} mr, @@ -32,15 +31,15 @@ profile software-properties-gtk @{exec_path} { @{bin}/aplay rPx, @{bin}/apt-key rPx, @{bin}/dpkg rPx -> child-dpkg, - @{bin}/ischroot rix, - @{bin}/lsb_release rPx -> lsb_release, + @{bin}/gpg rPx, # TODO: apt-gpg dedicated profile? + @{bin}/ischroot rPx, + @{bin}/lsb_release rPx, @{bin}/ubuntu-advantage rPx, /usr/share/distro-info/*.csv r, /usr/share/pixmaps/ r, /usr/share/python-apt/{,**} r, /usr/share/software-properties/{,**} r, - /usr/share/themes/{,**} r, /usr/share/ubuntu-drivers-common/detect/{,**} r, /usr/share/X11/xkb/{,**} r, /usr/share/xml/iso-codes/{,**} r, @@ -57,6 +56,10 @@ profile software-properties-gtk @{exec_path} { owner @{tmp}/tmp@{word8}/ rw, owner @{tmp}/tmp@{word8}/apt.conf rw, + /dev/shm/ r, + owner /dev/shm/sem.@{rand6} rwl -> /dev/shm/sem.@{rand6}, + owner /dev/shm/sem.mp-@{word8} rwl -> /dev/shm/sem.@{rand6}, + owner @{run}/user/@{uid}/gnome-shell-disable-extensions w, @{sys}/devices/ r, @@ -70,6 +73,7 @@ profile software-properties-gtk @{exec_path} { owner @{PROC}/@{pid}/environ r, owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/mounts r, + owner @{PROC}/@{pid}/stat r, # Silencer deny @{user_share_dirs}/gvfs-metadata/* r, diff --git a/apparmor.d/groups/ubuntu/subiquity-console-conf b/apparmor.d/groups/ubuntu/subiquity-console-conf index 58323b8ff4..166c8463ec 100644 --- a/apparmor.d/groups/ubuntu/subiquity-console-conf +++ b/apparmor.d/groups/ubuntu/subiquity-console-conf @@ -24,7 +24,7 @@ profile subiquity-console-conf @{exec_path} { @{sh_path} rix, @{bin}/cat rix, - @{bin}/grep rix, + @{bin}/{,e}grep rix, @{bin}/ip rix, @{bin}/mkdir rix, @{bin}/mv rix, @@ -35,10 +35,10 @@ profile subiquity-console-conf @{exec_path} { @{bin}/journalctl rCx -> journalctl, @{bin}/ssh-keygen rPx, - @{bin}/sshd rPx, + @{sbin}/sshd rPx, @{bin}/snap rPUx, - /usr/lib/snapd/snap-recovery-chooser rPUx, - /usr/share/netplan/netplan.script rPUx, # TODO: rPx, + @{lib}/snapd/snap-recovery-chooser rPUx, + /usr/share/netplan/netplan.script rPx, /usr/share/subiquity/{,**} r, /usr/share/subiquity/console-conf-tui rix, @@ -53,13 +53,13 @@ profile subiquity-console-conf @{exec_path} { @{run}/snapd-recovery-chooser-triggered r, @{run}/snapd.socket rw, - @{run}/udev/data/+acpi:* r, + @{run}/udev/data/+acpi:* r, # Exposes ACPI objects (power buttons, batteries, thermal) @{run}/udev/data/+dmi:* r, # For motherboard info @{run}/udev/data/+drm:card@{int}-* r, # For screen outputs @{run}/udev/data/+input:input@{int} r, # for mouse, keyboard, touchpad - @{run}/udev/data/+leds:* r, + @{run}/udev/data/+leds:* r, # Identifies all LEDs (keyboard, mouse, etc.) @{run}/udev/data/+pci:* r, # Identifies all PCI devices (CPU, GPU, Network, Disks, USB, etc.) - @{run}/udev/data/+platform:* r, + @{run}/udev/data/+platform:* r, # Identifies onboard devices (laptop/board model, power controllers, thermal sensors) @{run}/udev/data/+sound:card@{int} r, # For sound card @{run}/udev/data/c1:@{int} r, # For RAM disk @@ -72,9 +72,9 @@ profile subiquity-console-conf @{exec_path} { @{run}/udev/data/c89:@{int} r, # For I2C bus interface @{run}/udev/data/c108:@{int} r, # For /dev/ppp @{run}/udev/data/c116:@{int} r, # For ALSA - @{run}/udev/data/c226:@{int} r, # For /dev/dri/card* + @{run}/udev/data/c226:@{int} r, # For DRI card /dev/dri/card@{int} @{run}/udev/data/c@{dynamic}:@{int} r, # For dynamic assignment range 234 to 254, 384 to 511 - @{run}/udev/data/n@{int} r, + @{run}/udev/data/n@{int} r, # For network interfaces @{sys}/**/devices/ r, @{sys}/*/*/ r, @@ -89,7 +89,7 @@ profile subiquity-console-conf @{exec_path} { owner @{PROC}/@{pid}/fd/ r, /dev/tty rw, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, /dev/ttyS@{int} rw, profile journalctl { diff --git a/apparmor.d/groups/ubuntu/ubuntu-advantage b/apparmor.d/groups/ubuntu/ubuntu-advantage index 7d797bd974..623f670bb0 100644 --- a/apparmor.d/groups/ubuntu/ubuntu-advantage +++ b/apparmor.d/groups/ubuntu/ubuntu-advantage @@ -9,7 +9,8 @@ include @{exec_path} = @{bin}/ubuntu-advantage profile ubuntu-advantage @{exec_path} { include - include + include + include include include include @@ -29,13 +30,12 @@ profile ubuntu-advantage @{exec_path} { @{exec_path} mr, - @{bin}/ischroot rix, - @{bin}/apt rPx, @{bin}/apt-cache rPx, @{bin}/apt-config rPx, @{bin}/apt-get rPx, @{bin}/dpkg rPx -> child-dpkg, + @{bin}/ischroot rPx, @{bin}/ps rPx, @{bin}/snap rPUx, @{bin}/systemctl rCx -> systemctl, @@ -49,9 +49,17 @@ profile ubuntu-advantage @{exec_path} { /etc/apt/trusted.gpg.d/{,**} rw, /etc/apt/sources.list.d/{,**} rw, /etc/ubuntu-advantage/{,**} r, + /etc/machine-id r, + /var/lib/ubuntu-advantage/{,**} rw, - /etc/machine-id r, + /var/log/ubuntu-advantage.log w, + + owner /var/cache/apt/ w, + + owner @{desktop_cache_dirs}/ubuntu-pro/{,**} rw, + + owner @{user_cache_dirs}/ubuntu-pro/{,**} rw, owner @{tmp}/tmp[0-9a-z]*/apt.conf r, owner @{tmp}/[0-9a-z]*{,/} rw, @@ -59,9 +67,10 @@ profile ubuntu-advantage @{exec_path} { @{run}/ubuntu-advantage/{,**} rw, - @{PROC}/version_signature r, @{PROC}/@{pids}/mountinfo r, @{PROC}/@{pids}/mounts r, + @{PROC}/1/cgroup r, + @{PROC}/version_signature r, owner @{PROC}/@{pid}/fd/ r, profile systemctl { diff --git a/apparmor.d/groups/ubuntu/ubuntu-advantage-notification b/apparmor.d/groups/ubuntu/ubuntu-advantage-notification index bf3d4c6c05..421a005fc8 100644 --- a/apparmor.d/groups/ubuntu/ubuntu-advantage-notification +++ b/apparmor.d/groups/ubuntu/ubuntu-advantage-notification @@ -9,12 +9,9 @@ include @{exec_path} = @{lib}/update-notifier/ubuntu-advantage-notification profile ubuntu-advantage-notification @{exec_path} { include - include - include - include - include include include + include @{exec_path} mr, diff --git a/apparmor.d/groups/ubuntu/ubuntu-fan-net b/apparmor.d/groups/ubuntu/ubuntu-fan-net new file mode 100644 index 0000000000..ab83ebed46 --- /dev/null +++ b/apparmor.d/groups/ubuntu/ubuntu-fan-net @@ -0,0 +1,36 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/ubuntu-fan/fan-net +profile ubuntu-fan-net @{exec_path} { + include + + @{exec_path} mr, + + @{sh_path} mr, + @{bin}/{m,g,}awk ix, + @{bin}/kmod Cx -> kmod, + @{bin}/{,e}grep ix, + @{bin}/networkctl Px, + @{sbin}/fanctl Px, + + profile kmod { + include + include + + capability sys_module, + + @{sys}/module/compression r, + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/ubuntu/ubuntu-report b/apparmor.d/groups/ubuntu/ubuntu-report index 19273f449b..80ffda2883 100644 --- a/apparmor.d/groups/ubuntu/ubuntu-report +++ b/apparmor.d/groups/ubuntu/ubuntu-report @@ -21,7 +21,10 @@ profile ubuntu-report @{exec_path} { @{bin}/dpkg rPx -> child-dpkg, - owner @{user_cache_dirs}/ubuntu-report/{,*} r, + owner @{user_cache_dirs}/ubuntu-report/{,*} rw, + + owner @{PROC}/@{pid}/cgroup r, + owner @{PROC}/@{pid}/mountinfo r, include if exists } diff --git a/apparmor.d/groups/ubuntu/update-manager b/apparmor.d/groups/ubuntu/update-manager index 44e0cc403a..5f9d383d3b 100644 --- a/apparmor.d/groups/ubuntu/update-manager +++ b/apparmor.d/groups/ubuntu/update-manager @@ -9,23 +9,18 @@ include @{exec_path} = @{bin}/update-manager profile update-manager @{exec_path} flags=(attach_disconnected) { include + include include - include - include - include - include - include - include - include - include - include - include + include + include include include include include + include include include + include network inet dgram, network inet6 dgram, @@ -44,16 +39,16 @@ profile update-manager @{exec_path} flags=(attach_disconnected) { @{sh_path} rix, @{bin}/dpkg rPx -> child-dpkg, @{bin}/hwe-support-status rPx, - @{bin}/ischroot rix, - @{bin}/lsb_release rPx -> lsb_release, + @{bin}/ischroot rPx, + @{bin}/lsb_release rPx, @{bin}/snap rPUx, @{bin}/software-properties-gtk rPx, @{bin}/uname rix, @{lib}/apt/methods/http{,s} rPx, - @{lib}/@{python_name}/dist-packages/UpdateManager/{,**/}__pycache__/*.cpython-@{int}.pyc.@{int} rw, - @{lib}/@{python_name}/dist-packages/gi/{,**/}__pycache__/*.cpython-@{int}.pyc.@{int} rw, - @{lib}/@{python_name}/dist-packages/uaclient/{,**/}__pycache__/*.cpython-@{int}.pyc.@{int} rw, + @{lib}/@{python_name}/dist-packages/UpdateManager/{,**/}__pycache__/*.cpython-@{int}.pyc.@{u64} rw, + @{lib}/@{python_name}/dist-packages/gi/{,**/}__pycache__/*.cpython-@{int}.pyc.@{u64} rw, + @{lib}/@{python_name}/dist-packages/uaclient/{,**/}__pycache__/*.cpython-@{int}.pyc.@{u64} rw, /usr/share/distro-info/{,**} r, /usr/share/ubuntu-release-upgrader/{,**} r, @@ -63,7 +58,7 @@ profile update-manager @{exec_path} flags=(attach_disconnected) { /etc/ubuntu-advantage/uaclient.conf r, /etc/update-manager/{,**} r, - /boot/ r, + @{efi}/ r, /var/lib/dpkg/info/*.list r, /var/lib/dpkg/updates/ r, @@ -71,9 +66,14 @@ profile update-manager @{exec_path} flags=(attach_disconnected) { owner @{user_cache_dirs}/update-manager-core/{,**} rw, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + owner @{run}/user/@{uid}/ubuntu-drivers*.package-list w, + + @{att}@{run}/systemd/inhibit/@{int}.ref rw, + + @{sys}/devices/**/ r, @{PROC}/@{pids}/mountinfo r, + owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/mounts r, diff --git a/apparmor.d/groups/ubuntu/update-motd-fsck-at-reboot b/apparmor.d/groups/ubuntu/update-motd-fsck-at-reboot index 77b24fa279..6629e65aab 100644 --- a/apparmor.d/groups/ubuntu/update-motd-fsck-at-reboot +++ b/apparmor.d/groups/ubuntu/update-motd-fsck-at-reboot @@ -7,18 +7,23 @@ abi , include @{exec_path} = @{lib}/update-notifier/update-motd-fsck-at-reboot -profile update-motd-fsck-at-reboot @{exec_path} { +profile update-motd-fsck-at-reboot @{exec_path} flags=(attach_disconnected) { include + include + + capability dac_read_search, + + mqueue getattr type=posix, @{exec_path} mr, - @{bin}/dumpe2fs rPx, + @{sbin}/dumpe2fs rPx, @{sh_path} rix, @{bin}/{m,g,}awk rix, @{bin}/cat rix, @{bin}/cut rix, @{bin}/date rix, - @{bin}/grep rix, + @{bin}/{,e}grep rix, @{bin}/id rix, @{bin}/mount rCx -> mount, @{bin}/stat rix, @@ -28,8 +33,9 @@ profile update-motd-fsck-at-reboot @{exec_path} { @{run}/motd.dynamic.new w, @{PROC}/uptime r, + @{PROC}/@{pid}/mountinfo r, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, profile mount { include @@ -45,7 +51,7 @@ profile update-motd-fsck-at-reboot @{exec_path} { @{PROC}/@{pid}/mountinfo r, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/ubuntu/update-motd-updates-available b/apparmor.d/groups/ubuntu/update-motd-updates-available index 776cc9bf8a..09775cb6f4 100644 --- a/apparmor.d/groups/ubuntu/update-motd-updates-available +++ b/apparmor.d/groups/ubuntu/update-motd-updates-available @@ -9,7 +9,7 @@ include @{exec_path} = @{lib}/update-notifier/update-motd-updates-available profile update-motd-updates-available @{exec_path} { include - include + include include include include @@ -26,8 +26,8 @@ profile update-motd-updates-available @{exec_path} { @{bin}/dirname rix, @{bin}/dpkg rPx -> child-dpkg, @{bin}/find rix, - @{bin}/ischroot rix, - @{bin}/lsb_release rPx -> lsb_release, + @{bin}/ischroot rPx, + @{bin}/lsb_release rPx, @{bin}/mktemp rix, @{bin}/mv rix, @{bin}/rm rix, diff --git a/apparmor.d/groups/ubuntu/update-notifier b/apparmor.d/groups/ubuntu/update-notifier index 8d1571c1ec..c752934e20 100644 --- a/apparmor.d/groups/ubuntu/update-notifier +++ b/apparmor.d/groups/ubuntu/update-notifier @@ -9,15 +9,10 @@ include @{exec_path} = @{bin}/update-notifier profile update-notifier @{exec_path} { include + include include - include - include - include - include - include - include - include include + include include include include @@ -25,17 +20,22 @@ profile update-notifier @{exec_path} { unix (bind) type=stream addr=@@{udbus}/bus/systemd/bus-api-user, #aa:dbus talk bus=system name=org.debian.apt label=apt - #aa:dbus talk bus=session name=org.ayatana.NotificationItem label=gnome-shell + #aa:dbus talk bus=session name=org.ayatana.NotificationItem interface+=org.kde.StatusNotifierItem label=gnome-shell + + dbus receive bus=system path=/com/ubuntu/UnattendedUpgrade/Pending + interface=com.ubuntu.UnattendedUpgrade.Pending + member={Started,Finished} + peer=(name=@{busname}, label=unattended-upgrade), @{exec_path} mr, @{sh_path} rix, @{bin}/ionice rix, - @{bin}/ischroot rix, @{bin}/nice rix, @{bin}/dpkg rPx -> child-dpkg, - @{bin}/lsb_release rPx -> lsb_release, + @{bin}/ischroot rPx, + @{bin}/lsb_release rPx, @{bin}/pkexec rCx -> pkexec, @{bin}/snap rPUx, @{bin}/software-properties-gtk rPx, @@ -48,6 +48,7 @@ profile update-notifier @{exec_path} { @{lib}/update-notifier/package-system-locked rPx, /usr/share/apport/apport-checkreports rPx, /usr/share/apport/apport-gtk rPx, + @{open_path} Cx -> open, @{lib}/@{python_name}/dist-packages/{apt,gi}/**/__pycache__/{,**} rw, @@ -66,6 +67,7 @@ profile update-notifier @{exec_path} { owner @{tmp}/#@{int} rw, @{PROC}/@{pids}/mountinfo r, + owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/fd/ r, profile pkexec { @@ -85,7 +87,6 @@ profile update-notifier @{exec_path} { profile systemctl { include include - include dbus send bus=system path=/org/freedesktop/systemd1 interface=org.freedesktop.systemd1.Manager @@ -95,6 +96,16 @@ profile update-notifier @{exec_path} { include if exists } + profile open { + include + include + + @{bin}/update-manager Px, + @{bin}/software-properties-gtk Px, + + include if exists + } + include if exists } diff --git a/apparmor.d/groups/ubuntu/update-notifier-crash b/apparmor.d/groups/ubuntu/update-notifier-crash new file mode 100644 index 0000000000..eb00eeac9a --- /dev/null +++ b/apparmor.d/groups/ubuntu/update-notifier-crash @@ -0,0 +1,41 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/update-notifier/update-notifier-crash +profile update-notifier-crash @{exec_path} { + include + include + + @{exec_path} mr, + + @{bin}/{,e}grep ix, + @{bin}/groups Px, + @{bin}/systemctl Cx -> systemctl, + @{bin}/which{,.debianutils} rix, + @{sh_path} mr, + @{lib}/update-notifier/system-crash-notification PUx, # TODO: Px + /usr/share/apport/apport-checkreports Px, + + owner @{HOME}/ r, + + profile systemctl { + include + include + + dbus send bus=system path=/org/freedesktop/systemd1 + interface=org.freedesktop.systemd1.Manager + member=GetUnitFileState + peer=(name=org.freedesktop.systemd1, label="@{p_systemd}"), + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/umu/umu-bwrap b/apparmor.d/groups/umu/umu-bwrap new file mode 100644 index 0000000000..ce59ccb1f1 --- /dev/null +++ b/apparmor.d/groups/umu/umu-bwrap @@ -0,0 +1,35 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{share_dirs} = @{user_share_dirs}/umu +@{cache_dirs} = @{user_cache_dirs}/umu +@{runtime_dirs} = @{share_dirs}/steamrt@{int}/ +@{wineprefix_dirs} = @{HOME}/Games/umu/*/ @{HOME}/Games/Heroic/*/ @{HOME}/Games/steam/*/ +@{appid} = X + +@{exec_path} = @{runtime_dirs}/pressure-vessel/@{lib}/steam-runtime-tools-@{int}/srt-bwrap +profile umu-bwrap flags=(attach_disconnected,mediate_deleted) { + include + include + include + + capability dac_override, + capability dac_read_search, + + @{exec_path} mr, + + @{lib}/pressure-vessel/from-host/libexec/steam-runtime-tools-@{d}/pv-adverb Px -> umu-bwrap//&umu-game, + + /bindfile@{rand6} rw, + + owner @{tmp}/#@{int} rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/umu/umu-game b/apparmor.d/groups/umu/umu-game new file mode 100644 index 0000000000..f9b292f410 --- /dev/null +++ b/apparmor.d/groups/umu/umu-game @@ -0,0 +1,25 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{share_dirs} = @{user_share_dirs}/umu +@{cache_dirs} = @{user_cache_dirs}/umu +@{runtime_dirs} = @{share_dirs}/steamrt@{int}/ +@{wineprefix_dirs} = @{HOME}/Games/umu/*/ @{HOME}/Games/Heroic/*/ @{HOME}/Games/steam/*/ +@{appid} = X + +@{exec_path} = @{lib}/pressure-vessel/from-host/libexec/steam-runtime-tools-@{int}/pv-adverb +profile umu-game flags=(attach_disconnected,mediate_deleted) { + include + include + + @{exec_path} mr, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/umu/umu-run b/apparmor.d/groups/umu/umu-run new file mode 100644 index 0000000000..35b9ae9d62 --- /dev/null +++ b/apparmor.d/groups/umu/umu-run @@ -0,0 +1,149 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Security objectives of the steam profiles: +# - Ensure no user data is accessed by either umu or umu games +# - Limit what steam/games can access to the host +# +# Overall architecture of the steam profiles: +# umu-run +# ├── umu-runtime # Pressure-vessel, steam runtime, create the game sandbox +# │ └── steam-bwrap # Native games +# │ └── steam-game # Proton games (sandboxed) +# ├── umu-run//bwrap +# ├── umu-run//ldd +# └── umu-run//ldconfig + +abi , + +include + +@{share_dirs} = @{user_share_dirs}/umu +@{cache_dirs} = @{user_cache_dirs}/umu +@{runtime_dirs} = @{share_dirs}/steamrt@{int}/ +@{wineprefix_dirs} = @{HOME}/Games/umu/*/ @{HOME}/Games/Heroic/*/ @{HOME}/Games/steam/*/ + +@{exec_path} = @{bin}/umu-run +profile umu-run @{exec_path} flags=(attach_disconnected) { + include + include + include + include + include + include + include + include + include + include + include + + network inet dgram, + network inet stream, + network inet6 dgram, + network inet6 stream, + network netlink raw, + + signal send peer=umu-bwrap, + signal send peer=umu-bwrap//&umu-game, + signal send peer=umu-game, + + @{exec_path} mr, + + @{sh_path} r, + @{bin}/getopt rix, + @{bin}/readlink rix, + + @{bin}/gcc rix, + @{lib}/gcc/**/collect2 rix, + + @{bin}/bwrap Cx -> bwrap, + @{ldd_path} Cx -> &umu-run//ldd, + @{sbin}/ldconfig Cx -> &umu-run//ldconfig, + + @{runtime_dirs}/umu ix, + @{runtime_dirs}/run ix, + @{runtime_dirs}/*entry-point ix, + @{runtime_dirs}/pressure-vessel/bin/** rix, + @{runtime_dirs}/pressure-vessel/@{lib}/** rmix, + priority=1 @{runtime_dirs}/pressure-vessel/@{lib}/steam-runtime-tools-@{d}/srt-bwrap Px -> umu-bwrap, #aa:only apparmor>=4.1 + + /opt/cuda/targets/@{arch}-linux/lib/*.so mr, + /opt/cuda/targets/@{arch}-linux/lib/*.so.* mr, + /opt/cuda/targets/@{arch}-linux/lib/ r, + + / r, + @{lib}/ r, + owner @{HOME}/ r, + + owner @{wineprefix_dirs}/ w, + owner @{wineprefix_dirs}/** w, + + owner @{steam_lib_dirs}/{,*} rw, + owner @{steam_share_dirs}/compatibilitytools.d/{,**} rwm, + + owner @{user_config_dirs}/heroic/tools/proton/** r, + + owner @{cache_dirs}/ rw, + owner @{cache_dirs}/** rwlk -> @{share_dirs}/**, + + owner @{share_dirs}/ rw, + owner @{share_dirs}/** rwlk -> @{share_dirs}/**, + + owner @{run}/user/@{uid}/ r, + + @{PROC}/ r, + @{PROC}/@{pids}/status r, + owner @{PROC}/@{pid}/fd/ r, + owner @{PROC}/@{pid}/mounts r, + + owner /var/tmp/@{word8} rw, + owner @{tmp}/@{word8} rw, + owner @{tmp}/#@{int} rw, + owner @{tmp}/tmp@{word8} rw, + owner @{tmp}/tmp@{word8}/ w, + owner @{tmp}/tmp@{word8}/* rw, + owner @{tmp}/vdpau-drivers-@{rand6}/{,**} rw, + + owner /tmp/cc@{rand6}.* rw, + + @{sys}/module/nvidia/version r, + + /dev/tty rw, + + profile ldconfig flags=(attach_disconnected) { + include + include + + @{sbin}/ldconfig mr, + + @{sh_path} rix, + @{sbin}/ldconfig.real rix, + + include if exists + } + + profile ldd flags=(attach_disconnected) { + include + include + include + + @{ldd_path} mrix, + @{sh_path} r, + + include if exists + } + + profile bwrap flags=(attach_disconnected) { + include + include + + @{bin}/bwrap mr, + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/usb/lsusb b/apparmor.d/groups/usb/lsusb index f824343d67..c30453a5fc 100644 --- a/apparmor.d/groups/usb/lsusb +++ b/apparmor.d/groups/usb/lsusb @@ -14,6 +14,7 @@ profile lsusb @{exec_path} { include capability net_admin, + capability sys_admin, network netlink raw, @@ -21,6 +22,22 @@ profile lsusb @{exec_path} { /etc/udev/hwdb.bin r, + / r, + + @{sys}/devices/**/usb@{int}/** r, + + @{sys}/devices/**/usb@{int}/{,**/}bAlternateSetting r, + @{sys}/devices/**/usb@{int}/{,**/}bDeviceClass r, + @{sys}/devices/**/usb@{int}/{,**/}bInterfaceClass r, + @{sys}/devices/**/usb@{int}/{,**/}bInterfaceProtocol r, + @{sys}/devices/**/usb@{int}/{,**/}bInterfaceSubClass r, + @{sys}/devices/**/usb@{int}/{,**/}bNumEndpoints r, + @{sys}/devices/**/usb@{int}/{,**/}maxchild r, + @{sys}/devices/**/usb@{int}/{,**/}rx_lanes r, + @{sys}/devices/**/usb@{int}/{,**/}tx_lanes r, + + /dev/bus/usb/@{d}@{d}@{d}/@{d}@{d}@{d} wk, + include if exists } diff --git a/apparmor.d/groups/usb/usbguard-applet-qt b/apparmor.d/groups/usb/usbguard-applet-qt index a76398dd93..c483a00ea7 100644 --- a/apparmor.d/groups/usb/usbguard-applet-qt +++ b/apparmor.d/groups/usb/usbguard-applet-qt @@ -10,16 +10,11 @@ include @{exec_path} = @{bin}/usbguard-applet-qt profile usbguard-applet-qt @{exec_path} { include - include - include - include + include include - include - include - include - include - include + include include + include # Needed? ptrace (read), @@ -37,11 +32,6 @@ profile usbguard-applet-qt @{exec_path} { owner @{PROC}/@{pid}/cmdline r, - /usr/share/hwdata/pnp.ids r, - - /var/lib/dbus/machine-id r, - /etc/machine-id r, - include if exists } diff --git a/apparmor.d/groups/utils/agetty b/apparmor.d/groups/utils/agetty index 3eca54abcb..e927931b42 100644 --- a/apparmor.d/groups/utils/agetty +++ b/apparmor.d/groups/utils/agetty @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/agetty +@{exec_path} = @{sbin}/agetty profile agetty @{exec_path} { include include @@ -35,11 +35,12 @@ profile agetty @{exec_path} { /etc/inittab r, /etc/os-release r, + @{run}/credentials/serial-getty@hvc@{int}.service/ r, @{run}/credentials/getty@tty@{int}.service/ r, @{run}/credentials/serial-getty@ttyS@{int}.service/ r, owner @{run}/agetty.reload rw, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, owner /dev/ttyGS@{int} rw, owner /dev/ttyS@{int} rw, diff --git a/apparmor.d/groups/utils/blkid b/apparmor.d/groups/utils/blkid index 27207bdb72..3653d0d8da 100644 --- a/apparmor.d/groups/utils/blkid +++ b/apparmor.d/groups/utils/blkid @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/blkid +@{exec_path} = @{sbin}/blkid profile blkid @{exec_path} flags=(attach_disconnected) { include include @@ -28,14 +28,14 @@ profile blkid @{exec_path} flags=(attach_disconnected) { # Image files @{user_img_dirs}/{,**} r, + /var/tmp/mkinitramfs_@{rand6}/cryptroot/crypttab w, # file_inherit + # The standard location of the cache file # Without owner here if this tool should be used as a regular user @{run}/blkid/ rw, @{run}/blkid/blkid.tab{,-@{rand6}} rw, @{run}/blkid/blkid.tab.old rwl -> @{run}/blkid/blkid.tab, - @{run}/cloud-init/ds-identify.log w, # file_inherit - @{PROC}/@{pid}/mounts r, @{PROC}/partitions r, @{PROC}/swaps r, @@ -45,7 +45,12 @@ profile blkid @{exec_path} flags=(attach_disconnected) { /dev/.blkid.tab{,-@{rand6}} rw, /dev/blkid.tab.old rwl -> /dev/blkid.tab, - owner /dev/tty@{int} rw, + /tmp/tmp.@{rand10}/mkinitramfs_*/cryptroot/crypttab w, + + owner /dev/tty@{u8} rw, + + # file_inherit + deny @{run}/cloud-init/ds-identify.log w, include if exists } diff --git a/apparmor.d/groups/utils/blockdev b/apparmor.d/groups/utils/blockdev index 96e3ad23f8..0c5e7b17cf 100644 --- a/apparmor.d/groups/utils/blockdev +++ b/apparmor.d/groups/utils/blockdev @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/blockdev +@{exec_path} = @{sbin}/blockdev profile blockdev @{exec_path} { include include diff --git a/apparmor.d/groups/utils/chsh b/apparmor.d/groups/utils/chsh index 73f097a945..e3581be31a 100644 --- a/apparmor.d/groups/utils/chsh +++ b/apparmor.d/groups/utils/chsh @@ -24,7 +24,7 @@ profile chsh @{exec_path} { network netlink raw, - #aa:dbus talk bus=system name=org.freedesktop.home1 label=systemd-homed + #aa:dbus talk bus=system name=org.freedesktop.home1 label="@{p_systemd_homed}" @{exec_path} mr, diff --git a/apparmor.d/groups/utils/df b/apparmor.d/groups/utils/df index baceace65d..abca66c6b4 100644 --- a/apparmor.d/groups/utils/df +++ b/apparmor.d/groups/utils/df @@ -24,6 +24,12 @@ profile df @{exec_path} flags=(attach_disconnected) { owner @{PROC}/@{pid}/mountinfo r, + /dev/ptmx rw, + + # file_inherit + deny /var/crash/* w, + deny @{att}@{run}/systemd/inhibit/* w, + include if exists } diff --git a/apparmor.d/groups/utils/dmesg b/apparmor.d/groups/utils/dmesg index 14ace0dead..23abe6ac6c 100644 --- a/apparmor.d/groups/utils/dmesg +++ b/apparmor.d/groups/utils/dmesg @@ -13,6 +13,7 @@ profile dmesg @{exec_path} flags=(attach_disconnected) { include capability dac_read_search, + capability sys_admin, capability syslog, @{exec_path} mr, @@ -24,13 +25,19 @@ profile dmesg @{exec_path} flags=(attach_disconnected) { @{PROC}/sys/kernel/pid_max r, - /dev/kmsg r, + /dev/kmsg rw, + /dev/ptmx rw, + # file_inherit + deny @{sbin}/{,*/} r, deny @{bin}/{,*/} r, + deny /snap/bin/ r, deny /{usr/,}local/{,s}bin/ r, + deny /var/crash/* w, deny /var/lib/flatpak/exports/bin/ r, deny @{HOME}/.go/bin/ r, deny @{user_bin_dirs}/ r, + deny @{att}@{run}/systemd/inhibit/* w, include if exists } diff --git a/apparmor.d/groups/utils/du b/apparmor.d/groups/utils/du new file mode 100644 index 0000000000..b13032522b --- /dev/null +++ b/apparmor.d/groups/utils/du @@ -0,0 +1,24 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/du +profile du @{exec_path} { + include + include + + @{exec_path} mr, + + #aa:lint ignore=too-wide + # As a directory tree analyzer it needs full access to the filesystem + / r, + /** r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/utils/findmnt b/apparmor.d/groups/utils/findmnt index 0c027dc2c2..11592c4717 100644 --- a/apparmor.d/groups/utils/findmnt +++ b/apparmor.d/groups/utils/findmnt @@ -21,10 +21,9 @@ profile findmnt @{exec_path} flags=(attach_disconnected,complain) { /etc/fstab r, /etc/mtab r, - @{PROC}/@{pids}/mountinfo r, + / r, - # File Inherit - deny unix (receive) type=stream, + @{PROC}/@{pids}/mountinfo r, include if exists } diff --git a/apparmor.d/groups/utils/fsck b/apparmor.d/groups/utils/fsck index 5d05880266..6bc8964ff5 100644 --- a/apparmor.d/groups/utils/fsck +++ b/apparmor.d/groups/utils/fsck @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/fsck +@{exec_path} = @{sbin}/fsck profile fsck @{exec_path} flags=(attach_disconnected) { include include @@ -18,15 +18,16 @@ profile fsck @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, - @{bin}/e2fsck rPx, - @{bin}/fsck.* rPx, + @{sbin}/e2fsck rPx, + @{sbin}/fsck.* rPx, /etc/fstab r, # When a mount dir is passed to fsck as an argument. + / r, @{HOME}/ r, @{MOUNTS}/ r, - /boot/ r, + @{efi}/ r, @{run}/mount/utab r, @{run}/systemd/fsck.progress rw, diff --git a/apparmor.d/groups/utils/fstrim b/apparmor.d/groups/utils/fstrim index 211913f419..edbe1aeb7c 100644 --- a/apparmor.d/groups/utils/fstrim +++ b/apparmor.d/groups/utils/fstrim @@ -6,12 +6,13 @@ abi , include -@{exec_path} = @{bin}/fstrim +@{exec_path} = @{sbin}/fstrim profile fstrim @{exec_path} flags=(attach_disconnected) { include include capability dac_override, + capability dac_read_search, capability sys_admin, @{exec_path} mr, @@ -22,10 +23,11 @@ profile fstrim @{exec_path} flags=(attach_disconnected) { @{MOUNTDIRS}/ r, @{MOUNTS}/ r, / r, - /boot/ r, - /boot/efi/ r, + @{efi}/ r, /var/ r, + @{PROC}/@{pid}/mountinfo r, + include if exists } diff --git a/apparmor.d/groups/utils/hwclock b/apparmor.d/groups/utils/hwclock new file mode 100644 index 0000000000..d1433a605c --- /dev/null +++ b/apparmor.d/groups/utils/hwclock @@ -0,0 +1,30 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{sbin}/hwclock +profile hwclock @{exec_path} { + include + include + + capability audit_write, + capability sys_time, + + network netlink raw, + + @{exec_path} mr, + + /etc/adjtime rw, + + @{sys}/devices/pnp@{int}/*/rtc/rtc@{int}/{,*} r, + + /dev/rtc@{int} r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/utils/locale-gen b/apparmor.d/groups/utils/locale-gen index b9254171a7..b9dbe34bed 100644 --- a/apparmor.d/groups/utils/locale-gen +++ b/apparmor.d/groups/utils/locale-gen @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/locale-gen +@{exec_path} = @{sbin}/locale-gen profile locale-gen @{exec_path} { include include @@ -18,6 +18,7 @@ profile locale-gen @{exec_path} { @{exec_path} mr, @{sh_path} rix, + @{bin}/{e,}grep rix, @{bin}/cat rix, @{bin}/gzip rix, @{bin}/localedef rix, @@ -30,7 +31,8 @@ profile locale-gen @{exec_path} { /usr/share/i18n/{,**} r, - /etc/locale.gen r, + /etc/locale.gen rw, + /etc/sed@{rand6} rw, /var/lib/locales/supported.d/{,**} r, diff --git a/apparmor.d/groups/utils/login b/apparmor.d/groups/utils/login index 6968be40e4..4c0518f987 100644 --- a/apparmor.d/groups/utils/login +++ b/apparmor.d/groups/utils/login @@ -12,8 +12,11 @@ profile login @{exec_path} flags=(attach_disconnected) { include include include + include + include include include + include #aa:only RBAC capability audit_write, capability chown, @@ -34,42 +37,44 @@ profile login @{exec_path} flags=(attach_disconnected) { ptrace read, - #aa:dbus talk bus=system name=org.freedesktop.login1 label=systemd-logind + #aa:dbus talk bus=system name=org.freedesktop.login1 label="@{p_systemd_logind}" @{exec_path} mr, - @{shells_path} rUx, + @{shells_path} Ux, #aa:exclude RBAC @{etc_ro}/environment r, @{etc_ro}/security/group.conf r, - @{etc_ro}/security/limits.conf r, - @{etc_ro}/security/limits.d/{,*} r, - @{etc_ro}/security/pam_env.conf r, /etc/default/locale r, /etc/legal r, /etc/machine-id r, /etc/motd r, /etc/motd.d/ r, /etc/shells r, + /etc/u2f/{,**} r, /var/lib/faillock/@{user} rwk, + /var/lib/lastlog/ r, /var/log/btmp{,.@{int}} r, + owner @{user_cache_dirs}/ w, owner @{user_cache_dirs}/motd.legal-displayed rw, - @{att}/@{run}/systemd/sessions/@{int}.ref w, + @{att}@{run}/systemd/sessions/@{int}.ref w, + @{run}/cockpit/active.issue r, @{run}/credentials/getty@tty@{int}.service/ r, @{run}/faillock/@{user} rwk, @{run}/motd.d/{,*} r, @{run}/motd.dynamic{,.new} rw, + @{run}/systemd/io.systemd.Login rw, @{PROC}/@{pids}/cgroup r, @{PROC}/1/limits r, owner @{PROC}/@{pid}/loginuid rw, owner @{PROC}/@{pid}/uid_map r, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/utils/losetup b/apparmor.d/groups/utils/losetup index bb0ac6c74e..9b32074ba8 100644 --- a/apparmor.d/groups/utils/losetup +++ b/apparmor.d/groups/utils/losetup @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/losetup +@{exec_path} = @{sbin}/losetup profile losetup @{exec_path} { include include diff --git a/apparmor.d/groups/utils/lsblk b/apparmor.d/groups/utils/lsblk index 7559e4e48f..c22090caa0 100644 --- a/apparmor.d/groups/utils/lsblk +++ b/apparmor.d/groups/utils/lsblk @@ -19,6 +19,8 @@ profile lsblk @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, + / r, + @{PROC}/swaps r, owner @{PROC}/@{pid}/mountinfo r, @@ -27,6 +29,8 @@ profile lsblk @{exec_path} flags=(attach_disconnected) { # File Inherit deny network inet stream, deny network inet6 stream, + deny owner @{user_share_dirs}/gnome-shell/session.gvdb rw, + deny /dev/udmabuf rw, include if exists } diff --git a/apparmor.d/groups/virt/cni-flannel b/apparmor.d/groups/utils/lsclocks similarity index 50% rename from apparmor.d/groups/virt/cni-flannel rename to apparmor.d/groups/utils/lsclocks index 6bdccec8c4..e2ca714722 100644 --- a/apparmor.d/groups/virt/cni-flannel +++ b/apparmor.d/groups/utils/lsclocks @@ -1,18 +1,21 @@ # apparmor.d - Full set of apparmor profiles -# Copyright (C) 2022 Jeroen Rijken +# Copyright (C) 2026 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only abi , include -@{exec_path} = @{lib}/cni/flannel /opt/cni/bin/flannel -profile cni-flannel @{exec_path} flags=(complain,attach_disconnected){ +@{exec_path} = @{bin}/lsclocks +profile lsclocks @{exec_path} { include + include @{exec_path} mr, - include if exists + /dev/ r, + + include if exists } # vim:syntax=apparmor diff --git a/apparmor.d/groups/utils/lscpu b/apparmor.d/groups/utils/lscpu index caa2b56281..88c1a60ad4 100644 --- a/apparmor.d/groups/utils/lscpu +++ b/apparmor.d/groups/utils/lscpu @@ -8,7 +8,7 @@ abi , include @{exec_path} = @{bin}/lscpu -profile lscpu @{exec_path} { +profile lscpu @{exec_path} flags=(attach_disconnected) { include include @@ -24,7 +24,7 @@ profile lscpu @{exec_path} { @{PROC}/bus/pci/devices r, @{PROC}/sys/kernel/osrelease r, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, deny network unix stream, diff --git a/apparmor.d/groups/utils/lsfd b/apparmor.d/groups/utils/lsfd new file mode 100644 index 0000000000..adfdd207e6 --- /dev/null +++ b/apparmor.d/groups/utils/lsfd @@ -0,0 +1,70 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/lsfd +profile lsfd @{exec_path} flags=(attach_disconnected) { + include + include + + capability bpf, + capability checkpoint_restore, + capability dac_read_search, + capability net_admin, + capability sys_admin, + capability sys_chroot, + capability sys_ptrace, + capability sys_resource, + capability syslog, + + network inet dgram, + network inet stream, + network inet6 dgram, + network inet6 raw, + network inet6 stream, + network inet6 stream, + network netlink dgram, + network netlink raw, + network packet dgram, + + ptrace read, + ptrace trace, + + mqueue (read create delete getattr) type=posix /.lsfd-mqueue-nodev-test:@{int}, + + @{exec_path} mr, + + / r, + @{att}/ r, + + owner @{att}/.lsfd-mqueue-nodev-test:@{int} rw, + + @{run}/ r, + @{run}/netns/ r, + + @{sys}/kernel/cpu_byteorder r, + + @{PROC}/ r, + @{PROC}/@{pids}/ r, + @{PROC}/@{pids}/comm r, + @{PROC}/@{pids}/fd/ r, + @{PROC}/@{pids}/fdinfo/@{int} r, + @{PROC}/@{pids}/maps r, + @{PROC}/@{pids}/mountinfo r, + @{PROC}/@{pids}/net/* r, + @{PROC}/@{pids}/stat r, + @{PROC}/@{pids}/syscall r, + @{PROC}/@{pids}/task/ r, + @{PROC}/devices r, + @{PROC}/misc r, + @{PROC}/partitions r, + @{PROC}/tty/drivers r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/utils/lsipc b/apparmor.d/groups/utils/lsipc new file mode 100644 index 0000000000..7677a8a03e --- /dev/null +++ b/apparmor.d/groups/utils/lsipc @@ -0,0 +1,35 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/lsipc +profile lsipc @{exec_path} { + include + include + + @{exec_path} mr, + + @{PROC}/sys/fs/mqueue/msg_max r, + @{PROC}/sys/fs/mqueue/msgsize_max r, + @{PROC}/sys/fs/mqueue/queues_max r, + @{PROC}/sys/kernel/msgmax r, + @{PROC}/sys/kernel/msgmnb r, + @{PROC}/sys/kernel/msgmni r, + @{PROC}/sys/kernel/sem r, + @{PROC}/sys/kernel/shmall r, + @{PROC}/sys/kernel/shmmax r, + @{PROC}/sys/kernel/shmmni r, + @{PROC}/sysvipc/msg r, + @{PROC}/sysvipc/sem r, + @{PROC}/sysvipc/shm r, + + /dev/mqueue/ r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/utils/lsirq b/apparmor.d/groups/utils/lsirq new file mode 100644 index 0000000000..884ebb0b02 --- /dev/null +++ b/apparmor.d/groups/utils/lsirq @@ -0,0 +1,21 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/lsirq +profile lsirq @{exec_path} { + include + include + + @{exec_path} mr, + + @{PROC}/interrupts r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/utils/lslocks b/apparmor.d/groups/utils/lslocks new file mode 100644 index 0000000000..e168a9890e --- /dev/null +++ b/apparmor.d/groups/utils/lslocks @@ -0,0 +1,36 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/lslocks +profile lslocks @{exec_path} flags=(attach_disconnected) { + include + + capability dac_read_search, + capability sys_ptrace, + + ptrace read, + + @{exec_path} mr, + + @{sys}/devices/**/block/** r, + @{sys}/devices/**/host@{int}/** r, + + @{PROC}/ r, + @{PROC}/@{pid}/ r, + @{PROC}/@{pid}/comm r, + @{PROC}/@{pid}/fd/ r, + @{PROC}/@{pid}/fdinfo/ r, + @{PROC}/@{pid}/fdinfo/@{int} r, + @{PROC}/locks r, + owner @{PROC}/@{pid}/ r, + owner @{PROC}/@{pid}/mountinfo r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/utils/lslogins b/apparmor.d/groups/utils/lslogins new file mode 100644 index 0000000000..7a24767d3e --- /dev/null +++ b/apparmor.d/groups/utils/lslogins @@ -0,0 +1,33 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/lslogins +profile lslogins @{exec_path} { + include + include + include + + @{exec_path} mr, + + @{etc_ro}/login.defs r, + /etc/.pwd.lock w, + /etc/.pwd.lock wk, + /etc/shadow r, + + /var/log/lastlog r, + /var/log/wtmp rk, + + @{run}/systemd/userdb/ r, + + @{PROC}/ r, + @{PROC}/sys/kernel/random/boot_id r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/utils/lsmem b/apparmor.d/groups/utils/lsmem new file mode 100644 index 0000000000..97013e1ace --- /dev/null +++ b/apparmor.d/groups/utils/lsmem @@ -0,0 +1,23 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/lsmem +profile lsmem @{exec_path} { + include + include + + @{exec_path} mr, + + @{sys}/devices/system/memory/ r, + @{sys}/devices/system/memory/block_size_bytes r, + @{sys}/devices/system/memory/memory@{int}/{,*} r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/utils/lsns b/apparmor.d/groups/utils/lsns new file mode 100644 index 0000000000..504679b4c4 --- /dev/null +++ b/apparmor.d/groups/utils/lsns @@ -0,0 +1,45 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/lsns +profile lsns @{exec_path} flags=(attach_disconnected) { + include + include + include + + capability net_admin, + capability sys_ptrace, + capability dac_read_search, + + network, + + ptrace read, + ptrace trace, + + @{exec_path} mr, + + @{att}/ r, + + @{run}/*/netns/** r, + @{run}/*/ns/** r, + + @{sys}/devices/**/block/** r, + @{sys}/devices/**/host@{int}/** r, + + @{PROC}/ r, + @{PROC}/@{pid}/ r, + @{PROC}/@{pid}/stat r, + @{PROC}/@{pid}/cmdline r, + @{PROC}/@{pid}/comm r, + @{PROC}/@{pid}/fd/ r, + owner @{PROC}/@{pid}/mountinfo r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/utils/lspci b/apparmor.d/groups/utils/lspci index b390346bb2..c23c669d00 100644 --- a/apparmor.d/groups/utils/lspci +++ b/apparmor.d/groups/utils/lspci @@ -13,11 +13,13 @@ profile lspci @{exec_path} flags=(attach_disconnected) { include include + capability dac_read_search, capability sys_admin, - @{exec_path} mr, + network inet dgram, + network inet6 dgram, - /app/lib/libzypak-preload-host*.so rm, + @{exec_path} mr, /usr/share/hwdata/pci.ids r, /usr/share/misc/pci.ids r, @@ -37,13 +39,16 @@ profile lspci @{exec_path} flags=(attach_disconnected) { @{sys}/bus/pci/slots/@{int}-@{int}/address r, @{sys}/bus/pci/slots/@{int}/address r, @{sys}/devices/@{pci}/** r, + @{sys}/devices/**/@{uuid}/@{pci}/** r, @{sys}/module/compression r, @{PROC}/bus/pci/devices r, @{PROC}/cmdline r, @{PROC}/ioports r, - deny @{user_share_dirs}/gvfs-metadata/* r, + # file_inherit + deny owner @{user_share_dirs}/gvfs-metadata/* r, + deny owner @{user_cache_dirs}/*/** rw, include if exists } diff --git a/apparmor.d/groups/utils/lsscsi b/apparmor.d/groups/utils/lsscsi new file mode 100644 index 0000000000..e713b823cc --- /dev/null +++ b/apparmor.d/groups/utils/lsscsi @@ -0,0 +1,26 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/lsscsi +profile lsscsi @{exec_path} { + include + include + + @{exec_path} mr, + + / r, + + @{sys}/bus/scsi/devices/ r, + + /dev/ r, + /dev/** r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/utils/nologin b/apparmor.d/groups/utils/nologin index 3ee32cf346..795a1aa35a 100644 --- a/apparmor.d/groups/utils/nologin +++ b/apparmor.d/groups/utils/nologin @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/nologin +@{exec_path} = @{sbin}/nologin profile nologin @{exec_path} { include include diff --git a/apparmor.d/groups/utils/nproc b/apparmor.d/groups/utils/nproc new file mode 100644 index 0000000000..64b824308f --- /dev/null +++ b/apparmor.d/groups/utils/nproc @@ -0,0 +1,32 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/nproc +profile nproc @{exec_path} flags=(attach_disconnected) { + include + include + + @{exec_path} mr, + + @{sys}/fs/cgroup/user.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/session-@{int}.scope/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/cpu.max r, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/cpu.max r, + + owner @{PROC}/@{pid}/cgroup r, + + # file_inherit + deny network netlink raw, + deny owner @{user_config_dirs}/** rw, + deny /dev/ptmx rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/rfkill b/apparmor.d/groups/utils/rfkill similarity index 67% rename from apparmor.d/profiles-m-r/rfkill rename to apparmor.d/groups/utils/rfkill index c80211b092..1a5809a60c 100644 --- a/apparmor.d/profiles-m-r/rfkill +++ b/apparmor.d/groups/utils/rfkill @@ -7,16 +7,16 @@ abi , include -@{exec_path} = @{bin}/rfkill -profile rfkill @{exec_path} { +@{exec_path} = @{sbin}/rfkill +profile rfkill @{exec_path} flags=(attach_disconnected) { include @{exec_path} mr, - /dev/rfkill rw, + @{sys}/devices/**/rfkill@{int}/name r, + @{sys}/devices/**/rfkill@{int}/type r, - @{sys}/devices/@{pci}/rfkill@{int}/{name,type} r, - @{sys}/devices/platform/**/rfkill/rfkill@{int}/{name,type} r, + /dev/rfkill rw, include if exists } diff --git a/apparmor.d/groups/utils/sleep b/apparmor.d/groups/utils/sleep new file mode 100644 index 0000000000..9b507bfa04 --- /dev/null +++ b/apparmor.d/groups/utils/sleep @@ -0,0 +1,23 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/sleep +profile sleep @{exec_path} flags=(attach_disconnected) { + include + + signal receive set=term, + + @{exec_path} mr, + + # file_inherit + deny owner /dev/pts/@{u8} rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/utils/su b/apparmor.d/groups/utils/su index 4bd4735845..350a72d5dd 100644 --- a/apparmor.d/groups/utils/su +++ b/apparmor.d/groups/utils/su @@ -8,10 +8,11 @@ abi , include @{exec_path} = @{bin}/su -profile su @{exec_path} { +profile su @{exec_path} flags=(attach_disconnected) { include include include + include #aa:only RBAC capability chown, # pseudo-terminal @@ -21,8 +22,8 @@ profile su @{exec_path} { @{exec_path} mr, - @{bin}/@{shells} rUx, - @{bin}/nologin rPx, + @{bin}/@{shells} Ux, #aa:exclude RBAC + @{sbin}/nologin Px, @{etc_ro}/default/su r, /etc/default/locale r, @@ -30,6 +31,8 @@ profile su @{exec_path} { @{HOME}/.xauth@{rand6} rw, + @{run}/systemd/sessions/*.ref w, + include if exists } diff --git a/apparmor.d/groups/utils/sulogin b/apparmor.d/groups/utils/sulogin index ccf7216e0c..bdd86740fe 100644 --- a/apparmor.d/groups/utils/sulogin +++ b/apparmor.d/groups/utils/sulogin @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/sulogin +@{exec_path} = @{sbin}/sulogin profile sulogin @{exec_path} { include include @@ -25,6 +25,10 @@ profile sulogin @{exec_path} { @{PROC}/consoles r, + /dev/ r, + /dev/hvc@{int} rw, + /dev/ttyS@{int} rw, + include if exists } diff --git a/apparmor.d/groups/utils/swaplabel b/apparmor.d/groups/utils/swaplabel index 05dc5783ab..16abf153dc 100644 --- a/apparmor.d/groups/utils/swaplabel +++ b/apparmor.d/groups/utils/swaplabel @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/swaplabel +@{exec_path} = @{sbin}/swaplabel profile swaplabel @{exec_path} { include include diff --git a/apparmor.d/groups/utils/swapon b/apparmor.d/groups/utils/swapon index 83d2c6a3be..f741de7028 100644 --- a/apparmor.d/groups/utils/swapon +++ b/apparmor.d/groups/utils/swapon @@ -7,12 +7,13 @@ abi , include -@{exec_path} = @{bin}/swapon @{bin}/swapoff +@{exec_path} = @{sbin}/swapon @{sbin}/swapoff profile swapon @{exec_path} { include include capability sys_admin, + capability sys_resource, @{exec_path} mr, @@ -23,8 +24,9 @@ profile swapon @{exec_path} { owner /swapfile rw, @{PROC}/swaps r, + @{PROC}/@{pid}/oom_score_adj w, - /dev/pts/@{int} rw, + /dev/pts/@{u16} rw, include if exists } diff --git a/apparmor.d/groups/utils/sync b/apparmor.d/groups/utils/sync index 9b47b4df2e..728be9574c 100644 --- a/apparmor.d/groups/utils/sync +++ b/apparmor.d/groups/utils/sync @@ -7,12 +7,13 @@ abi , include @{exec_path} = @{bin}/sync -profile sync @{exec_path} { +profile sync @{exec_path} flags=(attach_disconnected) { include include @{exec_path} mr, + #aa:lint ignore=too-wide # All paths where sync can be used to flush all write operations on a single file to disk /{,**} rw, diff --git a/apparmor.d/groups/utils/uname b/apparmor.d/groups/utils/uname index 45a864c230..8391287632 100644 --- a/apparmor.d/groups/utils/uname +++ b/apparmor.d/groups/utils/uname @@ -14,8 +14,9 @@ profile uname @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, - @{att}/dev/tty@{int} rw, + @{att}/dev/tty@{u8} rw, + # File Inherit deny network, deny owner @{user_share_dirs}/gvfs-metadata/* r, deny owner @{user_share_dirs}/zed/**/data.mdb rw, diff --git a/apparmor.d/groups/utils/uuidd b/apparmor.d/groups/utils/uuidd index 4d75a70ed5..affe5e8fc4 100644 --- a/apparmor.d/groups/utils/uuidd +++ b/apparmor.d/groups/utils/uuidd @@ -6,19 +6,24 @@ abi , include -@{exec_path} = @{bin}/uuidd +@{exec_path} = @{sbin}/uuidd profile uuidd @{exec_path} flags=(attach_disconnected) { include include + capability dac_override, + network inet dgram, @{exec_path} mr, owner /var/lib/libuuid/clock.txt rwk, + owner /var/lib/libuuid/clock-cont.txt rwk, + + @{att}@{run}/uuidd/request rw, @{run}/uuidd/request rw, - @{att}/@{run}/uuidd/request rw, + @{run}/uuidd/uuidd.pid rwk, include if exists } diff --git a/apparmor.d/groups/utils/uuidgen b/apparmor.d/groups/utils/uuidgen index c056daaa0d..4cd8bdc1af 100644 --- a/apparmor.d/groups/utils/uuidgen +++ b/apparmor.d/groups/utils/uuidgen @@ -17,7 +17,7 @@ profile uuidgen @{exec_path} { owner /var/lib/libuuid/clock.txt w, - @{run}/uuidd/request w, + @{run}/uuidd/request rw, include if exists } diff --git a/apparmor.d/groups/utils/whereis b/apparmor.d/groups/utils/whereis index 32d4ffa51a..36e4579981 100644 --- a/apparmor.d/groups/utils/whereis +++ b/apparmor.d/groups/utils/whereis @@ -15,6 +15,7 @@ profile whereis @{exec_path} { @{exec_path} mr, @{bin}/{,*/} r, + @{sbin}/{,*/} r, @{lib}/ r, @{lib}/go-*/bin/ r, /usr/{local/,}games/ r, diff --git a/apparmor.d/groups/utils/who b/apparmor.d/groups/utils/who index 3da07f89d5..8c1b6afaad 100644 --- a/apparmor.d/groups/utils/who +++ b/apparmor.d/groups/utils/who @@ -8,18 +8,30 @@ abi , include @{exec_path} = @{bin}/who -profile who @{exec_path} { +profile who @{exec_path} flags=(attach_disconnected) { include - include - include include capability kill, @{exec_path} mr, + @{run}/systemd/sessions/* r, + + # Rotated logs from wutmp + /var/log/wtmp.@{int} r, + /var/log/btmp.@{int} r, + + # Deny the writes allowed by abstractions/wutmp + audit deny /var/** w, + audit deny @{run}/utmp w, + + # file_inherit + deny owner @{user_share_dirs}/gnome-shell/session.gvdb rw, deny owner @{user_share_dirs}/gvfs-metadata/{,*} r, deny owner @{user_share_dirs}/zed/**/data.mdb rw, + deny /dev/pts/@{u16} rw, + deny /dev/tty/@{u8} rw, include if exists } diff --git a/apparmor.d/groups/utils/zramctl b/apparmor.d/groups/utils/zramctl index 9dbf23243f..29428a96f5 100644 --- a/apparmor.d/groups/utils/zramctl +++ b/apparmor.d/groups/utils/zramctl @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/zramctl +@{exec_path} = @{sbin}/zramctl profile zramctl @{exec_path} { include include @@ -14,10 +14,12 @@ profile zramctl @{exec_path} { @{exec_path} mr, @{sys}/devices/virtual/block/zram@{int}/ r, - @{sys}/devices/virtual/block/zram@{int}/comp_algorithm r, + @{sys}/devices/virtual/block/zram@{int}/comp_algorithm rw, @{sys}/devices/virtual/block/zram@{int}/disksize r, + @{sys}/devices/virtual/block/zram@{int}/disksize w, @{sys}/devices/virtual/block/zram@{int}/max_comp_streams r, @{sys}/devices/virtual/block/zram@{int}/mm_stat r, + @{sys}/devices/virtual/block/zram@{int}/reset w, @{PROC}/swaps r, owner @{PROC}/@{pid}/mounts r, diff --git a/apparmor.d/groups/virt/cni-calico b/apparmor.d/groups/virt/cni-calico deleted file mode 100644 index a6c9149d2f..0000000000 --- a/apparmor.d/groups/virt/cni-calico +++ /dev/null @@ -1,47 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2022 Jeroen Rijken -# SPDX-License-Identifier: GPL-2.0-only - -abi , - -include - -@{exec_path} = @{lib}/cni/calico /opt/cni/bin/calico -profile cni-calico @{exec_path} flags=(attach_disconnected) { - include - - capability sys_admin, - capability net_admin, - - network inet dgram, - network inet6 dgram, - network inet stream, - network inet6 stream, - network netlink raw, - - signal (receive) set=kill peer=containerd, - - @{exec_path} mr, - @{exec_path}-ipam rix, - - / r, - - /etc/cni/net.d/{,**} r, - - /var/lib/calico/{,**} r, - /var/log/calico/cni/ r, - /var/log/calico/cni/*.log rw, - - /usr/share/mime/globs2 r, - - @{run}/calico/ rw, - @{run}/calico/ipam.lock rwk, - @{run}/netns/cni-@{uuid} r, - - @{PROC}/sys/net/ipv{4,6}/ip_forward rw, - @{PROC}/sys/net/ipv{4,6}/{conf,neigh}/cali[0-9a-z]*/* rw, - - include if exists -} - -# vim:syntax=apparmor diff --git a/apparmor.d/groups/virt/cni-host-local b/apparmor.d/groups/virt/cni-host-local deleted file mode 100644 index 5f645ce3f5..0000000000 --- a/apparmor.d/groups/virt/cni-host-local +++ /dev/null @@ -1,18 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2022 Jeroen Rijken -# SPDX-License-Identifier: GPL-2.0-only - -abi , - -include - -@{exec_path} = @{lib}/cni/host-local /opt/cni/bin/host-local -profile cni-host-local @{exec_path} flags=(complain,attach_disconnected){ - include - - @{exec_path} mr, - - include if exists -} - -# vim:syntax=apparmor diff --git a/apparmor.d/groups/virt/cni-loopback b/apparmor.d/groups/virt/cni-loopback deleted file mode 100644 index fd4f50df32..0000000000 --- a/apparmor.d/groups/virt/cni-loopback +++ /dev/null @@ -1,28 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2022 Jeroen Rijken -# SPDX-License-Identifier: GPL-2.0-only - -abi , - -include - -@{exec_path} = @{lib}/cni/loopback /opt/cni/bin/loopback -profile cni-loopback @{exec_path} flags=(attach_disconnected) { - include - - capability sys_admin, - capability net_admin, - - network netlink raw, - - @{exec_path} mr, - - / r, - - @{run}/netns/ r, - @{run}/netns/cni-@{uuid} rw, - - include if exists -} - -# vim:syntax=apparmor diff --git a/apparmor.d/groups/virt/cni-portmap b/apparmor.d/groups/virt/cni-portmap deleted file mode 100644 index 73ad13cb1a..0000000000 --- a/apparmor.d/groups/virt/cni-portmap +++ /dev/null @@ -1,25 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2022 Jeroen Rijken -# SPDX-License-Identifier: GPL-2.0-only - -abi , - -include - -@{exec_path} = @{lib}/cni/portmap /opt/cni/bin/portmap -profile cni-portmap @{exec_path} { - include - - capability net_admin, - - network netlink raw, - - @{exec_path} mr, - @{bin}/xtables-nft-multi rPx -> cni-xtables-nft, - - @{PROC}/sys/net/ipv{4,6}/conf/cali[0-9a-z]*/route_localnet rw, - - include if exists -} - -# vim:syntax=apparmor diff --git a/apparmor.d/groups/virt/cockpit-askpass b/apparmor.d/groups/virt/cockpit-askpass index b46a415ac3..d55edfc9a3 100644 --- a/apparmor.d/groups/virt/cockpit-askpass +++ b/apparmor.d/groups/virt/cockpit-askpass @@ -11,8 +11,12 @@ profile cockpit-askpass @{exec_path} { include include + unix (send receive) type=stream peer=(label=cockpit-bridge), + @{exec_path} mr, + owner @{PROC}/@{pid}/mounts r, + include if exists } diff --git a/apparmor.d/groups/virt/cockpit-bridge b/apparmor.d/groups/virt/cockpit-bridge index a6eb80e9f7..bf5ae89fd2 100644 --- a/apparmor.d/groups/virt/cockpit-bridge +++ b/apparmor.d/groups/virt/cockpit-bridge @@ -9,9 +9,18 @@ include @{exec_path} = @{bin}/cockpit-bridge profile cockpit-bridge @{exec_path} { include + include + include + include + include + include include + include + include + include include include + include capability dac_read_search, capability net_admin, @@ -26,6 +35,8 @@ profile cockpit-bridge @{exec_path} { ptrace read, + unix (send receive) type=stream peer=(label=cockpit-askpass), + signal send set=term peer=cockpit-pcp, signal send set=term peer=dbus-daemon, signal send set=term peer=journalctl, @@ -33,18 +44,28 @@ profile cockpit-bridge @{exec_path} { signal send set=term peer=unconfined, signal (send receive) set=term peer=cockpit-bridge//sudo, + #aa:dbus talk bus=session name=org.libvirt label=libvirt-dbus + #aa:dbus talk bus=system name=org.fedoraproject.FirewallD1 label=firewalld + #aa:dbus talk bus=system name=org.freedesktop.NetworkManager label=NetworkManager + #aa:dbus talk bus=system name=org.freedesktop.PackageKit path=/** label=packagekitd + #aa:dbus talk bus=system name=org.freedesktop.systemd1 label=@{p_systemd} + #aa:dbus talk bus=system name=org.libvirt label=libvirt-dbus + @{exec_path} mr, + @{python_path} ix, @{bin}/cat ix, @{bin}/date ix, + @{bin}/file ix, @{bin}/find ix, @{bin}/ip ix, - @{python_path} ix, @{bin}/test ix, - @{bin}/file ix, + + @{bin}/virt-xml PUx, + @{bin}/virt-xml-validate PUx, @{bin}/chage Px, - @{bin}/dmidecode Px, + @{sbin}/dmidecode Px, @{bin}/findmnt Px, @{bin}/journalctl Px, @{bin}/last Px, @@ -69,9 +90,7 @@ profile cockpit-bridge @{exec_path} { @{etc_ro}/login.defs r, /etc/cockpit/{,**} r, - /etc/httpd/conf/mime.types r, /etc/machine-id r, - /etc/mime.types r, /etc/motd r, /etc/shadow r, /etc/shells r, @@ -79,16 +98,13 @@ profile cockpit-bridge @{exec_path} { / r, @{HOME}/ r, - owner @{user_cache_dirs}/ssh-agent.[0-9A-Z]* rw, + audit owner @{user_cache_dirs}/ssh-agent.[0-9A-Z]* rw, owner @{user_share_dirs}/ r, - @{run}/user/@{uid}/ssh-agent.[0-9A-Z]* rw, + audit @{run}/user/@{uid}/ssh-agent.[0-9A-Z]* rw, @{run}/utmp r, - @{sys}/class/hwmon/ r, @{sys}/class/net/ r, - @{sys}/devices/**/hwmon@{int}/ r, - @{sys}/devices/**/hwmon@{int}/{name,temp*} r, @{sys}/fs/cgroup/ r, @{sys}/fs/cgroup/**/ r, @{sys}/fs/cgroup/**/cpu.{stat,weight} r, @@ -110,10 +126,12 @@ profile cockpit-bridge @{exec_path} { /dev/ptmx rw, - profile sudo { + profile sudo flags=(attach_disconnected) { include include + unix (send receive) type=stream peer=(label=cockpit-bridge), + signal (send receive) set=(cont hup term) peer=cockpit-bridge, @{bin}/cockpit-bridge Px, @@ -126,6 +144,9 @@ profile cockpit-bridge @{exec_path} { include include + @{run}/udev/data/b@{int}:* r, # For block devices + @{run}/udev/data/n@{int} r, # For network interfaces + include if exists } diff --git a/apparmor.d/groups/virt/cockpit-certificate-helper b/apparmor.d/groups/virt/cockpit-certificate-helper index ac9dd5f6f6..6cd122a7f9 100644 --- a/apparmor.d/groups/virt/cockpit-certificate-helper +++ b/apparmor.d/groups/virt/cockpit-certificate-helper @@ -9,6 +9,7 @@ include @{exec_path} = @{lib}/cockpit/cockpit-certificate-helper profile cockpit-certificate-helper @{exec_path} { include + include include @{exec_path} mr, @@ -21,10 +22,11 @@ profile cockpit-certificate-helper @{exec_path} { @{bin}/openssl rix, @{bin}/rm rix, @{bin}/sscg rix, + @{bin}/sync rix, @{bin}/tr rix, /etc/machine-id r, - /etc/cockpit/ws-certs.d/* w, + /etc/cockpit/ws-certs.d/* rw, owner @{run}/cockpit/certificate-helper/{,**} rw, diff --git a/apparmor.d/groups/virt/cockpit-desktop b/apparmor.d/groups/virt/cockpit-desktop index c2a7455ce7..bb1ba03bfe 100644 --- a/apparmor.d/groups/virt/cockpit-desktop +++ b/apparmor.d/groups/virt/cockpit-desktop @@ -10,6 +10,8 @@ include profile cockpit-desktop @{exec_path} { include + userns, + @{exec_path} mr, include if exists diff --git a/apparmor.d/groups/virt/cockpit-session b/apparmor.d/groups/virt/cockpit-session index 8eafd25a0a..e7eeec73f6 100644 --- a/apparmor.d/groups/virt/cockpit-session +++ b/apparmor.d/groups/virt/cockpit-session @@ -10,25 +10,41 @@ include profile cockpit-session @{exec_path} flags=(attach_disconnected) { include include + include include include capability audit_write, + capability chown, capability dac_read_search, capability net_admin, capability setgid, capability setuid, + capability sys_resource, network netlink raw, + signal send set=term peer=ssh-agent, + + dbus send bus=system path=/org/freedesktop/login1 + interface=org.freedesktop.login1.Manager + member=CreateSessionWithPIDFD + peer=(name=org.freedesktop.login1, label=systemd-logind), + + dbus send bus=system path=/org/freedesktop/login1 + interface=org.freedesktop.login1.Manager + member=ReleaseSession + peer=(name=org.freedesktop.login1, label=systemd-logind), + @{exec_path} mr, @{shells_path} rix, @{bin}/cockpit-bridge rPx, @{lib}/cockpit/cockpit-pcp rPx, + @{bin}/ssh-agent rPx, + @{bin}/ssh-add rCx -> ssh-add, @{etc_ro}/environment r, - @{etc_ro}/security/limits.d/{,*.conf} r, /etc/cockpit/disallowed-users r, /etc/group r, /etc/machine-id r, @@ -36,23 +52,42 @@ profile cockpit-session @{exec_path} flags=(attach_disconnected) { /etc/motd.d/ r, /etc/shells r, - @{att}/@{run}/systemd/sessions/*.ref rw, + /var/log/btmp rw, + /var/log/lastlog rw, + /var/log/wtmp rwk, + + /var/lib/lastlog/ r, + /var/lib/lastlog/lastlog2.db rwk, + /var/lib/lastlog/lastlog2.db-journal rw, + + @{run}/systemd/io.systemd.Login rw, + @{att}@{run}/systemd/sessions/*.ref rw, @{run}/cockpit/* r, @{run}/faillock/@{user} rwk, @{run}/motd.d/{,*} r, @{run}/utmp rwk, - /var/log/btmp rw, - /var/log/lastlog rw, - /var/log/wtmp rwk, - + @{PROC}/@{pids}/fd/ r, owner @{PROC}/@{pid}/loginuid rw, owner @{PROC}/@{pid}/uid_map r, - @{PROC}/@{pids}/fd/ r, /dev/tty rw, + profile ssh-add flags=(attach_disconnected) { + include + include + + @{bin}/ssh-add mr, + + owner @{HOME}/@{XDG_SSH_DIR}/{,*} r, + + owner @{tmp}/ssh-@{rand12}/ rw, + owner @{tmp}/ssh-@{rand12}/agent.@{int} rw, + + include if exists + } + include if exists } diff --git a/apparmor.d/groups/virt/cockpit-tls b/apparmor.d/groups/virt/cockpit-tls index 0037b132cc..cee0715017 100644 --- a/apparmor.d/groups/virt/cockpit-tls +++ b/apparmor.d/groups/virt/cockpit-tls @@ -17,6 +17,10 @@ profile cockpit-tls @{exec_path} flags=(attach_disconnected) { /etc/cockpit/ws-certs.d/{,**} r, + @{att}@{run}/cockpit/wsinstance/http.sock rw, + @{att}@{run}/cockpit/wsinstance/https-factory.sock rw, + @{att}@{run}/cockpit/wsinstance/https@@{hex64}.sock rw, + owner @{run}/cockpit/tls/{,**} rw, include if exists diff --git a/apparmor.d/groups/virt/cockpit-ws b/apparmor.d/groups/virt/cockpit-ws index 7b07791195..45521bffa9 100644 --- a/apparmor.d/groups/virt/cockpit-ws +++ b/apparmor.d/groups/virt/cockpit-ws @@ -7,7 +7,7 @@ abi , include @{exec_path} = @{lib}/cockpit/cockpit-ws -profile cockpit-ws @{exec_path} { +profile cockpit-ws @{exec_path} flags=(attach_disconnected) { include include include @@ -18,8 +18,17 @@ profile cockpit-ws @{exec_path} { @{lib}/cockpit/cockpit-session rPx, /usr/share/cockpit/{,**} r, + /etc/cockpit/ws-certs.d/{,**} r, /usr/share/pixmaps/{,**} r, - /etc/cockpit/ws-certs.d/ r, + /usr/share/plymouth/{,**} r, + + @{run}/cockpit/session rw, + @{att}@{run}/cockpit/session rw, + + @{run}/cockpit/wsinstance/https@@{hex64}.sock r, + @{att}@{run}/cockpit/wsinstance/https@@{hex64}.sock w, + + @{att}@{run}/systemd/userdb/io.systemd.Machine rw, owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/fd/ r, diff --git a/apparmor.d/groups/virt/cockpit-wsinstance-factory b/apparmor.d/groups/virt/cockpit-wsinstance-factory index b14a1e36fc..248ca43e80 100644 --- a/apparmor.d/groups/virt/cockpit-wsinstance-factory +++ b/apparmor.d/groups/virt/cockpit-wsinstance-factory @@ -9,11 +9,25 @@ include @{exec_path} = @{lib}/cockpit/cockpit-wsinstance-factory profile cockpit-wsinstance-factory @{exec_path} { include + include capability net_admin, + unix bind type=stream addr=@@{udbus}/bus/cockpit-wsinsta/system, + + dbus receive bus=system path=/org/freedesktop/systemd1 + interface=org.freedesktop.systemd1.Manager + member=JobRemoved + peer=(name=@{busname}, label="@{p_systemd}"), + dbus send bus=system path=/org/freedesktop/systemd1 + interface=org.freedesktop.systemd1.Manager + member=StartUnit + peer=(name=org.freedesktop.systemd1, label="@{p_systemd}"), + @{exec_path} mr, + @{run}/cockpit/wsinstance/https-factory.sock w, + include if exists } diff --git a/apparmor.d/groups/virt/containerd b/apparmor.d/groups/virt/containerd index 4f73ff9858..12be210d5b 100644 --- a/apparmor.d/groups/virt/containerd +++ b/apparmor.d/groups/virt/containerd @@ -46,11 +46,12 @@ profile containerd @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, - @{bin}/apparmor_parser rPx, + @{sbin}/apparmor_parser rPx, @{bin}/containerd-shim-runc-v2 rPx, @{bin}/kmod rPx, @{bin}/unpigz rPUx, /{usr/,}{local/,}{s,}bin/zfs rPx, + @{bin}/mkfs.erofs rPUx, / r, @@ -59,11 +60,14 @@ profile containerd @{exec_path} flags=(attach_disconnected) { /opt/cni/bin/bandwidth rPx, /opt/cni/bin/calico rPx, + /etc/cdi/{,**} r, /etc/calico/ rw, /etc/cni/ rw, /etc/cni/{,**} r, /etc/cni/net.d/ rw, /etc/containerd/*.toml r, + /etc/cdi/ r, + /etc/cdi/*.yaml r, /opt/containerd/{,**} rw, @@ -85,14 +89,13 @@ profile containerd @{exec_path} flags=(attach_disconnected) { @{run}/netns/cni-@{uuid} rw, @{run}/nri/ w, @{run}/nri/nri.sock rw, - @{run}/systemd/notify w, - /tmp/cri-containerd.apparmor.d@{int} rwl, - /tmp/ctd-volume@{int}/{,**} rw, - owner @{tmp}/** rwkl, - owner /var/tmp/** rwkl, + /tmp/cri-containerd.apparmor.d@{int} rwl, + /tmp/ctd-volume@{int}/{,**} rw, @{sys}/fs/cgroup/kubepods/** r, + @{sys}/fs/cgroup/system.slice/containerd.service/cpu.max r, + @{sys}/kernel/mm/hugepages/ r, @{sys}/kernel/security/apparmor/profiles r, @{sys}/module/apparmor/parameters/enabled r, diff --git a/apparmor.d/groups/virt/containerd-shim-runc-v2 b/apparmor.d/groups/virt/containerd-shim-runc-v2 index 5a963beaca..7462d0b773 100644 --- a/apparmor.d/groups/virt/containerd-shim-runc-v2 +++ b/apparmor.d/groups/virt/containerd-shim-runc-v2 @@ -18,6 +18,7 @@ profile containerd-shim-runc-v2 @{exec_path} flags=(attach_disconnected) { capability sys_admin, capability sys_ptrace, capability sys_resource, + capability kill, ptrace (read) peer=containerd, ptrace (read) peer=unconfined, @@ -25,12 +26,12 @@ profile containerd-shim-runc-v2 @{exec_path} flags=(attach_disconnected) { signal (send) set=kill peer=cri-containerd.apparmor.d, signal (receive) set=kill peer=containerd, - mount -> /run/containerd/io.containerd.runtime.v2.task/k8s.io/@{hex}/rootfs/, - umount /run/containerd/io.containerd.runtime.v2.task/k8s.io/@{hex}/rootfs/, + mount -> @{run}/containerd/io.containerd.runtime.v2.task/k8s.io/@{hex}/rootfs/, + umount @{run}/containerd/io.containerd.runtime.v2.task/k8s.io/@{hex}/rootfs/, @{exec_path} mrix, - @{bin}/runc rPUx, + @{sbin}/runc rPx, /tmp/runc-process@{int} rw, /tmp/pty@{int}/ rw, diff --git a/apparmor.d/groups/virt/docker b/apparmor.d/groups/virt/docker new file mode 100644 index 0000000000..5c0a8d0991 --- /dev/null +++ b/apparmor.d/groups/virt/docker @@ -0,0 +1,39 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/docker +profile docker @{exec_path} flags=(attach_disconnected) { + include + include + include + + capability dac_read_search, + + network inet dgram, + network inet stream, + network inet6 dgram, + network inet6 stream, + network netlink raw, + + unix (bind listen) type=stream addr=@docker_cli_@{hex32}, + unix (accept send receive) type=stream addr=@docker_cli_@{hex32} peer=(label=docker-buildx), + + @{exec_path} mr, + + @{lib}/docker/cli-plugins/docker-buildx Px, + + @{run}/docker.sock rw, + + @{PROC}/sys/net/core/somaxconn r, + owner @{PROC}/@{pid}/cgroup r, + owner @{PROC}/@{pid}/mountinfo r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/groups/virt/docker-proxy b/apparmor.d/groups/virt/docker-proxy index 9a8cbe3794..253f787795 100644 --- a/apparmor.d/groups/virt/docker-proxy +++ b/apparmor.d/groups/virt/docker-proxy @@ -6,13 +6,16 @@ abi , include -@{exec_path} = @{bin}/docker-proxy +@{exec_path} = @{bin}/docker-proxy @{sbin}/docker-proxy #aa:lint ignore=sbin profile docker-proxy @{exec_path} { include + include capability net_admin, capability net_bind_service, + network inet dgram, + network inet6 dgram, network inet stream, network inet6 stream, network netlink raw, @@ -21,7 +24,11 @@ profile docker-proxy @{exec_path} { @{exec_path} mr, + @{sys}/fs/cgroup/system.slice/docker.service/cpu.max r, + @{PROC}/sys/net/core/somaxconn r, + @{PROC}/@{pid}/mountinfo r, + @{PROC}/@{pid}/cgroup r, include if exists } diff --git a/apparmor.d/groups/virt/dockerd b/apparmor.d/groups/virt/dockerd index 3f18bbdccb..116daaa51e 100644 --- a/apparmor.d/groups/virt/dockerd +++ b/apparmor.d/groups/virt/dockerd @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/dockerd +@{exec_path} = @{bin}/dockerd @{sbin}/dockerd #aa:lint ignore=sbin profile dockerd @{exec_path} flags=(attach_disconnected) { include include @@ -38,15 +38,15 @@ profile dockerd @{exec_path} flags=(attach_disconnected) { mount /tmp/containerd-mount@{int}/, mount /var/lib/docker/**/, - mount options=(rw bind) -> /run/docker/netns/*, - mount options=(rw rprivate) -> /.pivot_root@{int}/, - mount options=(rw rslave) -> /, + mount options=(rw bind) -> @{run}/docker/netns/*, + mount options=(rw make-rprivate) /.pivot_root@{int}/, + mount options=(rw make-rslave) /, remount /tmp/containerd-mount@{int10}/, remount /var/lib/docker/**/, umount /.pivot_root@{int}/, - umount /run/docker/netns/*, + umount @{run}/docker/netns/*, umount /tmp/containerd-mount@{int}/, umount /var/lib/docker/**/, @@ -62,28 +62,39 @@ profile dockerd @{exec_path} flags=(attach_disconnected) { signal send set=kill peer=docker-*, signal send set=term peer=containerd, + #aa:dbus talk bus=system name=org.fedoraproject.FirewallD1 label=firewalld + @{exec_path} mrix, - @{bin}/apparmor_parser rPx, + @{sbin}/apparmor_parser rPx, + @{sbin}/docker-proxy rPx, @{bin}/containerd rPx, @{bin}/docker-init rCx -> init, @{lib}/docker/docker-init rCx -> init, - @{bin}/docker-proxy rPx, + @{bin}/docker-proxy rPx, #aa:lint ignore=sbin + @{bin}/tini-static rCx -> tini, @{bin}/git rCx -> git, - @{bin}/kmod rPx, + @{bin}/kmod rCx -> kmod, @{bin}/ps rPx, - @{bin}/runc rUx, + @{sbin}/runc rUx, + @{bin}/runc rUx, #aa:lint ignore=sbin @{bin}/unpigz rix, - @{bin}/xtables-nft-multi rix, + @{sbin}/nft rCx -> nft, + @{sbin}/xtables-{nft,legacy}-multi rCx -> nft, + #aa:lint ignore=too-wide # Docker needs full access of the containers it manages. # TODO: should be in a sub profile started with pivot_root, not supported yet. /{,**} rwl, #aa:only apt - @{att}/@{lib}/containerd/** rw, + @{att}@{lib}/containerd/** rw, + @{att}/var/lib/containerd/** rw, @{att}/var/lib/docker/{,**} rwk, + @{att}/@/var/lib/docker/{,**} rwk, + /etc/cdi/{,**} r, /etc/docker/{,**} r, + /etc/os-release r, @{att}/ r, @@ -95,9 +106,8 @@ profile dockerd @{exec_path} flags=(attach_disconnected) { /tmp/build/ w, /tmp/containerd-mount@{int}/{,**} rw, - @{run}/systemd/notify rw, - @{run}/containerd/containerd.sock rw, + @{run}/docker.sock rw, owner @{run}/docker.pid rw, owner @{run}/docker/ rw, owner @{run}/docker/** rwlk, @@ -106,6 +116,8 @@ profile dockerd @{exec_path} flags=(attach_disconnected) { @{sys}/fs/cgroup/cgroup.controllers r, @{sys}/fs/cgroup/cpuset.cpus.effective r, @{sys}/fs/cgroup/cpuset.mems.effective r, + @{sys}/fs/cgroup/system.slice/docker.service/cpu.max r, + @{sys}/kernel/mm/hugepages/ r, @{sys}/kernel/security/apparmor/profiles r, @{sys}/module/apparmor/parameters/enabled r, @@ -121,6 +133,7 @@ profile dockerd @{exec_path} flags=(attach_disconnected) { @{PROC}/sys/net/bridge/bridge-nf-call-ip*tables r, @{PROC}/sys/net/core/somaxconn r, @{PROC}/sys/net/ipv{4,6}/conf/*/disable_ipv{4,6} rw, + @{PROC}/sys/net/ipv{4,6}/conf/br-*/accept_ra w, @{PROC}/sys/net/ipv{4,6}/conf/docker@{int}/accept_ra rw, @{PROC}/sys/net/ipv{4,6}/ip_forward rw, @{PROC}/sys/net/ipv{4,6}/ip_local_port_range r, @@ -128,13 +141,60 @@ profile dockerd @{exec_path} flags=(attach_disconnected) { owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/mountinfo r, - owner @{PROC}/@{pid}/net/ip_tables_names r, owner @{PROC}/@{pid}/task/@{tid}/mountinfo r, owner @{PROC}/@{pid}/uid_map r, /dev/ r, /dev/**/ r, + profile nft flags=(attach_disconnected) { + include + include + + capability net_admin, + capability net_raw, + + network inet raw, + network inet6 dgram, + network inet6 raw, + network netlink raw, + + @{sbin}/nft rix, + @{sbin}/xtables-{nft,legacy}-multi rix, + @{bin}/kmod rPx -> dockerd//kmod, + + /usr/share/iproute2/* r, + + @{run}/xtables.lock rwk, + + @{PROC}/@{pid}/net/ip{,6}_tables_names r, + @{PROC}/sys/kernel/modprobe r, + + include if exists + } + + profile kmod { + include + include + + capability sys_module, + + @{run}/xtables.lock r, + + @{sys}/module/compression r, + @{sys}/module/*/initstate r, + + include if exists + } + + profile tini { + include + + @{bin}/tini-static mr, + + include if exists + } + profile init flags=(attach_disconnected) { include diff --git a/apparmor.d/groups/virt/k3s b/apparmor.d/groups/virt/k3s deleted file mode 100644 index 0949e72eeb..0000000000 --- a/apparmor.d/groups/virt/k3s +++ /dev/null @@ -1,176 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2022 Jeroen Rijken -# SPDX-License-Identifier: GPL-2.0-only - -abi , - -include - -@{exec_path} = /{usr/,}{local/,}bin/k3s -profile k3s @{exec_path} flags=(attach_disconnected) { - include - include - include - include - - capability chown, - capability kill, - capability dac_override, - capability dac_read_search, - capability fsetid, - capability fowner, - capability net_admin, - capability syslog, - capability sys_admin, - capability sys_ptrace, - capability sys_resource, - - ptrace peer=@{profile_name}, - ptrace (read) peer={cni-calico-node,cri-containerd.apparmor.d,cni-xtables-nft,ip,kmod,kubernetes-pause,mount,unconfined}, - - # k3s requires ptrace to all AppArmor profiles loaded in Kubernetes. - # For simplification, let's assume for now all AppArmor profiles start with a predefined prefix. - ptrace (read) peer=container-*, - ptrace (read) peer=docker-*, - ptrace (read) peer=k3s-*, - ptrace (read) peer=kubernetes-*, - # When using ZFS as storage provider instead of the default overlay2. - ptrace (read) peer=zfs, - ptrace (read) peer=zpool, - - network inet dgram, - network inet6 dgram, - network inet stream, - network inet6 stream, - network netlink raw, - - mount -> /var/lib/kubelet/pods/@{uuid}/volumes/kubernetes.io~*/{,**/}, - mount -> /var/lib/kubelet/pods/@{uuid}/volume-subpaths/{,**}, - - umount /var/lib/kubelet/pods/@{uuid}/volumes/kubernetes.io~*/{,**/}, - umount /var/lib/kubelet/pods/@{uuid}/volume-subpaths/{,**}, - - signal (send, receive) set=term, - signal (send) set=kill peer=unconfined, - - unix (bind,listen) type=stream addr=@xtables, - - @{exec_path} mr, - - @{bin}/kmod rPx, - @{bin}/mount rPx, - @{bin}/systemd-run rix, - @{bin}/{nano,emacs,ed} rPUx, - @{bin}/vim{,.basic} rPUx, - @{bin}/xtables-nft-multi rPx -> cni-xtables-nft, - - @{lib}/kubernetes/kubelet-plugins/volume/exec/nodeagent~uds/uds rix, - /var/lib/rancher/k3s/data/@{hex}/bin/* rix, - - @{lib}/kubernetes/kubelet-plugins/volume/exec/{,**} r, - /usr/share/mime/globs2 r, - - /etc/machine-id r, - /etc/rancher/{,**} rw, - - /var/lib/kubelet/{,**} rw, - /var/lib/rancher/{,**} rw, - /var/lib/rancher/k3s/data/.lock rwk, - /var/lib/rancher/k3s/server/db/{,**} rwk, - - /var/log/containers/ r, - /var/log/containers/** rw, - /var/log/rancher/{,**} r, - /var/log/kubelet/{,**} r, - /var/log/kubernetes/{,**} r, - /var/log/kubernetes/audit/** rw, - /var/log/pods/{,**} r, - /var/log/pods/{,**/} rw, - /var/log/pods/**/@{int}.log{,*} rw, - - owner @{HOME}/.kube/** rw, - - @{run}/containerd/containerd.sock rw, - @{run}/systemd/notify w, - @{run}/systemd/private rw, - @{run}/systemd/resolve/resolv.conf r, - @{run}/nodeagent/ rw, - @{run}/xtables.lock rwk, - - owner /var/tmp/** rwkl, - owner @{tmp}/** rwkl, - - owner @{PROC}/@{pids}/cgroup r, - owner @{PROC}/@{pids}/cpuset r, - @{PROC}/@{pids}/fd/ r, - @{PROC}/@{pids}/limits r, - owner @{PROC}/@{pids}/mounts r, - owner @{PROC}/@{pids}/mountinfo r, - @{PROC}/@{pids}/net/dev r, - @{PROC}/@{pids}/net/ip_tables_names r, - owner @{PROC}/@{pids}/net/ipv6_route r, - owner @{PROC}/@{pids}/net/route r, - owner @{PROC}/@{pids}/oom_score_adj rw, - owner @{PROC}/@{pids}/stat r, - owner @{PROC}/@{pids}/uid_map r, - - @{PROC}/diskstats r, - @{PROC}/loadavg r, - @{PROC}/modules r, - @{PROC}/sys/fs/pipe-max-size r, - @{PROC}/sys/kernel/keys/* r, - @{PROC}/sys/kernel/panic rw, - @{PROC}/sys/kernel/panic_on_oom rw, - @{PROC}/sys/kernel/panic_on_oops rw, - @{PROC}/sys/kernel/pid_max r, - @{PROC}/sys/kernel/osrelease r, - @{PROC}/sys/kernel/threads-max r, - @{PROC}/sys/net/core/somaxconn r, - @{PROC}/sys/net/ipv{4,6}/conf/all/* rw, - @{PROC}/sys/net/ipv{4,6}/conf/default/* rw, - @{PROC}/sys/net/bridge/bridge-nf-call-iptables r, - @{PROC}/sys/net/netfilter/* rw, - @{PROC}/sys/vm/panic_on_oom r, - - @{sys}/class/net/ r, - - @{sys}/devices/@{pci}/net/*/{address,mtu,speed} r, - @{sys}/devices/system/edac/mc/ r, - @{sys}/devices/system/cpu/cpu@{int}/cache/{,**} r, - @{sys}/devices/system/cpu/cpu@{int}/topology/{,**} r, - @{sys}/devices/system/cpu/cpufreq/policy@{int}/cpuinfo_max_freq r, - @{sys}/devices/system/cpu/present{,/} r, - @{sys}/devices/system/node/ r, - @{sys}/devices/system/node/node@{int}/ r, - @{sys}/devices/system/node/node@{int}/{cpumap,distance,meminfo} r, - @{sys}/devices/system/node/node@{int}/hugepages/{,**} r, - - @{sys}/devices/virtual/block/*/** r, - @{sys}/devices/virtual/dmi/id/* r, - @{sys}/devices/virtual/net/cali@{hex}/{address,mtu,speed} r, - @{sys}/devices/virtual/net/vxlan.calico/{address,mtu,speed} r, - - @{sys}/fs/cgroup/{,*,*/} r, - @{sys}/fs/cgroup/cgroup.subtree_control rw, - @{sys}/fs/cgroup/kubepods/{,**} rw, - @{sys}/fs/cgroup/system.slice/{,**/} r, - @{sys}/fs/cgroup/system.slice/k3s.service/* r, - @{sys}/fs/cgroup/user.slice/ r, - @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/ r, - @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user-runtime-dir@@{uid}.service/ r, - @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/{,**/} r, - @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/session-@{word}.scope/{,**/} r, - - @{sys}/kernel/mm/hugepages/ r, - @{sys}/kernel/mm/hugepages/hugepages-*/nr_hugepages r, - @{sys}/kernel/security/apparmor/profiles r, - - @{sys}/module/apparmor/parameters/enabled r, - - /dev/kmsg r, - /dev/pts/@{int} rw, - - include if exists -} - -# vim:syntax=apparmor diff --git a/apparmor.d/groups/virt/kubernetes-pause b/apparmor.d/groups/virt/kubernetes-pause deleted file mode 100644 index c762515a41..0000000000 --- a/apparmor.d/groups/virt/kubernetes-pause +++ /dev/null @@ -1,22 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2022 Jeroen Rijken -# SPDX-License-Identifier: GPL-2.0-only - -abi , - -include - -@{exec_path} = /pause -profile kubernetes-pause @{exec_path} flags=(attach_disconnected) { - include - - signal (receive) set=kill, - - ptrace (readby) peer={k3s,ps}, - - @{exec_path} mr, - - include if exists -} - -# vim:syntax=apparmor diff --git a/apparmor.d/groups/virt/libvirt-dbus b/apparmor.d/groups/virt/libvirt-dbus index 44d24f1ae4..670b4da5cf 100644 --- a/apparmor.d/groups/virt/libvirt-dbus +++ b/apparmor.d/groups/virt/libvirt-dbus @@ -6,8 +6,8 @@ abi , include -@{exec_path} = @{bin}/libvirt-dbus -profile libvirt-dbus @{exec_path} { +@{exec_path} = @{sbin}/libvirt-dbus +profile libvirt-dbus @{exec_path} flags=(attach_disconnected) { include include include @@ -16,21 +16,31 @@ profile libvirt-dbus @{exec_path} { #aa:dbus own bus=session name=org.libvirt #aa:dbus own bus=system name=org.libvirt + dbus receive bus=session + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), + @{exec_path} mr, - @{bin}/libvirtd rPx, + @{sbin}/libvirtd rPx, @{bin}/virtqemud rPx, /usr/share/dbus-1/interfaces/org.libvirt.*.xml r, owner @{user_cache_dirs}/libvirt/libvirtd.lock rwk, - @{run}/user/@{uid}/libvirt/ rw, - @{run}/user/@{uid}/libvirt/libvirtd.lock rwk, - @{run}/user/@{uid}/libvirt/virtqemud.lock rwk, + @{run}/libvirt/libvirt-sock rw, + + @{run}/user/@{uid}/libvirt/ rw, + @{run}/user/@{uid}/libvirt/libvirtd.lock rwk, + @{run}/user/@{uid}/libvirt/virtqemud.lock rwk, + owner @{run}/user/@{uid}/libvirt/libvirt-sock rw, + owner @{run}/user/@{uid}/libvirt/virtqemud-sock rw, @{sys}/devices/system/node/ r, @{sys}/devices/system/node/node*/meminfo r, + @{sys}/kernel/iommu_groups/ r, owner @{PROC}/@{pid}/fd/ r, diff --git a/apparmor.d/groups/virt/libvirtd b/apparmor.d/groups/virt/libvirtd index 061866717a..f4d913947b 100644 --- a/apparmor.d/groups/virt/libvirtd +++ b/apparmor.d/groups/virt/libvirtd @@ -14,13 +14,18 @@ abi , include -@{exec_path} = @{bin}/libvirtd +@{exec_path} = @{sbin}/libvirtd profile libvirtd @{exec_path} flags=(attach_disconnected) { include + include + include + include + include + include include - include include include + include include capability audit_write, @@ -46,19 +51,18 @@ profile libvirtd @{exec_path} flags=(attach_disconnected) { capability sys_pacct, capability sys_ptrace, capability sys_rawio, - capability sys_resource, + capability sys_resource, # Needed for vfio - network inet stream, network inet dgram, - network inet6 stream, + network inet stream, network inet6 dgram, + network inet6 stream, network netlink raw, network packet dgram, network packet raw, - mount options=(rw, rslave) -> /, + mount options=(rw, make-rslave) /, mount options=(rw, nosuid) -> @{run}/libvirt/qemu/*.dev/, - umount @{run}/libvirt/qemu/*.dev/, # Libvirt provides any mounts under /dev to qemu namespaces mount options=(rw, move) /dev/ -> @{run}/libvirt/qemu/*.dev/, @@ -66,6 +70,11 @@ profile libvirtd @{exec_path} flags=(attach_disconnected) { mount options=(rw, move) @{run}/libvirt/qemu/*.dev/ -> /dev/, mount options=(rw, move) @{run}/libvirt/qemu/*{,/} -> /dev/**, + umount @{run}/libvirt/qemu/*.dev/, + umount /dev/, + + mqueue getattr type=posix /, + ptrace (read,trace) peer=@{profile_name}, ptrace (read,trace) peer=dnsmasq, ptrace (read,trace) peer=gnome-boxes, @@ -85,10 +94,25 @@ profile libvirtd @{exec_path} flags=(attach_disconnected) { unix (send, receive) type=stream addr=none peer=(label=libvirtd//qemu_bridge_helper), unix (send, receive) type=stream addr=none peer=(label=unconfined addr=none), unix (send, receive) type=stream addr=none peer=(label=unconfined), + unix (send, receive) type=stream addr=none peer=(label=virt-manager), # Allow changing to our UUID-based named profiles change_profile -> libvirt-@{uuid}, + #aa:dbus talk bus=system name=org.fedoraproject.FirewallD1 label=firewalld + #aa:dbus talk bus=system name=org.freedesktop.machine1 label=systemd-machined + + dbus receive bus=session + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), + + # include + dbus send bus=system path=/org/freedesktop/DBus + interface=org.freedesktop.DBus + member={ListNames,ListActivatableNames} + peer=(name=org.freedesktop.DBus, label="@{p_dbus_system}"), + @{exec_path} mr, @{lib}/libvirt/libvirt_iohelper rix, @@ -103,26 +127,28 @@ profile libvirtd @{exec_path} flags=(attach_disconnected) { @{lib}/xen-common/bin/xen-toolstack rPUx, @{lib}/xen/bin/* rPUx, - @{bin}/dmidecode rPx, - @{bin}/dnsmasq rPx, - @{bin}/kmod rPx, - @{bin}/lvm rPUx, - @{bin}/mdevctl rPx, + @{bin}/kmod rCx -> kmod, + @{bin}/mdevctl rPx, #aa:lint ignore=sbin + @{bin}/ssh rPx, @{bin}/swtpm rPx, @{bin}/swtpm_ioctl rPx, @{bin}/swtpm_setup rPx, @{bin}/udevadm rPx, - @{bin}/virtiofsd rux, # TODO: WIP - @{bin}/virtlogd rPx, + @{bin}/virtiofsd rPx, # TODO: WIP + @{sbin}/dmidecode rPx, + @{sbin}/dnsmasq rPx, + @{sbin}/lvm rPUx, + @{sbin}/mdevctl rPx, + @{sbin}/virtlogd rPx, @{sh_path} rix, @{bin}/ip rix, - @{bin}/nft rix, + @{sbin}/nft rix, @{bin}/qemu-img rUx, # TODO: Integration with virt-aa-helper @{bin}/qemu-system* rUx, # TODO: Integration with virt-aa-helper - @{bin}/tc rix, + @{sbin}/tc rix, @{bin}/xmllint rix, - @{bin}/xtables-nft-multi rix, + @{sbin}/xtables-{nft,legacy}-multi rix, @{lib}/libvirt/virt-aa-helper rPx, /etc/libvirt/hooks/** rPUx, @@ -130,11 +156,12 @@ profile libvirtd @{exec_path} flags=(attach_disconnected) { /var/lib/libvirt/virtd* rix, /usr/share/edk2*/{,**} rk, + /usr/share/gvfs/remote-volume-monitors/{,**} r, /usr/share/hwdata/* r, /usr/share/iproute2/{,**} r, /usr/share/libvirt/{,**} r, - /usr/share/mime/mime.cache r, /usr/share/misc/pci.ids r, + /usr/share/OVMF/{,**} rk, /usr/share/qemu/{,**} r, @{etc_rw}/apparmor.d/libvirt/libvirt-@{uuid} r, @@ -143,8 +170,11 @@ profile libvirtd @{exec_path} flags=(attach_disconnected) { /etc/sasl2/qemu.conf r, /etc/xml/catalog r, + / r, + /var/cache/libvirt/{,**} rw, - /var/lib/libvirt/{,**} rwk, + /var/lib/libvirt/ rw, + /var/lib/libvirt/** rwk, /var/log/swtpm/libvirt/{,**} rw, # User VM images and share @@ -153,69 +183,63 @@ profile libvirtd @{exec_path} flags=(attach_disconnected) { @{user_vm_dirs}/{,**} rwk, @{user_publicshare_dirs}/{,**} rwk, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + owner @{user_cache_dirs}/libvirt/{,**} rwk, + owner @{user_config_dirs}/libvirt/{,**} rwk, + owner @{run}/user/@{uid}/libvirt/ rw, + owner @{run}/user/@{uid}/libvirt/** rwk, + + @{att}@{run}/systemd/inhibit/@{int}.ref rw, + + /dev/shm/ w, + + @{run}/credentials/libvirtd.service/secrets-encryption-key r, @{run}/libvirt/ rw, @{run}/libvirt/** rwk, @{run}/libvirtd.pid wk, @{run}/lock/LCK.._pts_@{int} rw, - @{run}/systemd/notify w, @{run}/utmp rk, - @{run}/udev/data/+backlight:* r, - @{run}/udev/data/+bluetooth:* r, - @{run}/udev/data/+dmi:* r, # for motherboard info - @{run}/udev/data/+drm:card@{int}-* r, # For screen outputs - @{run}/udev/data/+hid:* r, - @{run}/udev/data/+input:input@{int} r, # For mouse, keyboard, touchpad - @{run}/udev/data/+leds:* r, - @{run}/udev/data/+pci:* r, # Identifies all PCI devices (CPU, GPU, Network, Disks, USB, etc.) - @{run}/udev/data/+platform:* r, - @{run}/udev/data/+power_supply:* r, - @{run}/udev/data/+rfkill:* r, - @{run}/udev/data/+sound:card@{int} r, # For sound card - @{run}/udev/data/+thunderbolt:* r, - @{run}/udev/data/c1:@{int} r, # For RAM disk - @{run}/udev/data/c6:@{int} r, # For parallel printer devices /dev/lp* - @{run}/udev/data/c10:@{int} r, # For non-serial mice, misc features - @{run}/udev/data/c13:@{int} r, # For /dev/input/* - @{run}/udev/data/c21:@{int} r, # Generic SCSI access - @{run}/udev/data/c29:@{int} r, # For /dev/fb[0-9]* - @{run}/udev/data/c81:@{int} r, # For video4linux - @{run}/udev/data/c89:@{int} r, # For I2C bus interface - @{run}/udev/data/c90:@{int} r, # For RAM, ROM, Flash - @{run}/udev/data/c99:@{int} r, # For raw parallel ports /dev/parport* - @{run}/udev/data/c108:@{int} r, # For /dev/ppp - @{run}/udev/data/c116:@{int} r, # For ALSA - @{run}/udev/data/c202:@{int} r, # CPU model-specific registers - @{run}/udev/data/c203:@{int} r, # CPU CPUID information - @{run}/udev/data/c226:@{int} r, # For /dev/dri/card[0-9]* - @{run}/udev/data/c@{dynamic}:@{int} r, # For dynamic assignment range 234 to 254, 384 to 511 - @{run}/udev/data/n@{int} r, + @{run}/udev/data/+*:* r, # Identifies all subsystems + @{run}/udev/data/c@{int}:@{int} r, # Identifies all character devices + @{run}/udev/data/n@{int} r, # For network interfaces @{sys}/bus/[a-z]*/devices/ r, + @{sys}/bus/**/uevent r, + @{sys}/bus/hid/drivers/*/uevent r, @{sys}/bus/pci/drivers_probe w, @{sys}/bus/pci/drivers/*/unbind w, + @{sys}/bus/usb/drivers/*/uevent r, @{sys}/class/[a-z]*/ r, - @{sys}/devices/**/uevent r, - @{sys}/devices/@{pci}/{class,revision,subsystem_vendor,subsystem_device} r, - @{sys}/devices/@{pci}/{config,numa_node,device,vendor} r, + @{sys}/devices/@{pci}/class r, + @{sys}/devices/@{pci}/config r, + @{sys}/devices/@{pci}/device r, @{sys}/devices/@{pci}/driver_override w, @{sys}/devices/@{pci}/mdev_supported_types/{,**} r, @{sys}/devices/@{pci}/mdev_supported_types/*/create w, @{sys}/devices/@{pci}/net/*/{,**} r, + @{sys}/devices/@{pci}/numa_node r, @{sys}/devices/@{pci}/remove w, @{sys}/devices/@{pci}/resource r, + @{sys}/devices/@{pci}/revision r, @{sys}/devices/@{pci}/sriov_totalvfs r, + @{sys}/devices/@{pci}/subsystem_device r, + @{sys}/devices/@{pci}/subsystem_vendor r, + @{sys}/devices/@{pci}/vendor r, + @{sys}/devices/**/uevent r, + @{sys}/devices/@{pci}/distance r, + @{sys}/devices/@{pci}/meminfo r, @{sys}/devices/system/cpu/cpu@{int}/cache/{,**} r, @{sys}/devices/system/cpu/cpu@{int}/topology/{,**} r, @{sys}/devices/system/cpu/isolated r, @{sys}/devices/system/cpu/present r, @{sys}/devices/system/node/ r, @{sys}/devices/system/node/node@{int}/ r, - @{sys}/devices/system/node/node@{int}/{cpumap,distance,meminfo} r, + @{sys}/devices/system/node/node@{int}/cpumap r, + @{sys}/devices/system/node/node@{int}/distance r, @{sys}/devices/system/node/node@{int}/hugepages/{,**} r, + @{sys}/devices/system/node/node@{int}/meminfo r, @{sys}/devices/virtual/dmi/id/* r, @{sys}/devices/virtual/net/{,**} rw, @@ -225,6 +249,7 @@ profile libvirtd @{exec_path} flags=(attach_disconnected) { @{sys}/kernel/mm/hugepages/{,**} r, @{sys}/kernel/security/apparmor/profiles r, + @{sys}/module/*/uevent r, @{sys}/module/kvm_*/parameters/* r, @{sys}/module/vhost/parameters/max_mem_regions r, @@ -248,6 +273,7 @@ profile libvirtd @{exec_path} flags=(attach_disconnected) { @{PROC}/devices r, @{PROC}/mtrr w, @{PROC}/sys/net/ipv{4,6}/** rw, + @{PROC}/uptime r, owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/mounts r, owner @{PROC}/@{pid}/task/@{tid}/comm rw, @@ -258,19 +284,38 @@ profile libvirtd @{exec_path} flags=(attach_disconnected) { /dev/kvm rw, /dev/mapper/ r, /dev/mapper/control rw, + /dev/mqueue/ w, /dev/net/tun rw, /dev/ptmx rw, + /dev/pts/ w, + /dev/random rw, /dev/shm/libvirt/{,**} rw, + /dev/urandom rw, + /dev/userfaultfd w, /dev/vfio/@{int} rwk, /dev/vhost-net rw, # Force the use of virt-aa-helper - audit deny @{bin}/apparmor_parser rwxl, + audit deny @{sbin}/apparmor_parser rwxl, audit deny @{etc_rw}/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, + profile kmod { + include + include + + capability sys_module, + + @{sys}/module/compression r, + @{sys}/module/iommufd/initstate r, + @{sys}/module/irqbypass/initstate r, + @{sys}/module/vfio/initstate r, + + include if exists + } + profile qemu_bridge_helper { include @@ -289,7 +334,7 @@ profile libvirtd @{exec_path} flags=(attach_disconnected) { /etc/qemu/{,**} r, - owner @{PROC}/@{pids}/status r, + @{PROC}/@{pids}/status r, /dev/net/tun rw, diff --git a/apparmor.d/groups/virt/virt-aa-helper b/apparmor.d/groups/virt/virt-aa-helper index c10f449224..b49368f07a 100644 --- a/apparmor.d/groups/virt/virt-aa-helper +++ b/apparmor.d/groups/virt/virt-aa-helper @@ -19,16 +19,36 @@ profile virt-aa-helper @{exec_path} { @{exec_path} mr, - @{bin}/apparmor_parser rPx, + @{sbin}/apparmor_parser rPx, - /etc/apparmor.d/libvirt/* r, + @{etc_rw}/apparmor.d/libvirt/* r, @{etc_rw}/apparmor.d/libvirt/libvirt-@{uuid} rw, + @{etc_rw}/apparmor.d/libvirt/libvirt-@{uuid}.files rw, /etc/libnl{,-3}/classid r, # Allow reading libnl's classid file # System VM images /var/lib/libvirt/images/{,**} r, - /var/lib/nova/instances/_base/* r, + + # Openstack Nova base images & snapshots (LP: #907269 #1244694 #1644507) + /var/lib/nova/images/{,**} r, + /var/lib/nova/instances/_base/{,**} r, + /var/lib/nova/instances/snapshots/{,**} r, + /var/snap/nova-hypervisor/common/instances/_base/{,**} r, + /var/snap/nova-hypervisor/common/instances/snapshots/{,**} r, + + # Eucalyptus disks & loader (LP: #564914 #637544) + /var/lib/eucalyptus/instances/**/disk* r, + /var/lib/eucalyptus/instances/**/loader* r, + + # For uvtool + /var/lib/uvtool/libvirt/images/{,**} r, + + # For multipass + /var/snap/multipass/common/data/multipassd/vault/instances/{,**} r, + + # Common mount directories + @{MOUNTDIRS}/{,**} r, # User VM images @{user_share_dirs}/ r, @@ -45,7 +65,6 @@ profile virt-aa-helper @{exec_path} { @{PROC}/@{pid}/fd/ r, @{PROC}/@{pid}/net/psched r, deny @{PROC}/@{pid}/mounts r, - owner @{PROC}/@{pid}/status r, # For gl enabled graphics /dev/dri/{,*} r, diff --git a/apparmor.d/groups/virt/virtinterfaced b/apparmor.d/groups/virt/virtinterfaced index 4737dd806f..6954bdd4ba 100644 --- a/apparmor.d/groups/virt/virtinterfaced +++ b/apparmor.d/groups/virt/virtinterfaced @@ -20,7 +20,7 @@ profile virtinterfaced @{exec_path} flags=(attach_disconnected) { @{lib}/gconv/gconv-modules rm, @{lib}/gconv/gconv-modules.d/{,*} r, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, owner @{run}/user/@{uid}/libvirt/common/system.token rwk, owner @{run}/user/@{uid}/libvirt/interface/ rw, owner @{run}/user/@{uid}/libvirt/interface/run/{,*} rwk, diff --git a/apparmor.d/groups/virt/virtiofsd b/apparmor.d/groups/virt/virtiofsd index 899ecae045..63dba4113d 100644 --- a/apparmor.d/groups/virt/virtiofsd +++ b/apparmor.d/groups/virt/virtiofsd @@ -6,8 +6,8 @@ abi , include -@{exec_path} = @{lib}/{,qemu/}virtiofsd @{bin}/virtiofsd -profile virtiofsd @{exec_path} { +@{exec_path} = @{lib}/virtiofsd @{lib}/qemu/virtiofsd @{bin}/virtiofsd +profile virtiofsd @{exec_path} flags=(attach_disconnected) { include userns, @@ -27,17 +27,20 @@ profile virtiofsd @{exec_path} { mount options=(rw, bind) @{PROC}/1/fd/ -> @{PROC}, mount options=(rw, nosuid, nodev, noexec, relatime) -> @{PROC}, - mount options=(rw, rslave) -> /, + mount options=(rw, make-rslave) /, - mount options=(rw, rbind) -> @{user_publicshare_dirs}/, - mount options=(rw, rbind) -> @{user_vm_dirs}/, - mount options=(rw, rbind) -> @{user_vmshare_dirs}/, + mount options=(rw, rbind) -> @{user_projects_dirs}/{,**/}, + mount options=(rw, rbind) -> @{user_publicshare_dirs}/{,**/}, + mount options=(rw, rbind) -> @{user_vm_dirs}/{,**/}, + mount options=(rw, rbind) -> @{user_vmshare_dirs}/{,**/}, umount /, - pivot_root @{user_publicshare_dirs}/, # TODO: -> pivoted, - pivot_root @{user_vm_dirs}/, - pivot_root @{user_vmshare_dirs}/, + # TODO: -> pivoted + pivot_root oldroot=@{user_projects_dirs}/{,**/} @{user_projects_dirs}/{,**/}, + pivot_root oldroot=@{user_publicshare_dirs}/{,**/} @{user_publicshare_dirs}/{,**/}, + pivot_root oldroot=@{user_vm_dirs}/{,**/} @{user_vm_dirs}/{,**/}, + pivot_root oldroot=@{user_vmshare_dirs}/{,**/} @{user_vmshare_dirs}/{,**/}, signal (receive) set=term peer=libvirtd, @@ -48,15 +51,24 @@ profile virtiofsd @{exec_path} { / r, /var/lib/libvirt/qemu/*/fs@{int}-fs.sock rw, + @{user_projects_dirs}/{,**} r, @{user_publicshare_dirs}/{,**} r, @{user_vm_dirs}/{,**} r, @{user_vmshare_dirs}/{,**} r, owner @{run}/libvirt/qemu/*.pid rw, + @{att}/@{pid}/mountinfo r, + @{PROC}/ r, + @{PROC}/@{pid}/gid_map r, + @{PROC}/@{pid}/setgroups r, + @{PROC}/@{pid}/uid_map r, @{PROC}/sys/fs/file-max r, + @{PROC}/sys/fs/nr_open r, + # Allow read/write access to the shared directories + /{,**} rwl, # profile pivoted { # /{,**} rwl, # } diff --git a/apparmor.d/groups/virt/virtlockd b/apparmor.d/groups/virt/virtlockd index ea9336cef2..a0ae83710c 100644 --- a/apparmor.d/groups/virt/virtlockd +++ b/apparmor.d/groups/virt/virtlockd @@ -6,12 +6,18 @@ abi , include -@{exec_path} = @{bin}/virtlockd +@{exec_path} = @{sbin}/virtlockd profile virtlockd @{exec_path} { include @{exec_path} mr, + /etc/libvirt/virtlockd.conf r, + + @{run}/virtlockd.pid wk, + + @{sys}/devices/system/node/ r, + include if exists } diff --git a/apparmor.d/groups/virt/virtlogd b/apparmor.d/groups/virt/virtlogd index 44bf06ba07..f5b855087c 100644 --- a/apparmor.d/groups/virt/virtlogd +++ b/apparmor.d/groups/virt/virtlogd @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/virtlogd +@{exec_path} = @{sbin}/virtlogd profile virtlogd @{exec_path} flags=(attach_disconnected) { include include @@ -28,7 +28,8 @@ profile virtlogd @{exec_path} flags=(attach_disconnected) { owner @{run}/user/@{uid}/libvirt/virtlogd.pid rwk, owner @{run}/user/@{uid}/libvirt/virtlogd* w, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/libvirt/virtlogd-sock rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, @{run}/libvirt/common/system.token rwk, @{run}/libvirt/virtlogd-sock rw, diff --git a/apparmor.d/groups/virt/virtnetworkd b/apparmor.d/groups/virt/virtnetworkd index 42e13ef646..8f73661525 100644 --- a/apparmor.d/groups/virt/virtnetworkd +++ b/apparmor.d/groups/virt/virtnetworkd @@ -9,6 +9,8 @@ include @{exec_path} = @{bin}/virtnetworkd profile virtnetworkd @{exec_path} flags=(attach_disconnected) { include + include + include include network netlink raw, @@ -18,13 +20,13 @@ profile virtnetworkd @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, - @{bin}/dnsmasq rPx, + @{sbin}/dnsmasq rPx, /etc/libvirt/*.conf r, owner /var/lib/libvirt/dnsmasq/*.macs* rw, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, @{run}/libvirt/network/default.pid r, @{run}/utmp rk, @@ -39,7 +41,7 @@ profile virtnetworkd @{exec_path} flags=(attach_disconnected) { @{sys}/devices/system/node/node@{int}/meminfo r, owner @{PROC}/@{pid}/stat r, - owner @{PROC}/@{pids}/fd/ r, + owner @{PROC}/@{pid}/fd/ r, include if exists } diff --git a/apparmor.d/groups/virt/virtnodedevd b/apparmor.d/groups/virt/virtnodedevd index 957164e857..89b62f50f2 100644 --- a/apparmor.d/groups/virt/virtnodedevd +++ b/apparmor.d/groups/virt/virtnodedevd @@ -9,10 +9,13 @@ include @{exec_path} = @{bin}/virtnodedevd profile virtnodedevd @{exec_path} flags=(attach_disconnected) { include + include + include include include include include + include capability net_admin, capability sys_admin, @@ -24,7 +27,8 @@ profile virtnodedevd @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, - @{bin}/mdevctl rPx, + @{sbin}/mdevctl rPx, + @{bin}/mdevctl rPx, #aa:lint ignore=sbin /usr/share/hwdata/*.ids r, /usr/share/pci.ids r, @@ -32,7 +36,7 @@ profile virtnodedevd @{exec_path} flags=(attach_disconnected) { /etc/libvirt/*.conf r, /etc/mdevctl.d/{,**} r, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, owner @{run}/libvirt/common/system.token rwk, owner @{run}/libvirt/nodedev/ rw, @@ -44,18 +48,18 @@ profile virtnodedevd @{exec_path} flags=(attach_disconnected) { @{run}/utmp rk, - @{run}/udev/data/+backlight:* r, - @{run}/udev/data/+bluetooth:* r, + @{run}/udev/data/+backlight:* r, # For display backlights on laptops, monitors, and other screens. + @{run}/udev/data/+bluetooth:* r, # For bluetooth adapters, controllers, and active connections. @{run}/udev/data/+dmi:* r, # for motherboard info @{run}/udev/data/+drm:card@{int}-* r, # for screen outputs @{run}/udev/data/+input:input@{int} r, # for mouse, keyboard, touchpad - @{run}/udev/data/+leds:* r, + @{run}/udev/data/+leds:* r, # Identifies all LEDs (keyboard, mouse, etc.) @{run}/udev/data/+pci:* r, # Identifies all PCI devices (CPU, GPU, Network, Disks, USB, etc.) - @{run}/udev/data/+platform:* r, - @{run}/udev/data/+power_supply:* r, - @{run}/udev/data/+rfkill:* r, + @{run}/udev/data/+platform:* r, # Identifies onboard devices (laptop/board model, power controllers, thermal sensors) + @{run}/udev/data/+power_supply:* r, # For power supply devices (batteries, AC adapters, USB chargers) + @{run}/udev/data/+rfkill:* r, # Kill switch for wireless devices (Wi-Fi, Bluetooth, NFC) to save power @{run}/udev/data/+sound:card@{int} r, # For sound card - @{run}/udev/data/+thunderbolt:* r, + @{run}/udev/data/+thunderbolt:* r, # For Thunderbolt devices, such as docks, external GPUs, and storage devices. @{run}/udev/data/c1:@{int} r, # For RAM disk @{run}/udev/data/c10:@{int} r, # For non-serial mice, misc features @@ -69,9 +73,9 @@ profile virtnodedevd @{exec_path} flags=(attach_disconnected) { @{run}/udev/data/c116:@{int} r, # For ALSA @{run}/udev/data/c202:@{int} r, # CPU model-specific registers @{run}/udev/data/c203:@{int} r, # CPU CPUID information - @{run}/udev/data/c226:@{int} r, # For /dev/dri/card[0-9]* + @{run}/udev/data/c226:@{int} r, # For DRI card /dev/dri/card@{int} @{run}/udev/data/c@{dynamic}:@{int} r, # For dynamic assignment range 234 to 254, 384 to 511 - @{run}/udev/data/n@{int} r, + @{run}/udev/data/n@{int} r, # For network interfaces @{sys}/**/ r, @{sys}/devices/@{pci}/net/{,**} r, @@ -84,7 +88,6 @@ profile virtnodedevd @{exec_path} flags=(attach_disconnected) { @{sys}/devices/**/uevent r, @{sys}/devices/system/node/ r, @{sys}/devices/system/node/node@{int}/meminfo r, - @{sys}/devices/virtual/dmi/id/{product_name,product_serial,product_uuid,sys_vendor,board_vendor,bios_vendor,bios_date,bios_version,product_version} r, @{sys}/devices/virtual/net/{,**} r, @{sys}/kernel/iommu_groups/ r, @{sys}/kernel/iommu_groups/@{int}/devices/ r, diff --git a/apparmor.d/groups/virt/virtsecretd b/apparmor.d/groups/virt/virtsecretd index 9b3e7dda45..07da1abbe1 100644 --- a/apparmor.d/groups/virt/virtsecretd +++ b/apparmor.d/groups/virt/virtsecretd @@ -9,6 +9,7 @@ include @{exec_path} = @{bin}/virtsecretd profile virtsecretd @{exec_path} flags=(attach_disconnected) { include + include include network netlink raw, @@ -20,7 +21,7 @@ profile virtsecretd @{exec_path} flags=(attach_disconnected) { owner @{user_config_dirs}/libvirt/secrets/ rw, owner @{user_config_dirs}/libvirt/secrets/run/{,*} rwk, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, owner @{run}/user/@{uid}/libvirt/common/system.token rwk, owner @{run}/user/@{uid}/libvirt/secrets/ rw, diff --git a/apparmor.d/groups/virt/virtstoraged b/apparmor.d/groups/virt/virtstoraged index 00565fcf5b..4c5eba7fb4 100644 --- a/apparmor.d/groups/virt/virtstoraged +++ b/apparmor.d/groups/virt/virtstoraged @@ -11,6 +11,8 @@ include @{exec_path} = @{bin}/virtstoraged profile virtstoraged @{exec_path} flags=(attach_disconnected) { include + include + include include capability dac_read_search, @@ -46,15 +48,16 @@ profile virtstoraged @{exec_path} flags=(attach_disconnected) { owner @{run}/user/@{uid}/libvirt/common/ rw, owner @{run}/user/@{uid}/libvirt/common/system.token rwk, - owner @{run}/user/@{uid}/libvirt/virtstoraged* w, - owner @{run}/user/@{uid}/libvirt/virtstoraged.pid rwk, owner @{run}/user/@{uid}/libvirt/storage/{,**} rwk, + owner @{run}/user/@{uid}/libvirt/virtstoraged-sock rw, + owner @{run}/user/@{uid}/libvirt/virtstoraged.pid rwk, + owner @{run}/user/@{uid}/libvirt/virtstoraged* w, owner @{run}/libvirt/common/system.token rwk, owner @{run}/libvirt/storage/{,**} rwk, owner @{run}/virtstoraged.pid rwk, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, @{run}/utmp rwk, diff --git a/apparmor.d/groups/virt/xtables b/apparmor.d/groups/virt/xtables index 71f75b6428..511fa53fbf 100644 --- a/apparmor.d/groups/virt/xtables +++ b/apparmor.d/groups/virt/xtables @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/xtables-nft-multi @{bin}/xtables-legacy-multi +@{exec_path} = @{sbin}/xtables-{nft,legacy}-multi profile xtables { include include diff --git a/apparmor.d/groups/whonix/anondate b/apparmor.d/groups/whonix/anondate index 27e4eb594d..325535ccea 100644 --- a/apparmor.d/groups/whonix/anondate +++ b/apparmor.d/groups/whonix/anondate @@ -19,7 +19,7 @@ profile anondate @{exec_path} { @{bin}/cat rix, @{bin}/cp rix, @{bin}/date rix, - @{bin}/grep rix, + @{bin}/{,e}grep rix, @{bin}/minimum-unixtime-show rix, @{bin}/rm rix, @{bin}/systemd-cat rix, diff --git a/apparmor.d/groups/whonix/pam-info b/apparmor.d/groups/whonix/pam-info index 51053ccee4..23ab3aeb4a 100644 --- a/apparmor.d/groups/whonix/pam-info +++ b/apparmor.d/groups/whonix/pam-info @@ -14,8 +14,8 @@ profile pam-info @{exec_path} { @{exec_path} mr, @{sh_path} rix, - @{bin}/faillock rix, - @{bin}/grep rix, + @{sbin}/faillock rix, + @{bin}/{,e}grep rix, @{bin}/str_replace rix, @{bin}/wc rix, @{bin}/whoami rix, diff --git a/apparmor.d/groups/whonix/rads b/apparmor.d/groups/whonix/rads index e76570b34e..0165ad55e3 100644 --- a/apparmor.d/groups/whonix/rads +++ b/apparmor.d/groups/whonix/rads @@ -19,8 +19,8 @@ profile rads @{exec_path} { @{bin}/cat rix, @{bin}/chvt rix, @{bin}/free rix, - @{bin}/gawk rix, - @{bin}/grep rix, + @{bin}/{m,g,}awk rix, + @{bin}/{,e}grep rix, @{bin}/mkdir rix, @{bin}/rm rix, @{bin}/sed rix, @@ -41,7 +41,7 @@ profile rads @{exec_path} { owner @{run}/rads/{,**} rw, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, profile systemctl { include diff --git a/apparmor.d/groups/whonix/sdwdate b/apparmor.d/groups/whonix/sdwdate index d34f8087ca..1e4850e7ad 100644 --- a/apparmor.d/groups/whonix/sdwdate +++ b/apparmor.d/groups/whonix/sdwdate @@ -30,7 +30,7 @@ profile sdwdate @{exec_path} flags=(attach_disconnected) { @{bin}/touch rix, @{lib}/helper-scripts/* rix, @{bin}/url_to_unixtime rix, - @{bin}/grep rix, + @{bin}/{,e}grep rix, @{lib}/helper-scripts/ r, @{lib}/sdwdate/ r, diff --git a/apparmor.d/groups/whonix/systemcheck-canary b/apparmor.d/groups/whonix/systemcheck-canary index 4130d9cd9d..17bedc43bc 100644 --- a/apparmor.d/groups/whonix/systemcheck-canary +++ b/apparmor.d/groups/whonix/systemcheck-canary @@ -14,7 +14,7 @@ profile systemcheck-canary @{exec_path} { @{exec_path} mr, @{bin}/sleep rix, - @{bin}/grep rix, + @{bin}/{,e}grep rix, @{bin}/whoami rix, @{bin}/cat rix, @{bin}/date rix, diff --git a/apparmor.d/groups/whonix/torbrowser-wrapper b/apparmor.d/groups/whonix/torbrowser-wrapper index fc20ad0fba..c86d91099c 100644 --- a/apparmor.d/groups/whonix/torbrowser-wrapper +++ b/apparmor.d/groups/whonix/torbrowser-wrapper @@ -20,7 +20,7 @@ profile torbrowser-wrapper @{exec_path} { @{bin}/basename ix, @{bin}/cp ix, @{bin}/dirname ix, - @{bin}/grep ix, + @{bin}/{,e}grep ix, @{bin}/id ix, @{bin}/mkdir ix, @{bin}/mktemp ix, diff --git a/apparmor.d/groups/whonix/whonix-firewall-restarter b/apparmor.d/groups/whonix/whonix-firewall-restarter index a818e46a61..d9cdf77c14 100644 --- a/apparmor.d/groups/whonix/whonix-firewall-restarter +++ b/apparmor.d/groups/whonix/whonix-firewall-restarter @@ -10,7 +10,6 @@ include profile whonix-firewall-restarter @{exec_path} { include include - include include capability chown, @@ -27,19 +26,26 @@ profile whonix-firewall-restarter @{exec_path} { @{bin}/mkfifo rix, @{bin}/mktemp rix, @{bin}/rm rix, - @{bin}/systemctl rix, + @{bin}/systemctl rCx -> systemctl, /etc/machine-id r, - /{run,var}/log/journal/ r, - /{run,var}/log/journal/@{hex32}/ r, - /{run,var}/log/journal/@{hex32}/*.journal* r, - owner /tmp/tmp.@{rand10} rw, @{run}/sdwdate/{,*} rw, owner @{run}/updatesproxycheck/{,*} rw, + profile systemctl { + include + include + + /{run,var}/log/journal/ r, + /{run,var}/log/journal/@{hex32}/ r, + /{run,var}/log/journal/@{hex32}/*.journal* r, + + include if exists + } + include if exists } diff --git a/apparmor.d/groups/whonix/whonix-firewalld b/apparmor.d/groups/whonix/whonix-firewalld index 01e1cb4181..47ee460f67 100644 --- a/apparmor.d/groups/whonix/whonix-firewalld +++ b/apparmor.d/groups/whonix/whonix-firewalld @@ -29,7 +29,7 @@ profile whonix-firewalld @{exec_path} { @{bin}/rm rix, @{bin}/touch rix, @{bin}/whonix-*-firewall rix, - @{bin}/xtables-nft-multi rix, + @{sbin}/xtables-{nft,legacy}-multi rix, @{bin}/qubesdb-read rPUx, @{bin}/qubesdb-cmd rPUx, diff --git a/apparmor.d/groups/xfce/thunar b/apparmor.d/groups/xfce/thunar index bab16bca77..0a4beff237 100644 --- a/apparmor.d/groups/xfce/thunar +++ b/apparmor.d/groups/xfce/thunar @@ -9,13 +9,14 @@ include @{exec_path} = @{bin}/thunar profile thunar @{exec_path} flags=(attach_disconnected) { include - include include include include include include include + include + include network netlink raw, @@ -27,7 +28,7 @@ profile thunar @{exec_path} flags=(attach_disconnected) { @{bin}/thunar-volman rPx, @{bin}/dbus-launch rCx -> dbus, - @{open_path} rPx -> child-open, + @{open_path} rPx -> child-open-any, /usr/share/ r, /usr/share/anon-apps-config/share/{,**} r, #aa:only whonix @@ -38,6 +39,7 @@ profile thunar @{exec_path} flags=(attach_disconnected) { /etc/timezone r, /etc/xdg/{,xdg-xubuntu/}Thunar/{,**} r, + #aa:lint ignore=too-wide # Full access to user's data / r, /*/ r, @@ -53,12 +55,13 @@ profile thunar @{exec_path} flags=(attach_disconnected) { @{run}/mount/utab r, @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/cpu.max r, - @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/session-@{int}.scope/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/session-@{word}.scope/cpu.max r, owner @{PROC}/@{pid}/mountinfo r, + owner @{PROC}/@{pid}/cgroup r, # Silence non user's data - deny /boot/{,**} r, + deny @{efi}/{,**} r, deny /opt/{,**} r, deny /root/{,**} r, deny /tmp/.* rw, diff --git a/apparmor.d/groups/xfce/thunar-volman b/apparmor.d/groups/xfce/thunar-volman index fc73a14c9a..974c29c9c7 100644 --- a/apparmor.d/groups/xfce/thunar-volman +++ b/apparmor.d/groups/xfce/thunar-volman @@ -7,12 +7,14 @@ abi , include @{exec_path} = @{bin}/thunar-volman -profile thunar-volman @{exec_path} { +profile thunar-volman @{exec_path} flags=(attach_disconnected) { include - include include + include + include include include + include network netlink raw, @@ -20,6 +22,8 @@ profile thunar-volman @{exec_path} { /etc/fstab r, + / r, + @{sys}/devices/virtual/input/input@{int}/{,**/}uevent r, @{run}/udev/data/+input:input@{int} r, # for mouse, keyboard, touchpad diff --git a/apparmor.d/groups/xfce/tumblerd b/apparmor.d/groups/xfce/tumblerd index 3ba81c6885..070c41129c 100644 --- a/apparmor.d/groups/xfce/tumblerd +++ b/apparmor.d/groups/xfce/tumblerd @@ -9,7 +9,6 @@ include @{exec_path} = @{lib}/{,@{multiarch}/}tumbler-1/tumblerd profile tumblerd @{exec_path} { include - include include include include diff --git a/apparmor.d/groups/xfce/xfce-clipman b/apparmor.d/groups/xfce/xfce-clipman new file mode 100644 index 0000000000..45d2f42318 --- /dev/null +++ b/apparmor.d/groups/xfce/xfce-clipman @@ -0,0 +1,32 @@ +# 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, + + @{bin}/xfce4-clipman-history rix, + + /etc/xdg/autostart/xfce4-clipman*.desktop 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/groups/xfce/xfce-clipman-settings b/apparmor.d/groups/xfce/xfce-clipman-settings index 9e74d80469..021a377b85 100644 --- a/apparmor.d/groups/xfce/xfce-clipman-settings +++ b/apparmor.d/groups/xfce/xfce-clipman-settings @@ -9,7 +9,6 @@ include @{exec_path} = @{bin}/xfce4-clipman-settings profile xfce-clipman-settings @{exec_path} { include - include include include diff --git a/apparmor.d/groups/xfce/xfce-notifyd b/apparmor.d/groups/xfce/xfce-notifyd index c594b8ed31..be813a84de 100644 --- a/apparmor.d/groups/xfce/xfce-notifyd +++ b/apparmor.d/groups/xfce/xfce-notifyd @@ -10,7 +10,6 @@ include @{exec_path} = @{lib}/{,@{multiarch}/}xfce4/notifyd/xfce4-notifyd profile xfce-notifyd @{exec_path} { include - include include include include diff --git a/apparmor.d/groups/xfce/xfce-panel b/apparmor.d/groups/xfce/xfce-panel index b04ed2eb94..244230c200 100644 --- a/apparmor.d/groups/xfce/xfce-panel +++ b/apparmor.d/groups/xfce/xfce-panel @@ -9,8 +9,6 @@ include @{exec_path} = @{bin}/xfce4-panel @{lib}/{,@{multiarch}/}xfce4/panel/wrapper-2.0 profile xfce-panel @{exec_path} { include - include - include include include include diff --git a/apparmor.d/groups/xfce/xfce-power-manager b/apparmor.d/groups/xfce/xfce-power-manager index 91be9eede5..69cc4f519b 100644 --- a/apparmor.d/groups/xfce/xfce-power-manager +++ b/apparmor.d/groups/xfce/xfce-power-manager @@ -10,9 +10,7 @@ include profile xfce-power-manager @{exec_path} flags=(attach_disconnected) { include include - include include - include include include @@ -28,7 +26,7 @@ profile xfce-power-manager @{exec_path} flags=(attach_disconnected) { owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/stat r, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, include if exists } diff --git a/apparmor.d/groups/xfce/xfce-screensaver b/apparmor.d/groups/xfce/xfce-screensaver index 2c0f13bc18..b75dcceee2 100644 --- a/apparmor.d/groups/xfce/xfce-screensaver +++ b/apparmor.d/groups/xfce/xfce-screensaver @@ -9,7 +9,6 @@ include @{exec_path} = @{bin}/xfce4-screensaver profile xfce-screensaver @{exec_path} flags=(attach_disconnected) { include - include include include include @@ -29,7 +28,7 @@ profile xfce-screensaver @{exec_path} flags=(attach_disconnected) { /etc/xdg/menus/xfce4-screensavers.menu r, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, include if exists } diff --git a/apparmor.d/groups/xfce/xfce-sensors b/apparmor.d/groups/xfce/xfce-sensors index e7ee1080ba..0ab6812780 100644 --- a/apparmor.d/groups/xfce/xfce-sensors +++ b/apparmor.d/groups/xfce/xfce-sensors @@ -10,21 +10,13 @@ include profile xfce-sensors @{exec_path} { include include + include @{exec_path} mr, - @{sys}/class/hwmon/ r, @{sys}/class/power_supply/ r, @{sys}/class/thermal/ r, - @{sys}/devices/@{pci}/i2c-@{int}/{,**/}name r, - @{sys}/devices/**/hwmon@{int}/ r, - @{sys}/devices/**/hwmon@{int}/{name,temp*} r, - @{sys}/devices/**/hwmon@{int}/**/ r, - @{sys}/devices/**/hwmon@{int}/**/{name,temp*} r, - @{sys}/devices/**/hwmon/ r, - @{sys}/devices/**/hwmon/{name,temp*} r, - @{sys}/devices/**/hwmon/**/ r, - @{sys}/devices/**/hwmon/**/{name,temp*} r, + @{sys}/devices/@{pci}/i2c-*/{,**/}name r, @{sys}/devices/**/power_supply/**/{uevent,type,online} r, @{sys}/devices/virtual/thermal/thermal_zone@{int}/temp r, diff --git a/apparmor.d/groups/xfce/xfce-session b/apparmor.d/groups/xfce/xfce-session index beddcce1f5..26960fc42e 100644 --- a/apparmor.d/groups/xfce/xfce-session +++ b/apparmor.d/groups/xfce/xfce-session @@ -9,11 +9,9 @@ include @{exec_path} = @{bin}/xfce4-session profile xfce-session @{exec_path} flags=(attach_disconnected) { include + include include - include - include include - include include include include @@ -75,7 +73,6 @@ profile xfce-session @{exec_path} flags=(attach_disconnected) { profile dbus flags=(attach_disconnected) { include - include @{bin}/dbus-update-activation-environment mr, diff --git a/apparmor.d/groups/xfce/xfce-terminal b/apparmor.d/groups/xfce/xfce-terminal index 8d2f06a750..8eb9d41c9d 100644 --- a/apparmor.d/groups/xfce/xfce-terminal +++ b/apparmor.d/groups/xfce/xfce-terminal @@ -9,9 +9,7 @@ include @{exec_path} = @{bin}/xfce4-terminal profile xfce-terminal @{exec_path} { include - include include - include include include include diff --git a/apparmor.d/groups/xfce/xfconfd b/apparmor.d/groups/xfce/xfconfd index 9cd2735449..941dfcc667 100644 --- a/apparmor.d/groups/xfce/xfconfd +++ b/apparmor.d/groups/xfce/xfconfd @@ -24,7 +24,7 @@ profile xfconfd @{exec_path} { owner @{user_config_dirs}/xfce4/ r, owner @{user_config_dirs}/xfce4/xfconf/{,**} rw, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/groups/xfce/xfdesktop b/apparmor.d/groups/xfce/xfdesktop index ff36e8459b..6bc5ec15c9 100644 --- a/apparmor.d/groups/xfce/xfdesktop +++ b/apparmor.d/groups/xfce/xfdesktop @@ -10,7 +10,6 @@ include profile xfdesktop @{exec_path} { include include - include include include include diff --git a/apparmor.d/groups/xfce/xfpm-power-backlight-helper b/apparmor.d/groups/xfce/xfpm-power-backlight-helper index 236028f2e8..bfc58840bb 100644 --- a/apparmor.d/groups/xfce/xfpm-power-backlight-helper +++ b/apparmor.d/groups/xfce/xfpm-power-backlight-helper @@ -9,21 +9,11 @@ include @{exec_path} = @{bin}/xfpm-power-backlight-helper profile xfpm-power-backlight-helper @{exec_path} { include + include include @{exec_path} mr, - @{sys}/class/backlight/ r, - @{sys}/class/leds/ r, - @{sys}/devices/@{pci}/backlight/**/{,max_,actual_}brightness rw, - @{sys}/devices/@{pci}/backlight/**/{uevent,type,enabled} r, - @{sys}/devices/@{pci}/backlight/**/brightness rw, - @{sys}/devices/@{pci}/drm/card@{int}/**/{,max_,actual_}brightness rw, - @{sys}/devices/@{pci}/drm/card@{int}/**/{uevent,type,enabled} r, - @{sys}/devices/@{pci}/drm/card@{int}/**/brightness rw, - @{sys}/devices/@{pci}/*_backlight/{,max_,actual_}brightness rw, - @{sys}/devices/@{pci}/*_backlight/{uevent,type,enabled} r, - include if exists } diff --git a/apparmor.d/groups/xfce/xfsettingsd b/apparmor.d/groups/xfce/xfsettingsd index 22db3f80d2..08dc7d850e 100644 --- a/apparmor.d/groups/xfce/xfsettingsd +++ b/apparmor.d/groups/xfce/xfsettingsd @@ -10,9 +10,6 @@ include profile xfsettingsd @{exec_path} { include include - include - include - include include include diff --git a/apparmor.d/groups/xfce/xfwm b/apparmor.d/groups/xfce/xfwm index 7ecd2c8fe5..c41e5254ff 100644 --- a/apparmor.d/groups/xfce/xfwm +++ b/apparmor.d/groups/xfce/xfwm @@ -9,7 +9,6 @@ include @{exec_path} = @{bin}/xfwm4 profile xfwm @{exec_path} { include - include include include include diff --git a/apparmor.d/mappings/login/base b/apparmor.d/mappings/login/base new file mode 100644 index 0000000000..f74b90418c --- /dev/null +++ b/apparmor.d/mappings/login/base @@ -0,0 +1,30 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# It is used by login to run pre login scripts (as root) such as the motd. +# After the login, Apparmor libpam will transition to the roles defined in +# other files under + + @{shells_path} rCx -> shell, + + profile shell flags=(attach_disconnected) { + include + include + include + + @{shells_path} rix, + @{bin}/env rix, + @{bin}/run-parts rix, #aa:only apt + + #aa:only apt + /etc/update-motd.d/ r, + /etc/update-motd.d/* rPx, + /usr/share/landscape/landscape-sysinfo.wrapper rPx, + + @{run}/motd.dynamic.new rw, #aa:only apt + + include if exists + } + +# vim:syntax=apparmor diff --git a/apparmor.d/mappings/sshd/base b/apparmor.d/mappings/sshd/base new file mode 100644 index 0000000000..dd9218d9c5 --- /dev/null +++ b/apparmor.d/mappings/sshd/base @@ -0,0 +1,30 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# It is used by login to run pre login scripts (as root) such as the motd. +# After the login, Apparmor libpam will transition to the roles defined in +# other files under + + @{shells_path} rCx -> shell, + + profile shell flags=(attach_disconnected) { + include + include + include + + @{shells_path} rix, + @{bin}/env rix, + @{bin}/run-parts rix, #aa:only apt + + #aa:only apt + /etc/update-motd.d/ r, + /etc/update-motd.d/* rPx, + /usr/share/landscape/landscape-sysinfo.wrapper rPx, + + @{run}/motd.dynamic.new rw, #aa:only apt + + include if exists + } + +# vim:syntax=apparmor diff --git a/apparmor.d/mappings/sudo/base b/apparmor.d/mappings/sudo/base new file mode 100644 index 0000000000..95e3955015 --- /dev/null +++ b/apparmor.d/mappings/sudo/base @@ -0,0 +1,30 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# It is used by su/sudo to run pre login scripts (as root) such as the motd. +# After the login, Apparmor libpam will transition to the roles defined in +# other files under + + @{shells_path} rCx -> shell, + + profile shell flags=(attach_disconnected) { + include + include + include + + @{shells_path} rix, + @{bin}/env rix, + @{bin}/run-parts rix, #aa:only apt + + #aa:only apt + /etc/update-motd.d/ r, + /etc/update-motd.d/* rPx, + /usr/share/landscape/landscape-sysinfo.wrapper rPx, + + @{run}/motd.dynamic.new rw, #aa:only apt + + include if exists + } + +# vim:syntax=apparmor diff --git a/apparmor.d/namespaces/glycin/bwrap b/apparmor.d/namespaces/glycin/bwrap new file mode 100644 index 0000000000..fb74018add --- /dev/null +++ b/apparmor.d/namespaces/glycin/bwrap @@ -0,0 +1,58 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025-2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Confine glycin-loaders sandboxed with bwrap. It also confines bwrap itself. +# for this use case. + +abi , + +include + +profile :glycin:bwrap flags=(attach_disconnected) { + include + include + include + + # Need to be allowed for all peer because from the glycin namespace we do not + # see the root namespace. This is showned by 'peer=(label=---)' in the logs. + # + # As of today, we cannot specify the ns scope and view of the peer. + # See: https://gitlab.com/apparmor/apparmor/-/wikis/AppArmorPolicyView + unix (send receive) type=seqpacket, + unix (send receive) type=stream, + + @{bin}/bwrap mr, + + # To test sandbox functionalities + # See; https://gitlab.gnome.org/GNOME/glycin/-/blob/main/glycin/src/sandbox.rs#L676 + @{bin}/true ix, + + @{lib}/glycin-loaders/@{d}+/glycin-* Px -> bwrap//&loaders, + + /usr/share/glycin-loaders/{,**} r, + + /usr/share/gtksourceview-2.0/{,**} r, + /usr/share/gtksourceview-3.0/{,**} r, + /usr/share/gtksourceview-4/{,**} r, + /usr/share/gtksourceview-5/{,**} r, + + owner @{tmp}/gdk-pixbuf-glycin-tmp.@{rand6} rw, + + #aa:lint ignore=too-wide + # Safe deny of inherited files from parent process. + deny network inet dgram, + deny network inet6 dgram, + deny network inet stream, + deny network inet6 stream, + deny owner @{HOME}/.*/** rw, + deny owner /tmp/*/** w, + deny /opt/*/** rw, + deny @{sys}/devices/system/** r, + deny /dev/shm/** rw, + deny /dev/dri/* rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/namespaces/glycin/loaders b/apparmor.d/namespaces/glycin/loaders new file mode 100644 index 0000000000..1dbe0b447a --- /dev/null +++ b/apparmor.d/namespaces/glycin/loaders @@ -0,0 +1,29 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025-2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +profile :glycin:loaders flags=(attach_disconnected) { + include + include + + signal (send receive) peer=bwrap//&loaders, + + unix (send receive) type=stream, + + @{lib}/glycin-loaders/@{d}+/glycin-* mr, + + @{att}/usr/share/glycin-loaders/{,**} r, + + @{att}/usr/share/gtksourceview-2.0/{,**} r, + @{att}/usr/share/gtksourceview-3.0/{,**} r, + @{att}/usr/share/gtksourceview-4/{,**} r, + @{att}/usr/share/gtksourceview-5/{,**} r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-a-f/acpi b/apparmor.d/profiles-a-f/acpi index 2914180e69..3b42be2343 100644 --- a/apparmor.d/profiles-a-f/acpi +++ b/apparmor.d/profiles-a-f/acpi @@ -19,7 +19,6 @@ profile acpi @{exec_path} flags=(complain) { @{sys}/devices/**/power_supply/{,**} r, @{sys}/devices/virtual/thermal/{,**} r, - include if exists } diff --git a/apparmor.d/profiles-a-f/acpi-powerbtn b/apparmor.d/profiles-a-f/acpi-powerbtn index 7961941468..a87fd545fe 100644 --- a/apparmor.d/profiles-a-f/acpi-powerbtn +++ b/apparmor.d/profiles-a-f/acpi-powerbtn @@ -13,11 +13,10 @@ profile acpi-powerbtn flags=(attach_disconnected) { @{sh_path} rix, @{bin}/{e,}grep rix, - @{bin}/killall5 rix, - @{bin}/pgrep rix, + @{sbin}/killall5 rix, + @{bin}/pgrep rCx -> pgrep, @{bin}/pinky rix, @{bin}/sed rix, - @{bin}/shutdown rix, /etc/acpi/powerbtn.sh rix, @{bin}/dbus-send Cx -> bus, @@ -42,11 +41,18 @@ profile acpi-powerbtn flags=(attach_disconnected) { @{bin}/fgconsole r, /dev/tty rw, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } + profile pgrep { + include + include + + include if exists + } + profile bus flags=(complain) { include include diff --git a/apparmor.d/profiles-a-f/acpid b/apparmor.d/profiles-a-f/acpid index 5bf6c433a9..4985bca3a3 100644 --- a/apparmor.d/profiles-a-f/acpid +++ b/apparmor.d/profiles-a-f/acpid @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/acpid +@{exec_path} = @{sbin}/acpid profile acpid @{exec_path} flags=(attach_disconnected) { include include diff --git a/apparmor.d/profiles-a-f/adb b/apparmor.d/profiles-a-f/adb index 3affe4e7a8..4769d4f0b3 100644 --- a/apparmor.d/profiles-a-f/adb +++ b/apparmor.d/profiles-a-f/adb @@ -31,6 +31,7 @@ profile adb @{exec_path} flags=(attach_disconnected) { owner @{HOME}/.android/ rw, owner @{HOME}/.android/adb.@{int} rw, owner @{HOME}/.android/adbkey rw, + owner @{HOME}/.android/adbkey.pub rw, include if exists } diff --git a/apparmor.d/profiles-a-f/adduser b/apparmor.d/profiles-a-f/adduser index e1d8133247..323a5a6cde 100644 --- a/apparmor.d/profiles-a-f/adduser +++ b/apparmor.d/profiles-a-f/adduser @@ -7,8 +7,8 @@ abi , include -@{exec_path} = @{bin}/add{user,group} -profile adduser @{exec_path} { +@{exec_path} = @{sbin}/adduser +profile adduser @{exec_path} flags=(attach_disconnected) { include include include @@ -32,24 +32,31 @@ profile adduser @{exec_path} { @{bin}/chage rPx, @{bin}/chfn rPx, + @{bin}/ecryptfs-setup-private rPUx, @{bin}/gpasswd rPx, - @{bin}/groupadd rPx, - @{bin}/groupdel rPx, @{bin}/passwd rPx, - @{bin}/useradd rPx, - @{bin}/userdel rPx, - @{bin}/usermod rPx, + @{bin}/umount rPx, + @{sbin}/groupadd rPx, + @{sbin}/groupdel rPx, + @{sbin}/useradd rPx, + @{sbin}/userdel rPx, + @{sbin}/usermod rPx, /etc/{group,passwd,shadow} r, + /etc/adduser-*.conf r, + /etc/adduser-pool.d/{,**} r, /etc/adduser.conf r, - /etc/skel/{,.*} r, + /etc/skel/{,**} r, # To create user dirs and copy files from /etc/skel/ to them @{HOME}/ rw, - @{HOME}/.* w, - /var/lib/*/{,*} rw, + @{HOME}/* w, + @{HOME}/**/.Private/* rw, + /var/lib/*/ rw, + /var/lib/*/*/ rw, @{run}/adduser wk, + @{run}/userdb/ r, include if exists } diff --git a/apparmor.d/profiles-a-f/adequate b/apparmor.d/profiles-a-f/adequate index 28576423dd..504f2d0610 100644 --- a/apparmor.d/profiles-a-f/adequate +++ b/apparmor.d/profiles-a-f/adequate @@ -18,10 +18,10 @@ profile adequate @{exec_path} flags=(complain) { @{exec_path} r, - @{bin}/ldconfig rix, + @{sbin}/ldconfig rix, # It wants to ldd all binaries/libs in packages. - @{bin}/ldd rCx -> ldd, + @{ldd_path} rCx -> ldd, # Think what to do about this (#FIXME#) /usr/share/debconf/frontend rPx, @@ -38,6 +38,12 @@ profile adequate @{exec_path} flags=(complain) { /var/lib/adequate/pending rwk, + /etc/ r, + /etc/dbus-1/ r, + /etc/dbus-1/session.d/ r, + /etc/dbus-1/system.d/ r, + /etc/init.d/ r, + /etc/init.d/dhcpcd r, /etc/shadow r, /usr/share/python{,3}/debian_defaults r, @@ -45,24 +51,19 @@ profile adequate @{exec_path} flags=(complain) { /usr/share/**/__pycache__/ r, /usr/**/*.py r, - profile ldd flags=(complain) { include include - @{bin}/ldd mr, + @{ldd_path} mrix, @{bin}/* mr, /usr/games/* mr, - @{lib}{,x}/** mr, @{lib}/@{multiarch}/** mr, /usr/share/** r, /opt/google/chrome{,-beta,-unstable}/google-chrome{,-beta,-unstable} mr, - @{lib}/@{multiarch}/ld-*.so rix, - @{lib}{,x}32/ld-*.so rix, - include if exists } @@ -85,12 +86,9 @@ profile adequate @{exec_path} flags=(complain) { /usr/share/debconf/templates/adequate.templates r, # The following is needed when debconf uses GUI frontends. - include - include - include - include + include capability dac_read_search, - @{bin}/lsb_release rPx -> lsb_release, + @{bin}/lsb_release rPx, @{bin}/hostname rix, owner @{PROC}/@{pid}/mounts r, @{HOME}/.Xauthority r, diff --git a/apparmor.d/profiles-a-f/alacarte b/apparmor.d/profiles-a-f/alacarte index eed67619de..62a6fe8cce 100644 --- a/apparmor.d/profiles-a-f/alacarte +++ b/apparmor.d/profiles-a-f/alacarte @@ -7,10 +7,11 @@ abi , include @{exec_path} = @{bin}/alacarte -profile alacarte @{exec_path} { +profile alacarte @{exec_path} flags=(attach_disconnected) { include include include + include include @{exec_path} mr, diff --git a/apparmor.d/profiles-a-f/alsactl b/apparmor.d/profiles-a-f/alsactl index b2b97a62ab..adf0d5cd3a 100644 --- a/apparmor.d/profiles-a-f/alsactl +++ b/apparmor.d/profiles-a-f/alsactl @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/alsactl +@{exec_path} = @{sbin}/alsactl profile alsactl @{exec_path} { include include diff --git a/apparmor.d/profiles-a-f/amixer b/apparmor.d/profiles-a-f/amixer index 85989a7bf5..192d13fe45 100644 --- a/apparmor.d/profiles-a-f/amixer +++ b/apparmor.d/profiles-a-f/amixer @@ -22,7 +22,7 @@ profile amixer @{exec_path} { owner @{PROC}/@{pid}/task/@{tid}/comm rw, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-a-f/anyremote b/apparmor.d/profiles-a-f/anyremote index db67de3199..43ecdb0cd0 100644 --- a/apparmor.d/profiles-a-f/anyremote +++ b/apparmor.d/profiles-a-f/anyremote @@ -41,7 +41,7 @@ profile anyremote @{exec_path} { @{bin}/tail rix, @{bin}/tr rix, @{bin}/wc rix, - @{bin}/which{,.debianutils} rix, + @{bin}/which{,.debianutils} rix, @{bin}/convert-im6.q16 rCx -> imagemagic, @{bin}/killall rCx -> killall, diff --git a/apparmor.d/profiles-a-f/appstreamcli b/apparmor.d/profiles-a-f/appstreamcli index f2231479dd..c56c1e89cb 100644 --- a/apparmor.d/profiles-a-f/appstreamcli +++ b/apparmor.d/profiles-a-f/appstreamcli @@ -8,13 +8,15 @@ abi , include @{exec_path} = @{bin}/appstreamcli -profile appstreamcli @{exec_path} flags=(complain) { +profile appstreamcli @{exec_path} { include include - include + include + include include capability dac_read_search, + capability mknod, # optional: no audit @{exec_path} mr, diff --git a/apparmor.d/profiles-a-f/arandr b/apparmor.d/profiles-a-f/arandr index 77bf1bf96b..f554cb3e8a 100644 --- a/apparmor.d/profiles-a-f/arandr +++ b/apparmor.d/profiles-a-f/arandr @@ -10,10 +10,7 @@ include @{exec_path} = @{bin}/arandr profile arandr @{exec_path} { include - include - include - include - include + include include include include @@ -33,7 +30,7 @@ profile arandr @{exec_path} { /etc/fstab r, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-a-f/archivemount b/apparmor.d/profiles-a-f/archivemount index d445df0e28..003999d98b 100644 --- a/apparmor.d/profiles-a-f/archivemount +++ b/apparmor.d/profiles-a-f/archivemount @@ -24,12 +24,21 @@ profile archivemount @{exec_path} { owner @{HOME}/*/ r, owner @{HOME}/*/*/ r, + #aa:only test + mount fstype=fuse.archivemount options=(rw nodev nosuid) archivemount -> /tmp/tmp.@{rand10}/{,**}, + /tmp/tmp.@{rand10}/{,**} rw, + /dev/fuse rw, + profile fusermount { include include - mount fstype={fuse,fuse.archivemount} -> @{HOME}/*/, - mount fstype={fuse,fuse.archivemount} -> @{HOME}/*/*/, + capability setuid, + + unix type=stream peer=(label=archivemount), + + mount fstype={fuse,fuse.archivemount} options=(rw nodev nosuid) archivemount -> @{HOME}/*/, + mount fstype={fuse,fuse.archivemount} options=(rw nodev nosuid) archivemount -> @{HOME}/*/*/, umount @{HOME}/*/, umount @{HOME}/*/*/, @@ -37,6 +46,9 @@ profile archivemount @{exec_path} { /**.{tar,tar.gz,zip} r, /**.{TAR,TAR.GZ,ZIP} r, + #aa:only test + mount fstype=fuse.archivemount options=(rw nodev nosuid) archivemount -> /tmp/tmp.@{rand10}/**, + include if exists } diff --git a/apparmor.d/profiles-a-f/arduino b/apparmor.d/profiles-a-f/arduino index cfac12d42d..dd04a5786a 100644 --- a/apparmor.d/profiles-a-f/arduino +++ b/apparmor.d/profiles-a-f/arduino @@ -12,12 +12,11 @@ profile arduino @{exec_path} { include include include - include - include - include - include - include + include include + include + include + include network inet dgram, network inet6 dgram, @@ -46,12 +45,6 @@ profile arduino @{exec_path} { @{lib}/jvm/java-[0-9]*-openjdk-*/bin/java rix, @{lib}/jvm/java-[0-9]*-openjdk-*/lib/server/classes.jsa mr, - /usr/share/java/*.jar r, - /etc/java-[0-9]*-openjdk/** r, - /etc/ssl/certs/java/cacerts r, - owner @{HOME}/.java/fonts/*/ rw, - owner @{HOME}/.java/fonts/*/fcinfo[0-9]*.tmp rw, - owner @{HOME}/.java/fonts/*/fcinfo-*.properties rw, /usr/share/arduino/{,**} r, /usr/share/arduino-builder/{,**} r, @@ -59,13 +52,19 @@ profile arduino @{exec_path} { /usr/share/doc/arduino/{,**} r, /usr/share/doc/arduino-core/{,**} r, + /etc/fstab r, + + /etc/avrdude.conf r, + + owner @{HOME}/.java/fonts/*/ rw, + owner @{HOME}/.java/fonts/*/fcinfo[0-9]*.tmp rw, + owner @{HOME}/.java/fonts/*/fcinfo-*.properties rw, + owner @{HOME}/ r, owner @{HOME}/.arduino{,15}/{,**} rw, owner @{HOME}/Arduino/{,**} rw, owner @{HOME}/sketchbook/{,**} rw, - owner @{HOME}/.Xauthority r, - /tmp/ r, owner @{tmp}/cc*.{s,res,c,o,ld,le} rw, owner @{tmp}/hsperfdata_@{user}/ rw, @@ -95,9 +94,6 @@ profile arduino @{exec_path} { @{PROC}/@{pid}/net/if_inet6 r, @{PROC}/@{pid}/net/ipv6_route r, - /etc/fstab r, - - /etc/avrdude.conf r, @{sys}/fs/cgroup/{,**} r, @{sys}/class/tty/ r, diff --git a/apparmor.d/profiles-a-f/aspell b/apparmor.d/profiles-a-f/aspell index 16b5b6f6d7..629caca108 100644 --- a/apparmor.d/profiles-a-f/aspell +++ b/apparmor.d/profiles-a-f/aspell @@ -16,7 +16,7 @@ profile aspell @{exec_path} flags=(complain) { /usr/share/aspell/{,*} r, - /usr/lib/aspell/{,*} r, + @{lib}/aspell/{,*} r, /var/lib/aspell/{,*} r, /var/lib/aspell/*.rws rw, diff --git a/apparmor.d/profiles-a-f/aspell-autobuildhash b/apparmor.d/profiles-a-f/aspell-autobuildhash index b3baaaa8f8..f4b4e6eb7b 100644 --- a/apparmor.d/profiles-a-f/aspell-autobuildhash +++ b/apparmor.d/profiles-a-f/aspell-autobuildhash @@ -7,8 +7,8 @@ abi , include -@{exec_path} = @{bin}/aspell-autobuildhash -profile aspell-autobuildhash @{exec_path} flags=(complain) { +@{exec_path} = @{sbin}/aspell-autobuildhash +profile aspell-autobuildhash @{exec_path} { include include include @@ -32,8 +32,8 @@ profile aspell-autobuildhash @{exec_path} flags=(complain) { /usr/share/aspell/{,*} r, - /usr/lib/aspell/{,*} r, - /usr/lib/aspell/*.rws rw, + @{lib}/aspell/{,*} r, + @{lib}/aspell/*.rws rw, /var/lib/aspell/ r, /var/lib/aspell/* rw, @@ -47,7 +47,7 @@ profile aspell-autobuildhash @{exec_path} flags=(complain) { /usr/share/debconf/frontend r, - @{bin}/aspell-autobuildhash rPx, + @{sbin}/aspell-autobuildhash rPx, @{sh_path} rix, @{bin}/stty rix, @@ -57,15 +57,11 @@ profile aspell-autobuildhash @{exec_path} flags=(complain) { owner /var/cache/debconf/{config,passwords,templates}.dat{,-new,-old} rwk, # The following is needed when debconf uses GUI frontends. - include - include - include - include + include capability dac_read_search, - @{bin}/lsb_release rPx -> lsb_release, + @{bin}/lsb_release rPx, @{bin}/hostname rix, owner @{PROC}/@{pid}/mounts r, - @{HOME}/.Xauthority r, include if exists } diff --git a/apparmor.d/profiles-a-f/atd b/apparmor.d/profiles-a-f/atd index 3a0669c76e..c9b97a7f35 100644 --- a/apparmor.d/profiles-a-f/atd +++ b/apparmor.d/profiles-a-f/atd @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/atd +@{exec_path} = @{sbin}/atd profile atd @{exec_path} { include include @@ -20,6 +20,8 @@ profile atd @{exec_path} { capability setuid, capability sys_resource, + network (create receive send) netlink raw, + signal receive set=hup peer=at, ptrace read peer=unconfined, @@ -27,11 +29,10 @@ profile atd @{exec_path} { @{exec_path} mr, @{sh_path} rix, - @{bin}/sendmail rPUx, - @{bin}/exim4 rPx, + @{sbin}/sendmail rPUx, + @{sbin}/exim4 rPx, @{etc_ro}/environment r, - @{etc_ro}/security/limits.d/ r, /var/spool/cron/atjobs/{,*} rwl, /var/spool/cron/atspool/{,*} rwl, @@ -43,6 +44,9 @@ profile atd @{exec_path} { @{PROC}/1/limits r, @{PROC}/loadavg r, + #aa:only test + /tmp/tmp.@{rand10}/{,**} rw, + include if exists } diff --git a/apparmor.d/profiles-a-f/atftpd b/apparmor.d/profiles-a-f/atftpd index dc7f2bf366..2444bd128d 100644 --- a/apparmor.d/profiles-a-f/atftpd +++ b/apparmor.d/profiles-a-f/atftpd @@ -10,7 +10,7 @@ include @{exec_path} = @{bin}/atftpd profile atftpd @{exec_path} { include - include + include # For libwrap (TCP Wrapper) support include @@ -18,6 +18,12 @@ profile atftpd @{exec_path} { capability setgid, capability setuid, + network inet dgram, + network inet stream, + network inet6 dgram, + network inet6 stream, + network netlink raw, + @{exec_path} mr, # FTP dirs (add "w" if you need write permissions and hence upload files) diff --git a/apparmor.d/profiles-a-f/atool b/apparmor.d/profiles-a-f/atool index 99cb0fed61..2782aacc04 100644 --- a/apparmor.d/profiles-a-f/atool +++ b/apparmor.d/profiles-a-f/atool @@ -19,9 +19,9 @@ profile atool @{exec_path} { @{bin}/7z rix, @{bin}/arc rix, @{bin}/arj rix, + @{bin}/bzip rix, @{bin}/bzip2 rix, @{bin}/bzip2 rix, - @{bin}/bzip rix, @{bin}/compress rix, @{bin}/cpio rix, @{bin}/gunzip rix, @@ -30,16 +30,15 @@ profile atool @{exec_path} { @{bin}/jar rix, @{bin}/lha rix, @{bin}/lrunzip rix, + @{bin}/lrz rix, @{bin}/lrzcat rix, @{bin}/lrzip rix, - @{bin}/lrz rix, @{bin}/lrztar rix, @{bin}/lrzuntar rix, @{bin}/lzip rix, @{bin}/lzma rix, @{bin}/lzop rix, @{bin}/lzop rix, - @{lib}/p7zip/7z rix, @{bin}/rar rix, @{bin}/tar rix, @{bin}/unace rix, @@ -48,6 +47,7 @@ profile atool @{exec_path} { @{bin}/unzip rix, @{bin}/xz rix, @{bin}/zip rix, + @{lib}/p7zip/7z rix, /etc/atool.conf r, owner @{HOME}/.atoolrc r, diff --git a/apparmor.d/profiles-a-f/atril b/apparmor.d/profiles-a-f/atril index 284c359110..70ebe59692 100644 --- a/apparmor.d/profiles-a-f/atril +++ b/apparmor.d/profiles-a-f/atril @@ -10,19 +10,12 @@ include @{exec_path} = @{bin}/atril{,-*} profile atril @{exec_path} { include - include - include - include - include include include - include - include - include - include + include + include include include - include network netlink raw, @@ -38,7 +31,6 @@ profile atril @{exec_path} { @{lib}/{,@{multiarch}/}webkit{2,}gtk-*/WebKitWebProcess rix, /usr/share/atril/{,**} r, - /usr/share/poppler/{,**} r, /etc/fstab r, diff --git a/apparmor.d/profiles-a-f/auditctl b/apparmor.d/profiles-a-f/auditctl index d6881f3e77..4083291a15 100644 --- a/apparmor.d/profiles-a-f/auditctl +++ b/apparmor.d/profiles-a-f/auditctl @@ -6,9 +6,10 @@ abi , include -@{exec_path} = @{bin}/auditctl +@{exec_path} = @{sbin}/auditctl profile auditctl @{exec_path} flags=(attach_disconnected) { include + include capability audit_control, @@ -17,6 +18,9 @@ profile auditctl @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, /etc/audit/audit.rules r, + /etc/audit/auditd.conf r, + + /var/log/audit/{,**} r, include if exists } diff --git a/apparmor.d/profiles-a-f/auditd b/apparmor.d/profiles-a-f/auditd index bb2c64ceec..4bdfea7805 100644 --- a/apparmor.d/profiles-a-f/auditd +++ b/apparmor.d/profiles-a-f/auditd @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/auditd +@{exec_path} = @{sbin}/auditd profile auditd @{exec_path} flags=(attach_disconnected) { include include @@ -27,8 +27,10 @@ profile auditd @{exec_path} flags=(attach_disconnected) { /var/log/audit/{,**} rw, - @{att}/@{run}/systemd/userdb/io.systemd.DynamicUser rw, + @{att}@{run}/systemd/userdb/io.systemd.DynamicUser rw, + owner @{run}/audit/ w, + owner @{run}/audit/auditd.pid rwl, owner @{run}/auditd.pid rwl, owner @{run}/auditd.state rw, diff --git a/apparmor.d/profiles-a-f/augenrules b/apparmor.d/profiles-a-f/augenrules index 7a515c1ba2..5ae84876ba 100644 --- a/apparmor.d/profiles-a-f/augenrules +++ b/apparmor.d/profiles-a-f/augenrules @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/augenrules +@{exec_path} = @{sbin}/augenrules profile augenrules @{exec_path} flags=(attach_disconnected) { include include @@ -16,7 +16,7 @@ profile augenrules @{exec_path} flags=(attach_disconnected) { @{sh_path} rix, @{bin}/{,e,f}grep rix, @{bin}/{,g,m}awk rix, - @{bin}/auditctl rPx, + @{sbin}/auditctl rPx, @{bin}/cat rix, @{bin}/chmod rix, @{bin}/cmp rix, diff --git a/apparmor.d/profiles-a-f/badblocks b/apparmor.d/profiles-a-f/badblocks index e0f686b90a..ff3a710c38 100644 --- a/apparmor.d/profiles-a-f/badblocks +++ b/apparmor.d/profiles-a-f/badblocks @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/badblocks +@{exec_path} = @{sbin}/badblocks profile badblocks @{exec_path} { include include diff --git a/apparmor.d/profiles-a-f/baobab b/apparmor.d/profiles-a-f/baobab index 1f9f14dc1d..c49241f51d 100644 --- a/apparmor.d/profiles-a-f/baobab +++ b/apparmor.d/profiles-a-f/baobab @@ -7,23 +7,27 @@ abi , include @{exec_path} = @{bin}/baobab -profile baobab @{exec_path} { +profile baobab @{exec_path} flags=(attach_disconnected) { include - include + include + include include include + #aa:dbus own bus=session name=org.gnome.baobab + #aa:dbus talk bus=session name=org.gtk.vfs label="gvfsd{,-*}" @{exec_path} mr, @{open_path} rPx -> child-open-help, + #aa:lint ignore=too-wide # As a directory tree analyzer it needs full access to the filesystem / r, /** r, - deny /boot/{,**} r, + deny @{efi}/{,**} r, include if exists } diff --git a/apparmor.d/profiles-a-f/biosdecode b/apparmor.d/profiles-a-f/biosdecode index 8010b380a1..87457a1294 100644 --- a/apparmor.d/profiles-a-f/biosdecode +++ b/apparmor.d/profiles-a-f/biosdecode @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/biosdecode +@{exec_path} = @{sbin}/biosdecode profile biosdecode @{exec_path} { include diff --git a/apparmor.d/profiles-a-f/birdtray b/apparmor.d/profiles-a-f/birdtray index c63a8de7ce..f05d5e6eb3 100644 --- a/apparmor.d/profiles-a-f/birdtray +++ b/apparmor.d/profiles-a-f/birdtray @@ -40,7 +40,7 @@ profile birdtray @{exec_path} { owner @{HOME}/.thunderbird/*.*/{Imap,}Mail/**/*.msf r, owner @{user_config_dirs}/ulduzsoft/ rw, - owner @{user_config_dirs}/ulduzsoft/* rwkl -> /home/morfik/.config/ulduzsoft/*, + owner @{user_config_dirs}/ulduzsoft/* rwkl -> @{user_config_dirs}/ulduzsoft/*, owner @{user_config_dirs}/birdtray-config.json rwl -> @{user_config_dirs}/#@{int}, owner @{user_config_dirs}/birdtray-config.json.* rwl -> @{user_config_dirs}/#@{int}, @@ -53,7 +53,7 @@ profile birdtray @{exec_path} { owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/mounts r, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-a-f/blkdeactivate b/apparmor.d/profiles-a-f/blkdeactivate index 2cabb639fa..bff816339c 100644 --- a/apparmor.d/profiles-a-f/blkdeactivate +++ b/apparmor.d/profiles-a-f/blkdeactivate @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/blkdeactivate +@{exec_path} = @{sbin}/blkdeactivate profile blkdeactivate @{exec_path} flags=(complain) { include include @@ -15,12 +15,12 @@ profile blkdeactivate @{exec_path} flags=(complain) { @{exec_path} rm, @{sh_path} rix, - @{bin}/dmsetup rPUx, - @{bin}/grep rix, + @{sbin}/dmsetup rPx, + @{bin}/{,e}grep rix, @{bin}/touch rix, @{bin}/lsblk rPx, - @{bin}/lvm rPx, - @{bin}/multipathd rPx, + @{sbin}/lvm rPx, + @{sbin}/multipathd rPx, @{bin}/sort rix, @{bin}/umount rPx, diff --git a/apparmor.d/profiles-a-f/borg b/apparmor.d/profiles-a-f/borg index ff3f8b43a6..49641d0c69 100644 --- a/apparmor.d/profiles-a-f/borg +++ b/apparmor.d/profiles-a-f/borg @@ -8,7 +8,7 @@ abi , include @{exec_path} = @{bin}/borg -profile borg @{exec_path} { +profile borg @{exec_path} flags=(attach_disconnected) { include include include @@ -16,6 +16,8 @@ profile borg @{exec_path} { capability dac_override, capability dac_read_search, + capability fowner, + capability sys_admin, network inet dgram, network inet6 dgram, @@ -23,31 +25,38 @@ profile borg @{exec_path} { mount fstype=fuse options=(ro nosuid nodev) borgfs -> @{MOUNTS}/, mount fstype=fuse options=(ro nosuid nodev) borgfs -> @{MOUNTS}/*/, + mount fstype=fuse options=(ro nodev nosuid) borgfs -> /tmp/borg/, @{exec_path} r, @{bin}/ r, - @{python_path} r, + @{python_path} rix, @{bin}/{,@{multiarch}-}ld.bfd rix, @{bin}/cat rix, - @{bin}/ldconfig rix, + @{sbin}/ldconfig rix, @{bin}/uname rix, + @{bin}/ip rix, + @{bin}/gzip rix, @{bin}/ccache rCx -> ccache, @{bin}/fusermount{,3} rCx -> fusermount, @{bin}/pass rPx, @{bin}/ssh rPx, + /usr/share/iproute2/group r, + # Dirs that can be backed up / r, - /etc/{,**} r, + /etc/{,**} r, #aa:lint ignore=too-wide /home/{,**} r, @{MOUNTS}/{,**} r, /root/{,**} r, /srv/{,**} r, /var/{,**} r, + @{att}/var/{,**} r, + # The backup dirs owner @{MOUNTS}/ r, owner @{MOUNTS}/** rwkl -> @{MOUNTS}/**, @@ -60,23 +69,30 @@ profile borg @{exec_path} { owner @{user_config_dirs}/borg/** rw, # If /tmp/ isn't accessible, then /var/tmp/ is used. - owner @{tmp}/* rw, + /tmp/borg/ r, + owner @{tmp}/* rw, #aa:lint ignore=too-wide owner @{tmp}/borg-cache-*/ rw, owner @{tmp}/borg-cache-*/* rw, owner @{tmp}/tmp*/ rw, owner @{tmp}/tmp*/file rw, owner @{tmp}/tmp*/idx rw, owner /var/lib/libuuid/clock.txt w, - owner /var/tmp/* rw, + owner /var/tmp/* rw, #aa:lint ignore=too-wide owner /var/tmp/tmp*/ rw, owner /var/tmp/tmp*/file rw, owner /var/tmp/tmp*/idx rw, + @{PROC}/sys/fs/pipe-max-size r, owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/stat r, /dev/fuse rw, + #aa:only test + mount fstype=fuse options=(ro nosuid nodev) borgfs -> /tmp/autopkgtest.@{rand6}/**, + mount fstype=fuse options=(ro nosuid nodev) borgfs -> /tmp/tmp@{word8}/**, + owner /tmp/tmp@{word8}/{,**} rwlk, + profile ccache { include @@ -97,6 +113,10 @@ profile borg @{exec_path} { include include + capability setuid, + + unix type=stream peer=(label=borg), + mount fstype=fuse options=(ro nosuid nodev) borgfs -> @{MOUNTS}/, mount fstype=fuse options=(ro nosuid nodev) borgfs -> @{MOUNTS}/*/, @@ -106,6 +126,10 @@ profile borg @{exec_path} { @{MOUNTS}/ r, @{MOUNTS}/*/ r, + #aa:only test + mount fstype=fuse options=(ro nosuid nodev) borgfs -> /tmp/autopkgtest.@{rand6}/**, + mount fstype=fuse options=(ro nosuid nodev) borgfs -> /tmp/tmp@{word8}/**, + include if exists } diff --git a/apparmor.d/profiles-a-f/briar-desktop b/apparmor.d/profiles-a-f/briar-desktop index 9ea7a824c6..1cfda03d92 100644 --- a/apparmor.d/profiles-a-f/briar-desktop +++ b/apparmor.d/profiles-a-f/briar-desktop @@ -80,7 +80,7 @@ profile briar-desktop @{exec_path} { profile jspawnhelper flags=(attach_disconnected) { include - @{bin}/ldconfig ix, + @{sbin}/ldconfig ix, owner @{HOME}/.briar/desktop/tor/tor Px -> briar-desktop-tor, @{system_share_dirs}/java/briar-desktop.jar r, diff --git a/apparmor.d/profiles-a-f/browserpass b/apparmor.d/profiles-a-f/browserpass index ee7ff958c7..66ac964d8f 100644 --- a/apparmor.d/profiles-a-f/browserpass +++ b/apparmor.d/profiles-a-f/browserpass @@ -6,9 +6,10 @@ abi , include -@{exec_path} = @{bin}/browserpass +@{exec_path} = @{bin}/browserpass @{lib}/browserpass/browserpass-native profile browserpass @{exec_path} flags=(attach_disconnected) { include + include include network netlink raw, @@ -18,20 +19,18 @@ profile browserpass @{exec_path} flags=(attach_disconnected) { @{bin}/gpg{2,} rCx -> gpg, owner @{HOME}/.password-store/{,**} r, - owner @{HOME}/.mozilla/firefox/@{rand8}.*/.parentlock rw, - owner @{HOME}/.mozilla/firefox/@{rand8}.*/extensions/* r, + owner @{HOME}/.mozilla/firefox{,-esr}/@{rand8}.*/.parentlock rw, + owner @{HOME}/.mozilla/firefox{,-esr}/@{rand8}.*/extensions/* r, owner @{user_cache_dirs}/mozilla/firefox/@{rand8}.*/startupCache/scriptCache-*.bin r, owner @{user_cache_dirs}/mozilla/firefox/@{rand8}.*/startupCache/startupCache.*.little r, owner @{user_cache_dirs}/mozilla/firefox/@{rand8}.*/safebrowsing-updating/google@{d}/goog-phish-proto-@{int}.vlpset rw, owner @{tmp}/mozilla-temp-@{int} r, - owner @{PROC}/@{pid}/mountinfo r, - # Inherit Silencer deny network inet6, deny network inet, - deny owner @{HOME}/.mozilla/firefox/@{rand8}.*/features/*/*.xpi r, - deny owner @{HOME}/.mozilla/firefox/@{rand8}.*/storage/default/{,**} rw, + deny owner @{HOME}/.mozilla/firefox{,-esr}/@{rand8}.*/features/*/*.xpi r, + deny owner @{HOME}/.mozilla/firefox{,-esr}/@{rand8}.*/storage/default/{,**} rw, deny owner @{user_download_dirs}/{,**} rw, deny owner @{run}/user/@{uid}/gnome-shell-disable-extensions w, deny owner @{user_share_dirs}/gvfs-metadata/{,**} r, @@ -55,6 +54,8 @@ profile browserpass @{exec_path} flags=(attach_disconnected) { owner @{user_config_dirs}/*-store/ rw, owner @{user_config_dirs}/*-store/** rwkl -> @{user_config_dirs}/*-store/**, + owner @{run}/user/@{uid}/gnupg/S.gpg-agent rw, + include if exists } diff --git a/apparmor.d/profiles-a-f/btop b/apparmor.d/profiles-a-f/btop deleted file mode 100644 index bab483dde3..0000000000 --- a/apparmor.d/profiles-a-f/btop +++ /dev/null @@ -1,64 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - -abi , - -include - -@{exec_path} = @{bin}/btop -profile btop @{exec_path} { - include - include - include - include - - capability sys_ptrace, - - network netlink raw, - - signal (send), - ptrace (read), - - @{exec_path} mr, - - /usr/share/btop/{,**} r, - - /etc/fstab r, - - owner @{user_config_dirs}/btop/{,**} rw, - - @{sys}/bus/pci/devices/ r, - @{sys}/class/hwmon/ r, - @{sys}/class/power_supply/ r, - @{sys}/devices/@{pci}/**/stat r, - @{sys}/devices/@{pci}/net/*/{,**} r, - @{sys}/devices/@{pci}/usb@{int}/**/power_supply/** r, - @{sys}/devices/**/hwmon@{int}/{,*} r, - @{sys}/devices/**/power_supply/{AC,BAT@{int}}/{,**} r, - @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_{cur,min,max}_freq r, - @{sys}/devices/system/node/node@{int}/cpumap r, - @{sys}/devices/virtual/block/dm-@{int}/stat r, - @{sys}/devices/virtual/net/{,**} r, - @{sys}/devices/virtual/thermal/thermal_zone@{int}/{,} r, - - @{PROC} r, - @{PROC}/@{pid}/statm r, - @{PROC}/@{pids}/cmdline r, - @{PROC}/@{pids}/comm r, - @{PROC}/@{pids}/io r, - @{PROC}/@{pids}/stat r, - @{PROC}/devices r, - @{PROC}/driver/nvidia/capabilities/mig/monitor r, - @{PROC}/loadavg r, - @{PROC}/spl/kstat/zfs/arcstats r, - @{PROC}/uptime r, - owner @{PROC}/@{pid}/mounts r, - - /dev/nvidia-caps/ rw, - /dev/nvidia-caps/nvidia-cap@{int} rw, - - include if exists -} - -# vim:syntax=apparmor diff --git a/apparmor.d/profiles-a-f/calibre b/apparmor.d/profiles-a-f/calibre index 6d71ed28df..2f2ffe717f 100644 --- a/apparmor.d/profiles-a-f/calibre +++ b/apparmor.d/profiles-a-f/calibre @@ -12,12 +12,9 @@ include @{exec_path} += @{bin}/lrs2lrf @{bin}/lrf2lrs @{bin}/lrfviewer @{bin}/web2disk profile calibre @{exec_path} { include - include - include - include - include - include - include + include + include + include include include include @@ -35,11 +32,13 @@ profile calibre @{exec_path} { capability sys_ptrace, + network inet dgram, network inet stream, + network inet6 dgram, network inet6 stream, network netlink raw, - unix (send, receive) type=stream peer=(addr=none, label=xorg), + # unix (send, receive) type=stream peer=(addr=none, label=xorg), unix (bind, listen) type=stream addr="@*-calibre-gui.socket", unix (bind) type=stream addr="@calibre-*", @@ -47,9 +46,11 @@ profile calibre @{exec_path} { @{sh_path} rix, @{python_path} rix, + @{bin}/env r, @{bin}/file rix, - @{bin}/ldconfig{,.real} rix, + @{bin}/jpegtran rix, @{bin}/uname rix, + @{sbin}/ldconfig{,.real} rix, @{lib}/{,@{multiarch}/}qt{5,6}{,/libexec/}QtWebEngineProcess rix, @{bin}/pdftoppm rPUx, # (#FIXME#) @@ -63,15 +64,19 @@ profile calibre @{exec_path} { /etc/fstab r, /etc/inputrc r, /etc/magic r, - /etc/mime.types r, owner @{HOME}/ r, owner "@{HOME}/Calibre Library/{,**}" rw, owner "@{HOME}/Calibre Library/metadata.db" rwk, - owner @{user_documents_dirs}/{,**} rwl, + owner @{user_books_dirs}/{,**} rwl, + owner @{user_books_dirs}/Calibre/** rwk, + owner @{user_documents_dirs}/{,**} rwl, + owner @{user_documents_dirs}/Calibre/** rwk, owner @{user_torrents_dirs}/{,**} rwl, + owner @{user_torrents_dirs}/Calibre/** rwk, owner @{user_work_dirs}/{,**} rwl, + owner @{user_work_dirs}/Calibre/** rwk, owner @{user_config_dirs}/calibre/ rw, owner @{user_config_dirs}/calibre/** rwk, @@ -82,10 +87,10 @@ profile calibre @{exec_path} { owner @{user_cache_dirs}/calibre/ rw, owner @{user_cache_dirs}/calibre/** rwkl -> @{user_cache_dirs}/calibre/**, - owner @{tmp}/calibre_*_tmp_*/{,**} rw, - owner @{tmp}/calibre-*/{,**} rw, - owner @{tmp}/@{int}-*/ rw, - owner @{tmp}/@{int}-*/** rwl, + owner @{tmp}/@{rand8} rw, + audit owner @{tmp}/@{int}-*/ rw, + audit owner @{tmp}/@{int}-*/** rwl, + owner @{tmp}/calibre-@{word8}/{,**} rw, owner /dev/shm/#@{int} rw, @@ -108,7 +113,8 @@ profile calibre @{exec_path} { owner @{PROC}/@{pid}/task/@{tid}/comm rw, owner @{PROC}/@{pid}/task/@{tid}/status r, - owner /dev/tty@{int} rw, + /dev/tty r, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-a-f/cawbird b/apparmor.d/profiles-a-f/cawbird index 0d8c6a0003..2128bee20f 100644 --- a/apparmor.d/profiles-a-f/cawbird +++ b/apparmor.d/profiles-a-f/cawbird @@ -12,12 +12,9 @@ profile cawbird @{exec_path} { include include include + include include - include - include - include include - include include include @@ -35,9 +32,6 @@ profile cawbird @{exec_path} { /usr/share/xml/iso-codes/{,**} r, - /var/lib/dbus/machine-id r, - /etc/machine-id r, - owner @{user_config_dirs}/cawbird/ rw, owner @{user_config_dirs}/cawbird/** rwk, diff --git a/apparmor.d/profiles-a-f/cfdisk b/apparmor.d/profiles-a-f/cfdisk index 9cacb9324c..ee8d277f2b 100644 --- a/apparmor.d/profiles-a-f/cfdisk +++ b/apparmor.d/profiles-a-f/cfdisk @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/cfdisk +@{exec_path} = @{sbin}/cfdisk profile cfdisk @{exec_path} { include include diff --git a/apparmor.d/profiles-a-f/cgdisk b/apparmor.d/profiles-a-f/cgdisk index 0f91c1e851..8f3f11af08 100644 --- a/apparmor.d/profiles-a-f/cgdisk +++ b/apparmor.d/profiles-a-f/cgdisk @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/cgdisk +@{exec_path} = @{sbin}/cgdisk profile cgdisk @{exec_path} { include include diff --git a/apparmor.d/profiles-a-f/check-bios-nx b/apparmor.d/profiles-a-f/check-bios-nx index 775e3f640d..c44b6eaa5e 100644 --- a/apparmor.d/profiles-a-f/check-bios-nx +++ b/apparmor.d/profiles-a-f/check-bios-nx @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/check-bios-nx +@{exec_path} = @{sbin}/check-bios-nx profile check-bios-nx @{exec_path} { include include @@ -25,7 +25,7 @@ profile check-bios-nx @{exec_path} { @{bin}/kmod rCx -> kmod, - @{bin}/rdmsr rPx, + @{sbin}/rdmsr rPx, owner @{PROC}/@{pid}/fd/@{int} rw, diff --git a/apparmor.d/profiles-a-f/check-support-status-hook b/apparmor.d/profiles-a-f/check-support-status-hook index 4c805b9b11..9cd895382f 100644 --- a/apparmor.d/profiles-a-f/check-support-status-hook +++ b/apparmor.d/profiles-a-f/check-support-status-hook @@ -24,10 +24,10 @@ profile check-support-status-hook @{exec_path} { @{bin}/mktemp rix, @{bin}/rm rix, - @{bin}/adduser rPx, + @{sbin}/adduser rPx, @{bin}/check-support-status rPx, @{bin}/debconf-escape rCx -> debconf-escape, - @{bin}/runuser rCx -> runuser, + @{sbin}/runuser rCx -> runuser, # Think what to do about this (#FIXME#) /usr/share/debconf/frontend rPx, @@ -79,15 +79,11 @@ profile check-support-status-hook @{exec_path} { owner /var/cache/debconf/{config,passwords,templates}.dat{,-new,-old} rwk, # The following is needed when debconf uses GUI frontends. - include - include - include - include + include capability dac_read_search, - @{bin}/lsb_release rPx -> lsb_release, + @{bin}/lsb_release rPx, @{bin}/hostname rix, owner @{PROC}/@{pid}/mounts r, - @{HOME}/.Xauthority r, include if exists } @@ -111,7 +107,7 @@ profile check-support-status-hook @{exec_path} { # To write records to the kernel auditing log. capability audit_write, - @{bin}/runuser mr, + @{sbin}/runuser mr, @{sh_path} rix, @@ -120,8 +116,6 @@ profile check-support-status-hook @{exec_path} { owner @{PROC}/@{pids}/loginuid r, @{PROC}/1/limits r, - @{etc_ro}/security/limits.d/ r, - /tmp/ r, owner @{tmp}/debian-security-support.postinst.*/output w, diff --git a/apparmor.d/profiles-a-f/cheese b/apparmor.d/profiles-a-f/cheese new file mode 100644 index 0000000000..98d96edbd9 --- /dev/null +++ b/apparmor.d/profiles-a-f/cheese @@ -0,0 +1,53 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Roman Beslik +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/cheese +profile cheese @{exec_path} { + include + include + include + include + include + include + include + include + include + include + include + + network netlink raw, + + @{exec_path} mr, + + @{bin}/bwrap Px -> gnome-desktop-thumbnailers, + @{open_path} rPx -> child-open-help, + + @{system_share_dirs}/gnome-video-effects/{,*.effect} r, + @{system_share_dirs}/ladspa/rdf/{,**} r, + @{system_share_dirs}/thumbnailers/{,*.thumbnailer} r, + + /etc/machine-id r, + + owner @{HOME}/ r, # file save dialog + owner @{user_pictures_dirs}/{,**} rw, + owner @{user_videos_dirs}/{,**} rw, + + owner @{user_cache_dirs}/gnome-desktop-thumbnailer/gstreamer-1.0/ r, + + owner @{tmp}/flatpak-seccomp-@{rand6} rw, + owner @{tmp}/gnome-desktop-thumbnailer-@{rand6}/{,**} rw, + + @{run}/udev/data/c@{dynamic}:@{int} r, # For dynamic assignment range 234 to 254, 384 to 511 + + owner @{PROC}/@{pid}/task/@{tid}/comm rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-a-f/chronyd b/apparmor.d/profiles-a-f/chronyd index 155d82f075..e4a986c8af 100644 --- a/apparmor.d/profiles-a-f/chronyd +++ b/apparmor.d/profiles-a-f/chronyd @@ -8,7 +8,7 @@ abi , include -@{exec_path} = @{bin}/chronyd +@{exec_path} = @{sbin}/chronyd profile chronyd @{exec_path} flags=(attach_disconnected) { include include diff --git a/apparmor.d/profiles-a-f/cider b/apparmor.d/profiles-a-f/cider new file mode 100644 index 0000000000..a6e5dd9dbf --- /dev/null +++ b/apparmor.d/profiles-a-f/cider @@ -0,0 +1,39 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Stoppedpuma <58333920+Stoppedpuma@users.noreply.github.com> +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{name} = {C,c}ider sh.cider.genten +@{domain} = sh.cider.genten org.chromium.Chromium +@{lib_dirs} = @{lib}/cider +@{cache_dirs} = @{user_cache_dirs}/@{name} +@{config_dirs} = @{user_config_dirs}/@{name} + +@{exec_path} = @{bin}/{C,c}ider @{lib_dirs}/Cider +profile cider @{exec_path} flags=(attach_disconnected) { + include + include + include + include + include + include + + network inet dgram, + network inet6 dgram, + network inet stream, + network inet6 stream, + network netlink raw, + + @{exec_path} mrix, + + @{lib_dirs}/chrome-sandbox rPx, + + owner @{user_config_dirs}/sh.cider.genten/WidevineCdm/*/_platform_specific/linux_@{arch}/libwidevinecdm.so mr, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-a-f/claude b/apparmor.d/profiles-a-f/claude new file mode 100644 index 0000000000..4793a7c8da --- /dev/null +++ b/apparmor.d/profiles-a-f/claude @@ -0,0 +1,315 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# !!! warning +# +# This profile is **not** installed by default as it breaks the POLA principle +# in the way it **will** break some cappabilities of claude. +# +# **Architecture** +# +# Similar to `code` and `code-extensions`, the `claude` profile stack define a "world" +# with generic rules of what should be allowed for an AI assistant and what is not. + +abi , + +include + +@{code_name} = code{,-oss} vscode{,-oss} +@{code_config} = Code Code?-?OSS Code?-?Insiders +@{code_config_dirs} = @{HOME}/.@{code_name} @{user_config_dirs}/@{code_config} +@{code_ext_dirs} = @{code_config_dirs}/extensions + +@{exec_path} = @{bin}/claude /opt/claude-code/bin/claude +@{exec_path} += @{user_bin_dirs}/claude +@{exec_path} += @{user_share_dirs}/claude/versions/@{version} +@{exec_path} += @{code_ext_dirs}/anthropic.claude-code-*/resources/native-binary/claude +profile claude @{exec_path} flags=(attach_disconnected) { + include + include + include + include + include + + network inet dgram, + network inet stream, + network inet6 dgram, + network inet6 stream, + network netlink raw, + + signal send set=term peer=git, + signal receive set=term peer=code, + + unix (send receive) type=stream peer=(label=code), + unix (send receive) type=stream peer=(label=git), + deny unix (send receive) type=stream peer=(label=ssh), + + @{exec_path} mrix, + + @{bin}/git Cx -> git, + @{open_path} Px -> child-open-strict, + @{shells_path} Cx -> shell, + + @{bin}/env m, + @{bin}/rg ix, + @{bin}/uname ix, + @{bin}/which{,.debianutils} rix, + + # Nodes + @{bin}/node rix, + @{lib}/node_modules/npm/bin/npm-cli.js rix, + @{lib}/node_modules/npm/bin/npx-cli.js rix, + /usr/share/nodejs/npm/bin/npm-cli.js rix, + + #aa:lint ignore=too-wide + # TODO: should transition to a dev/plugin profile, not the shell one + priority=-1 /** Cx -> shell, + + owner @{HOME}/ r, + owner @{HOME}/.claude.* rw, + owner @{HOME}/.claude.*/{,**} rw, + owner @{HOME}/.claude/ rw, + owner @{HOME}/.claude/** rwkl -> @{HOME}/.claude/**, + owner @{HOME}/.npm/{,**} rw, + + owner @{user_share_dirs}/applications/claude-code-url-handler.desktop r, + + # TODO: deny this as self update is an abberation + owner @{user_bin_dirs}/claude w, + owner @{user_bin_dirs}/claude.tmp.* rw, + + owner @{user_lib_dirs}/node_modules/{,**} r, + + owner @{user_projects_dirs}/ r, + owner @{user_projects_dirs}/** rwkl -> @{user_projects_dirs}/**, + + owner @{user_cache_dirs}/claude/{,**} rw, + owner @{user_cache_dirs}/claude-cli-nodejs/ rw, + owner @{user_cache_dirs}/claude-cli-nodejs/** rwkl, + + owner @{user_state_dirs}/claude/{,**} rw, + + owner @{user_config_dirs}/git/ignore r, + owner @{user_config_dirs}/git/config r, + + owner @{user_share_dirs}/claude/{,**} rw, + + /tmp/ r, + owner @{tmp}/.@{hex16}-@{int8}.node mrw, + owner @{tmp}/claude{,-*} rw, + owner @{tmp}/claude{,-*}/{,**} rw, + owner @{tmp}/node-compile-cache/** rwlk, + owner @{tmp}/playwright-artifacts-@{rand6}/{,**} rw, + + @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_cur_freq r, + @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_max_freq r, + + @{sys}/fs/cgroup/user.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/session-@{int}.scope/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/session-@{int}.scope/memory.high r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/session-@{int}.scope/memory.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/cpu.max r, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/*-@{uuid}.scope/memory.* r, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/app-*-@{int}.scope/memory.* r, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/cpu.max r, + + @{PROC}/sys/vm/mmap_min_addr r, + @{PROC}/version r, + @{PROC}/version_signature r, + owner @{PROC}/@{pid}/cgroup r, + owner @{PROC}/@{pid}/mountinfo r, + owner @{PROC}/@{pid}/stat r, + owner @{PROC}/@{pid}/statm r, + + # Safety mechanisms + deny @{bin}/ssh x, + deny /etc/machine-id r, + deny / r, + deny /home/ r, + + # file_inherit + deny owner @{code_config_dirs}/logs/{,**} w, + deny owner /dev/shm/.org.chromium.Chromium.@{rand6} rw, + + profile shell flags=(attach_disconnected) { + include + include + include + include + include + include + include + + capability sys_ptrace, + + # network inet6 stream port=1024-66666, # failed af match, MPC only + network inet dgram, + network inet stream, + network inet6 dgram, + network inet6 stream, + network netlink raw, + + ptrace read, + + unix (send receive) type=stream peer=(label=claude), + + signal receive peer=claude, + + priority=1 @{bin}/flatpak Px -> claude//flatpak, + priority=1 @{bin}/git Px -> claude//git, + priority=1 @{bin}/scp PUx -> claude//ssh, + priority=1 @{bin}/ssh Px -> claude//ssh, + priority=1 @{ldd_path} Px -> claude//ldd, + + owner @{HOME}/.claude/{,**} r, + owner @{HOME}/.claude/shell-snapshots/* rw, + owner @{HOME}/.claude/plugins/{,**} rwlk, + + owner @{code_config_dirs}/logs/{,**} w, + owner @{user_config_dirs}/gh/*.yml r, + owner @{user_config_dirs}/git/* r, + + owner @{user_projects_dirs}/ r, + owner @{user_projects_dirs}/** rwlk, + + /var/tmp/@{word8} rw, + owner @{tmp}/* rwlk, #aa:lint ignore=too-wide + owner @{tmp}/claude-@{uid}/ rw, + owner @{tmp}/claude-@{uid}/** rwlk, + owner @{tmp}/claude-shell/ rw, + owner @{tmp}/claude-shell/** mix, + owner @{tmp}/claude-shell/** rwlk -> @{tmp}/claude/**, + owner @{tmp}/claude{,-code}/ rw, + owner @{tmp}/claude{,-code}/** mix, + owner @{tmp}/claude{,-code}/** rwlk -> @{tmp}/claude/**, + + # Required to copy result to clipboard + owner @{run}/user/@{uid}/wayland-@{int} rw, + + @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_cur_freq r, + @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_max_freq r, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/app-gnome-code-@{int}.scope/memory.* r, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/vte-spawn-@{uuid}.scope/memory.* r, + + @{PROC}/ r, + @{PROC}/@{pids}/cmdline r, + @{PROC}/@{pids}/stat r, + @{PROC}/sys/kernel/pid_max r, + @{PROC}/tty/drivers r, + @{PROC}/version_signature r, + owner @{PROC}/@{pid}/environ r, # This raise the sys_ptrace capability requirement, only allowed on user processes + owner @{PROC}/@{pid}/loginuid r, + owner @{PROC}/@{pid}/stat r, + + # Safety mechanisms + deny @{bin}/poweroff x, + deny @{bin}/reboot x, + deny @{bin}/rm x, + deny @{bin}/rmdir x, + deny @{bin}/shutdown x, + deny /etc/dpkg/dpkg.cfg r, + deny /etc/dpkg/dpkg.cfg.d/{,**} r, + deny /etc/pacman.conf r, + deny /etc/pacman.d/{,**} r, + deny /etc/rpm/{,**} r, + deny /var/lib/pacman/** r, + deny /var/lib/rpm/{,**} r, + deny /home/ r, + deny owner @{HOME}/ r, + deny owner @{HOME}/@{XDG_GPG_DIR}/*.conf r, + + # file_inherit + deny /etc/debuginfod/ r, + deny owner @{code_config_dirs}/logs/{,**} w, + deny owner /dev/shm/.org.chromium.Chromium.@{rand6} rw, + + include if exists + } + + profile git flags=(attach_disconnected,complain) { + include + include + + owner @{HOME}/.claude/ r, + owner @{HOME}/.claude/** rwlk, + + owner @{user_projects_dirs}/** rw, + + owner @{tmp}/claude{,-*}/ rw, + owner @{tmp}/claude{,-*}/** rwlk, + + include if exists + } + + profile ssh { + include + include + include + + @{bin}/ssh mr, + + @{etc_ro}/ssh/ssh_config r, + @{etc_ro}/ssh/ssh_config.d/{,*} r, + + owner @{user_projects_dirs}/**/ssh/{,*} r, + owner @{user_projects_dirs}/**/config r, + + owner @{PROC}/@{pid}/fd/ r, + + deny owner @{HOME}/@{XDG_SSH_DIR}/{,**} rwlk, + + include if exists + } + + profile flatpak { + include + + unix (send receive) type=stream peer=(label=claude), + + # Only runs: `flatpak --installations` + @{bin}/flatpak mr, + + # file_inherit + deny network netlink raw, + deny owner @{HOME}/.claude/** r, + deny owner @{code_config_dirs}/logs/** w, + deny owner @{user_projects_dirs}/** r, + deny owner @{user_config_dirs}/** r, + deny owner @{code_config_dirs}/logs/{,**} w, + deny owner /dev/shm/.org.chromium.Chromium.@{rand6} rw, + deny owner /tmp/claude-@{uid}/*/tasks/* rw, + + include if exists + } + + profile ldd { + include + include + include + + unix (send receive) type=stream peer=(label=claude), + + @{ldd_path} mrix, + + @{bin}/* mr, + @{sbin}/* mr, + @{lib}/** mr, + + # file_inherit + deny network netlink raw, + deny owner @{HOME}/.claude/** r, + deny owner @{code_config_dirs}/logs/** w, + deny owner @{user_projects_dirs}/** r, + deny owner @{user_config_dirs}/** r, + deny owner @{code_config_dirs}/logs/{,**} w, + deny owner /dev/shm/.org.chromium.Chromium.@{rand6} rw, + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-a-f/claws-mail b/apparmor.d/profiles-a-f/claws-mail index 7c5486c50a..ca89b2c1eb 100644 --- a/apparmor.d/profiles-a-f/claws-mail +++ b/apparmor.d/profiles-a-f/claws-mail @@ -11,34 +11,28 @@ include profile claws-mail @{exec_path} flags=(complain) { include include + include include - include - include - include - include include include - include include @{exec_path} mr, @{sh_path} rix, - @{bin}/which{,.debianutils} rix, + @{bin}/which{,.debianutils} rix, @{bin}/gpg{,2} rCx -> gpg, @{bin}/gpgsm rCx -> gpg, @{bin}/gpgconf rCx -> gpg, @{bin}/orage rPUx, - @{bin}/exim4 rPUx, + @{sbin}/exim4 rPUx, @{bin}/geany rPUx, /usr/share/publicsuffix/*.dafsa r, /etc/fstab r, - /etc/machine-id r, - /var/lib/dbus/machine-id r, owner /var/mail/* rwk, diff --git a/apparmor.d/profiles-a-f/cmus b/apparmor.d/profiles-a-f/cmus index c3916890f8..750fe93453 100644 --- a/apparmor.d/profiles-a-f/cmus +++ b/apparmor.d/profiles-a-f/cmus @@ -18,6 +18,9 @@ profile cmus @{exec_path} { /etc/machine-id r, + / r, + owner @{HOME}/ r, # For pwd + owner @{user_music_dirs}/{,**} r, owner @{user_config_dirs}/ r, diff --git a/apparmor.d/profiles-a-f/compton b/apparmor.d/profiles-a-f/compton index a6c7d193f4..6e09f6996f 100644 --- a/apparmor.d/profiles-a-f/compton +++ b/apparmor.d/profiles-a-f/compton @@ -20,7 +20,7 @@ profile compton @{exec_path} { owner @{HOME}/.Xauthority r, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, owner @{HOME}/.xsession-errors w, include if exists diff --git a/apparmor.d/profiles-a-f/conky b/apparmor.d/profiles-a-f/conky index 9e4372e1dc..b68950990b 100644 --- a/apparmor.d/profiles-a-f/conky +++ b/apparmor.d/profiles-a-f/conky @@ -11,9 +11,7 @@ include profile conky @{exec_path} { include include - include - include - include + include include include @@ -146,13 +144,14 @@ profile conky @{exec_path} { /usr/share/X11/XErrorDB r, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, owner @{HOME}/.xsession-errors w, profile browse { include include + include include include @@ -169,7 +168,6 @@ profile conky @{exec_path} { @{sh_path} rix, - /etc/mime.types r, /etc/mailcap r, /etc/lynx/* r, @@ -186,7 +184,7 @@ profile conky @{exec_path} { /usr/share/publicsuffix/public_suffix_list.* r, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, deny @{PROC}/@{pids}/net/dev r, deny @{PROC}/@{pids}/net/tcp r, deny @{PROC}/@{pids}/net/tcp6 r, diff --git a/apparmor.d/profiles-a-f/console-setup b/apparmor.d/profiles-a-f/console-setup index 7a11e407fa..aa0a56648a 100644 --- a/apparmor.d/profiles-a-f/console-setup +++ b/apparmor.d/profiles-a-f/console-setup @@ -13,7 +13,7 @@ profile console-setup @{exec_path} { @{exec_path} mr, @{sh_path} r, - @{bin}/uname rPx, + @{bin}/uname rix, @{bin}/mkdir rix, @{run}/console-setup/ rw, diff --git a/apparmor.d/profiles-a-f/console-setup-cached b/apparmor.d/profiles-a-f/console-setup-cached new file mode 100644 index 0000000000..f66305443d --- /dev/null +++ b/apparmor.d/profiles-a-f/console-setup-cached @@ -0,0 +1,37 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = /etc/console-setup/cached_setup_font.sh /etc/console-setup/cached_setup_terminal.sh +profile console-setup-cached @{exec_path} { + include + include + + capability sys_admin, # optional: no audit + capability sys_tty_config, + + @{exec_path} mr, + + @{sh_path} rix, + @{bin}/gzip rix, + @{bin}/ls ix, + @{bin}/mkdir ix, + @{bin}/setfont ix, + + /usr/share/consolefonts/{,**} r, + + @{run}/console-setup/ w, + @{run}/console-setup/font-loaded w, + + /dev/ r, + /dev/tty rw, + /dev/tty@{u8} rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-a-f/console-setup-keyboard b/apparmor.d/profiles-a-f/console-setup-keyboard new file mode 100644 index 0000000000..0f40d9bdf9 --- /dev/null +++ b/apparmor.d/profiles-a-f/console-setup-keyboard @@ -0,0 +1,31 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/console-setup/keyboard-setup.sh /etc/console-setup/cached_setup_keyboard.sh +profile console-setup-keyboard @{exec_path} { + include + include + + capability sys_tty_config, + + @{exec_path} mrix, + + @{sh_path} rix, + @{bin}/gzip rix, + @{bin}/kbd_mode rix, + @{bin}/loadkeys rix, + + /etc/console-setup/{,**} r, + + /dev/tty@{u8} rw, + /dev/tty rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-a-f/cracklib-packer b/apparmor.d/profiles-a-f/cracklib-packer index cc183f5273..4db396fa0e 100644 --- a/apparmor.d/profiles-a-f/cracklib-packer +++ b/apparmor.d/profiles-a-f/cracklib-packer @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/cracklib-packer +@{exec_path} = @{sbin}/cracklib-packer profile cracklib-packer @{exec_path} { include diff --git a/apparmor.d/profiles-a-f/crda b/apparmor.d/profiles-a-f/crda index 50d34bad49..d3b6cba6fa 100644 --- a/apparmor.d/profiles-a-f/crda +++ b/apparmor.d/profiles-a-f/crda @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/crda +@{exec_path} = @{sbin}/crda profile crda @{exec_path} { include diff --git a/apparmor.d/profiles-a-f/czkawka-gui b/apparmor.d/profiles-a-f/czkawka-gui index d7bb93f414..7bad2c44b1 100644 --- a/apparmor.d/profiles-a-f/czkawka-gui +++ b/apparmor.d/profiles-a-f/czkawka-gui @@ -11,10 +11,7 @@ include profile czkawka-gui @{exec_path} { include include - include - include - include - include + include @{exec_path} mr, diff --git a/apparmor.d/profiles-a-f/ddcutil b/apparmor.d/profiles-a-f/ddcutil index c752dcbb86..e1023bb0b1 100644 --- a/apparmor.d/profiles-a-f/ddcutil +++ b/apparmor.d/profiles-a-f/ddcutil @@ -7,7 +7,7 @@ abi , include @{exec_path} = @{bin}/ddcutil -profile ddcutil @{exec_path} { +profile ddcutil @{exec_path} flags=(attach_disconnected) { include include include @@ -18,17 +18,19 @@ profile ddcutil @{exec_path} { @{exec_path} mr, @{sh_path} rix, + @{bin}/{,e}grep rix, @{bin}/find rix, @{bin}/sed rix, + @{bin}/uname rix, @{bin}/xargs rix, - @{bin}/grep rix, / r, owner @{user_cache_dirs}/ddcutil/ rw, owner @{user_cache_dirs}/ddcutil/** rwlk, - @{run}/udev/data/* r, + @{run}/udev/data/+*:* r, # Identifies all subsystems + @{run}/udev/data/c@{int}:@{int} r, # Identifies all character devices @{sys}/ r, @{sys}/bus/ r, diff --git a/apparmor.d/profiles-a-f/deltachat-desktop b/apparmor.d/profiles-a-f/deltachat-desktop index 4f60099a9b..243f593bd0 100644 --- a/apparmor.d/profiles-a-f/deltachat-desktop +++ b/apparmor.d/profiles-a-f/deltachat-desktop @@ -7,21 +7,21 @@ abi , include +@{name} = deltachat-desktop +@{domain} = org.chromium.Chromium @{lib_dirs} = @{lib}/deltachat-desktop @{lib}/deltachat /opt/DeltaChat/ +@{config_dirs} = @{user_config_dirs}/DeltaChat +@{cache_dirs} = @{user_cache_dirs}/DeltaChat @{exec_path} = @{bin}/deltachat-desktop @{lib_dirs}/deltachat-desktop profile deltachat-desktop @{exec_path} { include include include - include - include - include - include + include include include include - include network inet dgram, network inet6 dgram, @@ -31,45 +31,18 @@ profile deltachat-desktop @{exec_path} { @{exec_path} mrix, - @{lib_dirs}/ r, - @{lib_dirs}/** r, - @{lib_dirs}/libffmpeg.so mr, - @{lib_dirs}/{swiftshader/,}libGLESv2.so mr, - @{lib_dirs}/{swiftshader/,}libEGL.so mr, - @{lib_dirs}/resources/app.asar.unpacked/node_modules/**.node mr, - @{lib_dirs}/resources/app.asar.unpacked/node_modules/**.so mr, - @{lib_dirs}/resources/app.asar.unpacked/node_modules/**.so.[0-9]* mr, @{lib_dirs}/chrome-sandbox rPx, @{bin}/xdg-settings rPx, @{open_path} rPx -> child-open-browsers, - owner @{user_config_dirs}/DeltaChat/ rw, - owner @{user_config_dirs}/DeltaChat/** rwk, - owner @{tmp}/@{hex}/ rw, - owner @{tmp}/@{hex}/db.sqlite-blobs/ rw, owner @{tmp}/@{hex}/db.sqlite rwk, + owner @{tmp}/@{hex}/db.sqlite-blobs/ rw, owner @{tmp}/@{hex}/db.sqlite-journal rw, - @{PROC}/ r, - @{PROC}/@{pid}/stat r, - @{PROC}/@{pid}/task/ r, - @{PROC}/@{pid}/task/@{tid}/status r, - @{PROC}/sys/fs/inotify/max_user_watches r, - @{PROC}/sys/kernel/yama/ptrace_scope r, - owner @{PROC}/@{pid}/cgroup r, - owner @{PROC}/@{pid}/cmdline r, - owner @{PROC}/@{pid}/fd/ r, - owner @{PROC}/@{pid}/oom_{,score_}adj rw, - owner @{PROC}/@{pid}/statm r, - /dev/ r, - # (#FIXME#) - deny @{sys}/bus/pci/devices/ r, - deny @{sys}/devices/virtual/tty/tty@{int}/active r, - include if exists } diff --git a/apparmor.d/profiles-a-f/deluser b/apparmor.d/profiles-a-f/deluser index 1c51858337..7a2df74559 100644 --- a/apparmor.d/profiles-a-f/deluser +++ b/apparmor.d/profiles-a-f/deluser @@ -7,36 +7,40 @@ abi , include -@{exec_path} = @{bin}/del{user,group} +@{exec_path} = @{sbin}/deluser profile deluser @{exec_path} { include include include include - capability dac_read_search, capability dac_override, + capability dac_read_search, + capability sys_admin, @{exec_path} r, @{sh_path} rix, + @{archive_path} rix, + @{bin}/logger rix, @{bin}/crontab rPx, @{bin}/gpasswd rPx, - @{bin}/groupdel rPx, + @{sbin}/groupdel rPx, @{bin}/mount rCx -> mount, - @{bin}/userdel rPx, + @{sbin}/userdel rPx, /etc/adduser.conf r, /etc/deluser.conf r, owner /etc/shadow r, + #aa:lint ignore=too-wide # This is for the "--remove-all-files" flag, which it used to remove all files owned by the user # that's going to be deleted. Basically it scans all the files in the system in each dir and look # for matches. This also includes files required by the "--remove-home" flag as well as the # "--backup" and --backup-to flags. / r, - /** rw, + /** rwk, profile mount { include diff --git a/apparmor.d/profiles-a-f/deno b/apparmor.d/profiles-a-f/deno new file mode 100644 index 0000000000..e46ca9c108 --- /dev/null +++ b/apparmor.d/profiles-a-f/deno @@ -0,0 +1,31 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{name} = deno + +@{exec_path} = @{bin}/deno +profile deno @{exec_path} { + include + + @{exec_path} mr, + + owner @{user_cache_dirs}/@{name}/{,**} rw, + owner @{user_cache_dirs}/@{name}/* k, + + @{sys}/fs/cgroup/user.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/cpu.max r, + owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/cpu.max r, + + owner @{PROC}/@{pid}/cgroup r, + owner @{PROC}/@{pid}/mountinfo r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-a-f/dhclient-script b/apparmor.d/profiles-a-f/dhclient-script index b650498cfb..9d84a4065b 100644 --- a/apparmor.d/profiles-a-f/dhclient-script +++ b/apparmor.d/profiles-a-f/dhclient-script @@ -10,13 +10,19 @@ include @{exec_path} = @{bin}/dhclient-script profile dhclient-script @{exec_path} { include - include + include include capability net_admin, capability sys_admin, audit capability sys_module, + network inet dgram, + network inet stream, + network inet6 dgram, + network inet6 stream, + network netlink raw, + @{exec_path} mr, @{sh_path} mrix, @@ -36,22 +42,22 @@ profile dhclient-script @{exec_path} { @{bin}/ping rPx, @{bin}/printenv rix, @{bin}/readlink rix, - @{bin}/resolvconf rPx, + @{sbin}/resolvconf rPx, @{bin}/rm rix, @{bin}/run-parts rCx -> run-parts, @{bin}/sed rix, - @{bin}/sysctl rix, + @{sbin}/sysctl rCx -> sysctl, @{bin}/tr rix, @{bin}/xxd rix, + @{etc_rw}/resolv.conf rw, + @{etc_rw}/resolv.conf.dhclient-new.@{pid} rw, + @{etc_rw}/samba/dhcp.conf{,.new} rw, /etc/default/ddclient r, /etc/dhcp/{,**} r, /etc/fstab r, /etc/iproute2/rt_tables r, /etc/iproute2/rt_tables.d/{,*} r, - @{etc_rw}/resolv.conf rw, - @{etc_rw}/resolv.conf.dhclient-new.@{pid} rw, - @{etc_rw}/samba/dhcp.conf{,.new} rw, /var/lib/dhcp/dhclient.leases r, /var/lib/samba/dhcp.conf{,.new} rw, @@ -65,7 +71,16 @@ profile dhclient-script @{exec_path} { @{sys}/devices/virtual/dmi/id/board_vendor r, owner @{PROC}/@{pid}/loginuid r, - @{PROC}/sys/net/ipv6/conf/*/stable_secret w, + + profile sysctl { + include + + @{sbin}/sysctl mr, + + @{PROC}/sys/net/ipv6/conf/*/stable_secret w, + + include if exists + } profile run-parts { include diff --git a/apparmor.d/profiles-a-f/dino b/apparmor.d/profiles-a-f/dino index e2ee5e9b29..ae138a44f9 100644 --- a/apparmor.d/profiles-a-f/dino +++ b/apparmor.d/profiles-a-f/dino @@ -32,7 +32,7 @@ profile dino @{exec_path} flags=(attach_disconnected) { @{bin}/gpg{,2} rix, @{bin}/gpgconf rix, @{bin}/gpgsm rix, - @{lib}/gnupg/keyboxd rix, + @{lib}/{,gnupg/}keyboxd rix, owner @{HOME}/@{XDG_GPG_DIR}/ rw, owner @{HOME}/@{XDG_GPG_DIR}/** rwkl -> @{HOME}/@{XDG_GPG_DIR}/**, diff --git a/apparmor.d/profiles-a-f/discord b/apparmor.d/profiles-a-f/discord index 53038a6d75..d2e630e3fc 100644 --- a/apparmor.d/profiles-a-f/discord +++ b/apparmor.d/profiles-a-f/discord @@ -8,18 +8,18 @@ abi , include @{name} = discord +@{domain} = org.chromium.Chromium @{lib_dirs} = /usr/share/@{name} /opt/@{name} @{config_dirs} = @{user_config_dirs}/@{name} @{user_config_dirs}/discordptb @{cache_dirs} = @{user_cache_dirs}/@{name} @{exec_path} = @{bin}/discord{,-ptb} @{lib_dirs}/Discord{,PTB} -profile discord @{exec_path} { +profile discord @{exec_path} flags=(attach_disconnected) { include include - include - include - include + include include + include include include @@ -31,28 +31,30 @@ profile discord @{exec_path} { @{exec_path} mrix, @{sh_path} rix, - @{bin}/lsb_release rPx -> lsb_release, @{lib_dirs}/chrome-sandbox rix, - @{lib_dirs}/chrome_crashpad_handler rix, + @{bin}/lsb_release rPx, @{open_path} rPx -> child-open-strict, + /etc/ r, /etc/lsb-release r, owner @{user_videos_dirs}/{,**} rwl, owner @{user_pictures_dirs}/{,**} rwl, owner @{config_dirs}/@{version}/modules/** m, + owner @{user_config_dirs}/autostart/discord.desktop rw, owner "@{tmp}/Discord Crashes/" rw, - owner @{tmp}/.org.chromium.Chromium.@{rand6}/** rw, owner @{tmp}/discord.sock rw, owner @{tmp}/net-export/ rw, owner @{run}/user/@{uid}/discord-ipc-@{int} rw, - owner @{PROC}/@{pid}/task/@{tid}/comm r, + owner @{PROC}/@{pid}/mem r, + + deny ptrace read, include if exists } diff --git a/apparmor.d/profiles-a-f/dkms b/apparmor.d/profiles-a-f/dkms index 75487fbec2..ccd2c5956f 100644 --- a/apparmor.d/profiles-a-f/dkms +++ b/apparmor.d/profiles-a-f/dkms @@ -4,15 +4,22 @@ # Copyright (C) 2022 Jeroen Rijken # SPDX-License-Identifier: GPL-2.0-only +# TODO: Revisit this profile: all build tasks should take place in a dedicated profile +# @{lib}/modules/*/build/ Cx. +# /var/lib/dkms/**/build/ Cx, + +# TODO: Also test the future profile with the zfs dkms module + abi , include -@{exec_path} = @{bin}/dkms +@{exec_path} = @{sbin}/dkms profile dkms @{exec_path} flags=(attach_disconnected) { include include include + include capability dac_override, capability dac_read_search, @@ -20,31 +27,44 @@ profile dkms @{exec_path} flags=(attach_disconnected) { capability setgid, capability setuid, - deny unix (receive) type=stream, + ptrace read peer=@{p_systemd}, + + unix (receive) type=stream, @{exec_path} rm, @{sh_path} rix, @{coreutils_path} rix, + @{archive_path} rix, + @{python_path} rix, @{bin}/as rix, @{bin}/bc rix, @{bin}/clang-@{version} rix, + @{bin}/file rix, + @{bin}/g++ rix, @{bin}/gcc rix, @{bin}/getconf rix, + @{bin}/git rix, + @{bin}/hostname rix, @{bin}/kill rix, @{bin}/kmod rCx -> kmod, @{bin}/ld rix, @{bin}/ld.lld rix, @{bin}/llvm-objcopy rix, - @{bin}/lsb_release rPx -> lsb_release, + @{bin}/lsb_release rPx, @{bin}/make rix, + @{bin}/msgfmt rix, + @{bin}/msgmerge rix, + @{bin}/nm rix, @{bin}/objcopy rix, + @{bin}/objdump rix, @{bin}/pahole rix, + @{bin}/pkgconf rix, @{bin}/readelf rix, @{bin}/rpm rPUx, @{bin}/strip rix, - @{bin}/update-secureboot-policy rPUx, - @{bin}/zstd rix, + @{bin}/xgettext rix, + @{sbin}/update-secureboot-policy rPUx, @{lib}/gcc/@{multiarch}/@{version}/* rix, @{lib}/linux-kbuild-*/scripts/** rix, @@ -56,10 +76,10 @@ profile dkms @{exec_path} flags=(attach_disconnected) { @{lib}/modules/*/build/tools/** rix, @{lib}/os-release rix, - /var/lib/dkms/**/build/* rix, - /var/lib/dkms/vboxhost/*/build/** rw, + /var/lib/dkms/**/build/** rix, /var/lib/dkms/**/configure rix, /var/lib/dkms/**/dkms.postbuild rix, + /var/lib/dkms/vboxhost/*/build/** rw, /var/lib/shim-signed/mok/** r, @@ -95,18 +115,28 @@ profile dkms @{exec_path} flags=(attach_disconnected) { owner @{HOME}/ r, - owner @{tmp}/* rw, - owner @{tmp}/cc* rw, - owner @{tmp}/dkms.*/ rw, - owner @{tmp}/sh-thd.* rw, - owner @{tmp}/tmp.* rw, - - @{PROC}/cpuinfo r, + @{sys}/fs/cgroup/system.slice/cpu.max r, + @{sys}/fs/cgroup/system.slice/dkms.service/cpu.max r, + @{sys}/fs/cgroup/user.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/*.slice/cpu.max r, + + /tmp/@{word8} rw, + /tmp/@{word8}/{,*} rw, + /tmp/conftest-@{rand6}.* rw, + @{tmp}/GMfifo@{int} rw, + owner @{tmp}/cc@{rand6}* rw, + owner @{tmp}/tmp.@{rand10} rw, + audit owner @{tmp}/dkms.*/ rw, + audit owner @{tmp}/sh-thd.* rw, + + @{PROC}/@{pid}/cgroup r, + @{PROC}/@{pid}/mountinfo r, @{PROC}/sys/kernel/osrelease r, - @{PROC}/sys/vm/overcommit_memory r, owner @{PROC}/@{pid}/fd/ r, - /dev/pts/@{int} rw, + /dev/pts/@{u16} rw, profile kmod { include @@ -115,7 +145,7 @@ profile dkms @{exec_path} flags=(attach_disconnected) { @{lib}/modules/*/modules.* rw, /var/lib/dkms/**/module/*.ko* r, - owner /boot/System.map-* r, + owner @{efi}/System.map-* r, owner @{tmp}/tmp.@{rand10} r, diff --git a/apparmor.d/profiles-a-f/dkms-autoinstaller b/apparmor.d/profiles-a-f/dkms-autoinstaller index ffce309217..d499fefee3 100644 --- a/apparmor.d/profiles-a-f/dkms-autoinstaller +++ b/apparmor.d/profiles-a-f/dkms-autoinstaller @@ -15,13 +15,14 @@ profile dkms-autoinstaller @{exec_path} { @{exec_path} rm, @{sh_path} rix, - @{bin}/dkms rPx, @{bin}/echo rix, @{bin}/plymouth rix, @{bin}/readlink rix, @{bin}/run-parts rCx -> run-parts, @{bin}/systemctl rCx -> systemctl, @{bin}/tput rix, + @{bin}/uname rix, + @{sbin}/dkms rPx, # For shell pwd / r, @@ -41,6 +42,8 @@ profile dkms-autoinstaller @{exec_path} { include include + capability net_admin, + include if exists } diff --git a/apparmor.d/profiles-a-f/dlocate b/apparmor.d/profiles-a-f/dlocate index 9f78af639f..f7d1e915e2 100644 --- a/apparmor.d/profiles-a-f/dlocate +++ b/apparmor.d/profiles-a-f/dlocate @@ -55,7 +55,7 @@ profile dlocate @{exec_path} { @{bin}/md5sum mr, # For the md5 check - /boot/** r, + @{efi}/** r, /usr/** r, include if exists diff --git a/apparmor.d/profiles-a-f/dmeventd b/apparmor.d/profiles-a-f/dmeventd index 0484cf99d8..9845455081 100644 --- a/apparmor.d/profiles-a-f/dmeventd +++ b/apparmor.d/profiles-a-f/dmeventd @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/dmeventd +@{exec_path} = @{sbin}/dmeventd profile dmeventd @{exec_path} flags=(complain) { include diff --git a/apparmor.d/profiles-a-f/dmidecode b/apparmor.d/profiles-a-f/dmidecode index aba4555351..680d259922 100644 --- a/apparmor.d/profiles-a-f/dmidecode +++ b/apparmor.d/profiles-a-f/dmidecode @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/dmidecode +@{exec_path} = @{sbin}/dmidecode profile dmidecode @{exec_path} { include include diff --git a/apparmor.d/profiles-a-f/dmsetup b/apparmor.d/profiles-a-f/dmsetup index b5a1f3ab77..91da67bd89 100644 --- a/apparmor.d/profiles-a-f/dmsetup +++ b/apparmor.d/profiles-a-f/dmsetup @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/dmsetup +@{exec_path} = @{sbin}/dmsetup profile dmsetup @{exec_path} { include include @@ -18,6 +18,10 @@ profile dmsetup @{exec_path} { @{PROC}/devices r, + /tmp/tmp.@{rand10}/mkinitramfs_@{rand6}/cryptroot/crypttab w, # file_inherit + /var/tmp/mkinitramfs_@{rand6}/cryptroot/crypttab w, # file_inherit + + include if exists } diff --git a/apparmor.d/profiles-a-f/dnscrypt-proxy b/apparmor.d/profiles-a-f/dnscrypt-proxy index 5573aaf835..12323c9eb7 100644 --- a/apparmor.d/profiles-a-f/dnscrypt-proxy +++ b/apparmor.d/profiles-a-f/dnscrypt-proxy @@ -51,6 +51,8 @@ profile dnscrypt-proxy @{exec_path} { @{PROC}/sys/kernel/hostname r, @{PROC}/sys/net/core/somaxconn r, + owner @{PROC}/@{pid}/cgroup r, + owner @{PROC}/@{pid}/mountinfo r, include if exists } diff --git a/apparmor.d/profiles-a-f/dracut-install b/apparmor.d/profiles-a-f/dracut-install new file mode 100644 index 0000000000..7cf07e445e --- /dev/null +++ b/apparmor.d/profiles-a-f/dracut-install @@ -0,0 +1,66 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/dracut/dracut-install +profile dracut-install @{exec_path} { + include + include + include + + capability syslog, + + @{exec_path} mr, + + @{bin}/cp rix, + + /usr/share/btrfsprogs/dracut* r, + /usr/share/kbd/{,**} r, + + /etc/ r, + /etc/depmod.d/{,**} r, + /etc/hostname r, + /etc/hosts r, /etc/machine-id r, + /etc/modules-load.d/{,**} r, + /etc/sysctl.d/{,**} r, + /etc/systemd/journald.conf.d/{,**} r, + /etc/systemd/system.conf.d/{,**} r, + /etc/udev/rules.d/{,**} r, + /etc/udev/udev.conf.d/{,**} r, + /etc/vconsole.conf r, + + /etc/modprobe.d/{,**} r, + @{lib}/modprobe.d/{,**} r, + @{run}/modprobe.d/{,**} r, + + # Can copy any program to the initframs + @{bin}/* r, + @{lib}/ r, + @{sbin}/* r, + /{usr/,}{local/,}{s,}bin/ r, + /{usr/,}{local/,}lib{,32,64}/ r, + + / r, + + /var/tmp/dracut.@{rand6}@{c}/{,**} rwl, + + /var/tmp/mkinitramfs_@{rand6}/usr/lib/modules/*/ r, + /var/tmp/mkinitramfs_@{rand6}/usr/lib/modules/*/kernel/{,**/} rw, + /var/tmp/mkinitramfs_@{rand6}/usr/lib/modules/*/kernel/**/*.ko* rw, + /var/tmp/mkinitramfs_@{rand6}/usr/lib/modules/*/modules.* rw, + /var/tmp/mkinitramfs_@{rand6}/usr/lib/modules/*/updates/{,**} r, + + @{sys}/devices/{,**} r, + @{sys}/module/compression r, + + @{PROC}/cmdline r, + @{PROC}/modules r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-a-f/dropbox b/apparmor.d/profiles-a-f/dropbox index 065fe92c59..7cbb37bb36 100644 --- a/apparmor.d/profiles-a-f/dropbox +++ b/apparmor.d/profiles-a-f/dropbox @@ -15,14 +15,12 @@ include @{exec_path} = @{bin}/dropbox profile dropbox @{exec_path} { include - include - include - include include include include include include + include include @{exec_path} mr, @@ -32,14 +30,14 @@ profile dropbox @{exec_path} { @{bin}/readlink rix, @{bin}/dirname rix, @{bin}/uname rix, - @{bin}/ldconfig rix, + @{sbin}/ldconfig rix, @{bin}/python3.@{int} rix, @{lib}/llvm-[0-9]*/bin/clang rix, @{bin}/{,@{multiarch}-}gcc-[0-9]* rix, @{bin}/{,@{multiarch}-}objdump rix, @{open_path} rPx -> child-open-strict, - @{bin}/lsb_release rPx -> lsb_release, + @{bin}/lsb_release rPx, owner @{HOME}/ r, owner @{config_dirs}/ rw, @@ -61,7 +59,6 @@ profile dropbox @{exec_path} { # Dropbox first tries the /tmp/ dir, and if it's denied it uses the /var/tmp/ dir instead owner @{tmp}/dropbox-antifreeze-* rw, owner @{tmp}/#@{int} rw, - owner /var/tmp/etilqs_@{hex16} rw, @{run}/systemd/users/@{uid} r, diff --git a/apparmor.d/profiles-a-f/dumpcap b/apparmor.d/profiles-a-f/dumpcap index 634aebd02a..a1050aa947 100644 --- a/apparmor.d/profiles-a-f/dumpcap +++ b/apparmor.d/profiles-a-f/dumpcap @@ -10,16 +10,14 @@ include @{exec_path} = @{bin}/dumpcap profile dumpcap @{exec_path} { include + include + include include - include - include # To capture packekts capability net_raw, capability net_admin, - signal (receive) peer=wireshark, - network inet dgram, network inet6 dgram, network netlink raw, @@ -27,6 +25,8 @@ profile dumpcap @{exec_path} { network packet raw, network bluetooth raw, + signal (receive) peer=wireshark, + dbus (eavesdrop) bus=session, @{exec_path} mr, diff --git a/apparmor.d/profiles-a-f/dumpe2fs b/apparmor.d/profiles-a-f/dumpe2fs index eb3d4d61ab..15c3163a20 100644 --- a/apparmor.d/profiles-a-f/dumpe2fs +++ b/apparmor.d/profiles-a-f/dumpe2fs @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/dumpe2fs @{bin}/e2mmpstatus +@{exec_path} = @{sbin}/dumpe2fs @{sbin}/e2mmpstatus profile dumpe2fs @{exec_path} { include include @@ -21,7 +21,7 @@ profile dumpe2fs @{exec_path} { owner @{run}/blkid/blkid.tab{,-@{rand6}} rw, owner @{run}/blkid/blkid.tab.old rwl -> @{run}/blkid/blkid.tab, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-a-f/dunst b/apparmor.d/profiles-a-f/dunst index e73e3370c3..2a1b78eaee 100644 --- a/apparmor.d/profiles-a-f/dunst +++ b/apparmor.d/profiles-a-f/dunst @@ -10,9 +10,7 @@ include @{exec_path} = @{bin}/dunst profile dunst @{exec_path} { include - include - include - include + include @{exec_path} mr, diff --git a/apparmor.d/profiles-a-f/dunstify b/apparmor.d/profiles-a-f/dunstify index c62e87f660..cc1264b365 100644 --- a/apparmor.d/profiles-a-f/dunstify +++ b/apparmor.d/profiles-a-f/dunstify @@ -16,7 +16,7 @@ profile dunstify @{exec_path} { owner @{PROC}/@{pid}/cgroup r, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-a-f/e2fsck b/apparmor.d/profiles-a-f/e2fsck index be5d26b9fa..c120a3590a 100644 --- a/apparmor.d/profiles-a-f/e2fsck +++ b/apparmor.d/profiles-a-f/e2fsck @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/e2fsck @{bin}/fsck.ext2 @{bin}/fsck.ext3 @{bin}/fsck.ext4 +@{exec_path} = @{sbin}/e2fsck @{sbin}/fsck.ext2 @{sbin}/fsck.ext3 @{sbin}/fsck.ext4 profile e2fsck @{exec_path} { include include @@ -21,7 +21,7 @@ profile e2fsck @{exec_path} { # To check for badblocks @{sh_path} rix, - @{bin}/badblocks rPx, + @{sbin}/badblocks rPx, /usr/share/file/misc/magic.mgc r, diff --git a/apparmor.d/profiles-a-f/e2image b/apparmor.d/profiles-a-f/e2image index b099f1ccfe..c7238f262a 100644 --- a/apparmor.d/profiles-a-f/e2image +++ b/apparmor.d/profiles-a-f/e2image @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/e2image +@{exec_path} = @{sbin}/e2image profile e2image @{exec_path} { include include diff --git a/apparmor.d/groups/virt/cni-bridge b/apparmor.d/profiles-a-f/e2scrub similarity index 52% rename from apparmor.d/groups/virt/cni-bridge rename to apparmor.d/profiles-a-f/e2scrub index 1e27d04a3b..2e7e88487c 100644 --- a/apparmor.d/groups/virt/cni-bridge +++ b/apparmor.d/profiles-a-f/e2scrub @@ -1,18 +1,18 @@ # apparmor.d - Full set of apparmor profiles -# Copyright (C) 2021-2024 Alexandre Pujol +# Copyright (C) 2025 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only abi , include -@{exec_path} = @{lib}/cni/bridge /opt/cni/bin/bridge -profile cni-bridge @{exec_path} { +@{exec_path} = @{sbin}/e2scrub +profile e2scrub @{exec_path} flags=(complain) { include @{exec_path} mr, - include if exists + include if exists } # vim:syntax=apparmor diff --git a/apparmor.d/profiles-a-f/e2scrub_all b/apparmor.d/profiles-a-f/e2scrub_all index 25fab12c71..e5d13f1de9 100644 --- a/apparmor.d/profiles-a-f/e2scrub_all +++ b/apparmor.d/profiles-a-f/e2scrub_all @@ -6,19 +6,20 @@ abi , include -@{exec_path} = @{bin}/e2scrub_all +@{exec_path} = @{sbin}/e2scrub_all profile e2scrub_all @{exec_path} flags=(attach_disconnected) { include include include + capability setuid, capability sys_admin, capability sys_rawio, @{exec_path} mr, - @{sh_path} r, - @{bin}/readlink rix, + @{sh_path} mr, + @{bin}/readlink ix, /etc/e2scrub.conf r, diff --git a/apparmor.d/profiles-a-f/element-desktop b/apparmor.d/profiles-a-f/element-desktop index 05a900889e..c449be3fb2 100644 --- a/apparmor.d/profiles-a-f/element-desktop +++ b/apparmor.d/profiles-a-f/element-desktop @@ -7,6 +7,7 @@ abi , include @{name} = {E,e}lement +@{domain} = org.chromium.Chromium @{lib_dirs} = @{lib}/@{name} @{config_dirs} = @{user_config_dirs}/@{name} @{cache_dirs} = @{user_cache_dirs}/@{name} @@ -15,11 +16,10 @@ include profile element-desktop @{exec_path} flags=(attach_disconnected) { include include - include - include - include + include include include + include include network inet dgram, @@ -30,12 +30,8 @@ profile element-desktop @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, - @{sh_path} r, @{open_path} rPx -> child-open-strict, - #aa:stack X xdg-settings - @{bin}/xdg-settings rPx -> element-desktop//&xdg-settings, - /usr/share/webapps/element/{,**} r, /etc/webapps/element/{,**} r, diff --git a/apparmor.d/profiles-a-f/engrampa b/apparmor.d/profiles-a-f/engrampa index c302ff4004..0d28914452 100644 --- a/apparmor.d/profiles-a-f/engrampa +++ b/apparmor.d/profiles-a-f/engrampa @@ -10,15 +10,11 @@ include @{exec_path} = @{bin}/engrampa profile engrampa @{exec_path} { include - include - include - include - include - include + include include include include - include + include include include include @@ -85,7 +81,7 @@ profile engrampa @{exec_path} { owner @{PROC}/@{pid}/fd/ r, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, deny owner @{user_share_dirs}/gvfs-metadata/{,*} r, diff --git a/apparmor.d/profiles-a-f/etckeeper b/apparmor.d/profiles-a-f/etckeeper index 023d13b470..5c4108094c 100644 --- a/apparmor.d/profiles-a-f/etckeeper +++ b/apparmor.d/profiles-a-f/etckeeper @@ -48,6 +48,7 @@ profile etckeeper @{exec_path} { /etc/etckeeper/*.d/* rix, /etc/etckeeper/daily rix, + #aa:lint ignore=too-wide /etc/ rw, /etc/** rwkl -> /etc/**, diff --git a/apparmor.d/profiles-a-f/evince b/apparmor.d/profiles-a-f/evince index 5ae754138e..c659cedf6b 100644 --- a/apparmor.d/profiles-a-f/evince +++ b/apparmor.d/profiles-a-f/evince @@ -9,16 +9,13 @@ include @{exec_path} = @{bin}/evince @{lib}/evinced profile evince @{exec_path} { include - include - include - include - include - include - include + include include include - include + include + include include + include include include include @@ -30,7 +27,6 @@ profile evince @{exec_path} { #aa:dbus own bus=session name=org.gnome.evince - #aa:dbus talk bus=session name=org.gnome.SettingsDaemon.MediaKeys label=gsd-media-keys #aa:dbus talk bus=session name=org.gtk.vfs label="gvfsd{,-*}" @{exec_path} rix, @@ -41,16 +37,17 @@ profile evince @{exec_path} { /usr/share/djvu/{,**} r, /usr/share/evince/{,**} r, /usr/share/ghostscript/{,**} r, - /usr/share/poppler/{,**} r, /usr/share/thumbnailers/{,*} r, - owner @{user_share_dirs}/ r, owner @{user_share_dirs}/gvfs-metadata/{,*} r, owner @{user_config_dirs}/evince/{,*} rw, + owner @{tmp}/.goutputstream-@{rand6} rw, owner @{tmp}/*.pdf r, owner @{tmp}/evince-@{int}/{,**} rw, - owner @{tmp}/gtkprint* rw, + owner @{tmp}/gtkprint_@{rand6} rw, + owner @{tmp}/gtkprint@{rand6} rw, + owner @{tmp}/org.gnome.Evince-@{int}/{,**} rw, owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/mountinfo r, diff --git a/apparmor.d/profiles-a-f/evince-previewer b/apparmor.d/profiles-a-f/evince-previewer deleted file mode 100644 index 1597c35af3..0000000000 --- a/apparmor.d/profiles-a-f/evince-previewer +++ /dev/null @@ -1,23 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2023-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - -abi , - -include - -@{exec_path} = @{bin}/evince-previewer -profile evince-previewer @{exec_path} { - include - include - include - include - include - include - - @{exec_path} mr, - - include if exists -} - -# vim:syntax=apparmor diff --git a/apparmor.d/profiles-a-f/evince-thumbnailer b/apparmor.d/profiles-a-f/evince-thumbnailer index 95fdba512f..6fbabaf284 100644 --- a/apparmor.d/profiles-a-f/evince-thumbnailer +++ b/apparmor.d/profiles-a-f/evince-thumbnailer @@ -9,10 +9,10 @@ include @{exec_path} = @{bin}/evince-thumbnailer profile evince-thumbnailer @{exec_path} flags=(attach_disconnected) { include + include @{exec_path} mr, - /usr/share/mime/mime.cache r, /usr/share/poppler/{,**} r, owner @{tmp}/gnome-desktop-file-to-thumbnail.pdf r, diff --git a/apparmor.d/profiles-a-f/execute-dput b/apparmor.d/profiles-a-f/execute-dput index 7161c59007..d7a8886f99 100644 --- a/apparmor.d/profiles-a-f/execute-dput +++ b/apparmor.d/profiles-a-f/execute-dput @@ -8,7 +8,7 @@ abi , include @{exec_path} = @{bin}/dput /usr/share/dput/execute-dput -profile execute-dput @{exec_path} flags=(complain) { +profile execute-dput @{exec_path} { include include include diff --git a/apparmor.d/profiles-a-f/exim4 b/apparmor.d/profiles-a-f/exim4 index 9aaccaa16a..3af283014e 100644 --- a/apparmor.d/profiles-a-f/exim4 +++ b/apparmor.d/profiles-a-f/exim4 @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/exim4 +@{exec_path} = @{sbin}/exim4 profile exim4 @{exec_path} flags=(attach_disconnected) { include include diff --git a/apparmor.d/profiles-a-f/exo-helper b/apparmor.d/profiles-a-f/exo-helper index b9d7652eec..f2d544c823 100644 --- a/apparmor.d/profiles-a-f/exo-helper +++ b/apparmor.d/profiles-a-f/exo-helper @@ -3,6 +3,8 @@ # Copyright (C) 2021-2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only +# Generic profile for exo utility. It is an equivalent of child-open-any. + abi , include @@ -10,14 +12,9 @@ include @{exec_path} = @{lib}/@{multiarch}/xfce[0-9]/exo-[0-9]/exo-helper-[0-9] profile exo-helper @{exec_path} { include - include include - - # These are needed when there's no default application set in the ~/.config/xfce4/helpers.rc - include - include - include - include + include + include @{exec_path} mr, @@ -26,12 +23,15 @@ profile exo-helper @{exec_path} { /usr/share/xfce4/helpers/ r, /usr/share/xfce4/helpers/*.desktop r, /usr/local/share/ r, + + /etc/xdg/{,xdg-*/}xfce4/helpers.rc r, + + /etc/fstab r, + owner @{user_share_dirs}/ r, owner @{user_share_dirs}/xfce4/ r, owner @{user_share_dirs}/xfce4/helpers/ r, - /etc/xdg/{,xdg-*/}xfce4/helpers.rc r, - owner @{user_config_dirs}/xfce4/helpers.rc rw, owner @{user_config_dirs}/xfce4/helpers.rc.@{pid}.tmp rw, owner @{user_share_dirs}/xfce4/helpers/*.desktop rw, @@ -39,17 +39,12 @@ profile exo-helper @{exec_path} { owner @{user_config_dirs}/mimeapps.list{,.@{rand6}} rw, - # Some missing icons - /usr/share/**.png r, - owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/mounts r, - /etc/fstab r, - # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-a-f/exo-open b/apparmor.d/profiles-a-f/exo-open index 2c5e86e30a..88c80ed2c9 100644 --- a/apparmor.d/profiles-a-f/exo-open +++ b/apparmor.d/profiles-a-f/exo-open @@ -10,11 +10,8 @@ include @{exec_path} = @{bin}/exo-open profile exo-open @{exec_path} { include - include - include - include - include - include + include + include include @{exec_path} mr, diff --git a/apparmor.d/profiles-a-f/f3fix b/apparmor.d/profiles-a-f/f3fix index 4d743fbb76..a2cfe43c55 100644 --- a/apparmor.d/profiles-a-f/f3fix +++ b/apparmor.d/profiles-a-f/f3fix @@ -21,7 +21,7 @@ profile f3fix @{exec_path} { @{sh_path} rix, - @{bin}/dmidecode rPx, + @{sbin}/dmidecode rPx, @{bin}/udevadm rCx -> udevadm, @{PROC}/swaps r, diff --git a/apparmor.d/profiles-a-f/fail2ban-server b/apparmor.d/profiles-a-f/fail2ban-server index 2506b1db9d..4be2ebe206 100644 --- a/apparmor.d/profiles-a-f/fail2ban-server +++ b/apparmor.d/profiles-a-f/fail2ban-server @@ -19,9 +19,9 @@ profile fail2ban-server @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, - @{sh_path} rix, - @{bin}/xtables-nft-multi rix, - @{bin}/iptables rix, + @{sh_path} rix, + @{sbin}/xtables-{nft,legacy}-multi rix, + @{bin}/iptables rix, @{bin}/ r, @{python_path} r, diff --git a/apparmor.d/profiles-a-f/fatlabel b/apparmor.d/profiles-a-f/fatlabel index c7ac0d3992..c8bdedaa36 100644 --- a/apparmor.d/profiles-a-f/fatlabel +++ b/apparmor.d/profiles-a-f/fatlabel @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/fatlabel +@{exec_path} = @{sbin}/fatlabel profile fatlabel @{exec_path} { include include diff --git a/apparmor.d/profiles-a-f/fatresize b/apparmor.d/profiles-a-f/fatresize index e299a109bc..6f4c86647f 100644 --- a/apparmor.d/profiles-a-f/fatresize +++ b/apparmor.d/profiles-a-f/fatresize @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/fatresize +@{exec_path} = @{sbin}/fatresize profile fatresize @{exec_path} { include include @@ -21,7 +21,7 @@ profile fatresize @{exec_path} { @{sh_path} rix, - @{bin}/dmidecode rPx, + @{sbin}/dmidecode rPx, @{bin}/udevadm rCx -> udevadm, @{PROC}/swaps r, diff --git a/apparmor.d/profiles-a-f/fd b/apparmor.d/profiles-a-f/fd new file mode 100644 index 0000000000..4a64f5a033 --- /dev/null +++ b/apparmor.d/profiles-a-f/fd @@ -0,0 +1,26 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 valoq +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/fd +profile fd @{exec_path} { + include + include + + capability dac_override, + capability dac_read_search, + + @{exec_path} mr, + + #aa:lint ignore=too-wide + ## Allow reading the entire filesystem to search for filenames + /{,**} r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-a-f/fdisk b/apparmor.d/profiles-a-f/fdisk index e6a7aeebf8..bab1525748 100644 --- a/apparmor.d/profiles-a-f/fdisk +++ b/apparmor.d/profiles-a-f/fdisk @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/fdisk +@{exec_path} = @{sbin}/fdisk profile fdisk @{exec_path} { include include diff --git a/apparmor.d/profiles-a-f/ffmpeg b/apparmor.d/profiles-a-f/ffmpeg index 5196881a7f..8ab42e392a 100644 --- a/apparmor.d/profiles-a-f/ffmpeg +++ b/apparmor.d/profiles-a-f/ffmpeg @@ -12,7 +12,7 @@ profile ffmpeg @{exec_path} { include include include - include + include include include include @@ -28,16 +28,14 @@ profile ffmpeg @{exec_path} { /var/lib/dbus/machine-id r, owner @{HOME}/.Xauthority r, + owner @{HOME}/.spotdl/** rw, # For spotdl owner @{user_music_dirs}/** rw, owner @{user_videos_dirs}/** rw, - owner @{tmp}/*.{png,jpg} rw, # To generate thumbnails in some apps + owner @{tmp}/*.@{image_ext} rw, # To generate thumbnails in some apps owner @{tmp}/vidcutter/** rw, # TMP files for apps using ffmpeg - @{sys}/devices/system/node/ r, - @{sys}/devices/system/node/node@{int}/meminfo r, - include if exists } diff --git a/apparmor.d/profiles-a-f/ffplay b/apparmor.d/profiles-a-f/ffplay index 6d3e1972d4..4152ed49aa 100644 --- a/apparmor.d/profiles-a-f/ffplay +++ b/apparmor.d/profiles-a-f/ffplay @@ -11,10 +11,9 @@ include profile ffplay @{exec_path} { include include - include + include include include - include network inet stream, network inet6 stream, @@ -30,7 +29,7 @@ profile ffplay @{exec_path} { owner @{user_videos_dirs}/** rw, @{sys}/devices/system/node/ r, - @{sys}/devices/system/node/node[0-9]/meminfo r, + @{sys}/devices/system/node/node@{int}/meminfo r, include if exists } diff --git a/apparmor.d/profiles-a-f/file-roller b/apparmor.d/profiles-a-f/file-roller index b8eedb2635..442f00ab9f 100644 --- a/apparmor.d/profiles-a-f/file-roller +++ b/apparmor.d/profiles-a-f/file-roller @@ -7,12 +7,12 @@ abi , include @{exec_path} = @{bin}/file-roller -profile file-roller @{exec_path} { +profile file-roller @{exec_path} flags=(attach_disconnected) { include - include - include + include include include + include include #aa:dbus own bus=session name=org.gnome.ArchiveManager1 @@ -20,35 +20,26 @@ profile file-roller @{exec_path} { @{exec_path} mr, - @{open_path} rPx -> child-open-help, + @{open_path} Px -> child-open-help, + @{bin}/dpkg-deb Px, @{bin}/mv rix, @{bin}/rm rix, # Archivers - @{bin}/7z rix, - @{bin}/7zz rix, - @{bin}/ar rix, - @{bin}/bzip2 rix, - @{bin}/cpio rix, - @{bin}/gzip rix, - @{bin}/tar rix, - @{bin}/unrar-nonfree rix, - @{bin}/unzip rix, - @{bin}/xz rix, - @{bin}/zip rix, - @{bin}/zstd rix, - @{lib}/p7zip/7z rix, + @{archive_path} rix, + owner /var/cache/fontconfig/ w, + + #aa:lint ignore=too-wide # Full access to user's data - @{MOUNTS}/** rw, - owner @{HOME}/** rw, + @{MOUNTS}/** rwl, + owner @{HOME}/** rwl, owner @{tmp}/** rw, @{run}/mount/utab r, owner @{PROC}/@{pid}/mountinfo r, - owner @{PROC}/@{pid}/stat r, include if exists } diff --git a/apparmor.d/profiles-a-f/filezilla b/apparmor.d/profiles-a-f/filezilla index 4463ac5817..27fed1a5b7 100644 --- a/apparmor.d/profiles-a-f/filezilla +++ b/apparmor.d/profiles-a-f/filezilla @@ -10,14 +10,13 @@ include @{exec_path} = @{bin}/filezilla profile filezilla @{exec_path} { include - include - include - include include include include include include + include + include include include @@ -38,7 +37,7 @@ profile filezilla @{exec_path} { @{bin}/fzsftp rPx, # When using SFTP protocol @{bin}/fzputtygen rPUx, - @{bin}/lsb_release rPx -> lsb_release, + @{bin}/lsb_release rPx, /usr/share/filezilla/{,**} r, @@ -69,7 +68,7 @@ profile filezilla @{exec_path} { owner @{PROC}/@{pid}/mounts r, /dev/tty rw, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-a-f/finalrd b/apparmor.d/profiles-a-f/finalrd index 7578b505dc..e9960b86ae 100644 --- a/apparmor.d/profiles-a-f/finalrd +++ b/apparmor.d/profiles-a-f/finalrd @@ -10,6 +10,7 @@ include @{exec_path} = @{bin}/finalrd profile finalrd @{exec_path} { include + include capability dac_read_search, capability sys_admin, @@ -20,30 +21,30 @@ profile finalrd @{exec_path} { @{exec_path} mr, @{sh_path} rix, - @{bin}/cp rix, - @{bin}/dirname rix, - @{bin}/env rix, - @{bin}/find rix, - @{bin}/grep rix, - @{bin}/ldconfig{,.real} rix, - @{bin}/ln rix, - @{bin}/mkdir rix, - @{bin}/mount rix, - @{bin}/readlink rix, - @{bin}/realpath rix, - @{bin}/rm rix, - @{bin}/run-parts rix, - @{bin}/sed rix, - @{bin}/touch rix, - - @{bin}/ldd rCx -> ldd, - @{bin}/systemd-tmpfiles rPx, - @{lib}/@{multiarch}/ld-linux-*so* rCx -> ldd, - @{lib}/systemd/systemd-shutdown rPx, - /usr/share/finalrd/*.finalrd rix, + @{bin}/cp ix, + @{bin}/dirname ix, + @{bin}/env ix, + @{bin}/find ix, + @{bin}/{,e}grep ix, + @{bin}/ln ix, + @{bin}/mkdir ix, + @{bin}/mount ix, + @{bin}/readlink ix, + @{bin}/realpath ix, + @{bin}/rm ix, + @{bin}/run-parts ix, + @{bin}/sed ix, + @{bin}/touch ix, + @{sbin}/ldconfig{,.real} ix, + + @{ldd_path} Cx -> ldd, + @{bin}/systemd-tmpfiles Px, + @{lib}/systemd/systemd-shutdown Px, + /usr/share/finalrd/*.finalrd ix, - @{lib}/{,*} r, @{bin}/{,*} r, + @{lib}/{,*} r, + @{sbin}/{,*} r, /usr/share/finalrd/{,**} r, /usr/share/initramfs-tools/hook-functions r, @@ -54,20 +55,23 @@ profile finalrd @{exec_path} { / r, - @{run}/initramfs/{,**} rw, @{run}/ r, - @{run}/mount/ r, @{run}/finalrd-libs.conf rw, + @{run}/initramfs/{,**} rw, + @{run}/mount/ r, + @{run}/mount/utab r, @{PROC}/@{pid}/mountinfo r, profile ldd { include + include include - @{bin}/ldd mr, - @{lib}/@{multiarch}/ld-linux-*so* mrix, - @{lib}/ld-linux.so* mr, + @{ldd_path} mrix, + + @{bin}/* mr, + @{sbin}/* mr, include if exists } diff --git a/apparmor.d/profiles-a-f/firecfg b/apparmor.d/profiles-a-f/firecfg index a54d1c9ac7..18c07b5685 100644 --- a/apparmor.d/profiles-a-f/firecfg +++ b/apparmor.d/profiles-a-f/firecfg @@ -19,7 +19,7 @@ profile firecfg @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, @{sh_path} rix, - @{bin}/apparmor_parser rPx, + @{sbin}/apparmor_parser rPx, @{etc_ro}/login.defs r, @@ -39,8 +39,8 @@ profile firecfg @{exec_path} flags=(attach_disconnected) { @{user_config_dirs}/firejail/{,*} r, /dev/tty rw, - /dev/tty@{int} rw, - owner /dev/pts/@{int} rw, + /dev/tty@{u8} rw, + owner /dev/pts/@{u16} rw, include if exists diff --git a/apparmor.d/profiles-a-f/foliate b/apparmor.d/profiles-a-f/foliate index f6380d1254..1fe00d7379 100644 --- a/apparmor.d/profiles-a-f/foliate +++ b/apparmor.d/profiles-a-f/foliate @@ -9,7 +9,7 @@ include @{exec_path} = @{bin}/foliate profile foliate @{exec_path} flags=(attach_disconnected) { include - include + include include include include @@ -29,10 +29,16 @@ profile foliate @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, - @{bin}/bwrap rix, - @{bin}/gjs-console rix, - @{bin}/speech-dispatcher rPx, - @{open_path} rPx -> child-open-help, + @{bin}/bwrap rix, + @{bin}/gjs-console rix, + @{bin}/speech-dispatcher Px, + @{open_path} Px -> child-open-help, + + #aa:only apparmor<5.0 + @{lib}/glycin-loaders/@{d}+/glycin-* Cx -> foliate//&glycin//loaders, + + #aa:only apparmor>=5.0 + @{lib}/glycin-loaders/@{d}+/glycin-* Px -> foliate//&:glycin:loaders, /usr/share/com.github.johnfactotum.Foliate/{,**} r, @@ -42,7 +48,6 @@ profile foliate @{exec_path} flags=(attach_disconnected) { owner @{user_cache_dirs}/com.github.johnfactotum.Foliate/{,**} rwlk, owner @{user_share_dirs}/com.github.johnfactotum.Foliate/{,**} rwlk, - @{sys}/devices/virtual/dmi/id/chassis_type r, @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/app-dbus*org.gnome.Nautilus.slice/dbus*org.gnome.Nautilus@*.service/memory.* r, @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/app-gnome-com.github.johnfactotum.Foliate-@{int}.scope/memory.* r, @@ -51,7 +56,6 @@ profile foliate @{exec_path} flags=(attach_disconnected) { owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/mounts r, owner @{PROC}/@{pid}/smaps r, - owner @{PROC}/@{pid}/stat r, owner @{PROC}/@{pid}/statm r, owner @{PROC}/@{pid}/task/@{tid}/stat r, diff --git a/apparmor.d/profiles-a-f/fprintd b/apparmor.d/profiles-a-f/fprintd index 182d9013d4..212ab70874 100644 --- a/apparmor.d/profiles-a-f/fprintd +++ b/apparmor.d/profiles-a-f/fprintd @@ -10,11 +10,12 @@ include profile fprintd @{exec_path} flags=(attach_disconnected) { include include - include + include include include capability net_admin, + capability sys_admin, capability sys_nice, network netlink raw, @@ -25,15 +26,17 @@ profile fprintd @{exec_path} flags=(attach_disconnected) { /etc/fprintd.conf r, + / r, + /var/lib/fprint/{,**} rw, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, @{run}/udev/data/c@{dynamic}:@{int} r, # For dynamic assignment range 234 to 254, 384 to 511 @{sys}/class/hidraw/ r, - @{sys}/devices/@{pci}/hidraw/hidraw@{int}/uevent r, - @{sys}/devices/virtual/**/hidraw/hidraw@{int}/uevent r, + @{sys}/class/spidev/ r, + @{sys}/devices/**/uevent r, include if exists } diff --git a/apparmor.d/profiles-a-f/fractal b/apparmor.d/profiles-a-f/fractal index c6746843d3..8c54b0deb0 100644 --- a/apparmor.d/profiles-a-f/fractal +++ b/apparmor.d/profiles-a-f/fractal @@ -12,8 +12,12 @@ profile fractal @{exec_path} flags=(attach_disconnected) { include include include + include include + include + include include + include network inet dgram, network inet stream, @@ -21,48 +25,26 @@ profile fractal @{exec_path} flags=(attach_disconnected) { network inet6 stream, network netlink raw, - signal send set=kill peer=fractal//bwrap, + #aa:dbus own bus=session name=org.gnome.Fractal @{exec_path} mr, @{open_path} rPx -> child-open-help, - @{bin}/bwrap rCx -> bwrap, - /usr/share/glycin-loaders/{,**} r, /usr/share/xml/iso-codes/{,**} r, owner @{tmp}/.@{rand6} rw, owner @{tmp}/.goutputstream-@{rand6} rw, owner @{tmp}/@{rand6} rw, - owner @{tmp}/etilqs_@{hex16} rw, owner @{run}/user/@{uid}/fractal/{,**} rw, @{PROC}/sys/net/ipv6/conf/all/disable_ipv6 r, owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/mountinfo r, - owner @{PROC}/@{pid}/stat r, /dev/ r, - profile bwrap flags=(attach_disconnected) { - include - include - - signal receive set=kill peer=fractal, - - @{bin}/bwrap mr, - @{lib}/glycin-loaders/*/glycin-* rix, - - owner @{run}/user/@{uid}/fractal/.tmp@{rand6} r, - - owner @{PROC}/@{pid}/fd/ r, - - deny @{user_share_dirs}/gvfs-metadata/* r, - - include if exists - } - include if exists } diff --git a/apparmor.d/profiles-a-f/freetube b/apparmor.d/profiles-a-f/freetube index 63bb82f112..81bc40a6ea 100644 --- a/apparmor.d/profiles-a-f/freetube +++ b/apparmor.d/profiles-a-f/freetube @@ -8,6 +8,7 @@ abi , include @{name} = {F,f}ree{T,t}ube{,-vue} +@{domain} = org.chromium.Chromium @{lib_dirs} = @{lib}/@{name} /opt/@{name} @{config_dirs} = @{user_config_dirs}/@{name} @{cache_dirs} = @{user_cache_dirs}/@{name} @@ -16,11 +17,11 @@ include profile freetube @{exec_path} flags=(attach_disconnected) { include include - include - include - include include include + include + include + include include include @@ -31,16 +32,12 @@ profile freetube @{exec_path} flags=(attach_disconnected) { network netlink raw, #aa:dbus own bus=session name=org.mpris.MediaPlayer2.freetube path=/org/mpris/MediaPlayer2 + #aa:dbus talk bus=session name=org.freedesktop.PowerManagement label=kde-powerdevil @{exec_path} mrix, @{open_path} rPx -> child-open-strict, - #aa:stack X xdg-settings - @{bin}/xdg-settings rPx -> freetube//&xdg-settings, - - deny @{sys}/devices/@{pci}/usb@{int}/** r, - include if exists } diff --git a/apparmor.d/profiles-a-f/fritzing b/apparmor.d/profiles-a-f/fritzing index 18b990bbc6..144ee03af1 100644 --- a/apparmor.d/profiles-a-f/fritzing +++ b/apparmor.d/profiles-a-f/fritzing @@ -10,15 +10,10 @@ include @{exec_path} = @{bin}/fritzing{,.real} profile fritzing @{exec_path} { include - include - include - include + include include - include + include include - include - include - include include network inet dgram, @@ -30,26 +25,22 @@ profile fritzing @{exec_path} { @{exec_path} mrix, - owner @{user_config_dirs}/Fritzing/ rw, - owner @{user_config_dirs}/Fritzing/** rwkl -> @{user_config_dirs}/Fritzing/**, - - owner @{HOME}/@{XDG_DOCUMENTS_DIR}/Fritzing/ rw, - owner @{HOME}/@{XDG_DOCUMENTS_DIR}/Fritzing/** rw, - /usr/share/fritzing/{,**} r, - /usr/share/hwdata/pnp.ids r, + /etc/debian_version r, + /etc/fstab r, - owner @{PROC}/@{pid}/cmdline r, - owner @{PROC}/@{pid}/mountinfo r, - owner @{PROC}/@{pid}/mounts r, + owner @{user_config_dirs}/Fritzing/ rw, + owner @{user_config_dirs}/Fritzing/** rwkl -> @{user_config_dirs}/Fritzing/**, - /etc/fstab r, + owner @{user_documents_dirs}/Fritzing/ rw, + owner @{user_documents_dirs}/Fritzing/** rw, - /var/lib/dbus/machine-id r, - /etc/machine-id r, + owner @{run}/lock/LCK..ttyACM[0-9]* rwk, - /etc/debian_version r, + @{run}/udev/data/c4:@{int} r, # for /dev/tty[0-9]* + @{run}/udev/data/c5:@{int} r, # for /dev/tty, /dev/console, /dev/ptmx + @{run}/udev/data/c166:@{int} r, # for /dev/ttyACM[0-9]* @{sys}/bus/ r, @{sys}/class/ r, @@ -57,15 +48,13 @@ profile fritzing @{exec_path} { @{sys}/devices/**/tty*/uevent r, @{sys}/devices/**/tty/**/uevent r, - @{run}/udev/data/c4:@{int} r, # for /dev/tty[0-9]* - @{run}/udev/data/c5:@{int} r, # for /dev/tty, /dev/console, /dev/ptmx - @{run}/udev/data/c166:@{int} r, # for /dev/ttyACM[0-9]* + owner @{PROC}/@{pid}/cmdline r, + owner @{PROC}/@{pid}/mountinfo r, + owner @{PROC}/@{pid}/mounts r, /dev/ttyS@{int} rw, /dev/ttyACM@{int} rw, - owner @{run}/lock/LCK..ttyACM[0-9]* rwk, - include if exists } diff --git a/apparmor.d/profiles-a-f/frontend b/apparmor.d/profiles-a-f/frontend deleted file mode 100644 index 3d7ee07f88..0000000000 --- a/apparmor.d/profiles-a-f/frontend +++ /dev/null @@ -1,133 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2019-2021 Mikhail Morfikov -# Copyright (C) 2022-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - -abi , - -include - -@{exec_path} = /usr/share/debconf/frontend -profile frontend @{exec_path} flags=(complain) { - include - include - include - include - include - include - include - include - - capability dac_read_search, - - @{exec_path} r, - @{bin}/perl r, - - @{sh_path} rix, - @{bin}/hostname rix, - @{bin}/locale rix, - @{bin}/lsb_release rPx -> lsb_release, - @{bin}/stty rix, - @{bin}/update-secureboot-policy rPx, - - # debconf apps - @{bin}/adequate rPx, - @{bin}/aspell-autobuildhash rPx, - @{bin}/debconf-apt-progress rPx, - @{bin}/linux-check-removal rPx, - @{bin}/pam-auth-update rPx, - @{bin}/ucf rPx, - @{bin}/whiptail rPx, - @{lib}/tasksel/tasksel-debconf rPx -> tasksel, - /usr/share/debian-security-support/check-support-status.hook rPx, - - # Grub - @{lib}/grub/grub-multi-install rPx, - /usr/share/grub/grub-check-signatures rPx, - - # Run the package maintainer's scripts - # What to do with it? Maintainer scripts can use lots of tools. (#FIXME#) - #/var/lib/dpkg/info/*.{config,templates} rPUx, - #/var/lib/dpkg/info/*.{preinst,postinst} rPUx, - #/var/lib/dpkg/info/*.{prerm,postrm} rPUx, - /var/lib/dpkg/info/*.control r, - #/var/lib/dpkg/tmp.ci/{config,templates} rPUx, - #/var/lib/dpkg/tmp.ci/{preinst,postinst} rPUx, - #/var/lib/dpkg/tmp.ci/{prerm,postrm} rPUx, - /var/lib/dpkg/tmp.ci/control r, - /var/lib/dpkg/info/*.{config,templates} rCx -> scripts, - /var/lib/dpkg/info/*.{preinst,postinst} rCx -> scripts, - /var/lib/dpkg/info/*.{prerm,postrm} rCx -> scripts, - /var/lib/dpkg/tmp.ci/{config,templates} rCx -> scripts, - /var/lib/dpkg/tmp.ci/{preinst,postinst} rCx -> scripts, - /var/lib/dpkg/tmp.ci/{prerm,postrm} rCx -> scripts, - - # DKMS scipts - # What to do with it? (#FIXME#) - @{lib}/dkms/common.postinst rPUx, - @{lib}/dkms/dkms-* rPUx, - @{lib}/dkms/dkms_* rPUx, - - /usr/share/debconf/{,**} r, - - /etc/debconf.conf r, - /etc/inputrc r, - /etc/shadow r, - - owner /var/cache/debconf/* rwk, - - owner @{tmp}/file* w, - owner @{tmp}/tmp.@{rand10} rw, - owner @{tmp}/updateppds.@{rand6} rw, - - @{HOME}/.Xauthority r, - - @{run}/user/@{uid}/pk-debconf-socket rw, - - owner @{PROC}/@{pid}/mounts r, - - profile scripts flags=(complain) { - include - include - - capability dac_read_search, - - /var/lib/dpkg/info/*.config r, - /var/lib/dpkg/info/*.{preinst,postinst} r, - /var/lib/dpkg/info/*.{prerm,postrm} r, - /var/lib/dpkg/tmp.ci/config r, - /var/lib/dpkg/tmp.ci/{preinst,postinst} r, - /var/lib/dpkg/tmp.ci/{prerm,postrm} r, - - / r, - - @{bin}/ r, - @{bin}/* rPUx, - - @{lib}/ r, - @{lib}/** rPUx, - - /usr/share/ r, - /usr/share/** rPUx, - - /etc/init.d/ r, - /etc/init.d/* rPUx, - - /etc/ r, - /etc/** rw, - /var/ r, - /var/** rw, - @{sys}/ r, - @{sys}/**/ r, - @{run}/ r, - @{run}/** rw, - /tmp/ r, - owner @{tmp}/** rw, - - include if exists - } - - include if exists -} - -# vim:syntax=apparmor diff --git a/apparmor.d/profiles-a-f/fuse-overlayfs b/apparmor.d/profiles-a-f/fuse-overlayfs index da61184a30..fca8e28ae7 100644 --- a/apparmor.d/profiles-a-f/fuse-overlayfs +++ b/apparmor.d/profiles-a-f/fuse-overlayfs @@ -7,18 +7,30 @@ abi , include @{exec_path} = @{bin}/fuse-overlayfs -profile fuse-overlayfs @{exec_path} { +profile fuse-overlayfs @{exec_path} flags=(attach_disconnected) { include - capability sys_admin, + capability chown, capability dac_override, capability dac_read_search, - capability chown, + capability fowner, + capability setfcap, + capability setuid, + capability sys_admin, + + unix (send receive) type=stream peer=(label=fusermount), + + mount fstype=fuse.overlayfs options=(rw,nodev,noatime) fuse-overlayfs -> @{user_share_dirs}/containers/storage/overlay/**/merged/, + mount fstype=fuse.fuse-overlayfs options=(rw noatime nodev nosuid) fuse-overlayfs -> @{HOME}/**/, @{exec_path} mr, - mount fstype=fuse.* options=(rw,nodev,noatime) @{user_share_dirs}/containers/storage/overlay/**/merged/ -> **, + @{bin}/mount rix, + @{bin}/umount rix, + @{bin}/fusermount{,3} Px, + owner @{HOME}/{,**} r, + owner @{HOME}/**/ rw, owner @{user_share_dirs}/containers/storage/overlay/{,**} rwl, @{PROC}/sys/kernel/overflowgid r, diff --git a/apparmor.d/profiles-a-f/fusermount b/apparmor.d/profiles-a-f/fusermount index 3df041e643..8ec87e09d2 100644 --- a/apparmor.d/profiles-a-f/fusermount +++ b/apparmor.d/profiles-a-f/fusermount @@ -8,28 +8,27 @@ abi , include @{exec_path} = @{bin}/fusermount{,3} -profile fusermount @{exec_path} { +profile fusermount @{exec_path} flags=(attach_disconnected) { include include + capability setuid, + # Be able to mount ISO images - mount fstype={fuse,fuse.*} -> @{HOME}/*/, - mount fstype={fuse,fuse.*} -> @{HOME}/*/*/, - mount fstype={fuse,fuse.*} -> @{user_cache_dirs}/**/, - mount fstype={fuse,fuse.*} -> @{MOUNTS}/*/, - mount fstype={fuse,fuse.*} -> @{MOUNTS}/*/*/, + mount fstype={fuse,fuse.*} -> @{HOME}/**/, + mount fstype={fuse,fuse.*} -> @{MOUNTS}/**/, mount fstype={fuse,fuse.*} -> @{run}/user/@{uid}/*/, mount fstype={fuse,fuse.*} -> /var/tmp/flatpak-cache-*/*/, mount fstype={fuse,fuse.*} -> /tmp/.mount_*@{rand6}/, - umount @{HOME}/*/, - umount @{HOME}/*/*/, - umount @{user_cache_dirs}/**/, - umount @{MOUNTS}/*/, - umount @{MOUNTS}/*/*/, + umount @{HOME}/**/, + umount @{MOUNTS}/**/, umount /tmp/.mount_*/, umount @{run}/user/@{uid}/*/, umount /var/tmp/flatpak-cache-*/*/, + umount /tmp/fsa/*/, # fsarchiver + + unix (send receive) type=stream peer=(label=fuse-overlayfs), @{exec_path} mr, @@ -38,15 +37,23 @@ profile fusermount @{exec_path} { /var/tmp/flatpak-cache-*/*/ r, # Where to mount ISO files - owner @{HOME}/*/ rw, - owner @{HOME}/*/*/ rw, - - owner @{user_cache_dirs}/**/ rw, + owner @{HOME}/**/ rw, + owner @{MOUNTS}/**/ rw, /tmp/.mount_*@{rand6}/ r, @{run}/user/@{uid}/doc/ r, + #aa:only test + mount /tmp/tmp@{word8}/, + mount fstype=(fuse fuse.*) /tmp/autopkgtest.*/** -> /tmp/autopkgtest.*/**, + mount fstype=fuse options=(ro nodev nosuid) borgfs -> /tmp/pytest-of-ubuntu/**, + mount fstype=fuse options=(ro nodev nosuid) borgfs -> /tmp/tmp@{word8}/, + umount /tmp/tmp@{word8}/, + umount /tmp/autopkgtest.*/**, + /tmp/tmp@{word8}/ rw, + /tmp/tmp@{word8}/mountpoint/ rw, + include if exists } diff --git a/apparmor.d/profiles-a-f/fwupd b/apparmor.d/profiles-a-f/fwupd index 75d5197aed..7f8ea87bc6 100644 --- a/apparmor.d/profiles-a-f/fwupd +++ b/apparmor.d/profiles-a-f/fwupd @@ -8,18 +8,20 @@ abi , include @{exec_path} = @{lib}/{,fwupd/}fwupd -profile fwupd @{exec_path} flags=(attach_disconnected,complain) { +profile fwupd @{exec_path} flags=(attach_disconnected) { include + include include - include - include - include - include - include + include include include include + include + include include + include + include + include capability dac_override, capability dac_read_search, @@ -38,7 +40,20 @@ profile fwupd @{exec_path} flags=(attach_disconnected,complain) { network netlink raw, #aa:dbus own bus=system name=org.freedesktop.fwupd path=/ + #aa:dbus talk bus=system name=org.bluez.GattCharacteristic1 label=bluetoothd + #aa:dbus talk bus=system name=org.freedesktop.Passim path=/ label=passimd #aa:dbus talk bus=system name=org.freedesktop.UDisks2 label=udisksd + #aa:dbus talk bus=system name=org.freedesktop.UPower label=upowerd + + dbus receive bus=system path=/ + interface=org.freedesktop.DBus.ObjectManager + member=InterfacesAdded + peer=(name=@{busname}, label=bluetoothd), + + dbus receive bus=system path=/org/bluez/hci0/dev_* + interface=org.bluez.Device1 + member=Disconnected + peer=(name=@{busname}, label=bluetoothd), @{exec_path} mr, @@ -49,8 +64,10 @@ profile fwupd @{exec_path} flags=(attach_disconnected,complain) { @{bin}/gpgsm rCx -> gpg, /usr/share/fwupd/{,**} r, + /usr/share/gvfs/remote-volume-monitors/{,**} r, /usr/share/hwdata/* r, - /usr/share/mime/mime.cache r, + /usr/share/libdrm/*.ids r, + /usr/share/misc/*.ids r, /etc/fwupd/{,**} rw, /etc/lsb-release r, @@ -60,45 +77,65 @@ profile fwupd @{exec_path} flags=(attach_disconnected,complain) { /etc/machine-id r, /var/lib/dbus/machine-id r, - /boot/{,**} r, - /boot/EFI/*/.goutputstream-@{rand6} rw, - /boot/EFI/*/fw/fwupd-*.cap{,.*} rw, - /boot/EFI/*/fwupdx@{int}.efi rw, + @{efi}/{,**} r, + @{efi}/EFI/*/.goutputstream-@{rand6} rw, + @{efi}/EFI/*/fw/fwupd-*.cap{,.*} rw, + @{efi}/EFI/*/fwupdx@{int}.efi rw, @{lib}/fwupd/efi/fwupdx@{int}.efi{,.signed} r, - /var/lib/flatpak/exports/share/mime/mime.cache r, - /var/tmp/etilqs_@{hex16} rw, + @{MOUNTS}/ r, + @{MOUNTS}/@{efi}/{,**} r, + @{MOUNTS}/@{efi}/fwupd/efi/fwupdx@{int}.efi{,.signed} r, + @{MOUNTS}/**/EFI/ r, + @{MOUNTS}/**/EFI/**/ r, + @{MOUNTS}/**/EFI/*/.goutputstream-@{rand6} rw, + @{MOUNTS}/**/EFI/*/fw/fwupd-*.cap{,.*} rw, + @{MOUNTS}/**/EFI/*/fwupdx@{int}.efi rw, + @{run}/media/**/EFI/ r, + @{run}/media/**/EFI/**/ r, + owner /var/cache/fwupd/ rw, owner /var/cache/fwupd/** rwk, + owner /var/lib/fwupd/ rw, owner /var/lib/fwupd/** rwk, - # In order to get to this file, the attach_disconnected flag has to be set + @{att}@{user_cache_dirs}/gnome-software/fwupd/{,**} r, owner @{user_cache_dirs}/fwupd/lvfs-metadata.xml.gz r, owner @{user_cache_dirs}/gnome-software/fwupd/{,**} r, @{sys}/**/ r, @{sys}/devices/** r, + @{sys}/**/uevent r, @{sys}/firmware/acpi/** r, @{sys}/firmware/dmi/tables/DMI r, @{sys}/firmware/dmi/tables/smbios_entry_point r, @{sys}/firmware/efi/** r, @{sys}/firmware/efi/efivars/Boot@{hex}-@{uuid} rw, @{sys}/firmware/efi/efivars/BootNext-@{uuid} rw, + @{sys}/firmware/efi/efivars/dbx-@{uuid} rw, + @{sys}/firmware/efi/efivars/db-@{uuid} rw, @{sys}/firmware/efi/efivars/fwupd-* rw, + @{sys}/firmware/efi/efivars/KEK-@{uuid} rw, @{sys}/kernel/security/lockdown r, @{sys}/kernel/security/tpm@{int}/binary_bios_measurements r, - @{sys}/**/uevent r, @{sys}/power/mem_sleep r, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, @{run}/motd.d/ r, @{run}/motd.d/@{int}-fwupd* rw, @{run}/motd.d/fwupd/{,**} rw, @{run}/mount/utab r, - @{run}/udev/data/* r, + + @{run}/udev/data/+*:* r, # Identifies all subsystems + @{run}/udev/data/c@{int}:@{int} r, # Identifies all character devices + + @{run}/reboot-required rw, + @{run}/reboot-required.@{rand6} rw, + @{run}/reboot-required.pkgs rw, + @{run}/reboot-required.pkgs.@{rand6} rw, @{PROC}/@{pids}/fd/ r, @{PROC}/@{pids}/mountinfo r, @@ -120,8 +157,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) { @@ -133,6 +168,18 @@ profile fwupd @{exec_path} flags=(attach_disconnected,complain) { @{bin}/gpg{,2} mr, @{bin}/gpgconf mr, @{bin}/gpgsm mr, + @{lib}/fwupd/efi/fwupdx@{int}.efi{,.signed} r, + + @{MOUNTS}/ r, + @{MOUNTS}/@{efi}/{,**} r, + @{MOUNTS}/@{efi}/fwupd/efi/fwupdx@{int}.efi{,.signed} r, + @{MOUNTS}/**/EFI/**/ r, + @{MOUNTS}/**/EFI/*/.goutputstream-@{rand6} rw, + @{MOUNTS}/**/EFI/*/fw/fwupd-*.cap{,.*} rw, + @{MOUNTS}/**/EFI/*/fwupdx@{int}.efi rw, + + owner /var/cache/fwupd/ rw, + owner /var/cache/fwupd/** rwk, @{bin}/gpg-agent rix, @{lib}/{,gnupg/}scdaemon rix, diff --git a/apparmor.d/profiles-a-f/fwupdmgr b/apparmor.d/profiles-a-f/fwupdmgr index 6dffac5a6f..b4c220f813 100644 --- a/apparmor.d/profiles-a-f/fwupdmgr +++ b/apparmor.d/profiles-a-f/fwupdmgr @@ -11,10 +11,10 @@ include profile fwupdmgr @{exec_path} flags=(attach_disconnected) { include include - include include - include + include include + include include capability sys_nice, @@ -27,18 +27,25 @@ profile fwupdmgr @{exec_path} flags=(attach_disconnected) { network inet6 dgram, network netlink raw, - #aa:dbus talk bus=system name=org.freedesktop.fwupd label=fwupd path=/ + #aa:dbus talk bus=system name=org.freedesktop.fwupd label="@{p_fwupd}" path=/ @{exec_path} mr, @{bin}/dbus-launch Cx -> bus, @{bin}/pkttyagent Px, + /usr/share/glib-2.0/gdb/{,**} r, + /usr/share/gvfs/remote-volume-monitors/{,**} r, + /usr/share/terminfo/** r, + + /etc/inputrc r, /etc/machine-id r, + /var/lib/dbus/machine-id r, owner /var/cache/private/fwupdmgr/fwupd/lvfs-metadata.xml.gz{,.asc}.* rw, owner /var/cache/private/fwupdmgr/fwupd/lvfs-metadata.xml.gz{,.asc} rw, + owner /var/lib/fwupd/ w, owner /var/lib/fwupd/.cache/ w, @{user_cache_dirs}/dconf/user rw, @@ -52,11 +59,12 @@ profile fwupdmgr @{exec_path} flags=(attach_disconnected) { /dev/i2c-@{int} rw, /dev/tty rw, - /dev/pts/@{int} rw, + /dev/pts/@{u16} rw, profile bus flags=(attach_disconnected) { include include + include if exists } diff --git a/apparmor.d/profiles-g-l/gajim b/apparmor.d/profiles-g-l/gajim index e06c49b9db..561e1af611 100644 --- a/apparmor.d/profiles-g-l/gajim +++ b/apparmor.d/profiles-g-l/gajim @@ -33,7 +33,7 @@ profile gajim @{exec_path} { @{bin}/ r, @{sh_path} rix, - @{bin}/ldconfig rix, + @{sbin}/ldconfig rix, @{bin}/uname rix, # To play sounds @@ -73,7 +73,7 @@ profile gajim @{exec_path} { owner @{user_cache_dirs}/gajim/** rwk, owner @{user_cache_dirs}/farstream/ rw, - owner @{user_cache_dirs}/farstream/codecs.audio.x86_64.cache{,.tmp@{rand6}} rw, + owner @{user_cache_dirs}/farstream/codecs.audio.@{arch}.cache{,.tmp@{rand6}} rw, owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/mounts r, diff --git a/apparmor.d/profiles-g-l/gamemoded b/apparmor.d/profiles-g-l/gamemoded index eb2d3fc1e9..99af781018 100644 --- a/apparmor.d/profiles-g-l/gamemoded +++ b/apparmor.d/profiles-g-l/gamemoded @@ -19,8 +19,10 @@ profile gamemoded @{exec_path} flags=(attach_disconnected) { @{bin}/pkexec Cx -> pkexec, @{lib}/gamemode/gpuclockctl Cx -> pkexec, + /etc/ r, /etc/gamemode.ini r, + owner @{HOME}/ r, owner @{user_config_dirs}/ r, @{sys}/devices/@{pci}/vendor r, @@ -57,8 +59,6 @@ profile gamemoded @{exec_path} flags=(attach_disconnected) { @{lib}/gamemode/gpuclockctl ix, @{lib}/gamemode/procsysctl ix, - @{etc_ro}/security/limits.d/ r, - @{etc_ro}/security/limits.d/@{int}-gamemode.conf r, /etc/shells r, @{sys}/devices/@{pci}/power_dpm_force_performance_level rw, diff --git a/apparmor.d/profiles-g-l/ganyremote b/apparmor.d/profiles-g-l/ganyremote index 79f8c2fc72..727bf8cdf8 100644 --- a/apparmor.d/profiles-g-l/ganyremote +++ b/apparmor.d/profiles-g-l/ganyremote @@ -30,7 +30,7 @@ profile ganyremote @{exec_path} { @{bin}/{,e}grep rix, @{bin}/cut rix, @{bin}/id rix, - @{bin}/which{,.debianutils} rix, + @{bin}/which{,.debianutils} rix, @{bin}/tr rix, @{bin}/{m,g,}awk rix, diff --git a/apparmor.d/profiles-g-l/gdisk b/apparmor.d/profiles-g-l/gdisk index 1357b03b6f..b49e20570f 100644 --- a/apparmor.d/profiles-g-l/gdisk +++ b/apparmor.d/profiles-g-l/gdisk @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/gdisk +@{exec_path} = @{sbin}/gdisk profile gdisk @{exec_path} { include include diff --git a/apparmor.d/profiles-g-l/gdk-pixbuf-query-loaders b/apparmor.d/profiles-g-l/gdk-pixbuf-query-loaders index b64c34a4b2..04c9a33f24 100644 --- a/apparmor.d/profiles-g-l/gdk-pixbuf-query-loaders +++ b/apparmor.d/profiles-g-l/gdk-pixbuf-query-loaders @@ -18,8 +18,10 @@ profile gdk-pixbuf-query-loaders @{exec_path} { @{exec_path} mr, - @{lib}/gdk-pixbuf-[0-9].@{int}/{,*}/loaders.cache.* rw, - @{lib}/gdk-pixbuf-[0-9].@{int}/*/loaders.cache rw, + @{lib}/@{multiarch}/gdk-pixbuf-@{version}/@{version}/ w, + @{lib}/@{multiarch}/gdk-pixbuf-@{version}/@{version}/loaders.cache w, + @{lib}/gdk-pixbuf-@{version}/{,*}/loaders.cache.* rw, + @{lib}/gdk-pixbuf-@{version}/@{version}/loaders.cache rw, /usr/share/gvfs/remote-volume-monitors/{,**} r, diff --git a/apparmor.d/profiles-g-l/gdk-pixbuf-thumbnailer b/apparmor.d/profiles-g-l/gdk-pixbuf-thumbnailer index 6ec661d316..d3df6f5f33 100644 --- a/apparmor.d/profiles-g-l/gdk-pixbuf-thumbnailer +++ b/apparmor.d/profiles-g-l/gdk-pixbuf-thumbnailer @@ -10,6 +10,8 @@ include profile gdk-pixbuf-thumbnailer @{exec_path} { include + @{exec_path} mr, + include if exists } diff --git a/apparmor.d/profiles-g-l/ghc-pkg b/apparmor.d/profiles-g-l/ghc-pkg index df66130420..3ccfdec4aa 100644 --- a/apparmor.d/profiles-g-l/ghc-pkg +++ b/apparmor.d/profiles-g-l/ghc-pkg @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/ghc-pkg{,-*} +@{exec_path} = @{bin}/ghc-pkg{,-*} @{lib}/ghc-@{version}/bin/ghc-pkg-@{version} profile ghc-pkg @{exec_path} { include include @@ -26,6 +26,8 @@ profile ghc-pkg @{exec_path} { @{sys}/devices/system/node/ r, + @{PROC}/@{pid}/task/@{tid}/comm rw, + include if exists } diff --git a/apparmor.d/profiles-g-l/gimp b/apparmor.d/profiles-g-l/gimp index 1588853757..633a343ab4 100644 --- a/apparmor.d/profiles-g-l/gimp +++ b/apparmor.d/profiles-g-l/gimp @@ -7,13 +7,14 @@ abi , include @{exec_path} = @{bin}/gimp{,-*} -profile gimp @{exec_path} { +profile gimp @{exec_path} flags=(attach_disconnected) { include - include - include + include + include include include include + include include include include @@ -21,21 +22,28 @@ profile gimp @{exec_path} { signal (send) set=(term, kill) peer=xsane-gimp, + #aa:dbus own bus=session name=org.gimp + #aa:dbus talk bus=session name=org.gnome.Shell.Screenshot label=gnome-shell - #aa:dbus talk bus=session name=org.gtk.vfs label="gvfsd{,-*}" @{exec_path} mr, - @{bin}/env rix, - @{bin}/gjs-console rix, - @{bin}/lua rix, - @{lib}/gimp/@{version}/extensions/*/* rix, - @{lib}/gimp/*/plug-ins/** rix, - @{python_path} rix, + @{python_path} rix, + @{bin}/env rix, + @{bin}/gimp-debug-tool-3.0 rix, + @{bin}/gimp-script-fu-interpreter-* rix, + @{bin}/gjs-console rix, + @{bin}/lua rix, + @{lib}/gimp/@{version}/extensions/*/* rix, + @{lib}/gimp/*/plug-ins/** rix, + @{bin}/darktable rPUx, @{bin}/xsane-gimp rPx, @{open_path} rPx -> child-open-help, + @{lib}/gimp/@{version}/plug-ins/python-console/__pycache__/{,*} w, + @{lib}/@{multiarch}/gimp/@{version}/plug-ins/** ix, + /usr/share/gimp/{,**} r, /usr/share/mypaint-data/{,**} r, /usr/share/xml/iso-codes/{,**} r, @@ -43,26 +51,35 @@ profile gimp @{exec_path} { /etc/fstab r, /etc/gimp/{,**} r, + owner @{HOME}/@{XDG_SCREENSHOTS_DIR}/{,**} rw, + owner @{HOME}/@{XDG_WALLPAPERS_DIR}/{,**} rw, + owner @{user_documents_dirs}/{,**} rw, owner @{user_pictures_dirs}/{,**} rw, owner @{user_work_dirs}/{,**} rw, owner @{user_cache_dirs}//thumbnails/normal/gimp-thumb* rw, owner @{user_cache_dirs}/babl/{,**} rw, - owner @{user_cache_dirs}/gegl-*/{,**} r, - owner @{user_cache_dirs}/gegl-*/{,**} r, + owner @{user_cache_dirs}/gegl-@{version}/{,**} rw, + owner @{user_cache_dirs}/gegl-@{version}/{,**} rw, owner @{user_cache_dirs}/gimp/{,**} rw, owner @{user_cache_dirs}/GIMP/{,**} rw, owner @{user_config_dirs}/gimp/{,**} rw, owner @{user_config_dirs}/GIMP/{,**} rw, - owner @{user_share_dirs}/gegl-*/{,**} r, + owner @{user_share_dirs}/gegl-@{version}/{,**} r, owner @{user_share_dirs}/GIMP/{,**} rw, owner @{tmp}/gimp/{,**} rw, + @{run}/mount/utab r, + + owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/mountinfo r, + owner @{PROC}/@{pid}/mounts r, + owner @{PROC}/@{pid}/stat r, + owner @{PROC}/@{pid}/task/@{tid}/stat r, include if exists } diff --git a/apparmor.d/profiles-g-l/git b/apparmor.d/profiles-g-l/git index 71bace3c3a..6423db11a3 100644 --- a/apparmor.d/profiles-g-l/git +++ b/apparmor.d/profiles-g-l/git @@ -14,72 +14,43 @@ include @{exec_path} += @{lib_dirs}/git @{lib_dirs}/git-* @{lib_dirs}/mergetools/* profile git @{exec_path} flags=(attach_disconnected) { include - include - include - include - - network inet dgram, - network inet6 dgram, - network inet stream, - network inet6 stream, - network netlink raw, + include signal send peer=aurpublish, + signal receive set=term peer=code, + + # unix (send receive) type=stream peer=(label=claude), + unix (send receive) type=stream peer=(label=code), + unix type=seqpacket peer=(label=code-shells), + unix type=seqpacket peer=(label=code), @{exec_path} mrix, - # When you mistype a command, git checks the $PATH variable and search its exec dirs to give you - # the most similar commands, which it thinks can be used instead. Git binaries are all under - # /usr/bin/ , so allow only this location. - @{bin}/ r, - deny @{bin}/*/ r, - deny /usr/games/ r, - deny /usr/local/{s,}bin/ r, - deny /usr/local/games/ r, - deny /var/lib/flatpak/exports/bin/ r, - deny owner @{HOME}/.go/bin/ r, - deny owner @{user_bin_dirs}/ r, - - # These are needed for "git submodule update" - @{sh_path} rix, - @{bin}/{,e}grep rix, - @{bin}/alts rix, - @{bin}/basename rix, - @{bin}/cat rix, - @{bin}/date rix, - @{bin}/dirname rix, - @{bin}/envsubst rix, - @{bin}/gettext rix, - @{bin}/gettext.sh rix, - @{bin}/hostname rix, - @{bin}/mkdir rix, - @{bin}/mv rix, - @{bin}/rm rix, - @{bin}/sed rix, - @{bin}/tar rix, - @{bin}/true rix, - @{bin}/uname rix, - @{bin}/wc rix, - @{bin}/whoami rix, - - @{pager_path} rPx -> child-pager, - - @{bin}/man rPx, - @{bin}/meld rPUx, - @{lib}/code/extensions/git/dist/askpass.sh rPx, - @{lib}/code/extensions/git/dist/git-editor.sh rPx, - /usr/share/aurpublish/*.hook rPx, - - @{bin}/gpg{,2} rCx -> gpg, - @{bin}/ssh rCx -> ssh, - @{editor_path} rCx -> editor, - - /usr/share/git{,-core}/{,**} r, + @{pager_path} Px -> child-pager, + + @{bin}/gh Px, + @{bin}/man Px, + @{bin}/meld PUx, + @{lib}/code/extensions/git/dist/askpass.sh Px, + @{lib}/code/extensions/git/dist/git-editor.sh Px, + /usr/share/aurpublish/*.hook Px, + + @{editor_path} Cx -> editor, + + # TODO: revisit the stacking. Profile with nnp flag that use git should + # not use this git profile but a more specific one. + @{bin}/gpg{,2} Cx -> &gpg, + @{bin}/ssh rCx -> &ssh, + @{bin}/ssh.hmac r, + /usr/share/libalternatives/{,**} r, /usr/share/terminfo/** r, - /etc/gitconfig r, /etc/mailname r, + @{etc_ro}/ssh/ssh_config r, + @{etc_ro}/ssh/ssh_config.d/{,*} r, + + / r, owner @{user_projects_dirs}/ rw, owner @{user_projects_dirs}/** rwkl -> @{user_projects_dirs}/**, @@ -92,10 +63,21 @@ profile git @{exec_path} flags=(attach_disconnected) { owner @{HOME}/.netrc r, owner @{user_config_dirs}/git/{,*} rw, - owner @{tmp}/.git_vtag_tmp@{rand6} rw, # For git log --show-signature - owner @{tmp}/git-commit-msg-.txt rw, # For android studio - owner @{tmp}/git-difftool.*/{,**} rw, # For diffs + owner @{HOME}/.ansible/tmp{,**} rwlk, + + # GPG / SSH + owner @{HOME}/@{XDG_SSH_DIR}/ rw, + owner @{HOME}/@{XDG_SSH_DIR}/** rwl -> @{HOME}/@{XDG_SSH_DIR}/**, + owner @{run}/user/@{uid}/keyring/ssh rw, + owner @{HOME}/@{XDG_GPG_DIR}/ rw, + owner @{HOME}/@{XDG_GPG_DIR}/** rwkl -> @{HOME}/@{XDG_GPG_DIR}/**, + owner @{tmp}/.git_vtag_tmp@{rand6} r, + owner @{run}/user/@{uid}/gnupg/S.gpg-agent rw, + + owner @{run}/user/@{uid}/gcr/ssh rw, + # file_inherit + deny /usr/share/code/{,**} r, deny owner @{code_config_dirs}/** rw, deny owner @{user_share_dirs}/gvfs-metadata/* r, deny owner @{user_share_dirs}/vulkan/** r, @@ -103,6 +85,9 @@ profile git @{exec_path} flags=(attach_disconnected) { deny /usr/share/nvidia/nvidia-application-profiles-* r, deny /dev/shm/.org.chromium.Chromium.@{rand6} rw, + #aa:only test + owner /tmp/*tests@{word8}/{,**} rwlk, + profile gpg flags=(attach_disconnected) { include include @@ -115,6 +100,8 @@ profile git @{exec_path} flags=(attach_disconnected) { owner @{tmp}/.git_vtag_tmp@{rand6} r, + owner @{run}/user/@{uid}/gnupg/S.gpg-agent rw, + deny @{user_share_dirs}/gvfs-metadata/* r, include if exists @@ -132,17 +119,23 @@ profile git @{exec_path} flags=(attach_disconnected) { network netlink raw, @{bin}/ssh mr, + @{bin}/ssh.hmac r, + + @{bin}/ksshaskpass ix, + @{lib}/code/extensions/git/dist/ssh-askpass.sh Px, @{etc_ro}/ssh/ssh_config.d/{,*} r, @{etc_ro}/ssh/ssh_config r, - owner @{HOME}/@{XDG_SSH_DIR}/* r, + owner @{HOME}/@{XDG_SSH_DIR}/{,*} r, owner @{HOME}/@{XDG_SSH_DIR}/known_hosts.old rwl, owner @{HOME}/@{XDG_SSH_DIR}/known_hosts{,.*} rw, owner @{HOME}/@{XDG_SSH_DIR}/ssh_control_* rwl, owner @{tmp}/git@*:@{int} rwl -> @{tmp}/git@*:@{int}.*, owner @{tmp}/ssh-*/agent.@{int} rw, + owner @{run}/user/@{uid}/keyring/ssh rw, + owner @{run}/user/@{uid}/gcr/ssh rw, owner @{PROC}/@{pid}/fd/ r, diff --git a/apparmor.d/profiles-g-l/gitg b/apparmor.d/profiles-g-l/gitg index ff5e124448..a4b700ded9 100644 --- a/apparmor.d/profiles-g-l/gitg +++ b/apparmor.d/profiles-g-l/gitg @@ -9,11 +9,10 @@ include @{exec_path} = @{bin}/gitg profile gitg @{exec_path} { include - include - include include include include + include include network inet dgram, diff --git a/apparmor.d/profiles-g-l/gitstatusd b/apparmor.d/profiles-g-l/gitstatusd index a62ce7fded..17c442b1e5 100644 --- a/apparmor.d/profiles-g-l/gitstatusd +++ b/apparmor.d/profiles-g-l/gitstatusd @@ -6,23 +6,38 @@ abi , include -@{exec_path} = /usr/share/zsh-theme-powerlevel@{int}k/gitstatus/usrbin/gitstatusd{,-*} -profile gitstatusd @{exec_path} { +@{exec_path} = @{user_cache_dirs}/gitstatus/gitstatusd{,-*} +@{exec_path} += /usr/share/zsh-theme-powerlevel{9,10}k/gitstatus/usrbin/gitstatusd{,-*} +profile gitstatusd @{exec_path} flags=(attach_disconnected) { include + include + + signal receive set=term peer=*//shell, + signal receive set=term peer={,vs}code, + signal receive set=term peer=code-shells, + + unix (send receive) type=stream peer=(label=code), @{exec_path} mr, + /etc/gitconfig r, + owner @{user_projects_dirs}/{,**} r, - owner @{user_projects_dirs}/**/.git/.gitstatus.@{rand6}/{,**} rw, + owner @{user_projects_dirs}/**/.git/{,**/}.gitstatus.@{rand6}/{,**} rw, owner @{HOME}/.gitconfig r, owner @{user_config_dirs}/git/{,*} r, + owner @{tmp}/gitstatus.POWERLEVEL9K.*.fifo r, + # Silencer deny capability dac_read_search, deny capability dac_override, + deny network netlink raw, + deny /usr/share/{,**} r, deny owner @{HOME}/.*-store/{,**} r, - deny owner @{user_share_dirs}/zed/**/data.mdb rw, + deny owner @{user_config_dirs}/*/logs/{,**} rw, + deny owner @{user_share_dirs}/**/data.mdb rw, include if exists } diff --git a/apparmor.d/profiles-g-l/glib-compile-schemas b/apparmor.d/profiles-g-l/glib-compile-schemas index fcabd84c3d..f1dfb68ce5 100644 --- a/apparmor.d/profiles-g-l/glib-compile-schemas +++ b/apparmor.d/profiles-g-l/glib-compile-schemas @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/glib-compile-schemas +@{exec_path} = @{bin}/glib-compile-schemas @{lib}/@{multiarch}/glib-2.0/glib-compile-schemas profile glib-compile-schemas @{exec_path} { include include @@ -16,16 +16,20 @@ profile glib-compile-schemas @{exec_path} { @{exec_path} mr, - /usr/share/glib-2.0/schemas/{,*} r, - /usr/share/glib-2.0/schemas/gschemas.compiled.@{rand6} rw, - /usr/share/glib-2.0/schemas/gschemas.compiled rw, + @{system_share_dirs}/ r, + @{system_share_dirs}/glib-2.0/schemas/{,*} r, + @{system_share_dirs}/glib-2.0/schemas/gschemas.compiled rw, + @{system_share_dirs}/glib-2.0/schemas/gschemas.compiled.@{rand6} rw, /usr/share/gnome-shell/extensions/*/schemas/org.gnome.shell.extensions.*.gschema.xml r, owner @{user_share_dirs}/gnome-shell/extension{,-updates}/*/schemas/ r, + owner @{user_share_dirs}/gnome-shell/extension{,-updates}/*/schemas/*.gschema.xml r, owner @{user_share_dirs}/gnome-shell/extension{,-updates}/*/schemas/gschemas.compiled rw, owner @{user_share_dirs}/gnome-shell/extension{,-updates}/*/schemas/gschemas.compiled.@{rand6} rw, - owner @{user_share_dirs}/gnome-shell/extension{,-updates}/*/schemas/org.gnome.shell.extensions.*.gschema.xml r, + + #aa:only test + /usr/share/mutter-*/tests/{,**} rw, include if exists } diff --git a/apparmor.d/groups/virt/cni-firewall b/apparmor.d/profiles-g-l/glib-mkenums similarity index 50% rename from apparmor.d/groups/virt/cni-firewall rename to apparmor.d/profiles-g-l/glib-mkenums index d5171e8dcc..a53bb7983e 100644 --- a/apparmor.d/groups/virt/cni-firewall +++ b/apparmor.d/profiles-g-l/glib-mkenums @@ -1,18 +1,21 @@ # apparmor.d - Full set of apparmor profiles -# Copyright (C) 2021-2024 Alexandre Pujol +# Copyright (C) 2021 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only abi , include -@{exec_path} = @{lib}/cni/firewall /opt/cni/bin/firewall -profile cni-firewall @{exec_path} { +@{exec_path} = @{bin}/glib-mkenums +profile glib-mkenums @{exec_path} { include @{exec_path} mr, - include if exists + @{bin}/ r, + + include if exists } # vim:syntax=apparmor + diff --git a/apparmor.d/profiles-g-l/globaltime b/apparmor.d/profiles-g-l/globaltime index 7f349b650d..ce5917bd93 100644 --- a/apparmor.d/profiles-g-l/globaltime +++ b/apparmor.d/profiles-g-l/globaltime @@ -10,10 +10,7 @@ include @{exec_path} = @{bin}/globaltime profile globaltime @{exec_path} { include - include - include - include - include + include @{exec_path} mr, @@ -21,7 +18,7 @@ profile globaltime @{exec_path} { owner @{user_config_dirs}/globaltime/globaltimerc{,.*} rw, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-g-l/glxgears b/apparmor.d/profiles-g-l/glxgears index 1e27790df4..2fe222f532 100644 --- a/apparmor.d/profiles-g-l/glxgears +++ b/apparmor.d/profiles-g-l/glxgears @@ -10,10 +10,10 @@ include @{exec_path} = @{bin}/glxgears profile glxgears @{exec_path} { include - include - include + include include include + include capability sys_admin, @@ -24,8 +24,6 @@ profile glxgears @{exec_path} { @{exec_path} mr, - owner @{HOME}/.Xauthority r, - include if exists } diff --git a/apparmor.d/profiles-g-l/glxinfo b/apparmor.d/profiles-g-l/glxinfo index eea7b6050d..16b6e83627 100644 --- a/apparmor.d/profiles-g-l/glxinfo +++ b/apparmor.d/profiles-g-l/glxinfo @@ -19,6 +19,8 @@ profile glxinfo @{exec_path} { @{exec_path} mr, + owner @{PROC}/@{pid}/task/@{tid}/comm w, + include if exists } diff --git a/apparmor.d/profiles-g-l/goxray_cli b/apparmor.d/profiles-g-l/goxray_cli new file mode 100644 index 0000000000..680e7da08b --- /dev/null +++ b/apparmor.d/profiles-g-l/goxray_cli @@ -0,0 +1,36 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2022-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/goxray_cli @{bin}/goxray_cli_linux_@{arch} +profile goxray_cli @{exec_path} { + include + include + include + include + include + + # Operate TUN interfaces + capability net_admin, + + network inet dgram, + network inet6 dgram, + network inet stream, + network inet6 stream, + network netlink raw, + + @{exec_path} mr, + + @{PROC}/@{pid}/net/route r, + @{PROC}/sys/net/core/somaxconn r, + + /dev/net/tun rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-g-l/gpa b/apparmor.d/profiles-g-l/gpa index 8a9c424435..5357ae5939 100644 --- a/apparmor.d/profiles-g-l/gpa +++ b/apparmor.d/profiles-g-l/gpa @@ -10,10 +10,7 @@ include @{exec_path} = @{bin}/gpa profile gpa @{exec_path} { include - include - include - include - include + include include include @@ -49,7 +46,7 @@ profile gpa @{exec_path} { @{lib}/firefox/firefox rPUx, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-g-l/gparted b/apparmor.d/profiles-g-l/gparted index d4511c62ca..501ee09daf 100644 --- a/apparmor.d/profiles-g-l/gparted +++ b/apparmor.d/profiles-g-l/gparted @@ -7,10 +7,13 @@ abi , include -@{exec_path} = @{bin}/gparted +@{exec_path} = @{sbin}/gparted profile gparted @{exec_path} flags=(attach_disconnected) { include include + include + + capability dac_read_search, ptrace read, @@ -20,7 +23,7 @@ profile gparted @{exec_path} flags=(attach_disconnected) { @{coreutils_path} rix, @{sh_path} rix, - @{bin}/killall5 rCx -> killall, + @{sbin}/killall5 rCx -> killall, @{bin}/systemctl rCx -> systemctl, @{bin}/udevadm rCx -> udevadm, @@ -29,7 +32,7 @@ profile gparted @{exec_path} flags=(attach_disconnected) { @{bin}/ps rPx, @{bin}/xhost rPx, - @{bin}/gpartedbin rPx, + @{sbin}/gpartedbin rPx, @{lib}/gparted/gpartedbin rPx, @{lib}/gpartedbin rPx, @@ -45,11 +48,16 @@ profile gparted @{exec_path} flags=(attach_disconnected) { /usr/local/bin/ r, /usr/local/sbin/ r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/app-gparted@@{hex32}.service/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/app-*-@{int}.scope/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/app-*-@{int}.scope/*/cpu.max r, + @{PROC}/@{pids}/cmdline r, @{PROC}/@{pids}/stat r, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, profile udevadm { include @@ -71,7 +79,7 @@ profile gparted @{exec_path} flags=(attach_disconnected) { ptrace (read), - @{bin}/killall5 mr, + @{sbin}/killall5 mr, @{PROC}/ r, @{PROC}/@{pids}/stat r, diff --git a/apparmor.d/profiles-g-l/gpartedbin b/apparmor.d/profiles-g-l/gpartedbin index a82bf8b473..314140ffc6 100644 --- a/apparmor.d/profiles-g-l/gpartedbin +++ b/apparmor.d/profiles-g-l/gpartedbin @@ -7,14 +7,15 @@ abi , include -@{exec_path} = @{bin}/gpartedbin @{lib}/{,gparted/}gpartedbin -profile gpartedbin @{exec_path} { +@{exec_path} = @{sbin}/gpartedbin @{lib}/{,gparted/}gpartedbin +profile gpartedbin @{exec_path} flags=(attach_disconnected) { include include include include include include + include capability dac_override, capability dac_read_search, @@ -30,40 +31,46 @@ profile gpartedbin @{exec_path} { @{sh_path} rix, - @{bin}/blkid rPx, - @{bin}/dmidecode rPx, - @{bin}/hdparm rPx, + @{sbin}/blkid rPx, + @{sbin}/dmidecode rPx, + @{sbin}/hdparm rPx, @{bin}/kmod rPx, - @{bin}/mount rCx -> mount, - @{bin}/udevadm rCx -> udevadm, - @{bin}/umount rCx -> umount, - - @{bin}/btrfs rPx, - @{bin}/btrfstune rPx, - @{bin}/dmraid rPUx, - @{bin}/dmsetup rPUx, - @{bin}/dumpe2fs rPx, - @{bin}/e2fsck rPx, - @{bin}/e2image rPx, - @{bin}/fsck.* rPUx, - @{bin}/lvm rPUx, - @{bin}/mdadm rPUx, - @{bin}/mke2fs rPx, - @{bin}/mkfs.* rPUx, - @{bin}/mkntfs rPx, - @{bin}/mkswap rPx, + @{bin}/dbus-launch rCx -> bus, + @{bin}/mount rCx -> mount, + @{bin}/udevadm rCx -> udevadm, + @{bin}/umount rCx -> umount, + + @{sbin}/btrfs rPx, + @{sbin}/btrfstune rPx, + @{sbin}/dmraid rPUx, + @{sbin}/dmsetup rPUx, + @{sbin}/dumpe2fs rPx, + @{sbin}/e2fsck rPx, + @{sbin}/e2image rPx, + @{sbin}/e2label rPx, + @{bin}/exfatfsck rix, + @{sbin}/fatlabel rPx, + @{sbin}/fsck.* rPUx, + @{sbin}/lvm rPUx, + @{sbin}/mdadm rPUx, + @{sbin}/mke2fs rPx, + @{sbin}/mkfs.* rPUx, + @{bin}/mkexfatfs rix, + @{sbin}/mkntfs rPx, + @{sbin}/mkswap rPx, + @{bin}/mkudffs rix, @{bin}/mtools rPx, @{bin}/ntfsinfo rPx, - @{bin}/ntfslabel rPx, - @{bin}/ntfsresize rPx, - @{bin}/resize2fs rPx, - @{bin}/swaplabel rPx, - @{bin}/swapoff rPx, - @{bin}/swapon rPx, + @{sbin}/ntfslabel rPx, + @{sbin}/ntfsresize rPx, + @{sbin}/resize2fs rPx, + @{sbin}/swaplabel rPx, + @{sbin}/swapoff rPx, + @{sbin}/swapon rPx, @{bin}/tune.* rPUx, - @{bin}/tune2fs rPx, - @{bin}/xfs_io rPUx, + @{sbin}/tune2fs rPx, + @{sbin}/xfs_io rPUx, @{open_path} rPx -> child-open, @@ -74,16 +81,32 @@ profile gpartedbin @{exec_path} { owner @{tmp}/gparted-*/ rw, + @{run}/blkid/blkid.tab r, @{run}/mount/utab r, + @{run}/user/@{uid}/xauth_@{rand6} r, + + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/app-gparted@@{hex32}.service/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/session-@{int}.scope/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/app-*-@{int}.scope/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/app-*-@{int}.scope/*/cpu.max r, @{PROC}/devices r, @{PROC}/partitions r, @{PROC}/swaps r, @{PROC}/version r, + @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/mounts r, + profile bus { + include + include + + include if exists + } + profile mount { include include @@ -92,7 +115,7 @@ profile gpartedbin @{exec_path} { mount /dev/{s,v}d[a-z]*@{int} -> /tmp/gparted-*/, - mount /dev/{s,v}d[a-z]*@{int} -> /boot/, + mount /dev/{s,v}d[a-z]*@{int} -> @{efi}/, mount /dev/{s,v}d[a-z]*@{int} -> @{MOUNTS}/, mount /dev/{s,v}d[a-z]*@{int} -> @{MOUNTS}/*/, @@ -108,7 +131,7 @@ profile gpartedbin @{exec_path} { umount /tmp/gparted-*/, - umount /boot/, + umount @{efi}/, umount @{MOUNTS}/, umount @{MOUNTS}/*/, @@ -127,6 +150,7 @@ profile gpartedbin @{exec_path} { include include include + include include if exists } diff --git a/apparmor.d/profiles-g-l/gpo b/apparmor.d/profiles-g-l/gpo index 562980d352..46ff3eec58 100644 --- a/apparmor.d/profiles-g-l/gpo +++ b/apparmor.d/profiles-g-l/gpo @@ -11,10 +11,11 @@ include profile gpo @{exec_path} { include include - include include - include + include + include include + include network inet dgram, network inet6 dgram, @@ -36,8 +37,6 @@ profile gpo @{exec_path} { owner @{HOME}/gPodder/ rw, owner @{HOME}/gPodder/** rwk, - owner /var/tmp/etilqs_@{hex16} rw, - owner @{PROC}/@{pid}/fd/ r, include if exists diff --git a/apparmor.d/profiles-g-l/gpodder b/apparmor.d/profiles-g-l/gpodder index 7ccf428c3f..e98d8bc149 100644 --- a/apparmor.d/profiles-g-l/gpodder +++ b/apparmor.d/profiles-g-l/gpodder @@ -14,6 +14,7 @@ profile gpodder @{exec_path} { include include include + include include include @@ -41,19 +42,16 @@ profile gpodder @{exec_path} { /usr/share/gpodder/{,**} r, /etc/fstab r, - /etc/mime.types r, owner @{HOME}/ r, owner @{HOME}/gPodder/ rw, owner @{HOME}/gPodder/** rwk, - owner /var/tmp/etilqs_@{hex16} rw, - owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/mounts r, owner @{PROC}/@{pid}/mountinfo r, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-g-l/gpu-manager b/apparmor.d/profiles-g-l/gpu-manager index 795c92f002..6add86d4f4 100644 --- a/apparmor.d/profiles-g-l/gpu-manager +++ b/apparmor.d/profiles-g-l/gpu-manager @@ -16,17 +16,19 @@ profile gpu-manager @{exec_path} { @{exec_path} mr, - @{sh_path} rix, - @{bin}/grep rix, + @{sh_path} rix, + @{bin}/{,e}grep rix, /etc/modprobe.d/{,**} r, - /usr/lib/modprobe.d/{,**} r, + @{lib}/modprobe.d/{,**} r, /var/lib/ubuntu-drivers-common/* rw, /var/log/gpu-manager.log w, /var/log/gpu-manager-switch.log w, + @{run}/modprobe.d/{,**} r, + @{sys}/devices/@{pci}/boot_vga r, @{sys}/module/compression r, diff --git a/apparmor.d/profiles-g-l/grim b/apparmor.d/profiles-g-l/grim new file mode 100644 index 0000000000..5717837ec4 --- /dev/null +++ b/apparmor.d/profiles-g-l/grim @@ -0,0 +1,24 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 valoq +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/grim +profile grim @{exec_path} { + include + include + include + + @{exec_path} mr, + + owner @{HOME}/@{int8}_**_grim.png w, + + owner /dev/shm/grim-@{rand6} rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-g-l/groups b/apparmor.d/profiles-g-l/groups index 916a73b223..f653732a40 100644 --- a/apparmor.d/profiles-g-l/groups +++ b/apparmor.d/profiles-g-l/groups @@ -15,7 +15,7 @@ profile groups @{exec_path} { @{exec_path} mr, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-g-l/gsettings b/apparmor.d/profiles-g-l/gsettings index bbdb3da623..52d65b063b 100644 --- a/apparmor.d/profiles-g-l/gsettings +++ b/apparmor.d/profiles-g-l/gsettings @@ -9,19 +9,27 @@ include @{exec_path} = @{bin}/gsettings profile gsettings @{exec_path} flags=(attach_disconnected) { include - include include + include include + include @{exec_path} mr, - /usr/share/glib-2.0/schemas/gschemas.compiled r, - /usr/share/dconf/profile/gdm r, - /usr/share/gdm/greeter-dconf-defaults r, - owner @{desktop_cache_dirs}/dconf/user rw, owner @{desktop_config_dirs}/dconf/user rw, - owner @{DESKTOP_HOME}/greeter-dconf-defaults r, + + # file_inherit + deny network netlink raw, + deny unix (send receive) type=seqpacket, + deny unix (send receive) type=stream, + deny /etc/nsswitch.conf r, + deny /etc/passwd r, + deny /opt/*/** r, + deny owner /.cache/ w, + deny owner @{user_config_dirs}/[^d]*/** rw, # all but dconf + deny owner /dev/shm/.org.chromium.Chromium.@{rand6} rw, + deny /dev/dri/* rw, include if exists } diff --git a/apparmor.d/profiles-g-l/gsimplecal b/apparmor.d/profiles-g-l/gsimplecal index b0b743359b..9903e3dcf2 100644 --- a/apparmor.d/profiles-g-l/gsimplecal +++ b/apparmor.d/profiles-g-l/gsimplecal @@ -10,7 +10,7 @@ include @{exec_path} = @{bin}/gsimplecal profile gsimplecal @{exec_path} { include - include + include include include diff --git a/apparmor.d/profiles-g-l/gsmartcontrol b/apparmor.d/profiles-g-l/gsmartcontrol index 5d04e33fbc..6486e061fe 100644 --- a/apparmor.d/profiles-g-l/gsmartcontrol +++ b/apparmor.d/profiles-g-l/gsmartcontrol @@ -20,7 +20,7 @@ profile gsmartcontrol @{exec_path} { @{bin}/dbus-launch Cx -> bus, @{bin}/dbus-send Cx -> bus, - @{bin}/smartctl Px, + @{sbin}/smartctl Px, @{bin}/xterm Cx -> terminal, /etc/fstab r, @@ -48,7 +48,7 @@ profile gsmartcontrol @{exec_path} { # hence this behavior should be blocked. deny @{open_path} rx, - profile bus flags=(complain) { + profile bus { include include @@ -67,7 +67,7 @@ profile gsmartcontrol @{exec_path} { capability setuid, @{bin}/xterm mr, - @{bin}/update-smart-drivedb rPx, + @{sbin}/update-smart-drivedb rPx, /usr/include/X11/bitmaps/vlines2 r, diff --git a/apparmor.d/profiles-g-l/gsmartcontrol-root b/apparmor.d/profiles-g-l/gsmartcontrol-root index 10c1f445b1..4fdb1084b3 100644 --- a/apparmor.d/profiles-g-l/gsmartcontrol-root +++ b/apparmor.d/profiles-g-l/gsmartcontrol-root @@ -15,7 +15,7 @@ profile gsmartcontrol-root @{exec_path} { @{exec_path} r, @{sh_path} rix, - @{bin}/which{,.debianutils} rix, + @{bin}/which{,.debianutils} rix, @{bin}/pkexec rCx -> pkexec, diff --git a/apparmor.d/profiles-g-l/gtk-query-immodules b/apparmor.d/profiles-g-l/gtk-query-immodules index 46aece91a6..a7cbf52ae3 100644 --- a/apparmor.d/profiles-g-l/gtk-query-immodules +++ b/apparmor.d/profiles-g-l/gtk-query-immodules @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/gtk-query-immodules-{2,3}.0 +@{exec_path} = @{bin}/gtk-query-immodules-* @{lib}/@{multiarch}/libgtk-*/gtk-query-immodules-* profile gtk-query-immodules @{exec_path} { include include @@ -17,7 +17,10 @@ profile gtk-query-immodules @{exec_path} { @{exec_path} mr, @{lib}/gtk-{2,3,4}.0/**/immodules.cache w, - @{lib}/gtk-{2,3,4}.0/**/immodules.cache.[0-9A-Z]* w, + @{lib}/gtk-{2,3,4}.0/**/immodules.cache.@{rand6} w, + + @{lib}/@{multiarch}/gtk-{2,3,4}.0/**/immodules.cache w, + @{lib}/@{multiarch}/gtk-{2,3,4}.0/**/immodules.cache.@{rand6} w, # Inherit silencer deny network inet6 stream, diff --git a/apparmor.d/profiles-g-l/gtk-update-icon-cache b/apparmor.d/profiles-g-l/gtk-update-icon-cache index b1a6779aeb..a7eeaf92f7 100644 --- a/apparmor.d/profiles-g-l/gtk-update-icon-cache +++ b/apparmor.d/profiles-g-l/gtk-update-icon-cache @@ -11,9 +11,14 @@ include profile gtk-update-icon-cache @{exec_path} flags=(attach_disconnected) { include include + include + + capability fowner, @{exec_path} mr, + /usr/share/icons/**.icon r, + @{system_share_dirs}/icons/{,**/} r, @{system_share_dirs}/icons/**/.icon-theme.cache rw, @{system_share_dirs}/icons/**/icon-theme.cache w, diff --git a/apparmor.d/profiles-g-l/gtk-youtube-viewer b/apparmor.d/profiles-g-l/gtk-youtube-viewer index 0b9075bc1e..7e40457f4b 100644 --- a/apparmor.d/profiles-g-l/gtk-youtube-viewer +++ b/apparmor.d/profiles-g-l/gtk-youtube-viewer @@ -10,10 +10,7 @@ include @{exec_path} = @{bin}/gtk{,2,3}-youtube-viewer profile gtk-youtube-viewer @{exec_path} { include - include - include - include - include + include include include include @@ -49,13 +46,10 @@ profile gtk-youtube-viewer @{exec_path} { owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/mounts r, - profile xterm { include include - include - include - include + include include include include @@ -86,9 +80,6 @@ profile gtk-youtube-viewer @{exec_path} { owner @{HOME}/.Xauthority r, owner @{HOME}/.ICEauthority r, - # file_inherit - owner @{HOME}/.xsession-errors w, - include if exists } diff --git a/apparmor.d/profiles-g-l/hardinfo b/apparmor.d/profiles-g-l/hardinfo index aaa28bd55a..dd8b13c0a7 100644 --- a/apparmor.d/profiles-g-l/hardinfo +++ b/apparmor.d/profiles-g-l/hardinfo @@ -11,10 +11,12 @@ include profile hardinfo @{exec_path} { include include - include include + include include include + include + include include # This is needed to display some content of devices -> resources @@ -39,14 +41,14 @@ profile hardinfo @{exec_path} { @{bin}/make rix, @{bin}/perl rix, @{python_path} rix, - @{bin}/route rix, + @{sbin}/route rix, @{bin}/ruby@{int}.@{int} rix, @{bin}/strace rix, @{bin}/tr rix, @{bin}/valgrind{,.bin} rix, @{lib}/@{multiarch}/valgrind/memcheck-*-linux rix, - @{bin}/lsb_release rPx -> lsb_release, + @{bin}/lsb_release rPx, @{open_path} rPx -> child-open, @{bin}/ccache rCx -> ccache, @{bin}/kmod rCx -> kmod, @@ -58,7 +60,7 @@ profile hardinfo @{exec_path} { @{bin}/netstat rPx, @{bin}/qtchooser rPx, - @{lib}/jvm/java-[0-9]*-openjdk-amd64/bin/javac rCx -> javac, + @{lib}/jvm/java-[0-9]*-openjdk-@{arch}/bin/javac rCx -> javac, /usr/share/gdb/python/ r, /usr/share/gdb/python/** r, @@ -82,12 +84,7 @@ profile hardinfo @{exec_path} { @{sys}/devices/system/cpu/** r, @{sys}/devices/virtual/dmi/id/* r, - @{sys}/devices/virtual/thermal/thermal_zone@{int}/hwmon@{int}/temp* r, - @{sys}/devices/virtual/thermal/thermal_zone@{int}/temp* r, - @{sys}/devices/platform/**/hwmon/hwmon@{int}/temp* r, - @{sys}/devices/platform/**/hwmon/hwmon@{int}/fan* r, @{sys}/devices/@{pci}/eeprom r, - @{sys}/devices/@{pci}/hwmon/hwmon@{int}/temp* r, @{sys}/devices/**/power_supply/** r, @{PROC}/@{pid}/net/arp r, @@ -108,7 +105,7 @@ profile hardinfo @{exec_path} { owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/mounts r, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, deny /usr/share/gdb/python/** w, @@ -132,9 +129,8 @@ profile hardinfo @{exec_path} { include include - @{lib}/jvm/java-[0-9]*-openjdk-amd64/bin/* mr, - - @{lib}/jvm/java-[0-9]*-openjdk-amd64/lib/** mr, + @{lib}/jvm/java-[0-9]*-openjdk-@{arch}/bin/* mr, + @{lib}/jvm/java-[0-9]*-openjdk-@{arch}/lib/** mr, /etc/java-[0-9]*-openjdk/** r, diff --git a/apparmor.d/profiles-g-l/haveged b/apparmor.d/profiles-g-l/haveged index 910e9a2f09..8b15b31530 100644 --- a/apparmor.d/profiles-g-l/haveged +++ b/apparmor.d/profiles-g-l/haveged @@ -9,7 +9,7 @@ abi , include -@{exec_path} = @{bin}/haveged +@{exec_path} = @{sbin}/haveged profile haveged @{exec_path} { include @@ -17,13 +17,15 @@ profile haveged @{exec_path} { @{exec_path} mr, + /dev/shm/sem.@{rand6} rw, + /dev/shm/sem.haveged_sem rwl -> /dev/shm/sem.@{rand6}, + @{sys}/devices/system/cpu/cpu@{int}/cache/ r, @{sys}/devices/system/cpu/cpu@{int}/cache/index*/{type,size,level} r, - @{PROC}/sys/kernel/osrelease r, - @{PROC}/sys/kernel/random/poolsize r, - @{PROC}/sys/kernel/random/write_wakeup_threshold w, - owner @{PROC}/@{pid}/status r, + @{PROC}/sys/kernel/osrelease r, + @{PROC}/sys/kernel/random/poolsize r, + @{PROC}/sys/kernel/random/write_wakeup_threshold w, /dev/random w, diff --git a/apparmor.d/profiles-g-l/hbbr b/apparmor.d/profiles-g-l/hbbr index 09b71b77fa..eece994a05 100644 --- a/apparmor.d/profiles-g-l/hbbr +++ b/apparmor.d/profiles-g-l/hbbr @@ -18,9 +18,8 @@ profile hbbr @{exec_path} { owner @{PROC}/@{pid}/cgroup r, owner /var/lib/rustdesk-server/ r, + owner /var/lib/rustdesk-server/id_ed25519 r, owner /var/lib/rustdesk-server/id_ed25519.pub r, - # Unknown non-essential purpose -# owner /var/lib/rustdesk-server/id_ed25519 r, include if exists } diff --git a/apparmor.d/profiles-g-l/hbbs b/apparmor.d/profiles-g-l/hbbs index 4e75327242..8517ed20fa 100644 --- a/apparmor.d/profiles-g-l/hbbs +++ b/apparmor.d/profiles-g-l/hbbs @@ -9,11 +9,16 @@ include @{exec_path} = @{bin}/hbbs profile hbbs @{exec_path} { include + include + include + include + include network inet stream, network inet6 stream, network inet dgram, network inet6 dgram, + network netlink raw, @{exec_path} mr, @@ -25,7 +30,14 @@ profile hbbs @{exec_path} { owner /var/lib/rustdesk-server/db_v2.sqlite3-wal rw, owner /var/lib/rustdesk-server/db_v2.sqlite3-shm rwk, + owner @{user_config_dirs}/ w, + owner @{user_config_dirs}/rustdesk/{,**} rw, + + @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_cur_freq r, + @{sys}/devices/platform/**/net/*/address r, + owner @{PROC}/@{pid}/cgroup r, + @{PROC}/@{pid}/net/route r, include if exists } diff --git a/apparmor.d/profiles-g-l/hddtemp b/apparmor.d/profiles-g-l/hddtemp index e96a45237f..55d2abb5dd 100644 --- a/apparmor.d/profiles-g-l/hddtemp +++ b/apparmor.d/profiles-g-l/hddtemp @@ -10,32 +10,20 @@ include @{exec_path} = @{bin}/hddtemp profile hddtemp @{exec_path} { include + include + include - # To remove the following errors: - # /dev/sda: Permission denied + capability sys_admin, capability sys_rawio, - # There's the following error in strace: - # ioctl(3, HDIO_DRIVE_CMD, 0x7ffdfeafc074) = -1 EACCES (Permission denied) - # This should be covered by CAP_SYS_RAWIO instead. - # (see: https://www.kernel.org/doc/Documentation/ioctl/hdio.rst) - # It looks like hddtemp works just fine without it. - deny capability sys_admin, - network inet stream, network inet6 stream, @{exec_path} mr, - # Monitored hard drives - /dev/sd[a-z]* r, - # Database file that allows hddtemp to recognize supported drives /etc/hddtemp.db r, - # Needed when the hddtemp daemon is started in the TCP/IP mode - /etc/gai.conf r, - include if exists } diff --git a/apparmor.d/profiles-g-l/hdparm b/apparmor.d/profiles-g-l/hdparm index a4fa349731..53e520509a 100644 --- a/apparmor.d/profiles-g-l/hdparm +++ b/apparmor.d/profiles-g-l/hdparm @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/hdparm +@{exec_path} = @{sbin}/hdparm profile hdparm @{exec_path} flags=(complain) { include include diff --git a/apparmor.d/profiles-g-l/hexchat b/apparmor.d/profiles-g-l/hexchat index 064e850c2c..afc182a0cc 100644 --- a/apparmor.d/profiles-g-l/hexchat +++ b/apparmor.d/profiles-g-l/hexchat @@ -10,17 +10,13 @@ include @{exec_path} = @{bin}/hexchat profile hexchat @{exec_path} { include - include - include - include - include + include include - include include - include - # For python/perl plugins - include include + include + include + include network inet dgram, network inet6 dgram, @@ -34,6 +30,11 @@ profile hexchat @{exec_path} { @{lib}/@{multiarch}/hexchat/** r, @{lib}/@{multiarch}/hexchat/plugins/*.so mr, + # External apps + @{lib}/firefox/firefox rPUx, + + /etc/fstab r, + # Hexchat home files owner @{HOME}/ r, owner @{user_config_dirs}/hexchat/ rw, @@ -41,14 +42,10 @@ profile hexchat @{exec_path} { owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/mountinfo r, - - /etc/fstab r, - - # External apps - @{lib}/firefox/firefox rPUx, + owner @{PROC}/@{pid}/cgroup r, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-g-l/homebank b/apparmor.d/profiles-g-l/homebank index cb459919fa..cfc1d01689 100644 --- a/apparmor.d/profiles-g-l/homebank +++ b/apparmor.d/profiles-g-l/homebank @@ -7,17 +7,27 @@ abi , include @{exec_path} = @{bin}/homebank -profile homebank @{exec_path} { +profile homebank @{exec_path} flags=(attach_disconnected) { include - include + include include + include + include + + #aa:dbus own bus=session name=fr.free.mdoyen.HomeBank @{exec_path} mr, /usr/share/homebank/{,**} r, + owner @{HOME}/**.xhb rw, + owner @{HOME}/**.xhb~ rw, + owner @{HOME}/**.xhb~.@{rand6} rw, + owner @{user_config_dirs}/homebank/{,**} rw, + owner @{PROC}/@{pid}/cgroup r, + include if exists } diff --git a/apparmor.d/profiles-g-l/host b/apparmor.d/profiles-g-l/host index cb9f8d2d91..458dcdc787 100644 --- a/apparmor.d/profiles-g-l/host +++ b/apparmor.d/profiles-g-l/host @@ -18,13 +18,13 @@ profile host @{exec_path} { network inet6 dgram, network inet stream, network inet6 stream, + network netlink raw, @{exec_path} mr, + @{PROC}/version_signature r, owner @{PROC}/@{pids}/task/@{tid}/comm rw, - @{sys}/kernel/mm/transparent_hugepage/enabled r, - include if exists } diff --git a/apparmor.d/profiles-g-l/hostname b/apparmor.d/profiles-g-l/hostname index 7e87173ccf..2e4b26a19d 100644 --- a/apparmor.d/profiles-g-l/hostname +++ b/apparmor.d/profiles-g-l/hostname @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/{hostname,domainname,ypdomainname,nisdomainname,nisdomainname} +@{exec_path} = @{bin}/hostname @{bin}/domainname @{bin}/ypdomainname @{bin}/nisdomainname @{bin}/dnsdomainname profile hostname @{exec_path} flags=(attach_disconnected) { include include @@ -17,12 +17,12 @@ profile hostname @{exec_path} flags=(attach_disconnected) { network inet dgram, network inet6 dgram, - # network ip=127.0.0.1:53, TODO: abi 4.0 network netlink raw, @{exec_path} mr, - owner /dev/tty@{int} rw, + /etc/defaultdomain r, + /etc/hostname r, deny owner @{user_share_dirs}/gvfs-metadata/{,*} r, diff --git a/apparmor.d/profiles-g-l/hugo b/apparmor.d/profiles-g-l/hugo index ed62f48f11..a15c432816 100644 --- a/apparmor.d/profiles-g-l/hugo +++ b/apparmor.d/profiles-g-l/hugo @@ -10,6 +10,7 @@ include @{exec_path} = @{bin}/hugo profile hugo @{exec_path} { include + include include include @@ -26,11 +27,8 @@ profile hugo @{exec_path} { @{lib}/go/bin/go rix, /usr/share/git{,-core}/{,**} r, - /usr/share/mime/{,**} r, /usr/share/terminfo/** r, - /etc/mime.types r, - owner @{user_projects_dirs}/{,**} rw, owner @{user_projects_dirs}/**/.hugo_build.lock rwk, owner @{user_projects_dirs}/**/go.{mod,sum} rwk, diff --git a/apparmor.d/profiles-g-l/hw-probe b/apparmor.d/profiles-g-l/hw-probe index 590d4427ed..7390732019 100644 --- a/apparmor.d/profiles-g-l/hw-probe +++ b/apparmor.d/profiles-g-l/hw-probe @@ -11,7 +11,6 @@ include profile hw-probe @{exec_path} flags=(attach_disconnected) { include include - include capability sys_admin, @@ -24,7 +23,7 @@ profile hw-probe @{exec_path} flags=(attach_disconnected) { @{bin}/{,e}grep rix, @{bin}/{m,g,}awk rix, @{bin}/dd rix, - @{bin}/efibootmgr rix, + @{sbin}/efibootmgr rix, @{bin}/efivar rix, @{bin}/find rix, @{bin}/md5sum rix, @@ -34,35 +33,26 @@ profile hw-probe @{exec_path} flags=(attach_disconnected) { @{bin}/tar rix, @{bin}/uname rix, + @{bin}/vulkaninfo rPUx, @{bin}/acpi rPx, @{bin}/amixer rPx, @{bin}/aplay rPx, - @{bin}/biosdecode rPx, @{bin}/cpuid rPx, @{bin}/cpupower rPx, @{bin}/curl rCx -> curl, @{bin}/df rPx, - @{bin}/dkms rPx, @{bin}/dmesg rPx, - @{bin}/dmidecode rPx, @{bin}/dpkg rPx -> child-dpkg, @{bin}/edid-decode rPx, - @{bin}/ethtool rCx -> netconfig, - @{bin}/fdisk rPx, @{bin}/glxgears rPx, @{bin}/glxinfo rPx, @{bin}/hciconfig rPx, - @{bin}/hdparm rPx, - @{bin}/hwinfo rPx, @{bin}/i2cdetect rPx, - @{bin}/ifconfig rCx -> netconfig, @{bin}/inxi rPx, - @{bin}/iw rCx -> netconfig, - @{bin}/iwconfig rCx -> netconfig, @{bin}/journalctl rCx -> journalctl, @{bin}/killall rCx -> killall, - @{bin}/kmod rix, - @{bin}/lsb_release rPx -> lsb_release, + @{bin}/kmod rCx -> kmod, + @{bin}/lsb_release rPx, @{bin}/lsblk rPx, @{bin}/lscpu rPx, @{bin}/lspci rPx, @@ -70,10 +60,8 @@ profile hw-probe @{exec_path} flags=(attach_disconnected) { @{bin}/memtester rPx, @{bin}/nmcli rPx, @{bin}/pacman rCx -> pacman, - @{bin}/rfkill rPx, @{bin}/rpm rCx -> rpm, @{bin}/sensors rPx, - @{bin}/smartctl rPx, @{bin}/systemctl rCx -> systemctl, @{bin}/systemd-analyze rPx, @{bin}/udevadm rCx -> udevadm, @@ -83,12 +71,23 @@ profile hw-probe @{exec_path} flags=(attach_disconnected) { @{bin}/xdpyinfo rPx, @{bin}/xinput rPx, @{bin}/xrandr rPx, + @{sbin}/biosdecode rPx, + @{sbin}/dkms rPx, + @{sbin}/dmidecode rPx, + @{sbin}/fdisk rPx, + @{sbin}/hdparm rPx, + @{bin}/boltctl rPUx, + @{sbin}/hwinfo rPx, + @{sbin}/rfkill rPx, + @{sbin}/smartctl rPx, /etc/modprobe.d/{,*.conf} r, + @{efi}/EFI/{,**} r, + owner @{HOME}/HW_PROBE/{,**} rw, - audit owner @{tmp}/*/ rw, + owner @{tmp}/@{rand10}/ rw, owner @{tmp}/*/cpu_perf rw, @{sys}/class/drm/ r, @@ -98,19 +97,34 @@ profile hw-probe @{exec_path} flags=(attach_disconnected) { @{sys}/devices/virtual/dmi/id/* r, @{sys}/firmware/efi/efivars/ r, @{sys}/firmware/efi/efivars/* r, - @{sys}/module/*/ r, - @{sys}/module/*/{coresize,refcnt} r, - @{sys}/module/*/holders/ r, @{PROC}/bus/input/devices r, @{PROC}/cmdline r, @{PROC}/interrupts r, @{PROC}/ioports r, - @{PROC}/modules r, @{PROC}/scsi/scsi r, /dev/{,**} r, + profile kmod { + include + include + + capability syslog, + + @{sys}/module/{,**} r, + + include if exists + } + + profile curl flags=(attach_disconnected) { + include + + @{bin}/curl mr, + + include if exists + } + profile pacman flags=(attach_disconnected) { include include @@ -158,9 +172,12 @@ profile hw-probe @{exec_path} flags=(attach_disconnected) { @{run}/log/ rw, /{run,var}/log/journal/ r, /{run,var}/log/journal/@{hex32}/ r, - /{run,var}/log/journal/@{hex32}/user-@{hex}.journal* r, /{run,var}/log/journal/@{hex32}/system.journal* r, - /{run,var}/log/journal/@{hex32}/system@@{hex}.journal* r, + /{run,var}/log/journal/@{hex32}/system@@{hex}-@{hex}.journal* r, + /{run,var}/log/journal/@{hex32}/system@@{hex32}-@{hex16}-@{hex16}.journal* r, + /{run,var}/log/journal/@{hex32}/user-@{hex}.journal* r, + /{run,var}/log/journal/@{hex32}/user-@{uid}@@{hex}-@{hex}.journal* r, + /{run,var}/log/journal/@{hex32}/user-@{uid}@@{hex32}-@{hex16}-@{hex16}.journal* r, owner @{PROC}/@{pid}/stat r, @@ -191,31 +208,6 @@ profile hw-probe @{exec_path} flags=(attach_disconnected) { include if exists } - profile netconfig flags=(attach_disconnected) { - include - - # Not needed - deny capability net_admin, - deny capability net_raw, - - network inet dgram, - network inet6 dgram, - network ipx dgram, - network ax25 dgram, - network appletalk dgram, - network netlink raw, - - @{bin}/iw mr, - @{bin}/ifconfig mr, - @{bin}/iwconfig mr, - @{bin}/ethtool mr, - - owner @{PROC}/@{pid}/net/if_inet6 r, - owner @{PROC}/@{pid}/net/dev r, - - include if exists - } - profile systemctl flags=(attach_disconnected) { include include diff --git a/apparmor.d/profiles-g-l/hwinfo b/apparmor.d/profiles-g-l/hwinfo index e7bf2937c1..3149752083 100644 --- a/apparmor.d/profiles-g-l/hwinfo +++ b/apparmor.d/profiles-g-l/hwinfo @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/hwinfo +@{exec_path} = @{sbin}/hwinfo profile hwinfo @{exec_path} { include include @@ -27,9 +27,10 @@ profile hwinfo @{exec_path} { @{bin}/kmod rCx -> kmod, @{bin}/udevadm rCx -> udevadm, - @{bin}/acpidump rPUx, + @{sbin}/acpidump rPUx, + @{bin}/lsscsi rPx, - @{bin}/dmraid rPUx, + @{sbin}/dmraid rPUx, /usr/share/hwinfo/{,**} r, @@ -39,7 +40,7 @@ profile hwinfo @{exec_path} { @{sys}/bus/{,**/} r, @{sys}/class/*/ r, - @{sys}/devices/@{pci}/** r, + @{sys}/devices/@{pci}/{,**} r, @{sys}/devices/**/{modalias,uevent} r, @{sys}/devices/**/input/**/dev r, @{sys}/devices/virtual/net/*/{type,carrier,address} r, @@ -70,9 +71,12 @@ profile hwinfo @{exec_path} { include include + capability sys_module, + owner @{tmp}/hwinfo*.txt rw, @{sys}/devices/@{pci}/drm/card@{int}/ r, + @{sys}/module/compression r, include if exists } diff --git a/apparmor.d/profiles-g-l/hypnotix b/apparmor.d/profiles-g-l/hypnotix index cda55bc595..ce1ad519b9 100644 --- a/apparmor.d/profiles-g-l/hypnotix +++ b/apparmor.d/profiles-g-l/hypnotix @@ -34,7 +34,7 @@ profile hypnotix @{exec_path} { @{python_path} r, @{sh_path} rix, - @{bin}/ldconfig rix, + @{sbin}/ldconfig rix, @{bin}/mkdir rix, @{bin}/xdg-screensaver rPx, diff --git a/apparmor.d/profiles-g-l/i2cdetect b/apparmor.d/profiles-g-l/i2cdetect index 5ce4da0bb3..f101c56e66 100644 --- a/apparmor.d/profiles-g-l/i2cdetect +++ b/apparmor.d/profiles-g-l/i2cdetect @@ -13,8 +13,13 @@ profile i2cdetect @{exec_path} { @{exec_path} mr, + @{sys}/class/i2c-dev/ r, + @{sys}/devices/@{pci}/i2c-*/{,**/}name r, + owner @{PROC}/@{pid}/mounts r, + /dev/i2c-@{int} rw, + include if exists } diff --git a/apparmor.d/profiles-g-l/i3lock b/apparmor.d/profiles-g-l/i3lock index ea72704c19..e56b2007b4 100644 --- a/apparmor.d/profiles-g-l/i3lock +++ b/apparmor.d/profiles-g-l/i3lock @@ -32,7 +32,7 @@ profile i3lock @{exec_path} { owner @{tmp}/tmp.*.png r, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-g-l/i3lock-fancy b/apparmor.d/profiles-g-l/i3lock-fancy index b192856d25..553758f852 100644 --- a/apparmor.d/profiles-g-l/i3lock-fancy +++ b/apparmor.d/profiles-g-l/i3lock-fancy @@ -41,7 +41,7 @@ profile i3lock-fancy @{exec_path} { owner @{tmp}/sh-thd.* rw, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, profile imagemagic { include @@ -65,7 +65,7 @@ profile i3lock-fancy @{exec_path} { owner @{tmp}/tmp.*.png rw, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-g-l/ifconfig b/apparmor.d/profiles-g-l/ifconfig index 5bebad6910..48181e1302 100644 --- a/apparmor.d/profiles-g-l/ifconfig +++ b/apparmor.d/profiles-g-l/ifconfig @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/ifconfig +@{exec_path} = @{sbin}/ifconfig profile ifconfig @{exec_path} { include include diff --git a/apparmor.d/profiles-g-l/ifup b/apparmor.d/profiles-g-l/ifup index aac25b8115..3c641f8e19 100644 --- a/apparmor.d/profiles-g-l/ifup +++ b/apparmor.d/profiles-g-l/ifup @@ -20,7 +20,7 @@ profile ifup @{exec_path} { @{sh_path} rix, @{bin}/ip rix, - @{bin}/route rix, + @{sbin}/route rix, @{bin}/seq rix, @{bin}/sleep rix, @{bin}/wc rix, @@ -32,7 +32,7 @@ profile ifup @{exec_path} { @{bin}/run-parts rCx -> run-parts, @{bin}/kmod rCx -> kmod, - @{bin}/sysctl rCx -> sysctl, + @{sbin}/sysctl rCx -> sysctl, /etc/network/interfaces r, /etc/network/interfaces.d/{,*} r, @@ -110,7 +110,7 @@ profile ifup @{exec_path} { capability net_admin, capability sys_admin, - @{bin}/sysctl mr, + @{sbin}/sysctl mr, @{PROC}/sys/ r, @{PROC}/sys/** r, diff --git a/apparmor.d/profiles-g-l/im-launch b/apparmor.d/profiles-g-l/im-launch index 04abb7e0cd..58581bd462 100644 --- a/apparmor.d/profiles-g-l/im-launch +++ b/apparmor.d/profiles-g-l/im-launch @@ -17,8 +17,10 @@ profile im-launch @{exec_path} { @{bin}/env rix, @{bin}/gettext{,.sh} rix, @{bin}/gnome-session rix, + @{lib}/gnome-session-binary rPx, @{bin}/gsettings rPx, @{bin}/locale rix, + @{bin}/ibus-daemon rPx, @{bin}/sed rix, @{bin}/sleep rix, @{bin}/startplasma-x11 rPx, @@ -26,7 +28,6 @@ profile im-launch @{exec_path} { @{bin}/true rix, @{bin}/uim-toolbar-gtk3 rPUx, @{bin}/uim-xim rPUx, - @{lib}/gnome-session-binary rPx, @{HOME}/.xsession-errors rw, /usr/share/im-config/{,**} r, @@ -37,7 +38,7 @@ profile im-launch @{exec_path} { owner @{HOME}/.xinputrc r, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-g-l/initd-kexec b/apparmor.d/profiles-g-l/initd-kexec index 074b4e7353..199483f4fb 100644 --- a/apparmor.d/profiles-g-l/initd-kexec +++ b/apparmor.d/profiles-g-l/initd-kexec @@ -19,7 +19,7 @@ profile initd-kexec @{exec_path} { @{bin}/tput rix, @{bin}/echo rix, - @{bin}/kexec rPx, + @{sbin}/kexec rPx, @{bin}/run-parts rCx -> run-parts, @{bin}/systemctl rCx -> systemctl, diff --git a/apparmor.d/profiles-g-l/initd-kexec-load b/apparmor.d/profiles-g-l/initd-kexec-load index 1b27d1a4ea..522d003f3f 100644 --- a/apparmor.d/profiles-g-l/initd-kexec-load +++ b/apparmor.d/profiles-g-l/initd-kexec-load @@ -25,7 +25,7 @@ profile initd-kexec-load @{exec_path} { @{bin}/readlink rix, @{bin}/tput rix, - @{bin}/kexec rPx, + @{sbin}/kexec rPx, @{bin}/run-parts rCx -> run-parts, @{bin}/systemctl rCx -> systemctl, @@ -36,7 +36,7 @@ profile initd-kexec-load @{exec_path} { @{sys}/kernel/kexec_loaded r, - owner /boot/grub/{grub.cfg,grubenv} r, + owner @{efi}/grub/{grub.cfg,grubenv} r, @{PROC}/cmdline r, diff --git a/apparmor.d/profiles-g-l/install-catalog b/apparmor.d/profiles-g-l/install-catalog index b1a56c41d6..6a26d4dea3 100644 --- a/apparmor.d/profiles-g-l/install-catalog +++ b/apparmor.d/profiles-g-l/install-catalog @@ -16,7 +16,7 @@ profile install-catalog @{exec_path} { @{sh_path} rix, @{bin}/basename rix, - @{bin}/grep rix, + @{bin}/{,e}grep rix, @{bin}/mv rix, @{bin}/rm rix, @{bin}/sed rix, diff --git a/apparmor.d/profiles-g-l/install-info b/apparmor.d/profiles-g-l/install-info index f155339b18..65bc75bb78 100644 --- a/apparmor.d/profiles-g-l/install-info +++ b/apparmor.d/profiles-g-l/install-info @@ -7,7 +7,7 @@ abi , include @{exec_path} = @{bin}/install-info -profile install-info @{exec_path} { +profile install-info @{exec_path} flags=(attach_disconnected) { include include diff --git a/apparmor.d/profiles-g-l/inxi b/apparmor.d/profiles-g-l/inxi index 09753107b4..2d6a67d4ad 100644 --- a/apparmor.d/profiles-g-l/inxi +++ b/apparmor.d/profiles-g-l/inxi @@ -13,6 +13,8 @@ profile inxi @{exec_path} { include include + capability dac_read_search, + network inet dgram, network inet6 dgram, network inet stream, @@ -43,11 +45,11 @@ profile inxi @{exec_path} { # shared object file): ignored. @{bin}/dpkg-query rpx, - @{bin}/blockdev rPx, + @{sbin}/blockdev rPx, @{bin}/compton rPx, @{bin}/df rPx, @{bin}/dig rPx, - @{bin}/dmidecode rPx, + @{sbin}/dmidecode rPx, @{bin}/glxinfo rPx, @{bin}/hddtemp rPx, @{bin}/lsblk rPx, @@ -56,7 +58,7 @@ profile inxi @{exec_path} { @{bin}/openbox rPx, @{bin}/ps rPx, @{bin}/sensors rPx, - @{bin}/smartctl rPx, + @{sbin}/smartctl rPx, @{bin}/sudo rPx, @{bin}/uptime rPx, @{bin}/who rPx, diff --git a/apparmor.d/profiles-g-l/ioping b/apparmor.d/profiles-g-l/ioping index 1ff3615f1a..0cb507e364 100644 --- a/apparmor.d/profiles-g-l/ioping +++ b/apparmor.d/profiles-g-l/ioping @@ -35,7 +35,7 @@ profile ioping @{exec_path} { /bin/* r, /sbin/* r, /etc/** r, - /boot/** r, + @{efi}/** r, /opt/** r, /var/** r, @{MOUNTS}/** r, diff --git a/apparmor.d/profiles-g-l/ip b/apparmor.d/profiles-g-l/ip index bcb521c014..7dfc3ba362 100644 --- a/apparmor.d/profiles-g-l/ip +++ b/apparmor.d/profiles-g-l/ip @@ -17,25 +17,33 @@ profile ip @{exec_path} flags=(attach_disconnected) { capability net_admin, capability sys_admin, capability sys_module, + capability sys_ptrace, network netlink raw, - mount fstype=sysfs -> /sys/, + mount fstype=sysfs -> @{sys}, mount options=(rw bind) / -> @{run}/netns/*, mount options=(rw rbind) @{run}/netns/ -> @{run}/netns/, mount options=(rw, bind) @{att}/ -> @{run}/netns/*, mount options=(rw, bind) /etc/netns/*/resolv.conf -> /etc/resolv.conf, mount options=(rw, rshared) -> @{run}/netns/, - mount options=(rw, rslave) -> /, + mount options=(rw, make-rslave) /, umount @{run}/netns/*, - umount /sys/, + umount @{sys}, + + ptrace read, @{exec_path} mrix, # To run command with 'ip netns exec' - @{shells_path} rUx, - @{bin}/sudo rPx, + @{shells_path} rUx, + @{bin}/sudo rPx, + @{bin}/taskset rPUx, + + @{bin}/firewall-cmd rPx, + @{sbin}/firewalld rPx, + @{sbin}/nft rPx, @{att}/ r, @@ -48,12 +56,13 @@ profile ip @{exec_path} flags=(attach_disconnected) { @{run}/netns/* rw, owner @{run}/netns/ rwk, + @{PROC}/ r, owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/net/dev_mcast r, owner @{PROC}/@{pid}/net/igmp{,6} r, owner @{PROC}/sys/net/ipv{4,6}/route/flush w, - /dev/tty@{int} rw, + /dev/net/tun rw, include if exists } diff --git a/apparmor.d/profiles-g-l/irqbalance b/apparmor.d/profiles-g-l/irqbalance index fec2d7c932..29e6e642db 100644 --- a/apparmor.d/profiles-g-l/irqbalance +++ b/apparmor.d/profiles-g-l/irqbalance @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/irqbalance +@{exec_path} = @{sbin}/irqbalance profile irqbalance @{exec_path} flags=(attach_disconnected) { include @@ -33,7 +33,8 @@ profile irqbalance @{exec_path} flags=(attach_disconnected) { @{sys}/devices/system/cpu/isolated r, @{sys}/devices/system/node/ r, @{sys}/devices/system/node/node@{int}/ r, - @{sys}/devices/system/node/node@{int}/{cpumap,meminfo} r, + @{sys}/devices/system/node/node@{int}/cpumap r, + @{sys}/devices/system/node/node@{int}/meminfo r, @{sys}/devices/system/cpu/nohz_full r, @{PROC}/interrupts r, diff --git a/apparmor.d/profiles-g-l/ischroot b/apparmor.d/profiles-g-l/ischroot new file mode 100644 index 0000000000..8c18782f99 --- /dev/null +++ b/apparmor.d/profiles-g-l/ischroot @@ -0,0 +1,23 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/ischroot +profile ischroot @{exec_path} flags=(attach_disconnected) { + include + include + + @{exec_path} mr, + + /var/lib/update-notifier/tmp.@{rand10} w, + + @{PROC}/@{pid}/mountinfo r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-g-l/issue-generator b/apparmor.d/profiles-g-l/issue-generator index 8f2d53f76b..093cd7100f 100644 --- a/apparmor.d/profiles-g-l/issue-generator +++ b/apparmor.d/profiles-g-l/issue-generator @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/issue-generator +@{exec_path} = @{sbin}/issue-generator profile issue-generator @{exec_path} { include include @@ -19,6 +19,7 @@ profile issue-generator @{exec_path} { @{bin}/cat rix, @{bin}/chmod rix, @{bin}/cmp rix, + @{bin}/mkdir rix, @{bin}/mktemp rix, @{bin}/mv rix, @{bin}/rm rix, @@ -30,7 +31,7 @@ profile issue-generator @{exec_path} { @{run}/agetty.reload w, @{run}/issue rw, @{run}/issue.@{rand10} rw, - @{run}/issue.d/{,**} r, + @{run}/issue.d/{,**} rw, /dev/tty rw, diff --git a/apparmor.d/profiles-g-l/iw b/apparmor.d/profiles-g-l/iw index c760c50f66..54155298cc 100644 --- a/apparmor.d/profiles-g-l/iw +++ b/apparmor.d/profiles-g-l/iw @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/iw +@{exec_path} = @{sbin}/iw profile iw @{exec_path} { include @@ -24,7 +24,7 @@ profile iw @{exec_path} { @{sys}/devices/@{pci}/ieee80211/phy@{int}/index r, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-g-l/iwconfig b/apparmor.d/profiles-g-l/iwconfig index 962b4ab235..ec6b9a46b4 100644 --- a/apparmor.d/profiles-g-l/iwconfig +++ b/apparmor.d/profiles-g-l/iwconfig @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/iwconfig +@{exec_path} = @{sbin}/iwconfig profile iwconfig @{exec_path} { include diff --git a/apparmor.d/profiles-g-l/iwlist b/apparmor.d/profiles-g-l/iwlist index 298c946885..b89af77b97 100644 --- a/apparmor.d/profiles-g-l/iwlist +++ b/apparmor.d/profiles-g-l/iwlist @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/iwlist +@{exec_path} = @{sbin}/iwlist profile iwlist @{exec_path} { include diff --git a/apparmor.d/profiles-g-l/jekyll b/apparmor.d/profiles-g-l/jekyll index d3444fea57..1c2c1b4dc2 100644 --- a/apparmor.d/profiles-g-l/jekyll +++ b/apparmor.d/profiles-g-l/jekyll @@ -29,7 +29,8 @@ profile jekyll @{exec_path} { owner @{user_projects_dirs}/**/_site/{,**} rw, owner @{user_projects_dirs}/**/.sass-cache/** rw, - @{PROC}/version r, + @{PROC}/version r, + owner @{PROC}/@{pid}/task/@{tid}/comm rw, include if exists } diff --git a/apparmor.d/profiles-g-l/jgmenu b/apparmor.d/profiles-g-l/jgmenu index 044eda4936..caa5658088 100644 --- a/apparmor.d/profiles-g-l/jgmenu +++ b/apparmor.d/profiles-g-l/jgmenu @@ -11,10 +11,7 @@ include profile jgmenu @{exec_path} { include include - include - include - include - include + include include include @@ -37,23 +34,16 @@ profile jgmenu @{exec_path} { owner @{user_config_dirs}/jgmenu/ rw, owner @{user_config_dirs}/jgmenu/** rw, - owner @{user_cache_dirs}/ rw, owner @{user_cache_dirs}/jgmenu/ rw, owner @{user_cache_dirs}/jgmenu/** rw, - owner @{HOME}/.Xauthority r, - owner @{PROC}/@{pid}/loginuid r, # For zsh shell /etc/zsh/zshenv r, - # For missing apps icon and desktop files - /usr/share/**.png r, - /usr/share/**.desktop r, - # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-g-l/kanyremote b/apparmor.d/profiles-g-l/kanyremote index 0e27fa5ae8..91eb37c581 100644 --- a/apparmor.d/profiles-g-l/kanyremote +++ b/apparmor.d/profiles-g-l/kanyremote @@ -31,7 +31,7 @@ profile kanyremote @{exec_path} { @{bin}/{,e}grep rix, @{bin}/cut rix, @{bin}/id rix, - @{bin}/which{,.debianutils} rix, + @{bin}/which{,.debianutils} rix, @{bin}/tr rix, @{bin}/{m,g,}awk rix, @{bin}/head rix, diff --git a/apparmor.d/profiles-g-l/kconfig-hardened-check b/apparmor.d/profiles-g-l/kconfig-hardened-check index 264e49ebcd..947cfabd12 100644 --- a/apparmor.d/profiles-g-l/kconfig-hardened-check +++ b/apparmor.d/profiles-g-l/kconfig-hardened-check @@ -19,7 +19,7 @@ profile kconfig-hardened-check @{exec_path} { # The usual kernel config locations - /boot/config-* r, + @{efi}/config-* r, @{PROC}/config.gz r, # This is for kernels, which are built manually diff --git a/apparmor.d/profiles-g-l/kdestroy b/apparmor.d/profiles-g-l/kdestroy new file mode 100644 index 0000000000..ccc0a2b25a --- /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/kdump-config b/apparmor.d/profiles-g-l/kdump-config new file mode 100644 index 0000000000..9396b125be --- /dev/null +++ b/apparmor.d/profiles-g-l/kdump-config @@ -0,0 +1,111 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{sbin}/kdump-config +profile kdump-config @{exec_path} flags=(attach_disconnected) { + include + + capability sys_admin, + + @{exec_path} mr, + + @{sh_path} rix, + @{bin}/{,e}grep ix, + @{bin}/basename ix, + @{bin}/cat ix, + @{bin}/cmp ix, + @{bin}/cp ix, + @{bin}/cut ix, + @{bin}/file ix, + @{bin}/find ix, + @{bin}/flock ix, + @{bin}/hexdump ix, + @{bin}/ln ix, + @{bin}/logger ix, + @{bin}/plymouth Px, + @{bin}/readlink ix, + @{bin}/rev ix, + @{bin}/rm ix, + @{bin}/run-parts ix, + @{bin}/sed ix, + @{bin}/systemctl Cx -> systemctl, + @{bin}/uname ix, + @{sbin}/kexec Cx -> kexec, + @{sbin}/sysctl Cx -> sysctl, + + /etc/kernel/postinst.d/kdump-tools rPx, + + /etc/kdump/{,**} r, + /etc/default/kdump-tools r, + /etc/magic r, + + / r, + @{efi}/ r, + + /var/crash/kdump_lock wk, + /var/crash/kexec_cmd w, + /var/lib/kdump/{,**} rw, + + owner /tmp/tmp.@{rand10}/mkinitramfs_@{rand6} rw, + owner /tmp/tmp.@{rand10}/mkinitramfs_@{rand6}/ rw, + owner /tmp/tmp.@{rand10}/mkinitramfs_@{rand6}/** rwl -> /tmp/tmp.@{rand10}/mkinitramfs_@{rand6}/**, + owner /tmp/tmp.@{rand10}/mkinitramfs-@{rand6} rw, + owner /tmp/tmp.@{rand10}/mkinitramfs-*_@{rand6} rw, + + @{sys}/firmware/efi/efivars/ r, + @{sys}/firmware/efi/efivars/SecureBoot-@{uuid} r, + @{sys}/firmware/efi/efivars/SetupMode-@{uuid} r, + @{sys}/kernel/kexec_crash_loaded r, + @{sys}/kernel/kexec/crash_loaded r, + + @{PROC}/cmdline r, + @{PROC}/iomem r, + + profile systemctl flags=(attach_disconnected) { + include + include + + capability net_admin, + capability sys_ptrace, + + ptrace read peer=@{p_systemd}, + + include if exists + } + + profile sysctl { + include + + @{sbin}/sysctl mr, + + @{PROC}/sys/kernel/panic_on_oops rw, + + include if exists + } + + profile kexec { + include + + capability sys_admin, + capability sys_boot, + + @{sbin}/kexec mr, + + @{efi}/* r, + + owner /var/lib/kdump/* r, + + @{PROC}/iomem r, + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-g-l/kdump-tools-init b/apparmor.d/profiles-g-l/kdump-tools-init new file mode 100644 index 0000000000..7767831a87 --- /dev/null +++ b/apparmor.d/profiles-g-l/kdump-tools-init @@ -0,0 +1,40 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = /etc/init.d/kdump-tools +profile kdump-tools-init @{exec_path} flags=(attach_disconnected) { + include + + @{exec_path} mr, + @{sh_path} mr, + + @{bin}/cat ix, + @{bin}/plymouth Px, + @{bin}/run-parts ix, + @{bin}/systemctl Cx -> systemctl, + @{sbin}/kdump-config Px, + + /etc/default/kdump-tools r, + + @{PROC}/cmdline r, + + profile systemctl flags=(attach_disconnected) { + include + include + + capability net_admin, + + ptrace read peer=@{p_systemd}, + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-g-l/kdump_mem_estimator b/apparmor.d/profiles-g-l/kdump_mem_estimator new file mode 100644 index 0000000000..5f85af3fea --- /dev/null +++ b/apparmor.d/profiles-g-l/kdump_mem_estimator @@ -0,0 +1,38 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = /usr/share/kdump-tools/kdump_mem_estimator +profile kdump_mem_estimator @{exec_path} { + include + + @{exec_path} mr, + + @{sh_path} r, + @{bin}/cat ix, + @{bin}/mkdir ix, + @{bin}/uname ix, + @{bin}/systemctl Cx -> systemctl, + @{bin}/uname ix, + + owner /var/lib/kdump/mem* w, + + profile systemctl { + include + include + + capability net_admin, + + ptrace read peer=@{p_systemd}, + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-g-l/keepassxc b/apparmor.d/profiles-g-l/keepassxc index de95d3c9f7..1b78ccc8c1 100644 --- a/apparmor.d/profiles-g-l/keepassxc +++ b/apparmor.d/profiles-g-l/keepassxc @@ -10,8 +10,6 @@ include @{exec_path} = @{bin}/keepassxc profile keepassxc @{exec_path} { include - include - include include include include @@ -76,9 +74,9 @@ profile keepassxc @{exec_path} { owner @{tmp}/keepassxc.socket rw, owner @{tmp}/runtime-user/ w, - owner @{run}/user/@{pid}/app/ w, - owner @{run}/user/@{pid}/app/org.keepassxc.KeePassXC/{,**} rw, owner @{run}/user/@{uid}/.[a-zA-Z]*/{,s} rw, + owner @{run}/user/@{uid}/app/ w, + owner @{run}/user/@{uid}/app/org.keepassxc.KeePassXC/{,**} rw, owner @{run}/user/@{uid}/kpxc_server rw, owner @{run}/user/@{uid}/org.keepassxc.KeePassXC.BrowserServer w, owner @{run}/user/@{uid}/org.keepassxc.KeePassXC/ w, @@ -94,7 +92,7 @@ profile keepassxc @{exec_path} { /dev/shm/#@{int} rw, /dev/tty rw, /dev/urandom w, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, # Silencer deny @{user_share_dirs}/gvfs-metadata/* r, diff --git a/apparmor.d/profiles-g-l/keepassxc-proxy b/apparmor.d/profiles-g-l/keepassxc-proxy index 24a30c56c9..03a64a64d4 100644 --- a/apparmor.d/profiles-g-l/keepassxc-proxy +++ b/apparmor.d/profiles-g-l/keepassxc-proxy @@ -24,10 +24,10 @@ profile keepassxc-proxy @{exec_path} { /usr/share/icons/*/index.theme r, - owner @{run}/user/@{pid}/app/ w, - owner @{run}/user/@{pid}/org.keepassxc.KeePassXC.BrowserServer rw, - owner @{run}/user/@{pid}/org.keepassxc.KeePassXC/ rw, + owner @{run}/user/@{uid}/app/ w, owner @{run}/user/@{uid}/app/org.keepassxc.KeePassXC/ rw, + owner @{run}/user/@{uid}/org.keepassxc.KeePassXC.BrowserServer rw, + owner @{run}/user/@{uid}/org.keepassxc.KeePassXC/ rw, # file_inherit deny owner @{run}/user/@{uid}/.[a-zA-Z]*/{,s} rw, diff --git a/apparmor.d/profiles-g-l/kernel b/apparmor.d/profiles-g-l/kernel new file mode 100644 index 0000000000..2aa7c45bd3 --- /dev/null +++ b/apparmor.d/profiles-g-l/kernel @@ -0,0 +1,83 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = /etc/kernel/{,header_}postinst.d/* /etc/kernel/postrm.d/* +@{exec_path} += /etc/kernel/preinst.d/* /etc/kernel/prerm.d/* +profile kernel @{exec_path} { + include + include + include + + @{exec_path} mr, + + @{sh_path} rix, + @{bin}/{,e}grep rix, + @{bin}/{,m,g}awk rix, + @{bin}/cat rix, + @{bin}/chmod rix, + @{bin}/cut rix, + @{bin}/dirname rix, + @{bin}/kernel-install rm, + @{bin}/kmod rCx -> kmod, + @{bin}/mv rix, + @{bin}/rm rix, + @{bin}/rmdir rix, + @{bin}/sed rix, + @{bin}/sort rix, + @{bin}/touch rix, + @{bin}/tr rix, + @{bin}/uname rix, + @{bin}/which{,.debianutils} rix, + + @{bin}/apt-config rPx, + @{bin}/bootctl rPx, + @{bin}/dpkg rPx -> child-dpkg, + @{bin}/kernel-install rPx, + @{bin}/systemd-detect-virt rPx, + @{bin}/update-alternatives rPx, + @{lib}/dkms/dkms_autoinstaller rPx, + @{sbin}/dkms rPx, + @{sbin}/update-grub rPx, + @{sbin}/update-initramfs rPx, + + @{lib}/modules/*/updates/ w, + @{lib}/modules/*/updates/dkms/ w, + + /etc/kernel/header_postinst.d/* r, + /etc/kernel/{postinst,postrm,preinst,prerm}.d/* r, + + # For shell pwd + / r, + @{efi}/ r, + + /etc/apt/apt.conf.d/ r, + /etc/apt/apt.conf.d/01autoremove-kernels{,.dpkg-new} rw, + + /var/lib/kdump/* w, + + @{run}/reboot-required w, + @{run}/reboot-required.pkgs rw, + + @{PROC}/devices r, + @{PROC}/cmdline r, + + profile kmod { + include + include + + capability sys_module, + + @{sys}/module/compression r, + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-g-l/kernel-install b/apparmor.d/profiles-g-l/kernel-install index 07c058124a..dede5da41c 100644 --- a/apparmor.d/profiles-g-l/kernel-install +++ b/apparmor.d/profiles-g-l/kernel-install @@ -11,22 +11,20 @@ include profile kernel-install @{exec_path} { include include + include include + capability sys_rawio, + capability sys_resource, + + ptrace read peer=@{p_systemd}, + @{exec_path} r, @{sh_path} rix, - + @{coreutils_path} rix, + @{bin}/kmod rCx -> kmod, @{bin}/mountpoint rix, - @{bin}/sort rix, - @{bin}/rm rix, - @{bin}/mkdir rix, - @{bin}/cp rix, - @{bin}/chown rix, - @{bin}/chmod rix, - @{bin}/basename rix, - @{pager_path} rPx -> child-pager, - @{bin}/kmod rCx -> kmod, @{lib}/kernel/install.d/ r, @{lib}/kernel/install.d/@{int2}-*.install rix, @@ -37,27 +35,39 @@ profile kernel-install @{exec_path} { @{lib}/os-release r, /etc/kernel/cmdline r, /etc/kernel/tries r, + /etc/kernel/entry-token r, /etc/machine-id r, /etc/os-release r, /var/lib/dbus/machine-id r, @{lib}/modules/*/modules.* w, - owner /boot/{vmlinuz,initrd.img}-* r, - owner /boot/[a-f0-9]*/*/ rw, - owner /boot/[a-f0-9]*/*/{linux,initrd} w, - owner /boot/loader/ rw, - owner /boot/loader/entries/ rw, - owner /boot/loader/entries/*.conf w, + / r, + + @{efi}/@{hex32}/** rw, + @{efi}/loader/entries.srel r, + owner @{efi}/{vmlinuz,initrd.img}-* r, + owner @{efi}/loader/ rw, + owner @{efi}/loader/entries/ rw, + owner @{efi}/loader/entries/*.conf w, + + owner /tmp/kernel-install.staging.@{rand6}/{,**} rw, owner @{tmp}/sh-thd.* rw, + @{PROC}/@{pid}/mountinfo r, + @{PROC}/1/environ r, @{PROC}/cmdline r, + @{PROC}/sys/kernel/osrelease r, profile kmod { include include + @{lib}/modules/*/modules.* w, + + @{sys}/module/compression r, + include if exists } diff --git a/apparmor.d/profiles-g-l/kernel-postinst-kdump b/apparmor.d/profiles-g-l/kernel-postinst-kdump new file mode 100644 index 0000000000..fa2074c2bd --- /dev/null +++ b/apparmor.d/profiles-g-l/kernel-postinst-kdump @@ -0,0 +1,66 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = /etc/kernel/postinst.d/kdump-tools +profile kernel-postinst-kdump @{exec_path} { + include + include + + @{exec_path} mr, + + @{sh_path} r, + @{bin}/{,e}grep rix, + @{bin}/{m,g,}awk rix, + @{bin}/cp rix, + @{bin}/du rix, + @{bin}/find rix, + @{bin}/kmod rCx -> kmod, + @{bin}/ischroot rPx, + @{bin}/linux-version rPx, + @{bin}/mkdir rix, + @{bin}/mktemp rix, + @{bin}/mv rix, + @{bin}/rm rix, + @{bin}/sync rix, + @{bin}/cut rix, + @{sbin}/mkinitramfs rPx, + + / r, + + /etc/initramfs-tools/{,**} r, + + owner /var/lib/kdump/** rw, + + owner /tmp/tmp.@{rand10}/ rw, + owner /tmp/tmp.@{rand10}/modules_@{rand6} rw, + + owner /tmp/tmp.@{rand10}/mkinitramfs_@{rand6} rw, + owner /tmp/tmp.@{rand10}/mkinitramfs_@{rand6}/ rw, + owner /tmp/tmp.@{rand10}/mkinitramfs_@{rand6}/** rwl -> /tmp/tmp.@{rand10}/mkinitramfs_@{rand6}/**, + owner /tmp/tmp.@{rand10}/mkinitramfs-@{rand6} rw, + owner /tmp/tmp.@{rand10}/mkinitramfs-*_@{rand6} rw, + + profile kmod { + include + include + + capability syslog, # optional: no audit + + @{sys}/module/*/ r, + @{sys}/module/*/coresize r, + @{sys}/module/*/holders/ r, + @{sys}/module/*/refcnt r, + @{sys}/module/compression r, + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-g-l/kerneloops b/apparmor.d/profiles-g-l/kerneloops index 815fa4e382..70c8b94607 100644 --- a/apparmor.d/profiles-g-l/kerneloops +++ b/apparmor.d/profiles-g-l/kerneloops @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/kerneloops +@{exec_path} = @{sbin}/kerneloops profile kerneloops @{exec_path} { include include diff --git a/apparmor.d/profiles-g-l/kerneloops-applet b/apparmor.d/profiles-g-l/kerneloops-applet index 8f5e66cbc6..9e54844184 100644 --- a/apparmor.d/profiles-g-l/kerneloops-applet +++ b/apparmor.d/profiles-g-l/kerneloops-applet @@ -10,8 +10,8 @@ include @{exec_path} = @{bin}/kerneloops-applet profile kerneloops-applet @{exec_path} { include - include include + include @{exec_path} mr, diff --git a/apparmor.d/profiles-g-l/kexec b/apparmor.d/profiles-g-l/kexec index 102b75d831..09c414430e 100644 --- a/apparmor.d/profiles-g-l/kexec +++ b/apparmor.d/profiles-g-l/kexec @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/kexec +@{exec_path} = @{sbin}/kexec profile kexec @{exec_path} flags=(complain) { include @@ -15,7 +15,7 @@ profile kexec @{exec_path} flags=(complain) { @{exec_path} mr, - owner /boot/{initrd.img,vmlinuz}-* r, + owner @{efi}/{initrd.img,vmlinuz}-* r, @{sys}/firmware/memmap/ r, @{sys}/firmware/memmap/@{int}/{start,end,type} r, diff --git a/apparmor.d/profiles-g-l/kinit b/apparmor.d/profiles-g-l/kinit new file mode 100644 index 0000000000..706a11c10a --- /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 0000000000..f21f34295e --- /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/kmod b/apparmor.d/profiles-g-l/kmod index 08fc10c226..3495865e30 100644 --- a/apparmor.d/profiles-g-l/kmod +++ b/apparmor.d/profiles-g-l/kmod @@ -10,7 +10,7 @@ include @{exec_path} = @{bin}/{kmod,lsmod,depmod,insmod,rmmod,modinfo,modprobe} profile kmod @{exec_path} flags=(attach_disconnected) { include - include + include include capability dac_read_search, @@ -28,17 +28,13 @@ profile kmod @{exec_path} flags=(attach_disconnected) { @{bin}/basename rix, @{bin}/false rix, @{bin}/id rix, - @{bin}/sysctl rPx, + @{sbin}/sysctl rCx -> sysctl, @{bin}/true rix, - @{lib}/modprobe.d/{,*.conf} r, @{lib}/modules/*/modules.* rw, @{run}/modprobe.d/{,*.conf} r, - /etc/depmod.d/{,**} r, - /etc/modprobe.d/{,*.conf} r, - /tmp/**/*.ko{,.zst} r, /usr/src/*/*.ko r, /var/lib/dkms/**/module/*.ko r, @@ -48,7 +44,7 @@ profile kmod @{exec_path} flags=(attach_disconnected) { owner /var/tmp/*modules*/{,**} rw, owner /var/tmp/dracut.*/{,**} rw, - owner /boot/System.map-* r, + owner @{efi}/System.map-* r, owner @{tmp}/mkinitcpio.*/{,**} rw, # For local kernel build @@ -66,14 +62,25 @@ profile kmod @{exec_path} flags=(attach_disconnected) { @{sys}/module/{,**} r, - @{PROC}/cmdline r, - @{PROC}/modules r, + @{PROC}/kallsyms r, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, deny @{user_share_dirs}/gvfs-metadata/* r, deny unix (receive) type=stream, + profile sysctl { + include + + @{sbin}/sysctl mr, + + /etc/sysctl.conf r, + /etc/sysctl.d/{,**} r, + @{lib}/sysctl.d/{,**} r, + + include if exists + } + include if exists } diff --git a/apparmor.d/profiles-g-l/kodi b/apparmor.d/profiles-g-l/kodi index fc6a6ede57..9d6c9d1c2c 100644 --- a/apparmor.d/profiles-g-l/kodi +++ b/apparmor.d/profiles-g-l/kodi @@ -30,11 +30,11 @@ profile kodi @{exec_path} { @{bin}/df rix, @{bin}/dirname rix, @{bin}/find rix, - @{bin}/ldconfig rix, + @{sbin}/ldconfig rix, @{bin}/mv rix, @{bin}/uname rix, - @{bin}/lsb_release rPx -> lsb_release, + @{bin}/lsb_release rPx, /usr/share/kodi/{,**} r, /usr/share/publicsuffix/* r, @@ -50,7 +50,8 @@ profile kodi @{exec_path} { owner @{HOME}/core w, owner @{HOME}/kodi_crashlog-@{int}_@{int}.log w, - @{run}/udev/data/* r, + @{run}/udev/data/+*:* r, # Identifies all subsystems + @{run}/udev/data/c@{int}:@{int} r, # Identifies all character devices @{sys}/**/ r, @{sys}/devices/@{pci}/usb@{int}/{bDeviceClass,idProduct,idVendor} r, diff --git a/apparmor.d/profiles-g-l/kvm-ok b/apparmor.d/profiles-g-l/kvm-ok index eb3d1cc80e..f62e9ddf98 100644 --- a/apparmor.d/profiles-g-l/kvm-ok +++ b/apparmor.d/profiles-g-l/kvm-ok @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/kvm-ok +@{exec_path} = @{sbin}/kvm-ok profile kvm-ok @{exec_path} { include @@ -20,7 +20,7 @@ profile kvm-ok @{exec_path} { @{bin}/kmod rCx -> kmod, - @{bin}/rdmsr rPx, + @{sbin}/rdmsr rPx, #/proc/cpuinfo r, #/dev/kvm r, diff --git a/apparmor.d/profiles-g-l/labwc b/apparmor.d/profiles-g-l/labwc index 93234bf520..351ffc116d 100644 --- a/apparmor.d/profiles-g-l/labwc +++ b/apparmor.d/profiles-g-l/labwc @@ -38,16 +38,14 @@ profile labwc @{exec_path} flags=(attach_disconnected) { @{sys}/devices/@{pci}/boot_vga r, @{sys}/devices/**/uevent r, - @{run}/udev/data/+acpi:* r, # for ? + @{run}/udev/data/+acpi:* r, # Exposes ACPI objects (power buttons, batteries, thermal) @{run}/udev/data/+drm:card@{int}-* r, # for screen outputs - @{run}/udev/data/+hid:* r, # for HID-Compliant Keyboard - @{run}/udev/data/+hid:* r, # for HID-Compliant Keyboard + @{run}/udev/data/+hid:* r, # For Human Interface Device (mice, controllers, drawing tablets, scanners) @{run}/udev/data/+pci:* r, # Identifies all PCI devices (CPU, GPU, Network, Disks, USB, etc.) - @{run}/udev/data/+platform:* r, # for ? + @{run}/udev/data/+platform:* r, # Identifies onboard devices (laptop/board model, power controllers, thermal sensors) @{run}/udev/data/+serio:* r, # for touchpad? @{run}/udev/data/+sound:card@{int} r, # for sound card @{run}/udev/data/c13:@{int} r, # for /dev/input/* - @{run}/udev/data/c226:@{int} r, # for /dev/dri/card* @{run}/systemd/sessions/* r, @{run}/systemd/seats/seat@{int} r, diff --git a/apparmor.d/profiles-g-l/landscape-sysinfo b/apparmor.d/profiles-g-l/landscape-sysinfo index 3b140b2bf8..42d67bf61e 100644 --- a/apparmor.d/profiles-g-l/landscape-sysinfo +++ b/apparmor.d/profiles-g-l/landscape-sysinfo @@ -9,6 +9,7 @@ include @{exec_path} = @{bin}/landscape-sysinfo profile landscape-sysinfo @{exec_path} { include + include include include include @@ -25,19 +26,20 @@ profile landscape-sysinfo @{exec_path} { @{exec_path} mr, - @{bin}/who rix, + @{bin}/who rPx, - @{lib}/@{python_name}/dist-packages/landscape/{,**/}__pycache__/ w, - @{lib}/@{python_name}/dist-packages/landscape/{,**/}__pycache__/**.pyc w, - @{lib}/@{python_name}/dist-packages/landscape/{,**/}__pycache__/**.pyc.@{u64} w, + @{lib}/@{python_name}/**/__pycache__/ w, + @{lib}/@{python_name}/**/__pycache__/**.pyc w, + @{lib}/@{python_name}/**/__pycache__/**.pyc.@{u64} w, /var/log/landscape/{,**} rw, + @{run}/systemd/sessions/{,*} r, @{run}/utmp rwk, @{sys}/class/hwmon/ r, @{sys}/class/thermal/ r, - @{sys}/devices/virtual/thermal/thermal_zone@{int}/temp r, + @{sys}/devices/virtual/thermal/thermal_zone@{int}/{,*} r, @{PROC}/ r, @{PROC}/@{pids}/cmdline r, @@ -47,7 +49,7 @@ profile landscape-sysinfo @{exec_path} { owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/mounts r, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-g-l/landscape-sysinfo.wrapper b/apparmor.d/profiles-g-l/landscape-sysinfo.wrapper index aeac3e6a11..5b978cc201 100644 --- a/apparmor.d/profiles-g-l/landscape-sysinfo.wrapper +++ b/apparmor.d/profiles-g-l/landscape-sysinfo.wrapper @@ -25,7 +25,7 @@ profile landscape-sysinfo.wrapper @{exec_path} { @{bin}/cut rix, @{bin}/date rix, @{bin}/find rix, - @{bin}/grep rix, + @{bin}/{,e}grep rix, @{bin}/landscape-sysinfo rPx, / r, @@ -37,7 +37,7 @@ profile landscape-sysinfo.wrapper @{exec_path} { @{PROC}/loadavg r, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-g-l/language-validate b/apparmor.d/profiles-g-l/language-validate index bf999b79ee..91f058d27d 100644 --- a/apparmor.d/profiles-g-l/language-validate +++ b/apparmor.d/profiles-g-l/language-validate @@ -15,11 +15,12 @@ profile language-validate @{exec_path} flags=(attach_disconnected) { @{exec_path} mrix, @{sh_path} rix, - @{bin}/grep rix, + @{bin}/{,e}grep rix, @{bin}/locale rix, + @{bin}/perl r, - /usr/share/locale-langpack/{,*} r, /usr/share/language-tools/{,*} r, + /usr/share/locale-langpack/{,*} r, include if exists } diff --git a/apparmor.d/profiles-g-l/libreoffice b/apparmor.d/profiles-g-l/libreoffice index b1b4ccb707..b818e5a20e 100644 --- a/apparmor.d/profiles-g-l/libreoffice +++ b/apparmor.d/profiles-g-l/libreoffice @@ -8,24 +8,23 @@ include @{exec_path} = @{bin}/libreoffice @{bin}/soffice @{exec_path} += @{lib}/libreoffice/program/soffice -profile libreoffice @{exec_path} { +profile libreoffice @{exec_path} flags=(attach_disconnected,mediate_deleted) { include include - include - include - include - include - include - include - include + include + include + include include include include include include include + include include include + include + include include include include @@ -36,17 +35,24 @@ profile libreoffice @{exec_path} { network inet6 stream, network netlink raw, - #aa:dbus own bus=session name=org.libreoffice interface+=org.gtk.Actions + #aa:dbus own bus=session name=org.libreoffice + + dbus send bus=system path=/org/freedesktop/hostname1 + interface=org.freedesktop.DBus.Properties + member=GetAll + peer=(name=@{busname}, label=systemd-hostnamed), @{exec_path} mr, @{sh_path} rix, + @{bin}/{,e}grep rix, @{bin}/basename rix, @{bin}/dirname rix, - @{bin}/grep rix, @{bin}/ls rix, + @{bin}/net rix, @{bin}/paperconf rix, @{bin}/sed rix, + @{bin}/testparm rix, @{bin}/uname rix, @{open_path} rPx -> child-open-browsers, @@ -54,6 +60,7 @@ profile libreoffice @{exec_path} { @{bin}/gpg rPx, @{bin}/gpgconf rPx, @{bin}/gpgsm rPx, + #aa:exec kioworker @{lib}/jvm/java*/bin/java rix, @{lib}/jvm/java*/lib/** rm, @@ -74,25 +81,32 @@ profile libreoffice @{exec_path} { /usr/share/mythes/{,**} r, /usr/share/thumbnailers/{,**} r, - /etc/java{,-}{,@{version}}-openjdk/{,**} r, + /etc/cups/ppd/*.ppd 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 @{lib}/@{python_name}/{,**/}__pycache__/ w, + owner @{lib}/@{python_name}/{,**/}__pycache__/uno**.pyc w, + owner @{lib}/@{python_name}/{,**/}__pycache__/uno**.pyc.@{u64} 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, - owner @{tmp}/ r, + @{tmp}/ r, owner @{tmp}/.java_pid@{int}{,.tmp} rw, owner @{tmp}/@{hex} rw, owner @{tmp}/@{rand6} rwk, @@ -100,22 +114,20 @@ profile libreoffice @{exec_path} { owner @{tmp}/*.tmp/{,**} rwk, owner @{tmp}/hsperfdata_@{user}/ rw, owner @{tmp}/hsperfdata_@{user}/@{int} rwk, - owner @{tmp}/OSL_PIPE_@{uid}_SingleOfficeIPC_@{hex32} rw, + owner @{tmp}/OSL_PIPE_@{uid}_SingleOfficeIPC_@{hex} rw, owner @{run}/user/@{uid}/#@{int} rw, + owner @{run}/user/@{uid}/soffice.bin@{rand6}.@{d}.kioworker.socket l -> @{run}/user/@{uid}/#@{int}, + owner @{run}/user/@{uid}/gvfsd/socket-@{rand8} rw, @{sys}/devices/system/cpu/cpu@{int}/microcode/version r, @{sys}/devices/virtual/block/**/queue/rotational r, @{sys}/kernel/mm/hugepages/ r, - @{sys}/kernel/mm/transparent_hugepage/enabled r, @{sys}/kernel/mm/transparent_hugepage/shmem_enabled r, - @{sys}/kernel/mm/transparent_hugepage/hpage_pmd_size r, - @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/session-@{word}.scope/{cpu,memory}.max r, - owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/**/memory.max r, - owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/session.slice/org.gnome.Shell@wayland.service/memory.max r, + @{PROC}/@{pid}/net/if_inet6 r, @{PROC}/cgroups r, - owner @{PROC}/@{pid}/cgroup r, + @{PROC}/version r, owner @{PROC}/@{pid}/coredump_filter rw, owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/mounts r, diff --git a/apparmor.d/profiles-g-l/light b/apparmor.d/profiles-g-l/light index 6ce5f2f576..2687894573 100644 --- a/apparmor.d/profiles-g-l/light +++ b/apparmor.d/profiles-g-l/light @@ -10,6 +10,7 @@ include @{exec_path} = @{bin}/light profile light @{exec_path} { include + include @{exec_path} mr, @@ -21,19 +22,8 @@ profile light @{exec_path} { owner @{user_config_dirs}/light/ rw, owner @{user_config_dirs}/light/** rw, - @{sys}/class/backlight/ r, - @{sys}/class/leds/ r, - @{sys}/devices/@{pci}/*_backlight/{,max_,actual_}brightness rw, - @{sys}/devices/@{pci}/*_backlight/{uevent,type,enabled} r, - @{sys}/devices/@{pci}/backlight/**/{,max_,actual_}brightness rw, - @{sys}/devices/@{pci}/backlight/**/{uevent,type,enabled} r, - @{sys}/devices/@{pci}/backlight/**/brightness rw, - @{sys}/devices/**/leds/**/{,max_,actual_}brightness rw, - @{sys}/devices/**/leds/**/{uevent,type,enabled} r, - @{sys}/devices/**/leds/**/brightness_hw_changed r, - # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, owner @{HOME}/.xsession-errors w, include if exists diff --git a/apparmor.d/profiles-g-l/light-locker b/apparmor.d/profiles-g-l/light-locker index 8d2fcdcc87..e8c93ffffd 100644 --- a/apparmor.d/profiles-g-l/light-locker +++ b/apparmor.d/profiles-g-l/light-locker @@ -11,19 +11,12 @@ include profile light-locker @{exec_path} { include include - include - include - include + include include - include include - include @{exec_path} mr, - @{PROC}/1/cgroup r, - owner @{PROC}/@{pid}/cgroup r, - # when locking the screen and switching/closing sessions @{run}/systemd/sessions/* r, @@ -33,8 +26,11 @@ profile light-locker @{exec_path} { @{sys}/devices/@{pci}/subsystem_vendor r, @{sys}/devices/@{pci}/subsystem_device r, + @{PROC}/1/cgroup r, + owner @{PROC}/@{pid}/cgroup r, + # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-g-l/linux-check-removal b/apparmor.d/profiles-g-l/linux-check-removal index 1c6ff2f03d..ac0219c6e6 100644 --- a/apparmor.d/profiles-g-l/linux-check-removal +++ b/apparmor.d/profiles-g-l/linux-check-removal @@ -8,44 +8,17 @@ abi , include @{exec_path} = @{bin}/linux-check-removal -profile linux-check-removal @{exec_path} flags=(complain) { +profile linux-check-removal @{exec_path} { include - include - include + include - @{exec_path} r, + @{exec_path} rmix, - # Think what to do about this (#FIXME#) - /usr/share/debconf/frontend rPx, - #/usr/share/debconf/frontend rCx -> frontend, + @{bin}/stty rix, + /etc/shadow r, - profile frontend flags=(complain) { - include - include - include - include - - /usr/share/debconf/frontend r, - - @{bin}/linux-check-removal rPx, - - @{sh_path} rix, - @{bin}/stty rix, - @{bin}/locale rix, - - # The following is needed when debconf uses dialog/whiptail frontend. - @{bin}/whiptail rPx, - owner @{tmp}/file* w, - - /usr/share/debconf/confmodule r, - - /etc/debconf.conf r, - owner /var/cache/debconf/{config,passwords,templates}.dat{,-new,-old} rwk, - /usr/share/debconf/templates/adequate.templates r, - - include if exists - } + @{PROC}/1/environ r, include if exists } diff --git a/apparmor.d/profiles-g-l/linux-update-symlinks b/apparmor.d/profiles-g-l/linux-update-symlinks new file mode 100644 index 0000000000..b97a0305b5 --- /dev/null +++ b/apparmor.d/profiles-g-l/linux-update-symlinks @@ -0,0 +1,25 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/linux-update-symlinks +profile linux-update-symlinks @{exec_path} { + include + include + include + + @{exec_path} mr, + + /etc/kernel-img.conf r, + + @{efi}/ r, + @{efi}/* rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-g-l/linux-version b/apparmor.d/profiles-g-l/linux-version index a956477127..c718b6495d 100644 --- a/apparmor.d/profiles-g-l/linux-version +++ b/apparmor.d/profiles-g-l/linux-version @@ -15,7 +15,7 @@ profile linux-version @{exec_path} { @{exec_path} r, - /boot/ r, + @{efi}/ r, include if exists } diff --git a/apparmor.d/profiles-g-l/linuxqq b/apparmor.d/profiles-g-l/linuxqq index 3f31344001..caafdd40cc 100644 --- a/apparmor.d/profiles-g-l/linuxqq +++ b/apparmor.d/profiles-g-l/linuxqq @@ -7,6 +7,7 @@ abi , include @{name} = QQ +@{domain} = org.chromium.Chromium @{lib_dirs} = /opt/QQ/ @{config_dirs} = @{user_config_dirs}/@{name} @{cache_dirs} = @{user_cache_dirs}/@{name} @@ -17,7 +18,6 @@ profile linuxqq @{exec_path} flags=(attach_disconnected) { include include include - include network netlink raw, network netlink dgram, @@ -29,14 +29,11 @@ profile linuxqq @{exec_path} flags=(attach_disconnected) { @{exec_path} mrix, @{sh_path} r, - @{bin}/grep rix, - @{lib_dirs}/chrome_crashpad_handler ix, + @{bin}/{,e}grep rix, @{lib_dirs}/resources/app/{,**} m, - @{open_path} rPx -> child-open-strict, - /etc/machine-id r, + @{open_path} rPx -> child-open-strict, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, @{run}/utmp r, owner @{PROC}/@{pid}/loginuid r, diff --git a/apparmor.d/profiles-g-l/localsend b/apparmor.d/profiles-g-l/localsend index ad2e23fc63..810694a5ce 100644 --- a/apparmor.d/profiles-g-l/localsend +++ b/apparmor.d/profiles-g-l/localsend @@ -9,15 +9,19 @@ include @{exec_path} = @{bin}/localsend profile localsend @{exec_path} { include - include - include + include include include + include + include + include include -# --system-talk-name=org.freedesktop.NetworkManager -# - --system-talk-name=org.freedesktop.hostname1 -# --talk-name=org.kde.StatusNotifierWatcher + network inet dgram, + network inet stream, + network inet6 dgram, + network inet6 stream, + network netlink raw, @{exec_path} mr, diff --git a/apparmor.d/profiles-g-l/logrotate b/apparmor.d/profiles-g-l/logrotate index fdd3b6209f..781a01a278 100644 --- a/apparmor.d/profiles-g-l/logrotate +++ b/apparmor.d/profiles-g-l/logrotate @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/logrotate +@{exec_path} = @{sbin}/logrotate profile logrotate @{exec_path} flags=(attach_disconnected) { include include @@ -21,8 +21,8 @@ profile logrotate @{exec_path} flags=(attach_disconnected) { capability setgid, capability setuid, - signal (send) set=(hup), - signal (send) set=(term cont) peer=systemd-tty-ask-password-agent, + signal send set=hup, + signal send set=(term cont) peer=systemd-tty-ask-password-agent, @{exec_path} mr, @@ -30,9 +30,9 @@ profile logrotate @{exec_path} flags=(attach_disconnected) { @{sh_path} rix, @{bin}/cat rix, - @{bin}/grep rix, + @{bin}/{,e}grep rix, @{bin}/gzip rix, - @{bin}/invoke-rc.d rix, + @{sbin}/invoke-rc.d rix, @{bin}/kill rix, @{bin}/ls rix, @{bin}/setfacl rix, @@ -80,6 +80,8 @@ profile logrotate @{exec_path} flags=(attach_disconnected) { capability net_admin, capability sys_ptrace, + ptrace read peer=@{p_systemd}, + dbus send bus=system path=/org/freedesktop/systemd1 interface=org.freedesktop.systemd1.Manager member=KillUnit diff --git a/apparmor.d/profiles-g-l/lsb-release b/apparmor.d/profiles-g-l/lsb-release new file mode 100644 index 0000000000..0fcd83b536 --- /dev/null +++ b/apparmor.d/profiles-g-l/lsb-release @@ -0,0 +1,48 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Note: named "lsb-release" to not conflict with upstreamed "lsb_release" that +# does attach @{bin}/lsb_release. + +abi , + +include + +@{exec_path} = @{bin}/lsb_release +profile lsb-release @{exec_path} flags=(attach_disconnected) { + include + include + + @{exec_path} mr, + + @{sh_path} rix, + @{bin}/ r, + @{bin}/basename rix, + @{bin}/cat rix, + @{bin}/cut rix, + @{bin}/find rix, + @{bin}/getopt rix, + @{bin}/head rix, + @{bin}/sed rix, + @{bin}/tr rix, + + #aa:only apt + @{bin}/dpkg-query px, + + @{etc_ro}/ r, + @{etc_ro}/*-release r, + @{etc_ro}/lsb-release r, + @{etc_ro}/lsb-release.d/{,*} r, + + # file_inherit + deny /opt/*/** r, + deny owner @{user_config_dirs}/*/** r, + deny owner @{user_share_dirs}/*/ r, + deny owner @{tmp}/.org.chromium.Chromium.@{rand6} rw, + deny owner /dev/shm/.org.chromium.Chromium.@{rand6} rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-g-l/lxappearance b/apparmor.d/profiles-g-l/lxappearance index a7c3a21777..4651c3c69c 100644 --- a/apparmor.d/profiles-g-l/lxappearance +++ b/apparmor.d/profiles-g-l/lxappearance @@ -28,7 +28,7 @@ profile lxappearance @{exec_path} { owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/mounts r, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, profile bus { include diff --git a/apparmor.d/profiles-g-l/lynx b/apparmor.d/profiles-g-l/lynx index a9613e7c17..0f324e6972 100644 --- a/apparmor.d/profiles-g-l/lynx +++ b/apparmor.d/profiles-g-l/lynx @@ -10,11 +10,12 @@ include @{exec_path} = @{bin}/lynx profile lynx @{exec_path} { include + include include - include include include include + include network inet dgram, network inet6 dgram, @@ -31,7 +32,6 @@ profile lynx @{exec_path} { /etc/lynx.lss r, /etc/lynx/{,**} r, /etc/mailcap r, - /etc/mime.types r, owner @{tmp}/lynxXXXX*/{,**} rw, diff --git a/apparmor.d/profiles-m-r/initramfs-hooks b/apparmor.d/profiles-m-r/initramfs-hooks new file mode 100644 index 0000000000..678792f748 --- /dev/null +++ b/apparmor.d/profiles-m-r/initramfs-hooks @@ -0,0 +1,126 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = /usr/share/initramfs-tools/hooks/** /etc/initramfs-tools/hooks/** +profile initramfs-hooks @{exec_path} { + include + include + include + include + + capability dac_read_search, + capability sys_admin, # optional: no audit + + mqueue getattr type=posix, + + @{exec_path} mr, + + @{sh_path} rix, + @{coreutils_path} rix, + @{bin}/{,3}cpio ix, + @{bin}/dpkg Px, + @{bin}/fc-cache ix, + @{bin}/fc-match Px, + @{bin}/ischroot Px, + @{bin}/plymouth Px, + @{bin}/update-alternatives Px, + @{ldd_path} Cx -> ldd, + @{lib}/dracut/dracut-install Px, + @{lib}/initramfs-tools/bin/busybox ix, + @{lib}/klibc/bin/fstype ix, + @{sbin}/blkid Px, + @{sbin}/cryptsetup PUx, + @{sbin}/dmsetup Px, + @{sbin}/iucode_tool ix, + @{sbin}/plymouth-set-default-theme Px, + /usr/share/mdadm/mkconf Px, + + @{bin}/* mr, + @{sbin}/* mr, + @{lib}/ r, + @{lib}/** mr, + + /usr/share/*/ r, + /usr/share/*/initramfs/{,**} r, + /usr/share/initramfs-tools/{,**} r, + /usr/share/pixmaps/*.png r, + /usr/share/plymouth/{,**} r, + + /etc/console-setup/{,**} r, + /etc/cryptsetup-initramfs/{,**} r, + /etc/crypttab r, + /etc/default/* r, + /etc/fstab r, + /etc/iscsi/*.iscsi r, + /etc/kdump/sysctl.conf r, + /etc/lvm/{,**} r, + /etc/mdadm/mdadm.conf r, + /etc/plymouth/plymouthd.conf r, + /etc/systemd/network/{,**} r, + /etc/udev/{,**} r, + /etc/xattr.conf r, + + / r, + @{efi}/config-* r, + + /var/tmp/ r, + /var/tmp/modules_@{rand6} rw, + owner /var/tmp/mkinitramfs_@{rand6} rw, + owner /var/tmp/mkinitramfs_@{rand6}/ rw, + owner /var/tmp/mkinitramfs_@{rand6}/** rwl -> /var/tmp/mkinitramfs_@{rand6}/**, + owner /var/tmp/mkinitramfs-@{rand6} rw, + owner /var/tmp/mkinitramfs-*_@{rand6} rw, + owner /var/tmp/mkinitramfs-EFW_@{rand10} rw, + owner /var/tmp/mkinitramfs-EFW_@{rand10}/{,**} rwl, + + /tmp/tmp.@{rand10}/mkinitramfs* rw, + /tmp/tmp.@{rand10}/mkinitramfs*/ rw, + /tmp/tmp.@{rand10}/mkinitramfs*/** rwl -> /tmp/tmp.@{rand10}/mkinitramfs*/**, + /tmp/tmp.@{rand10}/modules_@{rand6} rw, + + @{sys}/bus/platform/drivers/simple-framebuffer/ r, + @{sys}/class/ r, + @{sys}/class/drm/ r, + @{sys}/devices/ r, + @{sys}/devices/@{pci_bus}/ r, + @{sys}/devices/@{pci}/ r, + @{sys}/devices/@{pci}/drm/card@{int}/ r, + @{sys}/devices/@{pci}/drm/renderD128/ r, + @{sys}/devices/@{pci}/drm/renderD129/ r, + @{sys}/devices/@{pci}/modalias r, + @{sys}/devices/**/block/**/dev r, + @{sys}/devices/**/block/**/slaves/ r, + @{sys}/firmware/efi/efivars/ r, + @{sys}/module/firmware_class/parameters/path r, + + @{PROC}/@{pid}/fd/ r, + @{PROC}/@{pid}/mountinfo r, + @{PROC}/@{pid}/mounts r, + @{PROC}/cmdline r, + @{PROC}/swaps r, + + profile ldd { + include + include + include + + @{ldd_path} mrix, + + @{bin}/* mr, + @{sbin}/* mr, + @{lib}/** mr, + + /usr/share/brltty/initramfs/brltty.sh r, + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/initramfs-scripts b/apparmor.d/profiles-m-r/initramfs-scripts new file mode 100644 index 0000000000..7db940cedf --- /dev/null +++ b/apparmor.d/profiles-m-r/initramfs-scripts @@ -0,0 +1,56 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = /usr/share/initramfs-tools/scripts/** /etc/initramfs-tools/scripts/** +profile initramfs-scripts @{exec_path} { + include + include + + @{exec_path} mr, + + @{sh_path} rix, + @{coreutils_path} rix, + @{sbin}/blkid Px, + @{bin}/dd ix, + @{bin}/debconf-escape Px, + @{bin}/ischroot Px, + @{ldd_path} Cx -> ldd, + @{bin}/plymouth Px, + @{bin}/update-alternatives Px, + @{lib}/dracut/dracut-install Px, + @{lib}/initramfs-tools/bin/busybox Px, + /usr/share/mdadm/mkconf Px, + + /usr/share/initramfs-tools/{,**} r, + + /etc/cryptsetup-initramfs/{,**} r, + /etc/crypttab r, + /etc/default/console-setup r, + /etc/fstab r, + /etc/initramfs-tools/{,**} r, + /etc/mdadm/mdadm.conf r, + /etc/udev/rules.d/{,**} r, + + /var/tmp/modules_@{rand6} rw, + owner /var/tmp/mkinitramfs_@{rand6}/** rwl -> /var/tmp/mkinitramfs_@{rand6}/**, + + /tmp/tmp.@{rand10}/mkinitramfs_@{rand6}/** rwl -> /tmp/tmp.@{rand10}/mkinitramfs_@{rand6}/**, + + profile ldd { + include + include + + @{ldd_path} mrix, + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/man b/apparmor.d/profiles-m-r/man index c60325742e..22ad3a134e 100644 --- a/apparmor.d/profiles-m-r/man +++ b/apparmor.d/profiles-m-r/man @@ -7,7 +7,7 @@ abi , include @{exec_path} = @{bin}/man -profile man @{exec_path} { +profile man @{exec_path} flags=(attach_disconnected) { include include diff --git a/apparmor.d/profiles-m-r/mandb b/apparmor.d/profiles-m-r/mandb index 4826337d0a..be12d5649c 100644 --- a/apparmor.d/profiles-m-r/mandb +++ b/apparmor.d/profiles-m-r/mandb @@ -8,7 +8,7 @@ abi , include @{exec_path} = @{bin}/mandb -profile mandb @{exec_path} flags=(complain) { +profile mandb @{exec_path} { include include include @@ -17,23 +17,29 @@ profile mandb @{exec_path} flags=(complain) { @{exec_path} mr, + @{bin}/bzip2 rix, + /etc/man_db.conf r, /etc/manpath.config r, - /var/cache/man/ r, - /var/cache/man/** rwk, - - /usr/share/man/{,**} r, /usr/local/man/{,**} r, /usr/local/share/man/{,**} r, + /usr/share/*/man/{,**} r, + /usr/share/man/{,**} r, /usr/{,share/}man/{,**} r, /usr/local/{,share/}man/{,**} r, /usr/share/**/man/man@{u8}/*.@{int}.gz r, + owner /var/cache/man/ rw, + owner /var/cache/man/** rwk, + owner @{user_share_dirs}/man/** rwk, + #aa:only test + /tmp/tmp.@{rand10}/{,**} rw, + include if exists } diff --git a/apparmor.d/profiles-m-r/mdadm b/apparmor.d/profiles-m-r/mdadm new file mode 100644 index 0000000000..f172b4200b --- /dev/null +++ b/apparmor.d/profiles-m-r/mdadm @@ -0,0 +1,60 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# Copyright (C) 2025 Zane Zakraisek +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{sbin}/mdadm +profile mdadm @{exec_path} flags=(attach_disconnected) { + include + include + include + + capability dac_read_search, + capability sys_admin, + capability mknod, + capability net_admin, + + network netlink raw, + + mqueue (read getattr) type=posix /, + mqueue (read getattr) type=posix /att/mdadm/, + + @{exec_path} mr, + + @{sh_path} rix, + @{sbin}/sendmail rPUx, + + /etc/{,mdadm/}mdadm.conf r, + /etc/{,mdadm/}mdadm.conf.d/* r, + + @{run}/initctl r, + @{run}/mdadm/* rwk, + + /tmp/tmp.@{rand10}/mkinitramfs_@{rand6}/etc/mdadm/mdadm.conf.tmp rw, + /var/tmp/mkinitramfs_@{rand6}/etc/mdadm/mdadm.conf.tmp rw, + + @{sys}/bus/pci/drivers/*/ r, + @{sys}/devices/@{pci}/class r, + @{sys}/devices/@{pci}/device r, + @{sys}/devices/@{pci}/vendor r, + @{sys}/devices/virtual/block/md*/** rw, + @{sys}/module/md_mod/** rw, + + @{PROC}/@{pid}/fd/ r, + @{PROC}/cmdline r, + @{PROC}/devices r, + @{PROC}/kcore r, + @{PROC}/mdstat rw, + @{PROC}/partitions r, + + /dev/**/ r, + /dev/.tmp.md.* rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/mdadm-mkconf b/apparmor.d/profiles-m-r/mdadm-mkconf new file mode 100644 index 0000000000..aad3d63b79 --- /dev/null +++ b/apparmor.d/profiles-m-r/mdadm-mkconf @@ -0,0 +1,33 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = /usr/share/mdadm/mkconf +profile mdadm-mkconf @{exec_path} flags=(attach_disconnected) { + include + include + + @{exec_path} mr, + + @{sh_path} r, + @{bin}/date ix, + @{bin}/cat ix, + @{bin}/sed ix, + @{sbin}/mdadm Px, + + /etc/default/mdadm r, + /etc/mdadm/mdadm.conf r, + + / r, + + /var/tmp/mkinitramfs_@{rand6}/etc/mdadm/mdadm.conf.tmp rw, + /tmp/tmp.@{rand10}/mkinitramfs_@{rand6}/etc/mdadm/mdadm.conf.tmp rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/mdevctl b/apparmor.d/profiles-m-r/mdevctl index f1b5034e66..ea0efab15e 100644 --- a/apparmor.d/profiles-m-r/mdevctl +++ b/apparmor.d/profiles-m-r/mdevctl @@ -6,9 +6,10 @@ abi , include -@{exec_path} = @{bin}/mdevctl +@{exec_path} = @{sbin}/mdevctl @{bin}/mdevctl #aa:lint ignore=sbin profile mdevctl @{exec_path} { include + include @{exec_path} mr, @@ -18,8 +19,6 @@ profile mdevctl @{exec_path} { @{sys}/class/mdev_bus/ r, @{sys}/devices/@{pci}/mdev_supported_types/{,**} r, - @{PROC}/@{pids}/maps r, - include if exists } diff --git a/apparmor.d/profiles-m-r/mediainfo-gui b/apparmor.d/profiles-m-r/mediainfo-gui index 5a723d0024..2f81f1377e 100644 --- a/apparmor.d/profiles-m-r/mediainfo-gui +++ b/apparmor.d/profiles-m-r/mediainfo-gui @@ -11,10 +11,8 @@ include profile mediainfo-gui @{exec_path} { include include - include - include - include - include + include + include include @{exec_path} mr, diff --git a/apparmor.d/profiles-m-r/megasync b/apparmor.d/profiles-m-r/megasync index 3796c2b75a..e0b22d8835 100644 --- a/apparmor.d/profiles-m-r/megasync +++ b/apparmor.d/profiles-m-r/megasync @@ -56,7 +56,7 @@ profile megasync @{exec_path} { owner @{PROC}/@{pid}/mounts r, /dev/shm/#@{int} rw, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-m-r/merkaartor b/apparmor.d/profiles-m-r/merkaartor index e43460210e..22776543cf 100644 --- a/apparmor.d/profiles-m-r/merkaartor +++ b/apparmor.d/profiles-m-r/merkaartor @@ -10,16 +10,10 @@ include @{exec_path} = @{bin}/merkaartor profile merkaartor @{exec_path} { include - include - include - include - include - include - include - include - include - include + include + include include + include include include @@ -34,26 +28,18 @@ profile merkaartor @{exec_path} { /usr/share/merkaartor/{,**} r, - owner @{user_config_dirs}/Merkaartor/ rw, - owner @{user_config_dirs}/Merkaartor/* rwkl -> @{user_config_dirs}/Merkaartor/, - owner @{HOME}/.merkaartor/ rw, owner @{HOME}/.merkaartor/* rw, owner @{HOME}/merkaartor.log rw, - /var/lib/dbus/machine-id r, - /etc/machine-id r, - - /usr/share/hwdata/pnp.ids r, - - deny owner @{PROC}/@{pid}/cmdline r, + owner @{user_config_dirs}/Merkaartor/ rw, + owner @{user_config_dirs}/Merkaartor/* rwkl -> @{user_config_dirs}/Merkaartor/, owner @{tmp}/qtsingleapp-merkaa-* rw, owner @{tmp}/qtsingleapp-merkaa-*-lockfile rwk, - @{sys}/devices/system/node/ r, - @{sys}/devices/system/node/node@{int}/meminfo r, + deny owner @{PROC}/@{pid}/cmdline r, include if exists } diff --git a/apparmor.d/profiles-m-r/metadata-cleaner b/apparmor.d/profiles-m-r/metadata-cleaner index 4aa662cd01..d45911b5db 100644 --- a/apparmor.d/profiles-m-r/metadata-cleaner +++ b/apparmor.d/profiles-m-r/metadata-cleaner @@ -9,9 +9,7 @@ include @{exec_path} = @{bin}/metadata-cleaner profile metadata-cleaner @{exec_path} flags=(attach_disconnected) { include - include - include - include + include include include include @@ -20,17 +18,11 @@ profile metadata-cleaner @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, @{python_path} rix, - @{bin}/bwrap rCx -> bwrap, - @{open_path} rPx -> child-open-help, + @{bin}/bwrap Cx -> bwrap, + @{open_path} Px -> child-open-help, - /usr/share/metadata-cleaner/{,**} r, /usr/share/metadata-cleaner/src/metadatacleaner/{,*/}__pycache__/ w, - /usr/share/poppler/{,**} r, - - /etc/httpd/conf/mime.types r, - /etc/mime.types r, - owner @{tmp}/@{hex64}.* rw, owner @{tmp}/@{rand8} rw, owner @{tmp}/tmp@{word8} rw, @@ -38,20 +30,18 @@ profile metadata-cleaner @{exec_path} flags=(attach_disconnected) { @{run}/mount/utab r, - owner @{PROC}/@{pid}/cmdline r, owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/mounts r, - owner @{PROC}/@{pid}/task/@{tid}/comm rw, deny owner @{user_share_dirs}/gvfs-metadata/* r, deny owner @{user_cache_dirs}/thumbnails/** r, profile bwrap flags=(attach_disconnected) { include - include + include include - signal (receive) set=(kill) peer=metadata-cleaner, + signal receive set=(kill) peer=metadata-cleaner, @{bin}/bwrap mr, @{bin}/vendor_perl/exiftool rix, diff --git a/apparmor.d/profiles-m-r/mimetype b/apparmor.d/profiles-m-r/mimetype index d6823da9ba..32950dbc4e 100644 --- a/apparmor.d/profiles-m-r/mimetype +++ b/apparmor.d/profiles-m-r/mimetype @@ -10,23 +10,13 @@ include @{exec_path} = @{bin}/mimetype @{bin}/*_perl/mimetype profile mimetype @{exec_path} { include + include include @{exec_path} r, - /usr/bin/perl r, - - /usr/share/mime/**.xml r, - /usr/share/mime/globs r, - /usr/share/mime/aliases r, - /usr/share/mime/magic r, - - owner @{user_share_dirs}/mime/**.xml r, - owner @{user_share_dirs}/mime/globs r, - owner @{user_share_dirs}/mime/aliases r, - owner @{user_share_dirs}/mime/magic r, # To read files - /** r, + owner /** r, #aa:lint ignore=too-wide include if exists } diff --git a/apparmor.d/profiles-m-r/minitube b/apparmor.d/profiles-m-r/minitube index ce8380261a..fd940a3697 100644 --- a/apparmor.d/profiles-m-r/minitube +++ b/apparmor.d/profiles-m-r/minitube @@ -65,7 +65,7 @@ profile minitube @{exec_path} { owner @{PROC}/@{pid}/cmdline r, /dev/shm/#@{int} rw, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-m-r/mission-control b/apparmor.d/profiles-m-r/mission-control index b8e79c0dc8..9ff89a1e23 100644 --- a/apparmor.d/profiles-m-r/mission-control +++ b/apparmor.d/profiles-m-r/mission-control @@ -10,13 +10,13 @@ include profile mission-control @{exec_path} flags=(attach_disconnected) { include include + include network netlink raw, @{exec_path} mr, /usr/share/telepathy/{,**} r, - /usr/share/glib-2.0/schemas/gschemas.compiled r, owner @{user_share_dirs}/telepathy/ rw, owner @{user_share_dirs}/telepathy/mission-control/ rw, @@ -25,7 +25,7 @@ profile mission-control @{exec_path} flags=(attach_disconnected) { owner @{user_config_dirs}/libaccounts-glib/accounts.db{,-shm,-wal} rwk, owner @{user_cache_dirs}/.mc_connections rw, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, include if exists } diff --git a/apparmor.d/profiles-m-r/mkcert b/apparmor.d/profiles-m-r/mkcert index 3ae643e1dc..bedbbab020 100644 --- a/apparmor.d/profiles-m-r/mkcert +++ b/apparmor.d/profiles-m-r/mkcert @@ -12,6 +12,7 @@ profile mkcert @{exec_path} { include include include + include include network netlink raw, diff --git a/apparmor.d/profiles-m-r/mkinitramfs b/apparmor.d/profiles-m-r/mkinitramfs index fdc258da1e..f7b3c7a230 100644 --- a/apparmor.d/profiles-m-r/mkinitramfs +++ b/apparmor.d/profiles-m-r/mkinitramfs @@ -8,15 +8,20 @@ abi , include -@{exec_path} = @{bin}/mkinitramfs +@{exec_path} = @{sbin}/mkinitramfs profile mkinitramfs @{exec_path} { include + include include - capability syslog, capability chown, + capability dac_read_search, capability fowner, capability fsetid, + capability sys_admin, # optional: no audit + capability syslog, + + mqueue getattr type=posix, @{exec_path} r, @{sh_path} rix, @@ -30,9 +35,10 @@ profile mkinitramfs @{exec_path} { @{bin}/cat rix, @{bin}/chmod rix, @{bin}/cp rix, - @{bin}/cpio rix, + @{bin}/{,3}cpio rix, @{bin}/dirname rix, @{bin}/env rix, + @{bin}/find rix, @{bin}/getopt rix, @{bin}/gzip rix, @{bin}/id rix, @@ -47,30 +53,30 @@ profile mkinitramfs @{exec_path} { @{bin}/rmdir rix, @{bin}/sed rix, @{bin}/sort rix, + @{bin}/stat rix, @{bin}/touch rix, @{bin}/tr rix, @{bin}/tsort rix, + @{bin}/uname rix, @{bin}/uniq rix, @{bin}/xargs rix, @{bin}/xz rix, @{bin}/zstd rix, @{lib}/dracut/dracut-install rix, + @{sbin}/blkid rPx, - @{bin}/find rCx -> find, @{bin}/kmod rCx -> kmod, - @{bin}/ldconfig rCx -> ldconfig, - @{bin}/ldd rCx -> ldd, - @{lib}/@{multiarch}/ld-linux-*so* rCx -> ldd, - @{lib}/ld-linux.so* rCx -> ldd, + @{sbin}/ldconfig rCx -> ldconfig, + @{ldd_path} rCx -> ldd, @{bin}/dpkg rPx -> child-dpkg, @{bin}/linux-version rPx, - # What to do with it? (#FIXME#) - /usr/share/initramfs-tools/hooks/* rPUx, - /usr/share/initramfs-tools/scripts/*/* rPUx, - /etc/initramfs-tools/hooks/* rPUx, - /etc/initramfs-tools/scripts/*/* rPUx, + @{lib}/initramfs-tools/hooks/** rPx, + /etc/initramfs-tools/hooks/** rPx, + /etc/initramfs-tools/scripts/** rPx, + /usr/share/initramfs-tools/hooks/** rPx, + /usr/share/initramfs-tools/scripts/** rPx, /usr/share/initramfs-tools/{,**} r, /etc/initramfs-tools/{,**} r, @@ -84,23 +90,48 @@ profile mkinitramfs @{exec_path} { /etc/modprobe.d/{,*.conf} r, - /boot/ r, - owner /boot/config-* r, - owner /boot/initrd.img-*.new rw, - - /var/tmp/ r, - /var/tmp/modules_@{rand6} rw, - owner /var/tmp/mkinitramfs_@{rand6} rw, - owner /var/tmp/mkinitramfs_@{rand6}/ rw, - owner /var/tmp/mkinitramfs_@{rand6}/** rwl -> /var/tmp/mkinitramfs_@{rand6}/**, - owner /var/tmp/mkinitramfs-@{rand6} rw, - owner /var/tmp/mkinitramfs-*_@{rand6} rw, - - @{sys}/devices/platform/ r, - @{sys}/devices/platform/**/ r, - @{sys}/devices/platform/**/modalias r, + @{efi}/ r, + owner @{efi}/config-* r, + owner @{efi}/initrd.img-*.new rw, + + owner /var/lib/kdump/initramfs-tools/** rw, + owner /var/lib/kdump/initrd.* rw, + + /var/tmp/ r, + /var/tmp/mkinitramfs_@{rand6}/** w, + /var/tmp/modules_@{rand6} rw, + /var/tmp/mkinitramfs_@{rand6} rw, + /var/tmp/mkinitramfs_@{rand6}/ rw, + /var/tmp/mkinitramfs_@{rand6}/** rwl -> /var/tmp/mkinitramfs_@{rand6}/**, + /var/tmp/mkinitramfs-@{rand6} rw, + /var/tmp/mkinitramfs-*_@{rand6} rw, + + owner /tmp/tmp.@{rand10}/mkinitramfs_@{rand6} rw, + owner /tmp/tmp.@{rand10}/mkinitramfs_@{rand6}/ rw, + owner /tmp/tmp.@{rand10}/mkinitramfs_@{rand6}/** rwl -> /tmp/tmp.@{rand10}/mkinitramfs_@{rand6}/**, + owner /tmp/tmp.@{rand10}/mkinitramfs_@{rand6}/** w, + owner /tmp/tmp.@{rand10}/mkinitramfs-@{rand6} rw, + owner /tmp/tmp.@{rand10}/mkinitramfs-*_@{rand6} rw, + owner /tmp/tmp.@{rand10}/modules_@{rand6} rw, + + @{sys}/bus/ r, + @{sys}/bus/*/drivers/ r, + @{sys}/bus/*/drivers/*/ r, + @{sys}/class/ r, + @{sys}/class/*/ r, + @{sys}/devices/ r, + @{sys}/devices/**/ r, + @{sys}/devices/**/modalias r, + @{sys}/devices/**/uevent r, + @{sys}/module/ r, @{sys}/module/compression r, + @{sys}/module/firmware_class/parameters/path r, + @{sys}/bus/platform/drivers/simple-framebuffer/ r, + + @{PROC}/@{pid}/cgroup r, + @{PROC}/@{pid}/mountinfo r, + @{PROC}/@{pid}/mounts r, @{PROC}/cmdline r, @{PROC}/modules r, owner @{PROC}/@{pid}/fd/ r, @@ -110,16 +141,12 @@ profile mkinitramfs @{exec_path} { include include - @{bin}/ldd mr, - @{lib}/@{multiarch}/ld-linux-*so* mr, - @{lib}/ld-linux.so* mr, - - @{sh_path} rix, - @{bin}/kmod mr, - @{lib}/initramfs-tools/bin/* mr, + @{ldd_path} mrix, + @{sh_path} rix, - @{lib}/@{multiarch}/ld-*.so* rix, - @{lib}/ld-*.so{,.2} rix, + @{bin}/* mr, + @{sbin}/* mr, + @{lib}/** mr, include if exists } @@ -130,55 +157,38 @@ profile mkinitramfs @{exec_path} { capability sys_chroot, - @{bin}/ldconfig mr, + @{sbin}/ldconfig mr, @{sh_path} rix, - @{bin}/ldconfig.real rix, - - owner /var/tmp/mkinitramfs_@{rand6}/etc/ld.so.conf r, - owner /var/tmp/mkinitramfs_@{rand6}/etc/ld.so.conf.d/{,*.conf} r, + @{sbin}/ldconfig.real rix, - owner /var/tmp/mkinitramfs_@{rand6}/@{lib}/ r, - owner /var/tmp/mkinitramfs_@{rand6}/@{lib}/@{multiarch}/ r, - owner /var/tmp/mkinitramfs_@{rand6}/@{lib}/@{multiarch}/*.so* rw, - owner /var/tmp/mkinitramfs_@{rand6}/@{lib}/*.so* rw, - - owner /var/tmp/mkinitramfs_@{rand6}/etc/ld.so.cache{,~} rw, - - owner /var/tmp/mkinitramfs_@{rand6}/var/cache/ldconfig/ rw, - owner /var/tmp/mkinitramfs_@{rand6}/var/cache/ldconfig/aux-cache{,~} rw, + owner /var/tmp/mkinitramfs_@{rand6}/** rwl -> /var/tmp/mkinitramfs_@{rand6}/**, + owner /tmp/tmp.@{rand10}/mkinitramfs_@{rand6}/** rwl -> /tmp/tmp.@{rand10}/mkinitramfs_@{rand6}/**, include if exists } - profile find { - include - include - - @{bin}/find mr, - - # pwd dir - / r, - /etc/ r, - /root/ r, - - /usr/share/initramfs-tools/scripts/{,**/} r, - /etc/initramfs-tools/scripts/{,**/} r, - - owner /var/tmp/mkinitramfs_@{rand6}/{,**/} r, - - include if exists - } - profile kmod { include include owner /var/tmp/mkinitramfs_@{rand6}/usr/lib/modules/*/ r, - owner /var/tmp/mkinitramfs_@{rand6}/usr/lib/modules/*/modules.* rw, - owner /var/tmp/mkinitramfs_@{rand6}/usr/lib/modules/*/updates/{,**} r, owner /var/tmp/mkinitramfs_@{rand6}/usr/lib/modules/*/kernel/{,**/} r, owner /var/tmp/mkinitramfs_@{rand6}/usr/lib/modules/*/kernel/**/*.ko* r, + owner /var/tmp/mkinitramfs_@{rand6}/usr/lib/modules/*/modules.* rw, + owner /var/tmp/mkinitramfs_@{rand6}/usr/lib/modules/*/updates/{,**} r, + + /tmp/tmp.@{rand10}/mkinitramfs_@{rand6}/usr/lib/modules/*/ r, + /tmp/tmp.@{rand10}/mkinitramfs_@{rand6}/usr/lib/modules/*/kernel/{,**/} r, + /tmp/tmp.@{rand10}/mkinitramfs_@{rand6}/usr/lib/modules/*/kernel/**/*.ko* r, + /tmp/tmp.@{rand10}/mkinitramfs_@{rand6}/usr/lib/modules/*/modules.* rw, + /tmp/tmp.@{rand10}/mkinitramfs_@{rand6}/usr/lib/modules/*/updates/{,**} r, + + owner /tmp/tmp.@{rand10}/usr/lib/modules/*/ r, + owner /tmp/tmp.@{rand10}/usr/lib/modules/*/kernel/{,**/} r, + owner /tmp/tmp.@{rand10}/usr/lib/modules/*/kernel/**/*.ko* r, + owner /tmp/tmp.@{rand10}/usr/lib/modules/*/modules.* rw, + owner /tmp/tmp.@{rand10}/usr/lib/modules/*/updates/{,**} r, @{sys}/module/compression r, diff --git a/apparmor.d/profiles-m-r/mkosi b/apparmor.d/profiles-m-r/mkosi new file mode 100644 index 0000000000..f6489a501a --- /dev/null +++ b/apparmor.d/profiles-m-r/mkosi @@ -0,0 +1,25 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# This profile is large on purpose: +# - It is required to have a profile for mkosi to allow userns. +# - Mkosi uses a lot of different binaries and scripts inside sandbox. +# - Using the unconfined flag would Pix everything, we do not want that as the +# transitioned profile would have to account for mkosi paths too. + +abi , + +include + +@{exec_path} = @{bin}/mkosi @{user_share_dirs}/pipx/venvs/*/bin/mkosi +profile mkosi @{exec_path} flags=(attach_disconnected,mediate_deleted) { + include + + all, + userns, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/mkvtoolnix-gui b/apparmor.d/profiles-m-r/mkvtoolnix-gui index 835e1a3913..c96c52bc2d 100644 --- a/apparmor.d/profiles-m-r/mkvtoolnix-gui +++ b/apparmor.d/profiles-m-r/mkvtoolnix-gui @@ -10,19 +10,15 @@ include @{exec_path} = @{bin}/mkvtoolnix-gui profile mkvtoolnix-gui @{exec_path} { include - include + include include - include - include - include - include + include include - include include include + include include include - include signal (send) set=(term, kill) peer=mkvmerge, @@ -62,7 +58,7 @@ profile mkvtoolnix-gui @{exec_path} { @{PROC}/@{pid}/mountinfo r, @{PROC}/@{pid}/mounts r, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-m-r/modprobed-db b/apparmor.d/profiles-m-r/modprobed-db index cd2ddc0e68..90bf73cf34 100644 --- a/apparmor.d/profiles-m-r/modprobed-db +++ b/apparmor.d/profiles-m-r/modprobed-db @@ -17,9 +17,9 @@ profile modprobed-db @{exec_path} { @{bin}/cat rix, @{bin}/cp rix, @{bin}/cut rix, - @{bin}/gawk rix, + @{bin}/{m,g,}awk rix, @{bin}/getent rix, - @{bin}/grep rix, + @{bin}/{,e}grep rix, @{bin}/logname rix, @{bin}/md5sum rix, @{bin}/rm rix, diff --git a/apparmor.d/profiles-m-r/monitorix b/apparmor.d/profiles-m-r/monitorix index e847db8729..ab81622cc4 100644 --- a/apparmor.d/profiles-m-r/monitorix +++ b/apparmor.d/profiles-m-r/monitorix @@ -10,10 +10,12 @@ include @{exec_path} = @{bin}/monitorix profile monitorix @{exec_path} { include - include - include - include + include include + include + include + include + include capability net_admin, capability chown, @@ -28,80 +30,74 @@ profile monitorix @{exec_path} { network inet stream, network inet6 stream, - ptrace (read), + ptrace read, - signal (receive) set=(hup) peer=logroate, + signal receive set=(hup) peer=logroate, @{exec_path} mr, @{sh_path} rix, - @{bin}/{,e}grep rix, - @{bin}/df rix, - @{bin}/cat rix, - @{bin}/tail rix, - @{bin}/{m,g,}awk rix, - @{bin}/free rix, - @{bin}/ss rix, - @{bin}/who rix, - @{bin}/lvm rix, - @{bin}/xtables-nft-multi rix, - @{bin}/sensors rix, - @{bin}/getconf rix, - @{bin}/ps rix, - - /etc/monitorix/monitorix.conf r, - /etc/monitorix/conf.d/ r, - /etc/monitorix/conf.d/@{int2}-*.conf r, + @{bin}/{,e}grep ix, + @{bin}/{m,g,}awk ix, + @{bin}/cat ix, + @{bin}/df ix, + @{bin}/free ix, + @{bin}/getconf ix, + @{bin}/ps Px, + @{bin}/sensors Px, + @{bin}/tail ix, + @{bin}/who Px, + @{sbin}/lvm Px, + @{sbin}/ss Px, + @{sbin}/xtables-{nft,legacy}-multi rix, + + /var/lib/monitorix/www/cgi/monitorix.cgi ix, + + /etc/monitorix/{,**} r, + + /var/lib/monitorix/ rw, + /var/lib/monitorix/** rwk, /var/log/monitorix w, /var/log/monitorix-* w, - owner @{run}/monitorix.pid w, - - /var/lib/monitorix/*.rrd* rwk, - /var/lib/monitorix/www/** rw, - /var/lib/monitorix/www/cgi/monitorix.cgi rwix, + /srv/http/monitorix/ rw, + /srv/http/monitorix/** rwk, / r, /tmp/ r, - /etc/shadow r, - /dev/tty r, + owner @{run}/monitorix.pid w, @{run}/utmp rk, + @{sys}/class/i2c-adapter/ r, + @{sys}/devices/@{pci}/i2c-*/{,**/}name r, + @{sys}/devices/**/thermal*/{,**} r, + @{PROC}/ r, - @{PROC}/swaps r, + @{PROC}/@{pid}/net/dev r, + @{PROC}/@{pid}/net/tcp{,6} r, + @{PROC}/@{pid}/net/udp{,6} r, + @{PROC}/@{pids}/cmdline r, + @{PROC}/@{pids}/fdinfo/ r, + @{PROC}/@{pids}/io r, + @{PROC}/@{pids}/stat r, @{PROC}/diskstats r, - @{PROC}/loadavg r, - @{PROC}/sys/kernel/random/entropy_avail r, - @{PROC}/uptime r, @{PROC}/interrupts r, + @{PROC}/loadavg r, + @{PROC}/swaps r, @{PROC}/sys/fs/dentry-state r, @{PROC}/sys/fs/file-nr r, @{PROC}/sys/fs/inode-nr r, @{PROC}/sys/kernel/osrelease r, + @{PROC}/sys/kernel/pid_max r, + @{PROC}/sys/kernel/random/entropy_avail r, + @{PROC}/uptime r, owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/mounts r, - owner @{PROC}/@{pid}/net/dev r, owner @{PROC}/@{pid}/net/ip_tables_names r, owner @{PROC}/@{pid}/net/ip6_tables_names r, - @{PROC}/@{pid}/net/udp{,6} r, - @{PROC}/@{pid}/net/tcp{,6} r, - @{PROC}/sys/kernel/pid_max r, - @{PROC}/@{pids}/stat r, - @{PROC}/@{pids}/cmdline r, - @{PROC}/@{pids}/fdinfo/ r, - @{PROC}/@{pids}/io r, - - @{sys}/class/i2c-adapter/ r, - @{sys}/devices/@{pci}/i2c-@{int}/{,**/}name r, - @{sys}/class/hwmon/ r, - @{sys}/devices/**/thermal*/{,**} r, - @{sys}/devices/**/hwmon*/{,**} r, - - /etc/sensors3.conf r, - /etc/sensors.d/ r, include if exists } diff --git a/apparmor.d/profiles-m-r/mono-sgen b/apparmor.d/profiles-m-r/mono-sgen index bdaafd9c8f..fdee93a744 100644 --- a/apparmor.d/profiles-m-r/mono-sgen +++ b/apparmor.d/profiles-m-r/mono-sgen @@ -10,11 +10,10 @@ include profile mono-sgen @{exec_path} { include include - include + include include include include - include network inet dgram, network inet6 dgram, @@ -31,14 +30,13 @@ profile mono-sgen @{exec_path} { /usr/share/.mono/{,**} rw, /etc/mono/{,**} r, - /etc/machine-id r, owner @{user_config_dirs}/openra/{,**} rw, owner @{user_config_dirs}/.mono/{,**} r, owner @{tmp}/*.* rw, owner @{tmp}/CASESENSITIVETEST* rw, - owner /dev/shm/mono.* rw, + owner /dev/shm/mono.@{int} rw, owner @{PROC}/@{pid}/fd/ r, diff --git a/apparmor.d/profiles-m-r/motd b/apparmor.d/profiles-m-r/motd index fe684f6715..91f10493b5 100644 --- a/apparmor.d/profiles-m-r/motd +++ b/apparmor.d/profiles-m-r/motd @@ -12,13 +12,13 @@ profile motd @{exec_path} { include include - network inet dgram, - network inet stream, - network inet6 dgram, + capability net_admin, + + network inet6 stream, network inet6 stream, - network netlink raw, @{exec_path} mr, + @{bin}/ r, @{sh_path} rix, @{coreutils_path} rix, @@ -28,7 +28,7 @@ profile motd @{exec_path} { @{bin}/snap rPx, @{bin}/dpkg rPx -> child-dpkg, @{bin}/systemd-detect-virt rPx, - @{bin}/wget rix, + @{bin}/wget rCx -> wget, @{lib}/ubuntu-release-upgrader/release-upgrade-motd rPx, @{lib}/update-notifier/update-motd-fsck-at-reboot rPx, @@ -37,25 +37,52 @@ profile motd @{exec_path} { /usr/share/update-notifier/notify-updates-outdated rPx, / r, + /etc/cloud/cloud.cfg r, + /etc/cloud/cloud.cfg.d/{,*} r, /etc/default/motd-news r, /etc/lsb-release r, /etc/update-motd.d/* r, - /etc/cloud/cloud.cfg r, - /etc/cloud/cloud.cfg.d/{,*} r, + /etc/wgetrc r, /var/cache/motd-news rw, /var/lib/update-notifier/updates-available r, /var/lib/ubuntu-advantage/messages/motd-esm-announce r, + /var/lib/cloud/instances/nocloud/cloud-config.txt r, /tmp/tmp.@{rand10} rw, + @{run}/cloud-init/cloud.cfg r, @{run}/motd.d/{,*} r, @{run}/motd.dynamic.new rw, @{run}/reboot-required r, @{PROC}/@{pids}/mounts r, + @{PROC}/1/environ r, + @{PROC}/cmdline r, + + /dev/tty@{u8} rw, + + profile wget { + include + include + include + + capability net_admin, + + network inet dgram, + network inet stream, + network inet6 dgram, + network inet6 stream, + network netlink raw, - /dev/tty@{int} rw, + @{bin}/wget mr, + + /etc/wgetrc r, + + /tmp/tmp.@{rand10} rw, + + include if exists + } profile systemctl { include diff --git a/apparmor.d/profiles-m-r/mpd b/apparmor.d/profiles-m-r/mpd index 89b66253a7..f8cbcad0b7 100644 --- a/apparmor.d/profiles-m-r/mpd +++ b/apparmor.d/profiles-m-r/mpd @@ -12,7 +12,9 @@ include profile mpd @{exec_path} { include include + include include + include network inet dgram, network inet6 dgram, @@ -45,6 +47,9 @@ profile mpd @{exec_path} { owner @{PROC}/@{pid}/cmdline r, owner @{PROC}/@{pid}/task/ r, + #aa:only test + /tmp/@{rand10}/{,**} rw, + include if exists } diff --git a/apparmor.d/profiles-m-r/mpris-proxy b/apparmor.d/profiles-m-r/mpris-proxy new file mode 100644 index 0000000000..b5472c9221 --- /dev/null +++ b/apparmor.d/profiles-m-r/mpris-proxy @@ -0,0 +1,37 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/mpris-proxy +profile mpris-proxy @{exec_path} { + include + include + include + include + + #aa:dbus own bus=session name=org.mpris.MediaPlayer2 + #aa:dbus own bus=system name=org.mpris.MediaPlayer2.Player path=/{,**} + + #aa:dbus see bus=session name=org.bluez.obex path=/ label=obexd + + dbus send bus=session path=/org/mpris/MediaPlayer2 + interface=org.freedesktop.DBus.Properties + member=GetAll + peer=(name=org.mpris.MediaPlayer2.*, label="*"), + + # DBus.Introspectable: allow introspection from gnome-shell + dbus receive bus=session + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name=@{busname}, label="{gnome-shell,gnome-extension}"), + + @{exec_path} mr, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/mpsyt b/apparmor.d/profiles-m-r/mpsyt index 502f941be3..5ceab569b4 100644 --- a/apparmor.d/profiles-m-r/mpsyt +++ b/apparmor.d/profiles-m-r/mpsyt @@ -10,12 +10,11 @@ include @{exec_path} = @{bin}/mpsyt profile mpsyt @{exec_path} { include - include - include + include include + include include - - signal (send) set=(term, kill) peer=mpv, + include network inet dgram, network inet6 dgram, @@ -23,11 +22,13 @@ profile mpsyt @{exec_path} { network inet6 stream, network netlink raw, + signal send set=(term, kill) peer=mpv, + @{exec_path} r, @{python_path} r, @{bin}/ r, - @{bin}/ldconfig rix, + @{sbin}/ldconfig rix, @{bin}/tset rix, @{bin}/uname rix, @@ -35,27 +36,22 @@ profile mpsyt @{exec_path} { @{bin}/ffmpeg rPUx, @{bin}/ffprobe rPUx, - # MPV config files + /etc/inputrc r, /etc/mpv/* r, - owner @{user_config_dirs}/mpv/* r, - - # mps-yt config files - owner @{user_config_dirs}/mps-youtube/{,**} rw, - # Cache files owner @{user_cache_dirs}/youtube-dl/youtube-sigfuncs/js_*.json{,.*.tmp} rw, - /etc/inputrc r, - /etc/mime.types r, - - owner @{PROC}/@{pid}/fd/ r, - owner @{PROC}/@{pid}/mounts r, + owner @{user_config_dirs}/mpv/* r, + owner @{user_config_dirs}/mps-youtube/{,**} rw, /tmp/ r, owner @{tmp}/[a-z0-9]* rw, owner @{tmp}/mpsyt-input* rw, owner @{tmp}/mpsyt-mpv*.sock rw, + owner @{PROC}/@{pid}/fd/ r, + owner @{PROC}/@{pid}/mounts r, + include if exists } diff --git a/apparmor.d/profiles-m-r/mpv b/apparmor.d/profiles-m-r/mpv index 3d044049e7..8493a7ddd8 100644 --- a/apparmor.d/profiles-m-r/mpv +++ b/apparmor.d/profiles-m-r/mpv @@ -15,8 +15,11 @@ profile mpv @{exec_path} { include include include + include include + include include + include include network inet dgram, @@ -36,12 +39,9 @@ profile mpv @{exec_path} { @{bin}/youtube-dl rPx, @{bin}/yt-dlp rPx, - /etc/mpv/* r, + /etc/mpv/** r, /etc/samba/smb.conf r, - /etc/machine-id r, - /var/lib/dbus/machine-id r, - owner @{HOME}/ r, owner @{user_music_dirs}/{,**} rw, owner @{user_pictures_dirs}/{,**} rw, @@ -61,28 +61,19 @@ profile mpv @{exec_path} { owner @{run}/user/@{uid}/gvfs/smb-share:server=*,share=**/ r, owner @{run}/user/@{uid}/gvfs/smb-share:server=*,share=** r, - owner @{PROC}/@{pid}/cmdline r, - owner @{PROC}/@{pid}/task/ r, - owner @{PROC}/@{pid}/task/@{tid}/comm rw, - - @{run}/udev/data/+input:input@{int} r, # for mouse, keyboard, touchpad - @{run}/udev/data/c13:@{int} r, # for /dev/input/* @{run}/udev/data/c116:@{int} r, # for ALSA @{sys}/bus/ r, @{sys}/class/ r, - @{sys}/class/input/ r, - @{sys}/devices/**/input/**/capabilities/* r, - @{sys}/devices/**/input/**/uevent r, @{sys}/devices/**/sound/**/capabilities/* r, @{sys}/devices/**/sound/**/uevent r, - @{sys}/devices/virtual/dmi/id/bios_vendor r, - @{sys}/devices/virtual/dmi/id/board_vendor r, - @{sys}/devices/virtual/dmi/id/product_name r, - @{sys}/devices/virtual/dmi/id/sys_vendor r, - /dev/input/event@{int} r, - owner /dev/tty@{int} rw, + owner @{PROC}/@{pid}/cmdline r, + owner @{PROC}/@{pid}/task/ r, + owner @{PROC}/@{pid}/stat r, + owner @{PROC}/@{pid}/task/@{tid}/comm rw, + + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-m-r/mtr b/apparmor.d/profiles-m-r/mtr index 4ff851662e..3c2e5c448b 100644 --- a/apparmor.d/profiles-m-r/mtr +++ b/apparmor.d/profiles-m-r/mtr @@ -10,10 +10,7 @@ include @{exec_path} = @{bin}/mtr profile mtr @{exec_path} { include - include - include - include - include + include include network inet dgram, diff --git a/apparmor.d/profiles-m-r/mullvad-setup b/apparmor.d/profiles-m-r/mullvad-setup index bc20a0f9ad..974af1c115 100644 --- a/apparmor.d/profiles-m-r/mullvad-setup +++ b/apparmor.d/profiles-m-r/mullvad-setup @@ -6,13 +6,15 @@ abi , include -@{exec_path} = /opt/Mullvad*/resources/mullvad-setup -profile mullvad-setup @{exec_path} { +@{exec_path} = /opt/Mullvad*/resources/mullvad-setup @{lib}/mullvad-vpn/mullvad-setup +profile mullvad-setup @{exec_path} { include include @{exec_path} mr, + @{run}/mullvad-vpn rw, + @{sys}/fs/cgroup/user.slice/cpu.max r, @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/cpu.max r, @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/session-@{word}.scope/cpu.max r, diff --git a/apparmor.d/profiles-m-r/multipath b/apparmor.d/profiles-m-r/multipath index 409834fbc8..25634cd44b 100644 --- a/apparmor.d/profiles-m-r/multipath +++ b/apparmor.d/profiles-m-r/multipath @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/multipath +@{exec_path} = @{sbin}/multipath profile multipath @{exec_path} flags=(attach_disconnected) { include include @@ -23,6 +23,8 @@ profile multipath @{exec_path} flags=(attach_disconnected) { /etc/multipath/* rwk, /etc/systemd/system/ r, + / r, + @{run}/systemd/system/ r, @{sys}/bus/ r, diff --git a/apparmor.d/profiles-m-r/multipathd b/apparmor.d/profiles-m-r/multipathd index 14bb16cafb..e146395884 100644 --- a/apparmor.d/profiles-m-r/multipathd +++ b/apparmor.d/profiles-m-r/multipathd @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/multipathd +@{exec_path} = @{sbin}/multipathd profile multipathd @{exec_path} { include include @@ -20,7 +20,8 @@ profile multipathd @{exec_path} { network netlink raw, - unix (send, receive, connect) type=stream peer=(addr="@/org/kernel/linux/storage/multipathd"), + unix type=stream peer=(addr="@/org/kernel/linux/storage/multipathd"), + unix type=stream addr=@/org/kernel/linux/storage/multipathd, @{exec_path} mr, @@ -30,10 +31,12 @@ profile multipathd @{exec_path} { /etc/systemd/system/ r, @{run}/multipathd.pid rwk, - @{run}/systemd/notify w, + @{run}/multipathd.socket rw, @{sys}/bus/ r, @{sys}/class/ r, + @{sys}/devices/**/uevent r, + @{sys}/devices/platform/**/recovery_tmo w, @{PROC}/devices r, @{PROC}/sys/fs/nr_open r, diff --git a/apparmor.d/profiles-m-r/mumble b/apparmor.d/profiles-m-r/mumble index 48ed42d84b..3071d8ba6c 100644 --- a/apparmor.d/profiles-m-r/mumble +++ b/apparmor.d/profiles-m-r/mumble @@ -30,7 +30,7 @@ profile mumble @{exec_path} { @{exec_path} mrix, - @{bin}/lsb_release rPx -> lsb_release, + @{bin}/lsb_release rPx, @{browsers_path} rPx, @{open_path} rPx -> child-open, @@ -60,7 +60,7 @@ profile mumble @{exec_path} { /dev/shm/#@{int} rw, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-m-r/mumble-overlay b/apparmor.d/profiles-m-r/mumble-overlay index 8d17ef3d68..86792860c8 100644 --- a/apparmor.d/profiles-m-r/mumble-overlay +++ b/apparmor.d/profiles-m-r/mumble-overlay @@ -16,7 +16,7 @@ profile mumble-overlay @{exec_path} { @{sh_path} rix, @{bin}/file rix, - @{bin}/which{,.debianutils} rix, + @{bin}/which{,.debianutils} rix, @{bin}/glxgears rPx, diff --git a/apparmor.d/profiles-m-r/murmurd b/apparmor.d/profiles-m-r/murmurd index 9d7663ebbe..e0bd8d9762 100644 --- a/apparmor.d/profiles-m-r/murmurd +++ b/apparmor.d/profiles-m-r/murmurd @@ -10,7 +10,7 @@ include profile murmurd @{exec_path} { include include - include + include include include @@ -29,7 +29,7 @@ profile murmurd @{exec_path} { @{exec_path} mr, - @{bin}/lsb_release rPx -> lsb_release, + @{bin}/lsb_release rPx, /etc/mumble-server.ini r, diff --git a/apparmor.d/profiles-m-r/mutt b/apparmor.d/profiles-m-r/mutt index 28006f479a..0889fa9a73 100644 --- a/apparmor.d/profiles-m-r/mutt +++ b/apparmor.d/profiles-m-r/mutt @@ -10,6 +10,7 @@ include profile mutt @{exec_path} { include include + include include include include @@ -49,7 +50,6 @@ profile mutt @{exec_path} { /usr/share/mutt/** r, @{etc_ro}/mailcap r, - /etc/mime.types r, /etc/mutt{,**} r, /etc/Muttrc r, /etc/Muttrc.d/{*,} r, @@ -115,19 +115,7 @@ profile mutt @{exec_path} { profile pager { include - include - - @{pager_path} mr, - - /usr/share/terminfo/** r, - /usr/share/file/misc/magic.mgc r, - - owner @{HOME}/ r, - owner @{HOME}/.lesshs* rw, - owner @{HOME}/.terminfo/@{int}/* r, - owner @{user_cache_dirs}/lesshs* rw, - owner @{user_state_dirs}/ r, - owner @{user_state_dirs}/lesshs* rw, + include # This is the file that holds the message owner /{var/,}tmp/mutt* rw, diff --git a/apparmor.d/profiles-m-r/needrestart b/apparmor.d/profiles-m-r/needrestart index 397646c5ef..d59659592f 100644 --- a/apparmor.d/profiles-m-r/needrestart +++ b/apparmor.d/profiles-m-r/needrestart @@ -6,77 +6,73 @@ abi , include -@{exec_path} = @{bin}/needrestart +@{exec_path} = @{sbin}/needrestart profile needrestart @{exec_path} flags=(attach_disconnected) { include - include - include - include + include include - include capability checkpoint_restore, capability dac_read_search, - capability kill, capability sys_ptrace, ptrace read, - mqueue (r,getattr) type=posix /, + mqueue (read, getattr) type=posix /att/*/, @{exec_path} mrix, - @{bin}/* r, @{sh_path} rix, @{bin}/dpkg-query rpx, @{bin}/fail2ban-server rPx, - @{bin}/locale rix, - @{python_path} rix, - @{bin}/sed rix, @{bin}/stty rix, @{bin}/systemctl rCx -> systemctl, @{bin}/systemd-detect-virt rPx, @{bin}/udevadm rCx -> udevadm, - @{bin}/unix_chkpwd rPx, - @{bin}/whiptail rPx, - @{bin}/who rix, + @{bin}/which{,.debianutils} rix, + @{bin}/who rPx, @{lib}/needrestart/* rPx, - /usr/share/debconf/frontend rix, - - @{att}/@{lib}/@{python_name}/** r, + @{python_path} rix, + @{sbin}/unix_chkpwd rPx, - /usr/share/needrestart/{,**} r, - /usr/share/unattended-upgrades/unattended-upgrade-shutdown r, + @{etc_ro}/needrestart/hook.d/* rPx, + @{etc_ro}/needrestart/notify.d/* rPx, + @{etc_ro}/needrestart/restart.d/* rPx, - /etc/debconf.conf r, /etc/init.d/* r, /etc/needrestart/{,**} r, - /etc/needrestart/*.d/* rix, /etc/shadow r, / r, - /boot/ r, - /boot/intel-ucode.img r, - /boot/vmlinuz* r, - - owner /var/lib/juju/agents/{,**} r, - owner /var/cache/debconf/{config,passwords,templates}.dat{,-new,-old} rwk, + /att/**/ r, + @{efi}/ r, + @{efi}/* r, + /opt/*/** r, + @{bin}/* r, + @{lib}/** r, + @{sbin}/** r, + @{att}@{lib}/** r, + /usr/share/** r, + /var/lib/*/** r, + + @{run}/systemd/sessions/* r, /tmp/@{word10}/ rw, - owner @{run}/sshd.pid r, - @{PROC}/ r, @{PROC}/@{pids}/cgroup r, @{PROC}/@{pids}/cmdline r, @{PROC}/@{pids}/environ r, @{PROC}/@{pids}/maps r, @{PROC}/@{pids}/stat r, + @{PROC}/@{pids}/status r, owner @{PROC}/@{pid}/fd/ r, /dev/ r, /dev/**/ r, + deny mqueue type=posix /, + profile systemctl { include include diff --git a/apparmor.d/profiles-m-r/needrestart-apt-pinvoke b/apparmor.d/profiles-m-r/needrestart-apt-pinvoke index 480caf77e4..0c36cff0a2 100644 --- a/apparmor.d/profiles-m-r/needrestart-apt-pinvoke +++ b/apparmor.d/profiles-m-r/needrestart-apt-pinvoke @@ -10,7 +10,7 @@ include profile needrestart-apt-pinvoke @{exec_path} flags=(attach_disconnected) { include include - include + include include capability dac_read_search, @@ -19,7 +19,7 @@ profile needrestart-apt-pinvoke @{exec_path} flags=(attach_disconnected) { @{sh_path} rix, @{bin}/dbus-send rix, - @{bin}/needrestart rPx, + @{sbin}/needrestart rPx, @{bin}/rm rix, @{run}/needrestart/{,**} rw, diff --git a/apparmor.d/profiles-m-r/needrestart-dpkg-status b/apparmor.d/profiles-m-r/needrestart-dpkg-status index 3d54f896db..e596abc1d9 100644 --- a/apparmor.d/profiles-m-r/needrestart-dpkg-status +++ b/apparmor.d/profiles-m-r/needrestart-dpkg-status @@ -11,7 +11,8 @@ profile needrestart-dpkg-status @{exec_path} { include include - capability dac_read_search, + capability dac_read_search, + capability sys_admin, # optional: no audit @{exec_path} mr, diff --git a/apparmor.d/profiles-m-r/needrestart-hook b/apparmor.d/profiles-m-r/needrestart-hook new file mode 100644 index 0000000000..c8c9a12c4f --- /dev/null +++ b/apparmor.d/profiles-m-r/needrestart-hook @@ -0,0 +1,25 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{etc_ro}/needrestart/hook.d/* +profile needrestart-hook @{exec_path} { + include + include + include + + @{exec_path} mr, + @{sh_path} rix, + + @{bin}/dpkg-query px, + + /tmp/ r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/needrestart-iucode-scan-versions b/apparmor.d/profiles-m-r/needrestart-iucode-scan-versions index 75b150042c..ad8b119274 100644 --- a/apparmor.d/profiles-m-r/needrestart-iucode-scan-versions +++ b/apparmor.d/profiles-m-r/needrestart-iucode-scan-versions @@ -12,26 +12,30 @@ profile needrestart-iucode-scan-versions @{exec_path} { @{exec_path} mr, - @{bin}/iucode_tool rix, @{sh_path} rix, @{bin}/{,e}grep rix, @{bin}/bsdtar rix, @{bin}/cat rix, + @{bin}/find rix, + @{sbin}/iucode_tool rix, /usr/share/misc/ r, + /usr/share/misc/amd-microcode* r, /usr/share/misc/intel-microcode* r, + /etc/default/amd-microcode r, /etc/default/intel-microcode r, /etc/needrestart/iucode.sh r, - /boot/intel-ucode.img r, - /boot/early_ucode.cpio r, + @{efi}/amd-ucode.img r, + @{efi}/intel-ucode.img r, + @{efi}/early_ucode.cpio r, @{sys}/devices/system/cpu/cpu@{int}/microcode/processor_flags r, /dev/tty rw, - /dev/tty@{int} rw, - owner /dev/pts/@{int} rw, + /dev/tty@{u8} rw, + owner /dev/pts/@{u16} rw, include if exists } diff --git a/apparmor.d/profiles-m-r/needrestart-notify b/apparmor.d/profiles-m-r/needrestart-notify new file mode 100644 index 0000000000..82465ceb2d --- /dev/null +++ b/apparmor.d/profiles-m-r/needrestart-notify @@ -0,0 +1,35 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{etc_ro}/needrestart/notify.d/* +profile needrestart-notify @{exec_path} { + include + include + + capability dac_read_search, + capability sys_ptrace, + + ptrace read, + + @{exec_path} mr, + + @{sh_path} r, + @{bin}/fold ix, + @{bin}/gettext.sh r, + @{bin}/mail Px, + @{bin}/notify-send Px, + @{bin}/sed ix, + + /etc/needrestart/notify.conf r, + + @{PROC}/@{pid}/environ r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/needrestart-restart b/apparmor.d/profiles-m-r/needrestart-restart new file mode 100644 index 0000000000..23de12a488 --- /dev/null +++ b/apparmor.d/profiles-m-r/needrestart-restart @@ -0,0 +1,47 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{etc_ro}/needrestart/restart.d/* +profile needrestart-restart @{exec_path} { + include + + @{exec_path} mr, + @{sh_path} r, + + @{bin}/env mix, + @{bin}/kill Cx -> kill, + @{bin}/systemctl Cx -> systemctl, + + /var/log/unattended-upgrades/unattended-upgrades-dpkg.log rw, + + profile kill { + include + + capability kill, + + signal send, + + @{bin}/kill mr, + + include if exists + } + + profile systemctl { + include + include + + capability net_admin, + capability sys_ptrace, + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/needrestart-vmlinuz-get-version b/apparmor.d/profiles-m-r/needrestart-vmlinuz-get-version index 0c3c669a08..3828f92287 100644 --- a/apparmor.d/profiles-m-r/needrestart-vmlinuz-get-version +++ b/apparmor.d/profiles-m-r/needrestart-vmlinuz-get-version @@ -15,7 +15,7 @@ profile needrestart-vmlinuz-get-version @{exec_path} { @{sh_path} rix, @{bin}/bzip2 rix, - @{bin}/grep rix, + @{bin}/{,e}grep rix, @{bin}/gunzip rix, @{bin}/gzip rix, @{bin}/lzop rix, @@ -23,11 +23,12 @@ profile needrestart-vmlinuz-get-version @{exec_path} { @{bin}/rm rix, @{bin}/tail rix, @{bin}/tr rix, - @{bin}/which{,.debianutils} rix, + @{bin}/which{,.debianutils} rPx, @{bin}/xz rix, - /boot/intel-ucode.img r, - /boot/vmlinuz* r, + @{efi}/amd-ucode.img r, + @{efi}/intel-ucode.img r, + @{efi}/vmlinuz* r, owner @{tmp}/tmp.@{rand10} rw, diff --git a/apparmor.d/profiles-m-r/nemo b/apparmor.d/profiles-m-r/nemo index c7c9160d72..f4d7a1c682 100644 --- a/apparmor.d/profiles-m-r/nemo +++ b/apparmor.d/profiles-m-r/nemo @@ -28,6 +28,7 @@ profile nemo @{exec_path} { /usr/share/nemo/** r, /usr/share/thumbnailers/{,*.thumbnailer} r, + #aa:lint ignore=too-wide # Full access to user's data / r, /*/ r, diff --git a/apparmor.d/profiles-m-r/netstat b/apparmor.d/profiles-m-r/netstat index e19884997e..a23a095e9e 100644 --- a/apparmor.d/profiles-m-r/netstat +++ b/apparmor.d/profiles-m-r/netstat @@ -13,12 +13,18 @@ include profile netstat @{exec_path} { include include - include + include capability dac_read_search, capability sys_ptrace, capability syslog, + network inet dgram, + network inet stream, + network inet6 dgram, + network inet6 stream, + network netlink raw, + ptrace (trace,read), @{exec_path} rmix, diff --git a/apparmor.d/profiles-m-r/nmap b/apparmor.d/profiles-m-r/nmap index 348c3ac0e8..6f011d89e7 100644 --- a/apparmor.d/profiles-m-r/nmap +++ b/apparmor.d/profiles-m-r/nmap @@ -15,6 +15,8 @@ profile nmap @{exec_path} { capability net_bind_service, capability net_raw, + capability dac_override, + capability dac_read_search, network inet dgram, network inet6 dgram, diff --git a/apparmor.d/profiles-m-r/nslookup b/apparmor.d/profiles-m-r/nslookup index 41435f2f09..08628eefbe 100644 --- a/apparmor.d/profiles-m-r/nslookup +++ b/apparmor.d/profiles-m-r/nslookup @@ -21,6 +21,8 @@ profile nslookup @{exec_path} { owner @{PROC}/@{pids}/task/@{tid}/comm rw, + @{PROC}/version_signature r, + include if exists } diff --git a/apparmor.d/profiles-m-r/numlockx b/apparmor.d/profiles-m-r/numlockx index 5c88ec8461..84d158b9e8 100644 --- a/apparmor.d/profiles-m-r/numlockx +++ b/apparmor.d/profiles-m-r/numlockx @@ -16,7 +16,7 @@ profile numlockx @{exec_path} { owner @{HOME}/.Xauthority r, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, owner @{HOME}/.xsession-errors w, include if exists diff --git a/apparmor.d/profiles-m-r/nvidia-settings b/apparmor.d/profiles-m-r/nvidia-settings index 9e5944bfff..5513edc6bb 100644 --- a/apparmor.d/profiles-m-r/nvidia-settings +++ b/apparmor.d/profiles-m-r/nvidia-settings @@ -7,10 +7,11 @@ abi , include @{exec_path} = @{bin}/nvidia-settings -profile nvidia-settings @{exec_path} { +profile nvidia-settings @{exec_path} flags=(attach_disconnected) { include include include + include include @{exec_path} mr, @@ -21,8 +22,18 @@ profile nvidia-settings @{exec_path} { @{sys}/bus/pci/devices/ r, @{sys}/devices/@{pci}/config r, - - @{PROC}/devices r, + @{sys}/devices/system/node/ r, + @{sys}/devices/system/node/node@{int}/cpumap r, + + @{PROC}/devices r, + @{PROC}/driver/nvidia/capabilities/mig/config r, + @{PROC}/driver/nvidia/capabilities/mig/monitor r, + owner @{PROC}/@{pid}/cmdline r, + owner @{PROC}/@{pid}/task/@{tid}/comm rw, + + /dev/char/@{dynamic}:@{int} w, # For dynamic assignment range 234 to 254, 384 to 511 + /dev/nvidia-caps/ rw, + /dev/nvidia-caps/nvidia-cap@{int} r, include if exists } diff --git a/apparmor.d/profiles-m-r/nvidia-smi b/apparmor.d/profiles-m-r/nvidia-smi index 143808f76c..9be8571308 100644 --- a/apparmor.d/profiles-m-r/nvidia-smi +++ b/apparmor.d/profiles-m-r/nvidia-smi @@ -10,23 +10,21 @@ include profile nvidia-smi @{exec_path} { include include - include + include - @{exec_path} mr, + signal receive set=int peer=gnome-shell, # FIXME: shell extension only - @{sys}/devices/system/node/ r, - @{sys}/devices/system/node/node@{int}/cpumap r, + @{exec_path} mr, @{PROC}/devices r, @{PROC}/driver/nvidia/capabilities/mig/config r, @{PROC}/driver/nvidia/capabilities/mig/monitor r, owner @{PROC}/@{pid}/cmdline r, + owner @{PROC}/@{pid}/task/@{tid}/comm rw, /dev/char/@{dynamic}:@{int} w, # For dynamic assignment range 234 to 254, 384 to 511 /dev/nvidia-caps/ rw, - /dev/nvidia-caps/nvidia-cap@{int} r, - /dev/nvidia-uvm rw, - /dev/nvidia-uvm-tools r, + /dev/nvidia-caps/nvidia-cap@{int} rw, include if exists } diff --git a/apparmor.d/profiles-m-r/nvtop b/apparmor.d/profiles-m-r/nvtop index e4846d58e0..3fc7a7b766 100644 --- a/apparmor.d/profiles-m-r/nvtop +++ b/apparmor.d/profiles-m-r/nvtop @@ -12,48 +12,49 @@ profile nvtop @{exec_path} flags=(attach_disconnected) { include include include + include + include + include + include capability sys_ptrace, - ptrace (read), + ptrace read, @{exec_path} mr, /usr/share/terminfo/** r, + / r, + owner @{user_config_dirs}/nvtop/{,**} rw, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, @{run}/udev/data/+drm:card@{int}-* r, # for screen outputs @{run}/udev/data/+pci:* r, # Identifies all PCI devices (CPU, GPU, Network, Disks, USB, etc.) - @{run}/udev/data/c226:@{int} r, # For /dev/dri/card* @{run}/udev/data/c@{dynamic}:@{int} r, # For dynamic assignment range 234 to 254, 384 to 511 @{sys}/bus/ r, @{sys}/devices/@{pci}/ r, @{sys}/devices/@{pci}/current_link_{speed,width} r, @{sys}/devices/@{pci}/enable r, - @{sys}/devices/@{pci}/hwmon/hwmon@{int}/fan@{int}_{enable,max} r, - @{sys}/devices/@{pci}/hwmon/hwmon@{int}/power@{int}_cap r, - @{sys}/devices/@{pci}/hwmon/hwmon@{int}/pwm@{int} r, - @{sys}/devices/@{pci}/hwmon/hwmon@{int}/pwm@{int}_{enable,max} r, - @{sys}/devices/@{pci}/hwmon/hwmon@{int}/temp@{int}_crit r, @{sys}/devices/@{pci}/max_link_{speed,width} r, @{sys}/devices/@{pci}/pcie_bw r, + @{sys}/devices/**/uevent r, @{sys}/devices/system/node/node@{int}/cpumap r, - @{PROC}/ r, - @{PROC}/@{pids}/ r, - @{PROC}/@{pids}/cmdline r, - @{PROC}/@{pids}/fd/ r, - @{PROC}/@{pids}/fdinfo/ r, - @{PROC}/@{pids}/fdinfo/@{int} r, - @{PROC}/@{pids}/stat r, - @{PROC}/devices r, - @{PROC}/driver/nvidia/capabilities/mig/{config,monitor} r, - - /dev/dri/ r, + @{PROC}/ r, + @{PROC}/@{pid}/ r, + @{PROC}/@{pid}/cmdline r, + @{PROC}/@{pid}/fd/ r, + @{PROC}/@{pid}/fdinfo/ r, + @{PROC}/@{pid}/fdinfo/@{int} r, + @{PROC}/@{pid}/stat r, + @{PROC}/devices r, + @{PROC}/driver/nvidia/capabilities/mig/{config,monitor} r, + owner @{PROC}/@{pid}/task/@{tid}/comm rw, + /dev/nvidia-caps/ rw, /dev/nvidia-caps/nvidia-cap@{int} rw, diff --git a/apparmor.d/profiles-m-r/obconf b/apparmor.d/profiles-m-r/obconf index 7b11aaac5c..b35d025925 100644 --- a/apparmor.d/profiles-m-r/obconf +++ b/apparmor.d/profiles-m-r/obconf @@ -11,7 +11,7 @@ include profile obconf @{exec_path} { include include - include + include include include include @@ -34,7 +34,7 @@ profile obconf @{exec_path} { /etc/fstab r, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-m-r/ollama b/apparmor.d/profiles-m-r/ollama index 7b55218025..b1d29e8753 100644 --- a/apparmor.d/profiles-m-r/ollama +++ b/apparmor.d/profiles-m-r/ollama @@ -20,7 +20,7 @@ profile ollama @{exec_path} flags=(attach_disconnected) { network inet6 stream, network netlink raw, - @{exec_path} mr, + @{exec_path} mrix, /tmp/ollama@{int}/runners/*/* mr, /tmp/ollama@{int}/runners/*/ollama_*_server rix, # TODO: rPx and remove graphics from here. @@ -28,24 +28,39 @@ profile ollama @{exec_path} flags=(attach_disconnected) { /usr/ r, /usr/local/ r, /usr/local/lib/ r, + @{bin}/ r, - @{lib}/ r, + @{lib}/ollama/ r, + @{lib}/ollama/*.so mr, owner /var/lib/ollama/ rw, owner /var/lib/ollama/** rwlk, - /tmp/ r, + owner @{HOME}/.ollama/ rw, + owner @{HOME}/.ollama/** rwlk, + + @{tmp}/ r, + owner @{tmp}/@{int}.bin rw, owner @{tmp}/ollama@{int}/{,**} rw, owner @{tmp}/ollama@{int}/runners/{,**} mr, + @{sys}/devices/@{pci}/drm/card@{int}/ r, + @{sys}/devices/@{pci}/drm/card@{int}/*/ r, + @{sys}/devices/@{pci}/mem_info_vram_total r, + @{sys}/devices/@{pci}/mem_info_vram_used r, @{sys}/devices/@{pci}/numa_node r, @{sys}/devices/system/node/node@{int}/cpumap r, + @{sys}/fs/cgroup/system.slice/ollama.service/cpu.max r, @{PROC}/devices r, @{PROC}/sys/net/core/somaxconn r, + owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/cmdline r, + owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/task/@{tid}/comm w, + /dev/nvidia-caps/nvidia-cap@{int} r, + include if exists } diff --git a/apparmor.d/profiles-m-r/on-ac-power b/apparmor.d/profiles-m-r/on-ac-power index c92d4d8498..d6426f7175 100644 --- a/apparmor.d/profiles-m-r/on-ac-power +++ b/apparmor.d/profiles-m-r/on-ac-power @@ -7,17 +7,19 @@ abi , include -@{exec_path} = @{bin}/on_ac_power +@{exec_path} = @{sbin}/on_ac_power profile on-ac-power @{exec_path} { include @{exec_path} r, @{sh_path} rix, + @{bin}/{,e}grep rix, @{bin}/{m,g,}awk rix, @{bin}/cat rix, @{sys}/class/power_supply/ r, + @{sys}/class/typec/ r, @{sys}/devices/**/power_supply/**/{online,type} r, @{PROC}/pmu/info r, diff --git a/apparmor.d/profiles-m-r/open-iscsi-net-interface-handler b/apparmor.d/profiles-m-r/open-iscsi-net-interface-handler new file mode 100644 index 0000000000..2593b78ac7 --- /dev/null +++ b/apparmor.d/profiles-m-r/open-iscsi-net-interface-handler @@ -0,0 +1,19 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/open-iscsi/net-interface-handler +profile open-iscsi-net-interface-handler @{exec_path} flags=(complain) { + include + + @{exec_path} mr, + @{sh_path} r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/openbox b/apparmor.d/profiles-m-r/openbox index 15957b348f..f37fa42588 100644 --- a/apparmor.d/profiles-m-r/openbox +++ b/apparmor.d/profiles-m-r/openbox @@ -47,7 +47,7 @@ profile openbox @{exec_path} { owner @{PROC}/@{pid}/fd/ r, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, owner @{HOME}/.xsession-errors w, @@ -58,7 +58,7 @@ profile openbox @{exec_path} { @{lib}/@{multiarch}/openbox-xdg-autostart rix, @{sh_path} rix, - @{bin}/which{,.debianutils} rix, + @{bin}/which{,.debianutils} rix, # Apps allowed to run @{bin}/* rPUx, @@ -80,7 +80,7 @@ profile openbox @{exec_path} { # file_inherit owner @{HOME}/.xsession-errors w, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-m-r/openbox-session b/apparmor.d/profiles-m-r/openbox-session index 5313ed948e..687cf78331 100644 --- a/apparmor.d/profiles-m-r/openbox-session +++ b/apparmor.d/profiles-m-r/openbox-session @@ -22,7 +22,7 @@ profile openbox-session @{exec_path} { # file_inherit owner @{HOME}/.xsession-errors w, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-m-r/orage b/apparmor.d/profiles-m-r/orage index f87c0fa928..7b8576abfd 100644 --- a/apparmor.d/profiles-m-r/orage +++ b/apparmor.d/profiles-m-r/orage @@ -10,10 +10,7 @@ include @{exec_path} = @{bin}/orage profile orage @{exec_path} { include - include - include - include - include + include include include @@ -35,7 +32,7 @@ profile orage @{exec_path} { owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/mounts r, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-m-r/os-prober b/apparmor.d/profiles-m-r/os-prober index bfee591872..15bafcbff0 100644 --- a/apparmor.d/profiles-m-r/os-prober +++ b/apparmor.d/profiles-m-r/os-prober @@ -15,7 +15,7 @@ profile os-prober @{exec_path} flags=(attach_disconnected) { capability dac_read_search, capability sys_admin, - mount options=(rprivate, rw) -> /, + mount options=(rw, make-rprivate) /, mount options=(rw, nosuid, nodev) -> /var/lib/os-prober/mount/, umount /var/lib/os-prober/mount/, @@ -26,24 +26,24 @@ profile os-prober @{exec_path} flags=(attach_disconnected) { @{sh_path} rix, @{bin}/{e,f,}grep rix, - @{bin}/blkid rPx, - @{bin}/btrfs rPx, + @{sbin}/blkid rPx, + @{sbin}/btrfs rPx, @{bin}/cat rix, @{bin}/cut rix, - @{bin}/dmraid rPUx, + @{sbin}/dmraid rPUx, @{bin}/find rix, @{bin}/grub-mount rPx, - @{bin}/grub-probe rPx, + @{sbin}/grub-probe rPx, @{bin}/head rix, @{bin}/kmod rPx, @{bin}/logger rix, @{bin}/ls rix, @{bin}/lsblk rPx, - @{bin}/lvm rPx, + @{sbin}/lvm rPx, @{bin}/mkdir rix, @{bin}/mktemp rix, @{bin}/mount rix, - @{bin}/multipath rPx, + @{sbin}/multipath rPx, @{bin}/readlink rix, @{bin}/rm rix, @{bin}/rmdir rix, @@ -51,7 +51,7 @@ profile os-prober @{exec_path} flags=(attach_disconnected) { @{bin}/udevadm rPx, @{bin}/umount rix, @{bin}/uname rix, - @{bin}/which rix, + @{bin}/which{,.debianutils} rix, @{lib}/newns rix, @{lib}/os-prober/* rix, @{lib}/os-probes/{,**} rix, @@ -63,9 +63,9 @@ profile os-prober @{exec_path} flags=(attach_disconnected) { @{MOUNTS}/ r, / r, - /boot/{efi/,} r, - /boot/{efi/,}EFI/ r, - /boot/{efi/,}EFI/**/ r, + @{efi}/ r, + @{efi}/EFI/ r, + @{efi}/EFI/**/ r, owner @{tmp}/os-prober.*/{,**} rw, @@ -78,7 +78,7 @@ profile os-prober @{exec_path} flags=(attach_disconnected) { owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/mounts r, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-m-r/ouch b/apparmor.d/profiles-m-r/ouch index a5b62ca93f..d0bb4a1ed3 100644 --- a/apparmor.d/profiles-m-r/ouch +++ b/apparmor.d/profiles-m-r/ouch @@ -17,11 +17,16 @@ profile ouch @{exec_path} { owner @{HOME}/.tmp@{rand6}/{,**} rw, owner @{HOME}/.tmp-ouch@{rand6}/{,**} rw, + owner /tmp/ w, + owner /tmp/.tmp@{rand6}/{,**} rw, + owner /tmp/.tmp-ouch@{rand6}/{,**} rw, + @{sys}/fs/cgroup/user.slice/cpu.max r, @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/cpu.max r, @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/session-@{word}.scope/cpu.max r, owner @{PROC}/@{pid}/cgroup r, + owner @{PROC}/@{pid}/mountinfo r, include if exists } diff --git a/apparmor.d/profiles-m-r/packagekitd b/apparmor.d/profiles-m-r/packagekitd index bcd9ba6b72..6cf6646819 100644 --- a/apparmor.d/profiles-m-r/packagekitd +++ b/apparmor.d/profiles-m-r/packagekitd @@ -9,12 +9,12 @@ include @{exec_path} = @{lib}/packagekitd profile packagekitd @{exec_path} flags=(attach_disconnected) { include + include #aa:only apt include - include - include - include - include #aa:only apt + include + include include + include include capability chown, @@ -38,59 +38,78 @@ profile packagekitd @{exec_path} flags=(attach_disconnected) { signal send set=int peer=apt-methods-*, signal send set=term peer=systemd-inhibit, - #aa:dbus own bus=system name=org.freedesktop.PackageKit + #aa:dbus own bus=system name=org.freedesktop.PackageKit path=/** @{exec_path} mr, - @{bin}/gpg{,2} rCx -> gpg, - @{bin}/gpgconf rCx -> gpg, - @{bin}/gpgsm rCx -> gpg, + @{bin}/gpg{,2} Cx -> gpg, + @{bin}/gpgconf Cx -> gpg, + @{bin}/gpgsm Cx -> gpg, @{sh_path} rix, @{bin}/cp rix, @{bin}/echo rix, @{bin}/gdbus rix, @{bin}/gzip rix, - @{bin}/ischroot rix, - @{bin}/ldconfig rix, + @{bin}/id rix, + @{sbin}/ldconfig rix, # TODO: rCx @{bin}/repo2solv rix, @{bin}/tar rix, @{bin}/test rix, @{bin}/touch rix, - @{bin}/appstreamcli rPx, - @{bin}/arch-audit rPx, #aa:only arch - @{bin}/dpkg rPx -> child-dpkg, #aa:only apt - @{bin}/fc-cache rPx, - @{bin}/glib-compile-schemas rPx, - @{bin}/install-info rPx, - @{bin}/rpm rPUx, #aa:only opensuse - @{bin}/rpmdb2solv rPUx, #aa:only opensuse - @{bin}/systemd-inhibit rPx, - @{bin}/update-desktop-database rPx, - @{lib}/apt/methods/* rPx, #aa:only apt - @{lib}/cnf-update-db rPx, - @{lib}/update-notifier/update-motd-updates-available rPx, - @{lib}/zypp/plugins/appdata/InstallAppdata rPUx, # TODO: write the profile - /usr/share/libalpm/scripts/* rPx, + @{bin}/appstreamcli Px, + @{bin}/fc-cache Px, + @{bin}/glib-compile-schemas Px, + @{bin}/install-info Px, + @{bin}/ischroot Px, + @{bin}/systemctl Cx -> systemctl, + @{bin}/systemd-inhibit Px, + @{bin}/update-desktop-database Px, + @{lib}/cnf-update-db Px, + + #aa:only pacman + @{bin}/arch-audit Px, + /usr/share/libalpm/scripts/* Px, + + #aa:only apt + @{bin}/apt-listchanges Px, + @{bin}/dpkg Px, + @{lib}/apt/methods/* Px, + @{lib}/needrestart/apt-pinvoke Px, + @{sbin}/dpkg-preconfigure Px, + #aa:only opensuse + @{lib}/zypp/plugins/appdata/InstallAppdata PUx, # TODO: write the profile + @{bin}/rpm PUx, + @{bin}/rpmdb2solv PUx, + + #aa:only ubuntu + @{lib}/update-notifier/update-motd-updates-available Px, + + #aa:lint ignore=too-wide # Install/update packages / r, /*{,/} rw, - /boot/** rwl -> /boot/**, + @{efi}/** rwl -> @{efi}/**, /etc/** rwl -> /etc/**, /opt/** rwl -> /opt/**, /srv/** rwl -> /srv/**, /usr/** rwlk -> /usr/**, /var/** rwlk -> /var/**, + owner @{tmp}/packagekit* rw, + + #aa:only arch + owner @{tmp}/alpm_*/{,**} rw, + + #aa:only apt /tmp/apt-changelog-@{rand6}/ w, /tmp/apt-changelog-@{rand6}/*.changelog rw, - owner @{tmp}/alpm_*/{,**} rw, + /tmp/apt-dpkg-install-@{rand6}/ rw, owner @{tmp}/apt-changelog-@{rand6}/.apt-acquire-privs-test.@{rand6} rw, - owner @{tmp}/packagekit* rw, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, owner @{run}/systemd/users/@{uid} r, @@ -112,6 +131,7 @@ profile packagekitd @{exec_path} flags=(attach_disconnected) { owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/mounts r, + /dev/ptmx r, /dev/tty rw, profile gpg { @@ -149,6 +169,15 @@ profile packagekitd @{exec_path} flags=(attach_disconnected) { include if exists } + profile systemctl { + include + include + + capability net_admin, + + include if exists + } + include if exists } diff --git a/apparmor.d/profiles-m-r/pactl b/apparmor.d/profiles-m-r/pactl index 1e89ef3f21..e8dd535d92 100644 --- a/apparmor.d/profiles-m-r/pactl +++ b/apparmor.d/profiles-m-r/pactl @@ -23,7 +23,7 @@ profile pactl @{exec_path} { owner @{HOME}/.Xauthority r, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, owner @{HOME}/.xsession-errors w, owner @{HOME}/.anyRemote/anyremote.stdout w, diff --git a/apparmor.d/profiles-m-r/pam-auth-update b/apparmor.d/profiles-m-r/pam-auth-update index 3991299b91..28b06fa43f 100644 --- a/apparmor.d/profiles-m-r/pam-auth-update +++ b/apparmor.d/profiles-m-r/pam-auth-update @@ -7,59 +7,25 @@ abi , include -@{exec_path} = @{bin}/pam-auth-update +@{exec_path} = @{sbin}/pam-auth-update profile pam-auth-update @{exec_path} flags=(complain) { include - include - include + include - @{exec_path} mr, + @{exec_path} mrix, - @{bin}/md5sum rix, - @{bin}/cp rix, + @{bin}/cp ix, + @{bin}/md5sum ix, + @{bin}/stty ix, - # Think what to do about this (#FIXME#) - /usr/share/debconf/frontend rPx, - #/usr/share/debconf/frontend rCx -> frontend, - - /etc/pam.d/* rw, - /var/lib/pam/* rw, /usr/share/pam{,-configs}/{,*} r, + /etc/pam.d/* rw, + /etc/shadow r, - profile frontend flags=(complain) { - include - include - include - include - - /usr/share/debconf/frontend r, - - @{bin}/pam-auth-update rPx, - - @{sh_path} rix, - @{bin}/stty rix, - @{bin}/locale rix, - - /etc/debconf.conf r, - owner /var/cache/debconf/{config,passwords,templates}.dat{,-new,-old} rwk, - /usr/share/debconf/templates/adequate.templates r, - - # The following is needed when debconf uses GUI frontends. - include - include - include - include - capability dac_read_search, - @{bin}/lsb_release rPx -> lsb_release, - @{bin}/hostname rix, - owner @{PROC}/@{pid}/mounts r, - @{HOME}/.Xauthority r, - - /etc/shadow r, - - include if exists - } + /var/lib/dpkg/info/libpam-runtime.templates r, + /var/lib/dpkg/tmp.ci/control r, + /var/lib/pam/* rw, include if exists } diff --git a/apparmor.d/profiles-m-r/pam-tmpdir-helper b/apparmor.d/profiles-m-r/pam-tmpdir-helper index fc767e5b3b..6501960fac 100644 --- a/apparmor.d/profiles-m-r/pam-tmpdir-helper +++ b/apparmor.d/profiles-m-r/pam-tmpdir-helper @@ -19,7 +19,7 @@ profile pam-tmpdir-helper @{exec_path} { owner @{tmp}/ rw, /dev/ptmx rw, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-m-r/parted b/apparmor.d/profiles-m-r/parted index 4a98dbae81..1ae7f5478f 100644 --- a/apparmor.d/profiles-m-r/parted +++ b/apparmor.d/profiles-m-r/parted @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/parted +@{exec_path} = @{sbin}/parted profile parted @{exec_path} { include include @@ -22,7 +22,7 @@ profile parted @{exec_path} { @{sh_path} rix, @{bin}/udevadm rCx -> udevadm, - @{bin}/dmidecode rPx, + @{sbin}/dmidecode rPx, /etc/inputrc r, diff --git a/apparmor.d/profiles-m-r/partprobe b/apparmor.d/profiles-m-r/partprobe index 6a0a6c9cf2..79e4b0ffba 100644 --- a/apparmor.d/profiles-m-r/partprobe +++ b/apparmor.d/profiles-m-r/partprobe @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/partprobe +@{exec_path} = @{sbin}/partprobe profile partprobe @{exec_path} { include include @@ -23,7 +23,7 @@ profile partprobe @{exec_path} { @{sh_path} rix, @{bin}/udevadm rCx -> udevadm, - @{bin}/dmidecode rPx, + @{sbin}/dmidecode rPx, @{PROC}/devices r, @{PROC}/swaps r, diff --git a/apparmor.d/profiles-m-r/pass b/apparmor.d/profiles-m-r/pass index 5ae5df7e61..ded9e70121 100644 --- a/apparmor.d/profiles-m-r/pass +++ b/apparmor.d/profiles-m-r/pass @@ -24,7 +24,7 @@ profile pass @{exec_path} { @{bin}/env r, @{bin}/find ix, @{bin}/getopt ix, - @{bin}/grep ix, + @{bin}/{,e}grep ix, @{bin}/head ix, @{bin}/mkdir ix, @{bin}/mktemp ix, @@ -40,7 +40,7 @@ profile pass @{exec_path} { @{bin}/tr ix, @{bin}/tree ix, @{bin}/tty ix, - @{bin}/which ix, + @{bin}/which{,.debianutils} rix, @{bin}/git Cx -> git, @{bin}/gpg{2,} Cx -> gpg, @@ -144,10 +144,14 @@ profile pass @{exec_path} { owner @{user_passwordstore_dirs}/ rw, owner @{user_passwordstore_dirs}/** rwkl -> @{HOME}/.password-store/**, + owner /dev/shm/pass.@{rand}/* rw, owner @{tmp}/.git_vtag_tmp@{rand6} rw, # For git log --show-signature - owner /dev/pts/@{int} rw, + owner @{run}/user/@{uid}/gnupg/d.@{rand}/S.gpg-agent rw, + owner @{run}/user/@{uid}/gnupg/S.gpg-agent rw, + + owner /dev/pts/@{u16} rw, include if exists } diff --git a/apparmor.d/profiles-m-r/pass-import b/apparmor.d/profiles-m-r/pass-import index c8fb38e441..8d55dd156c 100644 --- a/apparmor.d/profiles-m-r/pass-import +++ b/apparmor.d/profiles-m-r/pass-import @@ -24,7 +24,7 @@ profile pass-import @{exec_path} { @{bin}/ r, @{bin}/gcc rix, # TODO: Test deny @{bin}/ld rix, - @{bin}/ldconfig rix, + @{sbin}/ldconfig rix, @{bin}/pass rPx, @{python_path} rix, @{lib}/gcc/**/collect2 rix, diff --git a/apparmor.d/profiles-m-r/passimd b/apparmor.d/profiles-m-r/passimd index c0aafeaf90..6c59152b50 100644 --- a/apparmor.d/profiles-m-r/passimd +++ b/apparmor.d/profiles-m-r/passimd @@ -9,8 +9,11 @@ include @{exec_path} = @{lib}/passimd profile passimd @{exec_path} flags=(attach_disconnected) { include + include include + include include + include capability dac_read_search, @@ -18,7 +21,7 @@ profile passimd @{exec_path} flags=(attach_disconnected) { network inet6 stream, network netlink raw, - #aa:dbus own bus=system name=org.freedesktop.Passim + #aa:dbus own bus=system name=org.freedesktop.Passim path=/ @{exec_path} mr, diff --git a/apparmor.d/profiles-m-r/pavucontrol b/apparmor.d/profiles-m-r/pavucontrol index 596cbacbdd..0b0756a5c4 100644 --- a/apparmor.d/profiles-m-r/pavucontrol +++ b/apparmor.d/profiles-m-r/pavucontrol @@ -28,7 +28,7 @@ profile pavucontrol @{exec_path} { owner @{PROC}/@{pid}/cmdline r, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-m-r/pcb-gtk b/apparmor.d/profiles-m-r/pcb-gtk index e736299fae..2923f70cdf 100644 --- a/apparmor.d/profiles-m-r/pcb-gtk +++ b/apparmor.d/profiles-m-r/pcb-gtk @@ -10,13 +10,9 @@ include @{exec_path} = @{bin}/pcb-gtk profile pcb-gtk @{exec_path} { include - include - include - include + include include - include - include - include + include include include @@ -24,7 +20,7 @@ profile pcb-gtk @{exec_path} { /usr/share/pcb/ListLibraryContents.sh rix, - @{bin}/dash rix, + @{sh_path} rix, @{bin}/cat rix, @{bin}/tr rix, diff --git a/apparmor.d/profiles-m-r/pcscd b/apparmor.d/profiles-m-r/pcscd index 984b566cf5..d62c10a375 100644 --- a/apparmor.d/profiles-m-r/pcscd +++ b/apparmor.d/profiles-m-r/pcscd @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/pcscd +@{exec_path} = @{sbin}/pcscd profile pcscd @{exec_path} { include include @@ -16,21 +16,25 @@ profile pcscd @{exec_path} { network netlink raw, - ptrace (read) peer=@{p_systemd_user}, - ptrace (read) peer=gsd-smartcard, - ptrace (read) peer=keepassxc, - ptrace (read) peer=pkcs11-register, - ptrace (read) peer=rngd, - ptrace (read) peer=scdaemon, - ptrace (read) peer=veracrypt, + ptrace read peer=@{p_systemd_user}, + ptrace read peer=gsd-smartcard, + ptrace read peer=keepassxc, + ptrace read peer=pkcs11-register, + ptrace read peer=rngd, + ptrace read peer=scdaemon, + ptrace read peer=veracrypt, @{exec_path} mr, /etc/libccid_Info.plist r, /etc/reader.conf.d/{,**} r, + / r, + owner @{run}/pcscd/{,pcscd.pid} rw, + @{sys}/devices/**/uevent r, + @{PROC}/@{pid}/fdinfo/@{int} r, @{PROC}/@{pids}/stat r, diff --git a/apparmor.d/profiles-m-r/pdfattach b/apparmor.d/profiles-m-r/pdfattach new file mode 100644 index 0000000000..5a063422e7 --- /dev/null +++ b/apparmor.d/profiles-m-r/pdfattach @@ -0,0 +1,22 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 valoq +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/pdfattach +profile pdfattach @{exec_path} { + include + include + include + + @{exec_path} mr, + + /usr/share/poppler/{,**} r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/pdfdetach b/apparmor.d/profiles-m-r/pdfdetach new file mode 100644 index 0000000000..bf6e589cc7 --- /dev/null +++ b/apparmor.d/profiles-m-r/pdfdetach @@ -0,0 +1,22 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 valoq +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/pdfdetach +profile pdfdetach @{exec_path} { + include + include + include + + @{exec_path} mr, + + /usr/share/poppler/{,**} r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/pdffonts b/apparmor.d/profiles-m-r/pdffonts new file mode 100644 index 0000000000..8cc71b2464 --- /dev/null +++ b/apparmor.d/profiles-m-r/pdffonts @@ -0,0 +1,21 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 valoq +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/pdffonts +profile pdffonts @{exec_path} { + include + include + + @{exec_path} mr, + + /usr/share/poppler/{,**} r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/pdfimages b/apparmor.d/profiles-m-r/pdfimages new file mode 100644 index 0000000000..0f3a6681b1 --- /dev/null +++ b/apparmor.d/profiles-m-r/pdfimages @@ -0,0 +1,22 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 valoq +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/pdfimages +profile pdfimages @{exec_path} { + include + include + include + + @{exec_path} mr, + + /usr/share/poppler/{,**} r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/pdfinfo b/apparmor.d/profiles-m-r/pdfinfo new file mode 100644 index 0000000000..b1c2929523 --- /dev/null +++ b/apparmor.d/profiles-m-r/pdfinfo @@ -0,0 +1,22 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 valoq +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/pdfinfo +profile pdfinfo @{exec_path} { + include + include + include + + @{exec_path} mr, + + /usr/share/poppler/{,**} r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/pdfseparate b/apparmor.d/profiles-m-r/pdfseparate new file mode 100644 index 0000000000..1026719f8e --- /dev/null +++ b/apparmor.d/profiles-m-r/pdfseparate @@ -0,0 +1,22 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 valoq +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/pdfseparate +profile pdfseparate @{exec_path} { + include + include + include + + @{exec_path} mr, + + /usr/share/poppler/{,**} r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/pdfsig b/apparmor.d/profiles-m-r/pdfsig new file mode 100644 index 0000000000..5f4cb3ce71 --- /dev/null +++ b/apparmor.d/profiles-m-r/pdfsig @@ -0,0 +1,23 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 valoq +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/pdfsig +profile pdfsig @{exec_path} { + include + include + include + include + + @{exec_path} mr, + + /usr/share/poppler/{,**} r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/pdftocairo b/apparmor.d/profiles-m-r/pdftocairo new file mode 100644 index 0000000000..65a8800577 --- /dev/null +++ b/apparmor.d/profiles-m-r/pdftocairo @@ -0,0 +1,22 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 valoq +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/pdftocairo +profile pdftocairo @{exec_path} { + include + include + include + + @{exec_path} mr, + + /usr/share/poppler/{,**} r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/pdftohtml b/apparmor.d/profiles-m-r/pdftohtml new file mode 100644 index 0000000000..3c44be2f51 --- /dev/null +++ b/apparmor.d/profiles-m-r/pdftohtml @@ -0,0 +1,22 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 valoq +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/pdftohtml +profile pdftohtml @{exec_path} { + include + include + include + + @{exec_path} mr, + + /usr/share/poppler/{,**} r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/pdftoppm b/apparmor.d/profiles-m-r/pdftoppm new file mode 100644 index 0000000000..4be131bd3b --- /dev/null +++ b/apparmor.d/profiles-m-r/pdftoppm @@ -0,0 +1,29 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 valoq +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/pdftoppm +profile pdftoppm @{exec_path} { + include + include + include + include + + @{exec_path} mr, + + /usr/share/poppler/{,**} r, + + owner /tmp/{,**}.ppm w, + owner /tmp/{,**}.png w, + owner /tmp/{,**}.jpg w, + owner /tmp/{,**}.jpeg w, + owner /tmp/{,**}.tiff w, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/pdftops b/apparmor.d/profiles-m-r/pdftops new file mode 100644 index 0000000000..1a390c576c --- /dev/null +++ b/apparmor.d/profiles-m-r/pdftops @@ -0,0 +1,22 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 valoq +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/pdftops +profile pdftops @{exec_path} { + include + include + include + + @{exec_path} mr, + + /usr/share/poppler/{,**} r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/pdftotext b/apparmor.d/profiles-m-r/pdftotext index 0394687f73..7fb2bed7bf 100644 --- a/apparmor.d/profiles-m-r/pdftotext +++ b/apparmor.d/profiles-m-r/pdftotext @@ -1,5 +1,5 @@ # apparmor.d - Full set of apparmor profiles -# Copyright (C) 2024 valoq +# Copyright (C) 2025 valoq # SPDX-License-Identifier: GPL-2.0-only abi , diff --git a/apparmor.d/profiles-m-r/pdfunite b/apparmor.d/profiles-m-r/pdfunite new file mode 100644 index 0000000000..7b2019af5a --- /dev/null +++ b/apparmor.d/profiles-m-r/pdfunite @@ -0,0 +1,22 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 valoq +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/pdfunite +profile pdfunite @{exec_path} { + include + include + include + + @{exec_path} mr, + + /usr/share/poppler/{,**} r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/picom b/apparmor.d/profiles-m-r/picom index 7d423f1489..1d841e65b3 100644 --- a/apparmor.d/profiles-m-r/picom +++ b/apparmor.d/profiles-m-r/picom @@ -33,7 +33,7 @@ profile picom @{exec_path} { owner @{PROC}/@{pid}/fd/ r, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-m-r/pidof b/apparmor.d/profiles-m-r/pidof index 76b9942fb0..7f4197b1d8 100644 --- a/apparmor.d/profiles-m-r/pidof +++ b/apparmor.d/profiles-m-r/pidof @@ -13,7 +13,7 @@ profile pidof @{exec_path} flags=(attach_disconnected) { capability sys_ptrace, - ptrace (read), + ptrace read, @{exec_path} mr, @@ -23,13 +23,12 @@ profile pidof @{exec_path} flags=(attach_disconnected) { @{sys}/devices/system/node/node@{int}/meminfo r, @{PROC}/ r, + @{PROC}/@{pids}/ r, @{PROC}/@{pids}/cmdline r, @{PROC}/@{pids}/stat r, @{PROC}/sys/kernel/osrelease r, @{PROC}/uptime r, - /dev/tty@{int} rw, - include if exists } diff --git a/apparmor.d/profiles-m-r/pinentry-curses b/apparmor.d/profiles-m-r/pinentry-curses index c14b410270..193e10b557 100644 --- a/apparmor.d/profiles-m-r/pinentry-curses +++ b/apparmor.d/profiles-m-r/pinentry-curses @@ -17,7 +17,7 @@ profile pinentry-curses @{exec_path} { /usr/share/terminfo/** r, - owner /dev/tty@{int} r, + owner /dev/tty@{u8} r, include if exists } diff --git a/apparmor.d/profiles-m-r/pinentry-gnome3 b/apparmor.d/profiles-m-r/pinentry-gnome3 index a955a9c6d6..40990bf9b7 100644 --- a/apparmor.d/profiles-m-r/pinentry-gnome3 +++ b/apparmor.d/profiles-m-r/pinentry-gnome3 @@ -11,8 +11,19 @@ profile pinentry-gnome3 @{exec_path} { include include include + include - signal (receive) set=(int) peer=gpg-agent, + signal receive set=int, + + dbus receive bus=session path=/org/gnome/keyring/Prompt/p@{int} + interface=org.gnome.keyring.internal.Prompter.Callback + member={PromptReady,PromptDone} + peer=(name=@{busname}), + + dbus send bus=session path=/org/gnome/keyring/Prompter + interface=org.gnome.keyring.internal.Prompter + member={BeginPrompting,PerformPrompt,StopPrompting} + peer=(name=org.gnome.keyring.SystemPrompter), @{exec_path} mr, diff --git a/apparmor.d/profiles-m-r/pinentry-gtk b/apparmor.d/profiles-m-r/pinentry-gtk index a0244956d3..a010c99b7d 100644 --- a/apparmor.d/profiles-m-r/pinentry-gtk +++ b/apparmor.d/profiles-m-r/pinentry-gtk @@ -11,18 +11,24 @@ include profile pinentry-gtk @{exec_path} { include include - include - include include - include + include - @{exec_path} mr, + dbus receive bus=session path=/org/gnome/keyring/Prompt/p@{int} + interface=org.gnome.keyring.internal.Prompter.Callback + member={PromptReady,PromptDone} + peer=(name=@{busname}), + + dbus send bus=session path=/org/gnome/keyring/Prompter + interface=org.gnome.keyring.internal.Prompter + member={BeginPrompting,PerformPrompt,StopPrompting} + peer=(name=org.gnome.keyring.SystemPrompter), - /usr/share/gtk-@{int}.@{int}/{,**} r, + @{exec_path} mr, - owner @{run}/user/@{uid}/.mutter-Xwaylandauth.@{rand6} r, + @{PROC}/@{pid}/cmdline r, - owner /dev/tty@{int} r, + owner /dev/tty@{u8} r, include if exists } diff --git a/apparmor.d/profiles-m-r/pinentry-kwallet b/apparmor.d/profiles-m-r/pinentry-kwallet index adff98c535..c70cdbf260 100644 --- a/apparmor.d/profiles-m-r/pinentry-kwallet +++ b/apparmor.d/profiles-m-r/pinentry-kwallet @@ -10,11 +10,22 @@ include @{exec_path} = @{bin}/pinentry-kwallet profile pinentry-kwallet @{exec_path} { include + include include include signal (send) set=(term, kill) peer=gpg-agent, + dbus receive bus=session path=/org/gnome/keyring/Prompt/p@{int} + interface=org.gnome.keyring.internal.Prompter.Callback + member={PromptReady,PromptDone} + peer=(name=@{busname}), + + dbus send bus=session path=/org/gnome/keyring/Prompter + interface=org.gnome.keyring.internal.Prompter + member={BeginPrompting,PerformPrompt,StopPrompting} + peer=(name=org.gnome.keyring.SystemPrompter), + @{exec_path} mr, @{bin}/date rix, diff --git a/apparmor.d/profiles-m-r/pinentry-qt b/apparmor.d/profiles-m-r/pinentry-qt index 3c5ec0a94b..1b638f65aa 100644 --- a/apparmor.d/profiles-m-r/pinentry-qt +++ b/apparmor.d/profiles-m-r/pinentry-qt @@ -17,6 +17,18 @@ profile pinentry-qt @{exec_path} { include include + ptrace read peer=gpg-agent, + + dbus receive bus=session path=/org/gnome/keyring/Prompt/p@{int} + interface=org.gnome.keyring.internal.Prompter.Callback + member={PromptReady,PromptDone} + peer=(name=@{busname}), + + dbus send bus=session path=/org/gnome/keyring/Prompter + interface=org.gnome.keyring.internal.Prompter + member={BeginPrompting,PerformPrompt,StopPrompting} + peer=(name=org.gnome.keyring.SystemPrompter), + @{exec_path} mr, /etc/machine-id r, diff --git a/apparmor.d/profiles-m-r/pkcs11-register b/apparmor.d/profiles-m-r/pkcs11-register index 989f6ec8bf..618b7fc692 100644 --- a/apparmor.d/profiles-m-r/pkcs11-register +++ b/apparmor.d/profiles-m-r/pkcs11-register @@ -9,13 +9,12 @@ include @{exec_path} = @{bin}/pkcs11-register profile pkcs11-register @{exec_path} { include + include @{exec_path} mr, - /etc/{,opensc/}opensc.conf r, - - owner @{HOME}/.mozilla/firefox/*/pkcs11.txt rw, - owner @{HOME}/.mozilla/firefox/profiles.ini r, + owner @{HOME}/.mozilla/firefox{,-esr}/*/pkcs11.txt rw, + owner @{HOME}/.mozilla/firefox{,-esr}/profiles.ini r, owner @{HOME}/.pki/nssdb/pkcs11.txt r, owner @{HOME}/.thunderbird/*/pkcs11.txt rw, owner @{HOME}/.thunderbird/profiles.ini r, diff --git a/apparmor.d/profiles-m-r/plank b/apparmor.d/profiles-m-r/plank index 9619326f2e..e643e8617a 100644 --- a/apparmor.d/profiles-m-r/plank +++ b/apparmor.d/profiles-m-r/plank @@ -11,7 +11,6 @@ include profile plank @{exec_path} { include include - include include include include diff --git a/apparmor.d/profiles-m-r/pokemmo b/apparmor.d/profiles-m-r/pokemmo index 111b157c5a..557f87b494 100644 --- a/apparmor.d/profiles-m-r/pokemmo +++ b/apparmor.d/profiles-m-r/pokemmo @@ -37,7 +37,7 @@ profile pokemmo @{exec_path} flags=(attach_disconnected) { @{bin}/java ix, @{bin}/perl ix, - @{bin}/which ix, + @{bin}/which{,.debianutils} ix, @{lib}/jvm/java-@{int}-openjdk/bin/java ix, # Installer @@ -90,7 +90,7 @@ profile pokemmo @{exec_path} flags=(attach_disconnected) { /dev/input/js@{int} rw, /dev/tty rw, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-m-r/pollinate b/apparmor.d/profiles-m-r/pollinate new file mode 100644 index 0000000000..5a10cc9e29 --- /dev/null +++ b/apparmor.d/profiles-m-r/pollinate @@ -0,0 +1,48 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/pollinate +profile pollinate @{exec_path} { + include + include + + network inet dgram, + network inet stream, + network inet6 dgram, + network inet6 stream, + network netlink raw, + + @{exec_path} mr, + + @{sh_path} rix, + @{coreutils_path} rix, + @{bin}/curl rix, + @{bin}/dpkg rPx -> child-dpkg, + @{bin}/dpkg-query rpx, + @{bin}/hostname rix, + @{bin}/logger rix, + @{bin}/systemd-detect-virt rPx, + @{bin}/xxd rix, + + /etc/cloud/build.info r, + /etc/default/pollinate r, + /etc/lsb-release r, + /etc/pollinate/{,**} r, + + owner /var/cache/pollinate/seeded w, + + owner /tmp/pollinate.@{rand12}/{,**} rw, + + @{PROC}/uptime r, + + /dev/urandom w, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/power-profiles-daemon b/apparmor.d/profiles-m-r/power-profiles-daemon index fe4e35724d..d2a54d94f1 100644 --- a/apparmor.d/profiles-m-r/power-profiles-daemon +++ b/apparmor.d/profiles-m-r/power-profiles-daemon @@ -10,9 +10,10 @@ include profile power-profiles-daemon @{exec_path} flags=(attach_disconnected) { include include - include - include + include + include include + include capability dac_read_search, capability net_admin, @@ -27,17 +28,21 @@ profile power-profiles-daemon @{exec_path} flags=(attach_disconnected) { /var/lib/power-profiles-daemon/{,**} rw, - @{run}/udev/data/+platform:* r, - @{run}/udev/data/+power_supply:* r, + @{run}/udev/data/+platform:* r, # Identifies onboard devices (laptop/board model, power controllers, thermal sensors) + @{run}/udev/data/+power_supply:* r, # For power supply devices (batteries, AC adapters, USB chargers) + @{run}/udev/data/+drm:card@{int}-* r, # For screen outputs + @{run}/udev/data/c226:@{int} r, # For /dev/dri/card[0-9]* @{sys}/bus/ r, @{sys}/bus/platform/devices/ r, + @{sys}/devices/platform/*/dytc_lapmode r, @{sys}/class/ r, + @{sys}/class/drm/ r, @{sys}/class/power_supply/ r, + @{sys}/devices/**/status r, @{sys}/devices/**/power_supply/*/scope r, @{sys}/devices/**/uevent r, @{sys}/devices/system/cpu/*_pstate/{no_turbo,turbo_pct} r, - @{sys}/devices/system/cpu/*_pstate/status r, @{sys}/devices/system/cpu/cpu@{int}/power/energy_perf_bias rw, @{sys}/devices/system/cpu/cpufreq/ r, @{sys}/devices/system/cpu/cpufreq/policy@{int}/* rw, diff --git a/apparmor.d/profiles-m-r/protonmail b/apparmor.d/profiles-m-r/protonmail index c6d309a943..a381ac4b81 100644 --- a/apparmor.d/profiles-m-r/protonmail +++ b/apparmor.d/profiles-m-r/protonmail @@ -7,38 +7,31 @@ abi , include -@{name} = proton-mail "Proton Mail" -@{lib_dirs} = /opt/@{name} +@{name} = protonmail proton-mail Proton?Mail +@{domain} = org.chromium.Chromium +@{lib_dirs} = /opt/@{name} /usr/share/@{name} @{config_dirs} = @{user_config_dirs}/@{name} @{cache_dirs} = @{user_cache_dirs}/@{name} -@{exec_path} = @{bin}/proton-mail /opt/proton-mail/Proton* -profile protonmail @{exec_path} flags=(complain) { +@{exec_path} = @{bin}/@{name} /opt/proton-mail/@{name} +profile protonmail @{exec_path} flags=(attach_disconnected) { include - include - include include + include network inet stream, network inet dgram, network inet6 dgram, network netlink raw, - ptrace read peer=xdg-settings, + # I need a proof for this, it is not common for such a program + # io_uring sqpoll, @{exec_path} mrix, - @{bin}/xdg-settings Px, - @{open_path} Px -> child-open, - - owner @{user_config_dirs}/ibus/bus/ r, - - @{sys}/devices/@{pci}/boot_vga r, - - owner @{tmp}/gtkprint_ppd_@{rand6} rw, + @{open_path} rPx -> child-open-strict, include if exists - } # vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/protonmail-bridge-core b/apparmor.d/profiles-m-r/protonmail-bridge-core index 92d379724d..3e80688dbc 100644 --- a/apparmor.d/profiles-m-r/protonmail-bridge-core +++ b/apparmor.d/profiles-m-r/protonmail-bridge-core @@ -12,9 +12,12 @@ abi , include @{exec_path} = @{lib}/protonmail/bridge/bridge -profile protonmail-bridge-core @{exec_path} { +profile protonmail-bridge-core @{exec_path} flags=(attach_disconnected) { include + include + include include + include include network inet dgram, @@ -25,12 +28,13 @@ profile protonmail-bridge-core @{exec_path} { @{exec_path} mr, - @{bin}/pass rCx -> pass, + @{bin}/pass Cx -> pass, @{lib}/protonmail/bridge/bridge-gui ix, /etc/lsb-release r, /etc/machine-id r, + /etc/os-release r, owner @{user_passwordstore_dirs}/docker-credential-helpers/{,**} r, owner @{user_passwordstore_dirs}/protonmail-credentials/{,**} r, @@ -42,14 +46,11 @@ profile protonmail-bridge-core @{exec_path} { owner "@{user_config_dirs}/autostart/Proton Mail Bridge.desktop" rw, owner @{tmp}/bridge@{int} rw, - owner @{tmp}/etilqs_@{hex16} rw, - owner /var/tmp/etilqs_@{hex16} rw, @{PROC}/ r, @{PROC}/1/cgroup r, @{PROC}/sys/net/core/somaxconn r, - deny @{bin}/pass x, deny owner @{user_passwordstore_dirs}/** r, profile pass { @@ -72,10 +73,11 @@ profile protonmail-bridge-core @{exec_path} { @{bin}/tail rix, @{bin}/tree rix, @{bin}/tty rix, - @{bin}/which rix, + @{bin}/which{,.debianutils} rix, owner @{user_passwordstore_dirs}/ r, owner @{user_passwordstore_dirs}/.gpg-id r, + owner @{user_passwordstore_dirs}/docker-credential-helpers/{,**} rw, owner @{user_passwordstore_dirs}/protonmail-credentials/{,**} rw, deny owner @{user_passwordstore_dirs}/**/ r, diff --git a/apparmor.d/profiles-m-r/psi b/apparmor.d/profiles-m-r/psi index 33435fa8d1..de4b248053 100644 --- a/apparmor.d/profiles-m-r/psi +++ b/apparmor.d/profiles-m-r/psi @@ -18,6 +18,7 @@ profile psi @{exec_path} { include include include + include include include include @@ -34,7 +35,7 @@ profile psi @{exec_path} { @{bin}/aplay rCx -> aplay, @{bin}/gpg{,2} rPx, - @{bin}/lsb_release rPx -> lsb_release, + @{bin}/lsb_release rPx, @{open_path} rPx -> child-open, @{lib}/firefox/firefox rPUx, @@ -54,17 +55,16 @@ profile psi @{exec_path} { owner @{user_share_dirs}/psi/** rwk, owner @{tmp}/#@{int} rw, - owner @{tmp}/etilqs_@{hex16} rw, owner @{tmp}/Psi.* rwl -> /tmp/#@{int}, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, owner @{PROC}/@{pid}/cmdline r, owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/mounts r, /dev/shm/#@{int} rw, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, profile aplay { include diff --git a/apparmor.d/profiles-m-r/psi-plus b/apparmor.d/profiles-m-r/psi-plus index 32c05e55b8..ad1164be8f 100644 --- a/apparmor.d/profiles-m-r/psi-plus +++ b/apparmor.d/profiles-m-r/psi-plus @@ -18,6 +18,7 @@ profile psi-plus @{exec_path} { include include include + include include include include @@ -34,7 +35,7 @@ profile psi-plus @{exec_path} { @{bin}/aplay rCx -> aplay, @{bin}/gpg{,2} rPx, - @{bin}/lsb_release rPx -> lsb_release, + @{bin}/lsb_release rPx, @{open_path} rPx -> child-open, @{lib}/firefox/firefox rPUx, @@ -54,17 +55,16 @@ profile psi-plus @{exec_path} { owner @{user_share_dirs}/psi+/** rwk, owner @{tmp}/#@{int} rw, - owner @{tmp}/etilqs_@{hex16} rw, owner @{tmp}/Psi+.* rwl -> /tmp/#@{int}, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, owner @{PROC}/@{pid}/cmdline r, owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/mounts r, /dev/shm/#@{int} rw, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, profile aplay { include diff --git a/apparmor.d/profiles-m-r/pulseeffects b/apparmor.d/profiles-m-r/pulseeffects index e57e221dd1..235a2e52d3 100644 --- a/apparmor.d/profiles-m-r/pulseeffects +++ b/apparmor.d/profiles-m-r/pulseeffects @@ -11,12 +11,9 @@ include profile pulseeffects @{exec_path} { include include - include - include - include - include - include + include include + include network netlink raw, @@ -34,7 +31,7 @@ profile pulseeffects @{exec_path} { owner @{PROC}/@{pid}/fd/ r, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-m-r/pycompile b/apparmor.d/profiles-m-r/pycompile new file mode 100644 index 0000000000..6f9607e5a2 --- /dev/null +++ b/apparmor.d/profiles-m-r/pycompile @@ -0,0 +1,61 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/py{,3}compile @{bin}/py{,3}clean +profile pycompile @{exec_path} flags=(attach_disconnected,complain) { + include + include + include + include + include + + capability dac_override, + capability dac_read_search, + + @{exec_path} mr, + @{python_path} rix, + + @{bin}/dpkg rCx -> dpkg, + + priority=1 @{lib}/**/__pycache__/ rw, + priority=1 @{lib}/**/__pycache__/*.pyc rw, + priority=1 @{lib}/**/__pycache__/*.pyc.* rw, + + /usr/share/**/ r, + + /usr/share/**/__pycache__/ rw, + /usr/share/**/__pycache__/*.pyc rw, + /usr/share/**/__pycache__/*.pyc.* rw, + + /usr/share/@{python_name}/{,**} r, + /usr/share/**.py r, + + / r, + @{bin}/ r, + @{sbin}/ r, + + profile dpkg { + include + include + include + + capability dac_read_search, + + @{bin}/dpkg mr, + @{bin}/dpkg-query rpx, + + /etc/dpkg/dpkg.cfg.d/{,*} r, + /etc/dpkg/dpkg.cfg r, + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/qbittorrent b/apparmor.d/profiles-m-r/qbittorrent index 5d9cba0879..ae9a284af0 100644 --- a/apparmor.d/profiles-m-r/qbittorrent +++ b/apparmor.d/profiles-m-r/qbittorrent @@ -10,17 +10,12 @@ include @{exec_path} = @{bin}/qbittorrent profile qbittorrent @{exec_path} { include - include - include - include - include - include include include include include include - include + include include include include @@ -38,33 +33,6 @@ profile qbittorrent @{exec_path} { network netlink dgram, network netlink raw, - dbus send bus=session path=/StatusNotifierItem - interface=org.kde.StatusNotifierItem - member={NewToolTip,NewIcon} - peer=(name=org.freedesktop.DBus), - - dbus receive bus=session path=/StatusNotifierItem - interface=org.kde.StatusNotifierItem - member=Activate - peer=(name=:*), - - dbus receive bus=session path=/{StatusNotifierItem,MenuBar} - interface=org.freedesktop.DBus.Properties - member=GetAll - peer=(name=:*), - - dbus send bus=session path=/MenuBar - interface=com.canonical.dbusmenu - member=ItemsPropertiesUpdated - peer=(name=org.freedesktop.DBus), - - dbus receive bus=session path=/MenuBar - interface=com.canonical.dbusmenu - member={GetLayout,GetGroupProperties,AboutToShow,AboutToShowGroup,EventGroup,Event} - peer=(name=:*), - - dbus bind bus=session name=org.kde.StatusNotifierItem-*, - @{exec_path} mr, @{open_path} rPx -> child-open, @@ -113,7 +81,7 @@ profile qbittorrent @{exec_path} { owner @{PROC}/@{pids}/mountinfo r, owner @{PROC}/@{pids}/mounts r, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, profile python { include diff --git a/apparmor.d/profiles-m-r/qdbus b/apparmor.d/profiles-m-r/qdbus index fa67bad979..6816079ac4 100644 --- a/apparmor.d/profiles-m-r/qdbus +++ b/apparmor.d/profiles-m-r/qdbus @@ -9,6 +9,7 @@ include @{exec_path} = @{bin}/qdbus @{lib}/qt{5,6}/bin/qdbus profile qdbus @{exec_path} { include + include @{exec_path} mr, diff --git a/apparmor.d/profiles-m-r/qemu-ga b/apparmor.d/profiles-m-r/qemu-ga index 461d27c61a..e477ac2b86 100644 --- a/apparmor.d/profiles-m-r/qemu-ga +++ b/apparmor.d/profiles-m-r/qemu-ga @@ -6,13 +6,17 @@ abi , include -@{exec_path} = @{bin}/qemu-ga -profile qemu-ga @{exec_path} { +@{exec_path} = @{sbin}/qemu-ga @{bin}/qemu-ga #aa:lint ignore=sbin +profile qemu-ga @{exec_path} flags=(attach_disconnected) { include + network bind netlink raw, + network inet stream, + network inet6 stream, + @{exec_path} mr, - audit @{bin}/systemctl Cx -> systemctl, + @{bin}/systemctl Cx -> systemctl, /etc/qemu/qemu-ga.conf r, @@ -22,6 +26,7 @@ profile qemu-ga @{exec_path} { @{sys}/devices/system/node/ r, @{sys}/devices/system/node/node@{int}/meminfo r, + @{PROC}/@{pid}/net/dev r, @{PROC}/sys/vm/max_map_count r, /dev/vport@{int}p@{int} rw, @@ -32,9 +37,11 @@ profile qemu-ga @{exec_path} { capability net_admin, + unix type=stream addr=@@{udbus}/bus/poweroff/system, + unix type=stream addr=@@{udbus}/bus/shutdown/, unix type=stream addr=@@{udbus}/bus/shutdown/system, - #aa:dbus talk bus=system name=org.freedesktop.login1 label=systemd-logind + #aa:dbus talk bus=system name=org.freedesktop.login1 label="@{p_systemd_logind}" include if exists } diff --git a/apparmor.d/profiles-m-r/qnapi b/apparmor.d/profiles-m-r/qnapi index d02ff94269..b7665aaa58 100644 --- a/apparmor.d/profiles-m-r/qnapi +++ b/apparmor.d/profiles-m-r/qnapi @@ -68,7 +68,7 @@ profile qnapi @{exec_path} { owner @{PROC}/@{pid}/mounts r, owner /dev/shm/#@{int} rw, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-m-r/qpdfview b/apparmor.d/profiles-m-r/qpdfview index f743e95b35..d6f0a22479 100644 --- a/apparmor.d/profiles-m-r/qpdfview +++ b/apparmor.d/profiles-m-r/qpdfview @@ -29,7 +29,6 @@ profile qpdfview @{exec_path} { @{lib}/firefox/firefox rPUx, @{open_path} rPx -> child-open, - /usr/share/poppler/** r, /usr/share/djvu/** r, /etc/fstab r, @@ -58,7 +57,7 @@ profile qpdfview @{exec_path} { owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/mounts r, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-m-r/quiterss b/apparmor.d/profiles-m-r/quiterss index 89395f8b50..d2708871f7 100644 --- a/apparmor.d/profiles-m-r/quiterss +++ b/apparmor.d/profiles-m-r/quiterss @@ -18,6 +18,7 @@ profile quiterss @{exec_path} { include include include + include include include @@ -47,7 +48,6 @@ profile quiterss @{exec_path} { owner @{tmp}/qtsingleapp-quiter-@{int}-@{int} rw, owner @{tmp}/qtsingleapp-quiter-@{int}-@{int}-lockfile rwk, - owner /var/tmp/etilqs_@{hex16} rw, @{PROC}/sys/kernel/random/boot_id r, owner @{PROC}/@{pid}/cmdline r, @@ -57,7 +57,7 @@ profile quiterss @{exec_path} { /dev/shm/#@{int} rw, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-m-r/rdmsr b/apparmor.d/profiles-m-r/rdmsr index 47dd9beabe..81f43b3e61 100644 --- a/apparmor.d/profiles-m-r/rdmsr +++ b/apparmor.d/profiles-m-r/rdmsr @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/rdmsr +@{exec_path} = @{sbin}/rdmsr profile rdmsr @{exec_path} { include diff --git a/apparmor.d/profiles-m-r/remmina b/apparmor.d/profiles-m-r/remmina index c2bc95465c..691b71056f 100644 --- a/apparmor.d/profiles-m-r/remmina +++ b/apparmor.d/profiles-m-r/remmina @@ -7,24 +7,21 @@ abi , include @{exec_path} = @{bin}/remmina -profile remmina @{exec_path} { +profile remmina @{exec_path} flags=(attach_disconnected) { include include - include - include - include - include - include - include - include - include - include - include + include + include + include include include include - include + include + include include + include + include + include include include include @@ -35,40 +32,44 @@ profile remmina @{exec_path} { network inet6 dgram, network netlink raw, - #aa:dbus own bus=session name=org.remmina.Remmina interface+=org.gtk.Actions + #aa:dbus own bus=session name=org.remmina.Remmina #aa:dbus talk bus=session name=org.ayatana.NotificationItem label=gnome-shell - #aa:dbus talk bus=session name=org.gtk.vfs label="gvfsd{,-*}" @{exec_path} rm, + @{python_path} rix, @{open_path} rPx -> child-open-browsers, + @{bin}/lsb_release rPx, /usr/share/remmina/{,**} r, - /usr/share/themes/{,**} r, + /etc/debian_version r, /etc/fstab r, + /etc/lsb-release r, /etc/ssh/ssh_config r, /etc/ssh/ssh_config.d/{,*} r, /etc/timezone r, owner @{HOME}/@{XDG_SSH_DIR}/config r, - owner @{HOME}/@{XDG_SSH_DIR}/known_hosts r, + owner @{HOME}/@{XDG_SSH_DIR}/known_hosts* r, owner @{user_cache_dirs}/org.remmina.Remmina/{,**} rw, owner @{user_cache_dirs}/remmina/{,**} rw, owner @{user_config_dirs}/autostart/remmina-applet.desktop r, - owner @{user_config_dirs}/freerdp/known_hosts2 rwk, + owner @{user_config_dirs}/freerdp/known_hosts* rwk, owner @{user_config_dirs}/remmina/{,**} rw, owner @{user_share_dirs}/remmina/{,**} rw, - owner @{PROC}/@{pid}/task/@{tid}/comm rw, - owner @{PROC}/@{pid}/mountinfo r, + owner @{tmp}/remmina_log_file.log rw, owner @{run}/user/@{uid}/keyring/ssh rw, @{sys}/devices/system/node/ r, @{sys}/devices/system/node/node@{int}/meminfo r, + owner @{PROC}/@{pid}/task/@{tid}/comm rw, + owner @{PROC}/@{pid}/mountinfo r, + include if exists } diff --git a/apparmor.d/profiles-m-r/repo b/apparmor.d/profiles-m-r/repo index 5ad84fb15d..f596ee037a 100644 --- a/apparmor.d/profiles-m-r/repo +++ b/apparmor.d/profiles-m-r/repo @@ -31,7 +31,7 @@ profile repo @{exec_path} { @{bin}/uname rix, @{lib}/git{,-core}/git* rix, - @{bin}/gpg{,2} rCx -> gpg, + @{bin}/gpg{,2} rPx, @{bin}/ssh rPx, /usr/share/git-core/{,**} r, @@ -59,19 +59,6 @@ profile repo @{exec_path} { # Silencer deny /etc/.repo_gitconfig.json w, - profile gpg { - include - - @{bin}/gpg{,2} mr, - - owner @{HOME}/@{XDG_GPG_DIR}/** rwkl -> @{HOME}/@{XDG_GPG_DIR}/**, - owner @{HOME}/.repoconfig/gnupg/** rwkl -> @{HOME}/.repoconfig/gnupg/**, - - owner @{tmp}/.git_vtag_tmp@{rand6} r, - - include if exists - } - include if exists } diff --git a/apparmor.d/profiles-m-r/reprepro b/apparmor.d/profiles-m-r/reprepro index 866b7cbfa5..1630ba1949 100644 --- a/apparmor.d/profiles-m-r/reprepro +++ b/apparmor.d/profiles-m-r/reprepro @@ -7,54 +7,36 @@ abi , include -@{REPO_DIR} = @{MOUNTS}/debuilder/repo - @{exec_path} = @{bin}/reprepro profile reprepro @{exec_path} { include + include @{exec_path} mr, @{bin}/gpgconf rCx -> gpg, @{bin}/gpg{,2} rCx -> gpg, @{bin}/gpgsm rCx -> gpg, + @{bin}/zstd ix, - owner @{PROC}/@{pid}/fd/ r, - - # The repository dir - owner @{REPO_DIR}/debian/ r, - owner @{REPO_DIR}/debian/conf/{distributions,options} r, - - owner @{REPO_DIR}/debian/db/lockfile rw, - owner @{REPO_DIR}/debian/db/version{,.new} rw, - owner @{REPO_DIR}/debian/db/packages.db rw, - owner @{REPO_DIR}/debian/db/references.db rw, - owner @{REPO_DIR}/debian/db/release.caches.db rw, - owner @{REPO_DIR}/debian/db/contents.cache.db rw, - owner @{REPO_DIR}/debian/db/checksums.db rw, - - owner @{REPO_DIR}/debian/dists/*/*/binary-*/Packages{,.gz} w, - owner @{REPO_DIR}/debian/dists/*/*/binary-*/Packages{,.gz}.new rw, - owner @{REPO_DIR}/debian/dists/*/*/source/Sources{,.gz} w, - owner @{REPO_DIR}/debian/dists/*/*/source/Sources{,.gz}.new rw, - owner @{REPO_DIR}/debian/dists/*/{In,}Release{,.new} rw, - owner @{REPO_DIR}/debian/dists/*/Release.gpg{,.new} rw, - - owner @{REPO_DIR}/debian/**/ w, - owner @{REPO_DIR}/debian/pool/*/*/*/*.tar.* rw, - owner @{REPO_DIR}/debian/pool/*/*/*/*.dsc rw, - owner @{REPO_DIR}/debian/pool/*/*/*/*.deb rw, - owner @{REPO_DIR}/debian/pool/*/*/*/*.git rw, - - # Dirs containing .deb files - owner @{REPO_DIR}/*.deb r, /var/cache/apt/archives/*.deb r, + owner @{user_projects_dirs}/** rw, + owner @{user_build_dirs}/** rw, + + owner @{user_pkg_dirs}/ rw, + owner @{user_pkg_dirs}/** rwlk, + # For package building owner @{user_build_dirs}/pbuilder/result/*.{dsc,changes} r, owner @{user_build_dirs}/pbuilder/result/*.deb r, owner @{user_build_dirs}/pbuilder/result/*.tar.* r, + owner @{PROC}/@{pid}/fd/ r, + + #aa:only test + /tmp/@{rand10}/** rwlk, + profile gpg { include @@ -65,6 +47,8 @@ profile reprepro @{exec_path} { owner @{HOME}/@{XDG_GPG_DIR}/ rw, owner @{HOME}/@{XDG_GPG_DIR}/** rwkl -> @{HOME}/@{XDG_GPG_DIR}/**, + owner @{run}/user/@{uid}/gnupg/S.gpg-agent rw, + include if exists } diff --git a/apparmor.d/profiles-m-r/resize2fs b/apparmor.d/profiles-m-r/resize2fs index 7b28a1d229..38d4823268 100644 --- a/apparmor.d/profiles-m-r/resize2fs +++ b/apparmor.d/profiles-m-r/resize2fs @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/resize2fs +@{exec_path} = @{sbin}/resize2fs profile resize2fs @{exec_path} { include include diff --git a/apparmor.d/profiles-m-r/resolvconf b/apparmor.d/profiles-m-r/resolvconf index c050ce970f..8e39c7620b 100644 --- a/apparmor.d/profiles-m-r/resolvconf +++ b/apparmor.d/profiles-m-r/resolvconf @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/resolvconf +@{exec_path} = @{sbin}/resolvconf profile resolvconf @{exec_path} { include include @@ -26,7 +26,7 @@ profile resolvconf @{exec_path} { @{bin}/systemctl rCx -> systemctl, @{lib}/resolvconf/list-records rix, - /usr/lib/resolvconf/{,**} r, + @{lib}/resolvconf/{,**} r, @{etc_rw}/resolv.conf.bak rw, @{etc_rw}/resolv.conf rw, diff --git a/apparmor.d/profiles-m-r/resources b/apparmor.d/profiles-m-r/resources new file mode 100644 index 0000000000..6c7d1061e5 --- /dev/null +++ b/apparmor.d/profiles-m-r/resources @@ -0,0 +1,150 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/resources +profile resources @{exec_path} flags=(attach_disconnected) { + include + include + include + include + include + + network netlink raw, + + #aa:dbus own bus=session name=net.nokyan.Resources + + @{exec_path} mr, + + @{bin}/lscpu Px, + @{bin}/pkexec Cx -> pkexec, + @{bin}/udevadm Cx -> udevadm, + @{lib}/resources/resources-adjust Cx -> adjust, + @{lib}/resources/resources-kill Cx -> kill, + @{lib}/resources/resources-processes Cx -> processes, + + /snap/*/@{uid}/**.@{icon_ext} r, + /usr/share/misc/*.ids r, + /usr/share/resources/{,**} r, + + owner @{user_cache_dirs}/flatpak/system-cache/ r, + + @{sys}/block/ r, + @{sys}/class/*/ r, + @{sys}/devices/@{pci}/ata@{int}/ r, + @{sys}/devices/@{pci}/ata@{int}/**/sata_spd r, + @{sys}/devices/@{pci}/ip_discovery/**/major r, + @{sys}/devices/**/address r, + @{sys}/devices/**/model r, + @{sys}/devices/**/queue/rotational r, + @{sys}/devices/**/removable r, + @{sys}/devices/**/ro r, + @{sys}/devices/**/size r, + @{sys}/devices/**/speed r, + @{sys}/devices/**/stat r, + @{sys}/devices/**/statistics/rx_bytes r, + @{sys}/devices/**/statistics/tx_bytes r, + @{sys}/devices/system/cpu/cpufreq/policy@{int}/cpuinfo_avg_freq r, + + @{PROC}/devices r, + @{PROC}/uptime r, + + owner @{PROC}/@{pid}/cgroup r, + owner @{PROC}/@{pid}/mountinfo r, + owner @{PROC}/@{pid}/task/@{tid}/comm rw, + + /dev/nvidia-caps/nvidia-cap@{int} r, + + profile processes { + include + include + include + + capability sys_ptrace, + + ptrace read, + + @{lib}/resources/resources-processes mr, + + @{PROC}/ r, + @{PROC}/@{pids}/cgroup r, + @{PROC}/@{pids}/cmdline r, + @{PROC}/@{pids}/comm r, + @{PROC}/@{pids}/fdinfo/@{int} r, + @{PROC}/@{pids}/stat r, + @{PROC}/@{pids}/statm r, + @{PROC}/@{pids}/status r, + @{PROC}/@{pids}/status r, + owner @{PROC}/@{pid}/environ r, + owner @{PROC}/@{pid}/fdinfo/ r, + owner @{PROC}/@{pid}/io r, + owner @{PROC}/@{pid}/mountinfo r, + owner @{PROC}/@{pid}/stat r, + owner @{PROC}/@{pid}/statm r, + owner @{PROC}/@{pid}/task/@{tid}/comm w, + + /dev/nvidia-caps/nvidia-cap@{int} r, + + include if exists + } + + profile adjust { + include + + capability sys_nice, + + @{lib}/resources/resources-adjust mr, + + owner @{PROC}/@{pid}/task/ r, + + include if exists + } + + profile kill { + include + + capability kill, + + signal send, + + @{lib}/resources/resources-kill mr, + + include if exists + } + + profile udevadm { + include + + @{bin}/udevadm mr, + + /etc/udev/udev.conf r, + + / r, + + @{run}/udev/data/+dmi:* r, # for motherboard info + + @{sys}/devices/virtual/dmi/id/uevent r, + + include if exists + } + + profile pkexec { + include + include + + ptrace read peer=resources, + + @{lib}/resources/resources-adjust Px -> resources//adjust, + @{lib}/resources/resources-kill Px -> resources//kill, + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/rg b/apparmor.d/profiles-m-r/rg new file mode 100644 index 0000000000..b1c2539c19 --- /dev/null +++ b/apparmor.d/profiles-m-r/rg @@ -0,0 +1,26 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 valoq +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/rg +profile rg @{exec_path} { + include + include + + capability dac_override, + capability dac_read_search, + + @{exec_path} mr, + + #aa:lint ignore=too-wide + # Allow reading the entire filesystem to search for strings + /{,**} r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/rga b/apparmor.d/profiles-m-r/rga new file mode 100644 index 0000000000..2e3deee441 --- /dev/null +++ b/apparmor.d/profiles-m-r/rga @@ -0,0 +1,40 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 valoq +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/rga +profile rga @{exec_path} { + include + + capability dac_override, + capability dac_read_search, + + @{exec_path} mr, + + @{bin}/rg ix, + @{bin}/ffmpeg ix, + @{bin}/ffprobe ix, + @{bin}/pandoc ix, + @{bin}/pdftotext ix, + @{bin}/rga-preproc ix, + + /usr/share/poppler/** r, + + owner @{user_cache_dirs}/ripgrep-all/cache.sqlite3 rwk, + owner @{user_cache_dirs}/ripgrep-all/cache.sqlite3-shm rwk, + owner @{user_cache_dirs}/ripgrep-all/cache.sqlite3-wal rwk, + + #aa:lint ignore=too-wide + ## Allow reading the entire filesystem to search for strings + /{,**} r, + + owner @{PROC}/@{pid}/task/@{tid}/comm w, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/rngd b/apparmor.d/profiles-m-r/rngd index 8ae73c5d07..4de82597e5 100644 --- a/apparmor.d/profiles-m-r/rngd +++ b/apparmor.d/profiles-m-r/rngd @@ -7,11 +7,12 @@ abi , include -@{exec_path} = @{bin}/rngd +@{exec_path} = @{sbin}/rngd profile rngd @{exec_path} flags=(attach_disconnected) { include include include + include capability dac_read_search, capability net_admin, @@ -24,9 +25,11 @@ profile rngd @{exec_path} flags=(attach_disconnected) { /etc/conf.d/rngd r, /etc/machine-id r, - /etc/{,opensc/}opensc.conf r, /var/lib/dbus/machine-id r, + / r, + + @{sys}/devices/**/uevent r, @{sys}/devices/virtual/misc/hw_random/rng_available r, @{PROC}/sys/kernel/random/poolsize r, diff --git a/apparmor.d/profiles-m-r/rsyslogd b/apparmor.d/profiles-m-r/rsyslogd index b4ae4b211f..464f1821d2 100644 --- a/apparmor.d/profiles-m-r/rsyslogd +++ b/apparmor.d/profiles-m-r/rsyslogd @@ -7,38 +7,38 @@ abi , include -# Debugging the syslogger can be difficult if it can't write to the file -# that the kernel is logging denials to. In these cases, you can do the -# following: -# watch -n 1 'dmesg | tail -5' - -@{exec_path} = @{bin}/rsyslogd +@{exec_path} = @{sbin}/rsyslogd profile rsyslogd @{exec_path} { include - include + include - capability chown, # For creating new log files and changing their owner/group - capability net_admin, # For remote logs - capability setgid, # For downgrading privileges + capability dac_override, + capability dac_read_search, + capability setgid, capability setuid, capability sys_nice, + capability sys_tty_config, capability syslog, + network inet dgram, + network inet6 dgram, + + signal receive set=hup peer=@{p_systemd}, + @{exec_path} mr, + @{sh_path} mr, @{lib}/@{multiarch}/rsyslog/*.so mr, /etc/rsyslog.conf r, /etc/rsyslog.d/{,**} r, - /etc/CA/*.crt r, - /etc/CA/*.key r, - /var/log/** rw, /var/spool/rsyslog/ r, /var/spool/rsyslog/** rw, - @{run}/systemd/notify rw, + @{run}/systemd/sessions/ r, + owner @{run}/rsyslogd.pid{,.tmp} rwk, owner @{run}/systemd/journal/syslog w, @@ -46,6 +46,7 @@ profile rsyslogd @{exec_path} { @{PROC}/cmdline r, @{PROC}/kmsg r, @{PROC}/sys/kernel/osrelease r, + @{PROC}/sys/net/ipv6/conf/all/disable_ipv6 r, include if exists } diff --git a/apparmor.d/profiles-m-r/rtkit-daemon b/apparmor.d/profiles-m-r/rtkit-daemon index 68837a52d2..274e5f2022 100644 --- a/apparmor.d/profiles-m-r/rtkit-daemon +++ b/apparmor.d/profiles-m-r/rtkit-daemon @@ -11,9 +11,13 @@ include profile rtkit-daemon @{exec_path} flags=(attach_disconnected) { include include - include + include include + # As abstractions/bus-session is not set, only the bus=system part of the + # abstraction will be allowed. i.e. org.freedesktop.login1.Manager + include + capability dac_read_search, capability setgid, capability setuid, @@ -25,6 +29,8 @@ profile rtkit-daemon @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, + @{att}@{run}/systemd/inhibit/@{int}.ref rw, + # When applying policies to processes @{PROC}/@{pids}/stat r, @{PROC}/@{pids}/task/@{tid}/stat r, diff --git a/apparmor.d/profiles-m-r/rtkitctl b/apparmor.d/profiles-m-r/rtkitctl index 9417c93b10..733573d6b7 100644 --- a/apparmor.d/profiles-m-r/rtkitctl +++ b/apparmor.d/profiles-m-r/rtkitctl @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/rtkitctl +@{exec_path} = @{sbin}/rtkitctl profile rtkitctl @{exec_path} { include diff --git a/apparmor.d/profiles-m-r/run-parts b/apparmor.d/profiles-m-r/run-parts index fc46c29677..1bc6a51167 100644 --- a/apparmor.d/profiles-m-r/run-parts +++ b/apparmor.d/profiles-m-r/run-parts @@ -4,12 +4,6 @@ # Copyright (C) 2022 Jeroen Rijken # SPDX-License-Identifier: GPL-2.0-only -# TODO: Rewrite this profile. Most of the rule should be confined directly by the calling profile -# Possible confinement depending of profile architecture: -# - As rix, -# - As rCx -> run-parts, -# - As rPx -> foo-run-parts, - abi , include @@ -25,11 +19,12 @@ profile run-parts @{exec_path} { @{exec_path} mrix, @{sh_path} rix, - @{bin}/anacron rix, + @{sbin}/anacron rix, @{bin}/cat rix, @{bin}/date rix, @{bin}/nice rix, @{bin}/snapper rix, + @{bin}/systemctl rPx, /usr/share/update-notifier/notify-reboot-required rPx, /usr/share/update-notifier/notify-updates-outdated rPx, @@ -76,6 +71,8 @@ profile run-parts @{exec_path} { /etc/network/if-down.d/openvpn rPUx, /etc/network/if-down.d/resolvconf rPUx, /etc/network/if-down.d/wpasupplicant rPUx, + /etc/network/if-down.d/resolved rPUx, + /etc/network/if-down.d/clamav-freshclam-ifupdown rPUx, /etc/hostapd/ifupdown.sh rPUx, /etc/macchanger/ifupdown.sh rPUx, @@ -108,41 +105,31 @@ profile run-parts @{exec_path} { /etc/network/if-up.d/ifenslave rPUx, /etc/network/if-up.d/openvpn rPUx, /etc/network/if-up.d/postfix rPUx, + /etc/network/if-up.d/resolved rPUx, /etc/network/if-up.d/ubuntu-fan rPx, /etc/network/if-up.d/wpasupplicant rPUx, + /etc/network/if-up.d/clamav-freshclam-ifupdown rPUx, # Motd /etc/update-motd.d/ r, /etc/update-motd.d/* rPx, # Kernel - /etc/kernel/header_postinst.d/ r, - /etc/kernel/header_postinst.d/dkms rCx -> kernel, - - /etc/kernel/postinst.d/ r, - /etc/kernel/postinst.d/apt-auto-removal rCx -> kernel, - /etc/kernel/postinst.d/dkms rCx -> kernel, - /etc/kernel/postinst.d/initramfs-tools rCx -> kernel, - /etc/kernel/postinst.d/unattended-upgrades rCx -> kernel, - /etc/kernel/postinst.d/zz-update-grub rCx -> kernel, - /etc/kernel/postinst.d/zz-shim rCx -> kernel, - /etc/kernel/postinst.d/xx-update-initrd-links rCx -> kernel, - + /etc/kernel/{,header_}postinst.d/ r, + /etc/kernel/{,header_}postinst.d/* rPx, /etc/kernel/postrm.d/ r, - /etc/kernel/postrm.d/initramfs-tools rCx -> kernel, - /etc/kernel/postrm.d/zz-update-grub rCx -> kernel, - + /etc/kernel/postrm.d/* rPx, /etc/kernel/preinst.d/ r, - /etc/kernel/preinst.d/intel-microcode rCx -> kernel, - + /etc/kernel/preinst.d/* rPx, /etc/kernel/prerm.d/ r, - /etc/kernel/prerm.d/dkms rCx -> kernel, + /etc/kernel/prerm.d/* rPx, + # Finalrd /usr/share/finalrd/ r, - /usr/share/finalrd/mdadm.finalrd rPUx, - /usr/share/finalrd/open-iscsi.finalrd rPUx, + /usr/share/finalrd/mdadm.finalrd rPUx, + /usr/share/finalrd/open-iscsi.finalrd rPUx, - /usr/share/landscape/landscape-sysinfo.wrapper rPUx, + /usr/share/landscape/landscape-sysinfo.wrapper rPx, /root/ r, @@ -152,116 +139,11 @@ profile run-parts @{exec_path} { owner @{tmp}/$anacron@{rand6} rw, owner @{tmp}/file@{rand6} rw, - owner @{sys}/class/power_supply/ r, + owner @{sys}/class/power_supply/ r, @{run}/motd.dynamic.new w, - /dev/tty@{int} rw, - - profile motd { - include - include - - network inet dgram, - network inet6 dgram, - network netlink raw, - - @{sh_path} rix, - @{bin}/{e,}grep rix, - @{bin}/cat rix, - @{bin}/cut rix, - @{bin}/find rix, - @{bin}/head rix, - @{bin}/id rix, - @{bin}/sort rix, - @{bin}/tr rix, - @{bin}/uname rix, - @{bin}/hostname rPx, - - @{bin}/snap rPUx, - @{lib}/ubuntu-release-upgrader/release-upgrade-motd rPx, - @{lib}/update-notifier/update-motd-fsck-at-reboot rPx, - @{lib}/update-notifier/update-motd-reboot-required rix, - /usr/share/unattended-upgrades/update-motd-unattended-upgrades rix, - /usr/share/update-notifier/notify-updates-outdated rPx, - - / r, - /etc/default/motd-news r, - /etc/lsb-release r, - /etc/update-motd.d/* r, - - /var/cache/motd-news rw, - /var/lib/update-notifier/updates-available r, - /var/lib/ubuntu-advantage/messages/motd-esm-announce r, - - @{run}/motd.d/{,*} r, - - @{PROC}/@{pids}/mounts r, - - /dev/tty@{int} rw, - - include if exists - } - - profile kernel { - include - include - include - - capability sys_module, - - @{sh_path} rix, - @{bin}/{,e}grep rix, - @{bin}/{,m,g}awk rix, - @{bin}/cat rix, - @{bin}/chmod rix, - @{bin}/cut rix, - @{bin}/dirname rix, - @{bin}/kmod rix, - @{bin}/mv rix, - @{bin}/rm rix, - @{bin}/rmdir rix, - @{bin}/sed rix, - @{bin}/sort rix, - @{bin}/touch rix, - @{bin}/tr rix, - @{bin}/uname rix, - @{bin}/which{,.debianutils} rix, - - @{bin}/apt-config rPx, - @{bin}/dkms rPx, - @{bin}/dpkg rPx -> child-dpkg, - @{bin}/systemd-detect-virt rPx, - @{bin}/update-alternatives rPx, - @{bin}/update-grub rPUx, - @{bin}/update-initramfs rPx, - @{lib}/dkms/dkms_autoinstaller rPx, - - @{lib}/modules/*/updates/ w, - @{lib}/modules/*/updates/dkms/ w, - - /etc/kernel/header_postinst.d/* r, - /etc/kernel/{postinst,postrm,preinst,prerm}.d/* r, - - # For shell pwd - / r, - /boot/ r, - - /etc/apt/apt.conf.d/ r, - /etc/apt/apt.conf.d/01autoremove-kernels{,.dpkg-new} rw, - /etc/modprobe.d/ r, - /etc/modprobe.d/*.conf r, - - @{run}/reboot-required w, - @{run}/reboot-required.pkgs rw, - - @{sys}/module/compression r, - - @{PROC}/devices r, - @{PROC}/cmdline r, - - include if exists - } + /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-m-r/runit-helper b/apparmor.d/profiles-m-r/runit-helper new file mode 100644 index 0000000000..94b3816c97 --- /dev/null +++ b/apparmor.d/profiles-m-r/runit-helper @@ -0,0 +1,23 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/runit-helper/runit-helper +profile runit-helper @{exec_path} { + include + + @{exec_path} mr, + + @{bin}/mkdir rix, + + @{run}/runit/ rw, + @{run}/runit/supervise/ w, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-m-r/runuser b/apparmor.d/profiles-m-r/runuser index 9931c07fbe..1c381f0a14 100644 --- a/apparmor.d/profiles-m-r/runuser +++ b/apparmor.d/profiles-m-r/runuser @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/runuser +@{exec_path} = @{sbin}/runuser profile runuser @{exec_path} { include include @@ -25,8 +25,8 @@ profile runuser @{exec_path} { @{exec_path} mr, @{bin}/@{shells} rUx, + @{bin}/mkdir ix, - @{etc_ro}/security/limits.d/ r, /etc/default/runuser r, owner @{tmp}/debian-security-support.postinst.*/output w, diff --git a/apparmor.d/profiles-m-r/rustdesk b/apparmor.d/profiles-m-r/rustdesk index acdad56400..84f5bd0cdd 100644 --- a/apparmor.d/profiles-m-r/rustdesk +++ b/apparmor.d/profiles-m-r/rustdesk @@ -6,14 +6,14 @@ abi , include -@{exec_path} = @{bin}/rustdesk +@{exec_path} = @{bin}/rustdesk /usr/share/rustdesk/rustdesk profile rustdesk @{exec_path} { include include - include include - include include + include + include include include @@ -28,18 +28,21 @@ profile rustdesk @{exec_path} { @{exec_path} mrix, - @{bin}/w rPx, - @{bin}/ps rPx, - @{bin}/whoami rPx, - @{bin}/loginctl rPx, - @{bin}/curl rix, - @{bin}/ls rix, + @{bin}/loginctl rPx, # connection popup + @{bin}/ls rix, + @{bin}/which{,.debianutils} rix, @{bin}/sudo rCx -> sudo, - @{python_path} rCx -> python, - @{sh_path} rCx -> shell, + @{sh_path} rPx -> rustdesk_shell, /etc/gdm{,3}/custom.conf r, + /usr/share/rustdesk/{,**} r, + /usr/share/rustdesk/lib/*.so mr, + /usr/share/terminfo/** r, + /usr/share/uim/**.scm r, + /var/lib/uim/*.scm r, + /tmp/[rR]ust[dD]esk/{,**} rw, + owner /tmp/.X@{int}-unix/ r, owner @{HOME}/ r, # fails otherwise owner @{HOME}/[rR]ust[dD]esk/{,**} rw, @@ -50,82 +53,75 @@ profile rustdesk @{exec_path} { owner @{user_share_dirs}/logs/[rR]ust[dD]esk/{,**} rw, owner @{user_config_dirs}/[rR]ust[dD]esk/{,**} rw, - /tmp/[rR]ust[dD]esk/{,**} rw, + owner @{sddm_share_dirs}/logs/ w, + owner @{sddm_share_dirs}/logs/[rR]ust[dD]esk/{,**} rw, + owner @{sddm_config_dirs}/[rR]ust[dD]esk/{,**} rw, @{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_{cur,min,max}_freq r, - + @{sys}/devices/@{pci}/net/*/address r, + @{sys}/fs/cgroup/user.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/cpu.max r, + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/cpu.max r, + @{sys}/fs/cgroup/system.slice/cpu.max r, + @{sys}/fs/cgroup/system.slice/rustdesk.service/* r, + + @{PROC}/ r, @{PROC}/uptime r, + @{PROC}/loadavg r, owner @{PROC}/@{pid}/cgroup r, - owner @{PROC}/@{pid}/cmdline r, + owner @{PROC}/@{pid}/mountinfo r, + + signal (receive) set=(kill, term) peer=rustdesk_shell, profile sudo { include include - include - - @{bin}/rustdesk rPx, - @{python_path} rPx -> rustdesk//python, - - include if exists - } - - profile python { - include - include - - capability dac_read_search, - capability dac_override, - - @{python_path} r, - @{sh_path} rix, - @{bin}/chmod rix, - @{bin}/uname rix, - /usr/share/rustdesk/files/pynput_service.py rix, + capability kill, - /usr/share/[rR]ust[dD]esk/files/{,**} r, - /tmp/[rR]ust[dD]esk/ w, - /tmp/[rR]ust[dD]esk/pynput_service rw, + @{exec_path} rPx, - @{run}/user/@{uid}/gdm{,3}/Xauthority r, + signal (receive) set=(kill, term) peer=rustdesk, - owner @{PROC}/@{pid}/fd/ r, - - # X-tiny - /tmp/.X11-unix/* rw, - owner @{HOME}/.xsession-errors w, - owner @{HOME}/.Xauthority r, - - include if exists + include if exists } + include if exists +} - profile shell { - include +profile rustdesk_shell { + include + include - capability dac_override, - capability dac_read_search, - capability sys_ptrace, + capability dac_override, + capability dac_read_search, + capability kill, - ptrace read, + signal (send) set=(kill, term) peer=rustdesk, - @{sh_path} r, + @{sh_path} r, - @{bin}/tr rix, - @{bin}/{,e}grep rix, - @{bin}/tail rix, - @{bin}/xargs rix, - @{bin}/sed rix, - @{bin}/cat rix, + @{bin}/tr rix, + @{bin}/{,f,e}grep rix, + @{bin}/tail rix, + @{bin}/xargs rix, + @{bin}/sed rix, + @{bin}/cat rix, + @{bin}/getent rix, + @{bin}/whoami rix, + @{bin}/{,g,m}awk rix, + @{bin}/wc rix, + @{bin}/kill rix, - @{bin}/ps rPx, + @{bin}/ps rPx, + @{bin}/xrandr rPx, - @{PROC}/@{pid}/environ r, - owner @{PROC}/@{pid}/fd/ r, + @{PROC}/@{pid}/environ r, + owner @{PROC}/@{pid}/fd/ r, - include if exists - } + /usr/share/rustdesk/{,**} r, - include if exists + include if exists } # vim:syntax=apparmor diff --git a/apparmor.d/profiles-s-z/YACReader b/apparmor.d/profiles-s-z/YACReader index 3552b6dc02..14e60e2b4b 100644 --- a/apparmor.d/profiles-s-z/YACReader +++ b/apparmor.d/profiles-s-z/YACReader @@ -14,6 +14,7 @@ profile YACReader @{exec_path} flags=(attach_disconnected,mediate_deleted) { include include include + include include include include @@ -28,8 +29,6 @@ profile YACReader @{exec_path} flags=(attach_disconnected,mediate_deleted) { /usr/share/yacreader/{,**} r, - /etc/machine-id r, - owner @{user_books_dirs}/{,**} r, owner @{user_share_dirs}/YACReader/ rw, @@ -37,11 +36,15 @@ profile YACReader @{exec_path} flags=(attach_disconnected,mediate_deleted) { owner @{user_share_dirs}/YACReader/YACReader/ rw, owner @{user_share_dirs}/YACReader/YACReader/** rwlk, + owner @{tmp}/@{uuid} rw, + owner @{PROC}/@{pid}/cmdline r, owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/stat r, owner @{PROC}/@{pid}/task/@{tid}/comm rw, + /dev/char/@{dynamic}:@{int} w, # For dynamic assignment range 234 to 254, 384 to 511 + include if exists } diff --git a/apparmor.d/profiles-s-z/YACReaderLibrary b/apparmor.d/profiles-s-z/YACReaderLibrary index 38336fbc73..e8c39ba7fe 100644 --- a/apparmor.d/profiles-s-z/YACReaderLibrary +++ b/apparmor.d/profiles-s-z/YACReaderLibrary @@ -9,11 +9,11 @@ include @{exec_path} = @{bin}/YACReaderLibrary profile YACReaderLibrary @{exec_path} flags=(attach_disconnected,mediate_deleted) { include - include include include include include + include include include include @@ -27,26 +27,22 @@ profile YACReaderLibrary @{exec_path} flags=(attach_disconnected,mediate_deleted @{exec_path} mr, + @{bin}/ r, @{bin}/YACReader rPx, @{open_path} rPx -> child-open, /usr/share/yacreader/{,**} r, - /etc/machine-id r, - owner @{user_books_dirs}/{,**} rw, owner @{user_books_dirs}/**/.yacreaderlibrary/{,**} rwk, owner @{user_cache_dirs}/YACReader/ rw, - owner @{user_cache_dirs}/YACReader/YACReaderLibrary/ rw, - owner @{user_cache_dirs}/YACReader/YACReaderLibrary/** rwlk, + owner @{user_cache_dirs}/YACReader/** rwlk, owner @{user_share_dirs}/YACReader/ rw, - owner @{user_share_dirs}/YACReader/* r, - owner @{user_share_dirs}/YACReader/YACReaderLibrary/ rw, - owner @{user_share_dirs}/YACReader/YACReaderLibrary/** rwlk, + owner @{user_share_dirs}/YACReader/** rwlk, - owner @{tmp}/@{uuid} w, + owner @{tmp}/@{uuid} rw, @{run}/mount/utab r, diff --git a/apparmor.d/profiles-s-z/s3fs b/apparmor.d/profiles-s-z/s3fs index aaf34d49ce..67ae325b1c 100644 --- a/apparmor.d/profiles-s-z/s3fs +++ b/apparmor.d/profiles-s-z/s3fs @@ -9,6 +9,7 @@ include @{exec_path} = @{bin}/s3fs profile s3fs @{exec_path} { include + include include include @@ -25,7 +26,6 @@ profile s3fs @{exec_path} { @{bin}/fusermount{,3} rCx -> fusermount, - /etc/mime.types r, /etc/passwd-s3fs r, owner @{HOME}/.passwd-s3fs r, diff --git a/apparmor.d/profiles-s-z/sbctl b/apparmor.d/profiles-s-z/sbctl index 9dbbf0933e..bd4b08ff8c 100644 --- a/apparmor.d/profiles-s-z/sbctl +++ b/apparmor.d/profiles-s-z/sbctl @@ -9,6 +9,9 @@ include @{exec_path} = @{bin}/sbctl profile sbctl @{exec_path} { include + include + include + include capability dac_read_search, capability linux_immutable, @@ -20,20 +23,19 @@ profile sbctl @{exec_path} { /usr/share/secureboot/{,**} rw, /var/lib/sbctl/{,**} rw, - /{boot,efi}/{,**} r, - /{boot,efi}/EFI/{,**} rw, - /{boot,efi}/vmlinuz-linux* rw, + @{efi}/{,**} rw, @{lib}/fwupd/efi/{,**} rw, @{lib}/systemd/boot/efi/systemd-boot*.efi.signed rw, + @{sys}/devices/virtual/dmi/id/* r, + @{sys}/firmware/efi/efivars/db-@{uuid} rw, @{sys}/firmware/efi/efivars/KEK-@{uuid} rw, @{sys}/firmware/efi/efivars/PK-@{uuid} rw, @{sys}/firmware/efi/efivars/SecureBoot-@{uuid} r, @{sys}/firmware/efi/efivars/SetupMode-@{uuid} r, - /dev/pts/@{int} rw, - /dev/tpmrm@{int} rw, + @{PROC}/@{pid}/mountinfo r, # File Inherit deny network inet stream, diff --git a/apparmor.d/profiles-s-z/scrcpy b/apparmor.d/profiles-s-z/scrcpy index 83af575ddc..904e291ac7 100644 --- a/apparmor.d/profiles-s-z/scrcpy +++ b/apparmor.d/profiles-s-z/scrcpy @@ -14,6 +14,7 @@ profile scrcpy @{exec_path} { include include include + include network inet stream, network inet6 stream, @@ -23,6 +24,7 @@ profile scrcpy @{exec_path} { @{exec_path} mr, @{bin}/adb rPx, + @{lib}/android-sdk/platform-tools/adb rPx, /usr/share/scrcpy/{,*} r, @@ -34,6 +36,7 @@ profile scrcpy @{exec_path} { owner @{user_config_dirs}/ibus/bus/@{hex32}-unix-{,wayland-}@{int} r, owner @{PROC}/@{pid}/cmdline r, + owner @{PROC}/@{pid}/task/@{tid}/comm w, deny @{user_share_dirs}/gvfs-metadata/* r, diff --git a/apparmor.d/profiles-s-z/secure-time-sync b/apparmor.d/profiles-s-z/secure-time-sync index 51016373d9..9c3f6d9df7 100644 --- a/apparmor.d/profiles-s-z/secure-time-sync +++ b/apparmor.d/profiles-s-z/secure-time-sync @@ -23,7 +23,7 @@ profile secure-time-sync @{exec_path} flags=(attach_disconnected) { @{sh_path} rix, @{bin}/curl rix, @{bin}/date rix, - @{bin}/grep rix, + @{bin}/{,e}grep rix, @{bin}/id rPx, @{bin}/sed rix, diff --git a/apparmor.d/profiles-s-z/sensors b/apparmor.d/profiles-s-z/sensors index 4028680a61..8f8d306aca 100644 --- a/apparmor.d/profiles-s-z/sensors +++ b/apparmor.d/profiles-s-z/sensors @@ -8,9 +8,10 @@ abi , include @{exec_path} = @{bin}/sensors -profile sensors @{exec_path} { +profile sensors @{exec_path} flags=(attach_disconnected) { include include + include @{exec_path} mr, @@ -19,11 +20,9 @@ profile sensors @{exec_path} { /etc/sensors3.conf r, @{sys}/bus/i2c/devices/ r, - @{sys}/class/hwmon/ r, @{sys}/class/i2c-adapter/ r, - @{sys}/devices/{,platform/*.{i2c,hdmi}/}i2c-@{int}/name r, + @{sys}/devices/{,platform/*.{i2c,hdmi}/}i2c-*/name r, @{sys}/devices/@{pci}/name r, - @{sys}/devices/**/hwmon*/{,**} r, # file_inherit deny @{PROC}/@{pid}/net/dev r, diff --git a/apparmor.d/profiles-s-z/sensors-detect b/apparmor.d/profiles-s-z/sensors-detect index e3eca4e22e..a8d2f636c4 100644 --- a/apparmor.d/profiles-s-z/sensors-detect +++ b/apparmor.d/profiles-s-z/sensors-detect @@ -7,10 +7,11 @@ abi , include -@{exec_path} = @{bin}/sensors-detect +@{exec_path} = @{sbin}/sensors-detect profile sensors-detect @{exec_path} { include include + include capability syslog, @@ -27,12 +28,8 @@ profile sensors-detect @{exec_path} { @{sys}/bus/pci/devices/ r, @{sys}/class/i2c-adapter/ r, @{sys}/devices/@{pci}/{class,vendor,device} r, - @{sys}/devices/@{pci}/i2c-@{int}/{,**/}name r, + @{sys}/devices/@{pci}/i2c-*/{,**/}name r, @{sys}/devices/@{pci}/modalias r, - @{sys}/devices/virtual/dmi/id/board_{version,vendor,name} r, - @{sys}/devices/virtual/dmi/id/chassis_type r, - @{sys}/devices/virtual/dmi/id/product_{version,name} r, - @{sys}/devices/virtual/dmi/id/sys_vendor r, @{PROC}/modules r, owner @{PROC}/@{pid}/mounts r, diff --git a/apparmor.d/profiles-s-z/session-desktop b/apparmor.d/profiles-s-z/session-desktop index 4817f330a2..266ac00be0 100644 --- a/apparmor.d/profiles-s-z/session-desktop +++ b/apparmor.d/profiles-s-z/session-desktop @@ -7,17 +7,15 @@ abi , include @{name} = {S,s}ession +@{domain} = org.chromium.Chromium @{lib_dirs} = /opt/@{name} @{config_dirs} = @{user_config_dirs}/@{name} @{cache_dirs} = @{user_cache_dirs}/@{name} @{exec_path} = @{bin}/session-messenger-desktop @{lib_dirs}/session-desktop -profile session-desktop @{exec_path} { +profile session-desktop @{exec_path} flags=(attach_disconnected) { include include - include - include - include include include @@ -31,7 +29,7 @@ profile session-desktop @{exec_path} { @{lib_dirs}/resources/app.asar.unpacked/ts/webworker/workers/node/**.node mr, - @{open_path} rPx -> child-open-strict, + @{open_path} rPx -> child-open-strict, deny / r, deny @{HOME}/ r, diff --git a/apparmor.d/profiles-s-z/setvtrgb b/apparmor.d/profiles-s-z/setvtrgb index 6c9a3fe62b..197a1ebe4e 100644 --- a/apparmor.d/profiles-s-z/setvtrgb +++ b/apparmor.d/profiles-s-z/setvtrgb @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/setvtrgb +@{exec_path} = @{sbin}/setvtrgb profile setvtrgb @{exec_path} { include include @@ -17,7 +17,7 @@ profile setvtrgb @{exec_path} { /etc/console-setup/vtrgb r, - /dev/tty@{int} rw, + /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-s-z/sfdisk b/apparmor.d/profiles-s-z/sfdisk index 0009d52cbb..ea282f2691 100644 --- a/apparmor.d/profiles-s-z/sfdisk +++ b/apparmor.d/profiles-s-z/sfdisk @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/sfdisk +@{exec_path} = @{sbin}/sfdisk profile sfdisk @{exec_path} { include include @@ -17,6 +17,8 @@ profile sfdisk @{exec_path} { @{exec_path} mr, + /var/tmp/.#sfdisk@{hex16} rw, + # For backups owner @{HOME}/**.{bak,back} rwk, owner @{MOUNTS}/*/**.{bak,back} rwk, diff --git a/apparmor.d/profiles-s-z/sgdisk b/apparmor.d/profiles-s-z/sgdisk index ecc6abcdbc..769f3b8ece 100644 --- a/apparmor.d/profiles-s-z/sgdisk +++ b/apparmor.d/profiles-s-z/sgdisk @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/sgdisk +@{exec_path} = @{sbin}/sgdisk profile sgdisk @{exec_path} { include include @@ -23,6 +23,9 @@ profile sgdisk @{exec_path} { # For disk images owner @{user_img_dirs}/{,**} rwk, + #aa:only test + /tmp/@{rand10}/{,**} rw, + include if exists } diff --git a/apparmor.d/profiles-s-z/signal-desktop b/apparmor.d/profiles-s-z/signal-desktop index b6a4777075..8b7543a1e0 100644 --- a/apparmor.d/profiles-s-z/signal-desktop +++ b/apparmor.d/profiles-s-z/signal-desktop @@ -8,22 +8,24 @@ abi , include @{name} = signal-desktop{,-beta} +@{domain} = org.chromium.Chromium @{lib_dirs} = @{lib}/signal-desktop /opt/Signal{,?Beta} @{config_dirs} = @{user_config_dirs}/Signal{,?Beta} @{cache_dirs} = @{user_cache_dirs}/@{name} @{exec_path} = @{lib_dirs}/@{name} -profile signal-desktop @{exec_path} { +profile signal-desktop @{exec_path} flags=(attach_disconnected) { include include - include - include - include + include + include + include include include - include + include + include + include include - include network inet dgram, network inet6 dgram, @@ -33,28 +35,9 @@ profile signal-desktop @{exec_path} { @{exec_path} mrix, - @{bin}/getconf rix, @{open_path} rPx -> child-open-strict, - #aa:stack X xdg-settings - @{bin}/xdg-settings rPx -> signal-desktop//&xdg-settings, - - audit @{lib_dirs}/chrome-sandbox rPx, - @{lib_dirs}/chrome_crashpad_handler rix, - - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, - - @{sys}/fs/cgroup/user.slice/cpu.max r, - @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/cpu.max r, - @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/session-@{word}.scope/memory.high r, - @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/session-@{word}.scope/memory.max r, - @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/cpu.max r, - owner @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/app.slice/cpu.max r, - - @{PROC}/@{pid}/fd/ r, - @{PROC}/vmstat r, - - /dev/tty rw, + owner @{user_config_dirs}/signal-desktop-flags.conf r, include if exists } diff --git a/apparmor.d/profiles-s-z/signal-desktop-chrome-sandbox b/apparmor.d/profiles-s-z/signal-desktop-chrome-sandbox index 51c625d53f..33afbfd20e 100644 --- a/apparmor.d/profiles-s-z/signal-desktop-chrome-sandbox +++ b/apparmor.d/profiles-s-z/signal-desktop-chrome-sandbox @@ -29,7 +29,7 @@ profile signal-desktop-chrome-sandbox @{exec_path} { @{PROC}/@{pid}/oom_score_adj w, # Silencer - deny /dev/pts/@{int} rw, # file_inherit + deny /dev/pts/@{u16} rw, # file_inherit include if exists } diff --git a/apparmor.d/profiles-s-z/simple-scan b/apparmor.d/profiles-s-z/simple-scan index f79b284fbb..ad746f4e27 100644 --- a/apparmor.d/profiles-s-z/simple-scan +++ b/apparmor.d/profiles-s-z/simple-scan @@ -7,12 +7,13 @@ abi , include @{exec_path} = @{bin}/simple-scan -profile simple-scan @{exec_path} { +profile simple-scan @{exec_path} flags=(attach_disconnected) { include - include - include + include include include + include + include include network inet dgram, @@ -23,19 +24,22 @@ profile simple-scan @{exec_path} { @{open_path} rPx -> child-open-help, - /usr/share/snmp/{,**} r, + @{system_share_dirs}/snmp/{,**} r, /etc/sane.d/{,**} r, + /etc/snmp/snmp.conf r, + + owner /var/lib/snmp/{mib,cert}_indexes/ rw, + owner /var/lib/snmp/mibs/{iana,ietf}/ r, + owner /var/lib/snmp/mibs/{iana,ietf}/[A-Z]* r, @{sys}/bus/scsi/devices/ r, - @{sys}/devices/virtual/dmi/id/board_name r, - @{sys}/devices/virtual/dmi/id/board_vendor r, - @{sys}/devices/virtual/dmi/id/board_version r, - @{sys}/devices/virtual/dmi/id/product_name r, - @{sys}/devices/virtual/dmi/id/product_version r, - @{sys}/devices/virtual/dmi/id/sys_vendor r, + @{sys}/devices/**/uevent r, @{PROC}/scsi/scsi r, + @{PROC}/sys/dev/parport/ r, + @{PROC}/sys/dev/parport/parport@{int}/base-addr r, + @{PROC}/sys/dev/parport/parport@{int}/irq r, /dev/video@{int} rw, diff --git a/apparmor.d/profiles-s-z/sing-box b/apparmor.d/profiles-s-z/sing-box index 9f395735ef..1890510ae6 100644 --- a/apparmor.d/profiles-s-z/sing-box +++ b/apparmor.d/profiles-s-z/sing-box @@ -12,7 +12,6 @@ include profile sing-box @{exec_path} { include include - include capability net_bind_service, diff --git a/apparmor.d/profiles-s-z/slurp b/apparmor.d/profiles-s-z/slurp new file mode 100644 index 0000000000..8ffe32b106 --- /dev/null +++ b/apparmor.d/profiles-s-z/slurp @@ -0,0 +1,25 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 valoq +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/slurp +profile slurp @{exec_path} { + include + include + include + + @{exec_path} mr, + + /usr/share/icons/{,**} r, + + # often used in combination with grim screen cature tool + owner /dev/shm/grim-@{rand6} rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-s-z/smartctl b/apparmor.d/profiles-s-z/smartctl index 4af40c8aba..d025d160b9 100644 --- a/apparmor.d/profiles-s-z/smartctl +++ b/apparmor.d/profiles-s-z/smartctl @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/smartctl +@{exec_path} = @{sbin}/smartctl profile smartctl @{exec_path} { include include diff --git a/apparmor.d/profiles-s-z/smartd b/apparmor.d/profiles-s-z/smartd index d0f9c28fd7..da181ae696 100644 --- a/apparmor.d/profiles-s-z/smartd +++ b/apparmor.d/profiles-s-z/smartd @@ -8,7 +8,7 @@ abi , include -@{exec_path} = @{bin}/smartd +@{exec_path} = @{sbin}/smartd profile smartd @{exec_path} { include include @@ -39,8 +39,6 @@ profile smartd @{exec_path} { /var/lib/smartmontools/smartd.*.state{,~} rw, /var/lib/smartmontools/attrlog.*.csv rw, - @{run}/systemd/notify rw, - @{sys}/class/scsi_host/ r, @{PROC}/devices r, diff --git a/apparmor.d/profiles-s-z/smplayer b/apparmor.d/profiles-s-z/smplayer index 858c736373..cf603f6698 100644 --- a/apparmor.d/profiles-s-z/smplayer +++ b/apparmor.d/profiles-s-z/smplayer @@ -71,7 +71,7 @@ profile smplayer @{exec_path} { @{PROC}/@{pid}/mounts r, /dev/ r, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-s-z/smtube b/apparmor.d/profiles-s-z/smtube index c318328b6d..035ffaf0be 100644 --- a/apparmor.d/profiles-s-z/smtube +++ b/apparmor.d/profiles-s-z/smtube @@ -11,17 +11,12 @@ include profile smtube @{exec_path} { include include - include - include - include - include - include - include + include + include + include include - include include include - include network inet dgram, network inet6 dgram, @@ -32,6 +27,16 @@ profile smtube @{exec_path} { @{exec_path} mr, + # Players + @{bin}/mpv rPUx, + @{bin}/smplayer rPUx, + @{bin}/vlc rPUx, + @{bin}/cvlc rPUx, + @{bin}/youtube-dl rPUx, + @{bin}/yt-dlp rPUx, + + @{open_path} rPx -> child-open, + # SMTube config files owner @{user_config_dirs}/smtube/ rw, owner @{user_config_dirs}/smtube/* rwkl -> @{user_config_dirs}/smtube/#@{int}, @@ -49,29 +54,14 @@ profile smtube @{exec_path} { owner @{user_cache_dirs}/smtube/ rw, owner @{user_cache_dirs}/smtube/* rwk, - /var/lib/dbus/machine-id r, - /etc/machine-id r, - - /usr/share/hwdata/pnp.ids r, - /dev/shm/#@{int} rw, deny owner @{PROC}/@{pid}/cmdline r, owner @{PROC}/@{pid}/fd/ r, deny @{PROC}/sys/kernel/random/boot_id r, - # Players - @{bin}/mpv rPUx, - @{bin}/smplayer rPUx, - @{bin}/vlc rPUx, - @{bin}/cvlc rPUx, - @{bin}/youtube-dl rPUx, - @{bin}/yt-dlp rPUx, - - @{open_path} rPx -> child-open, - # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-s-z/snapshot b/apparmor.d/profiles-s-z/snapshot index 91ca7cd69d..9713880ce8 100644 --- a/apparmor.d/profiles-s-z/snapshot +++ b/apparmor.d/profiles-s-z/snapshot @@ -11,10 +11,24 @@ include profile snapshot @{exec_path} flags=(attach_disconnected) { include include + include include include + include include - include + + network netlink raw, + + #aa:dbus own bus=session name=org.gnome.Snapshot + + dbus send bus=session path=/org/freedesktop/portal/desktop + interface=org.freedesktop.portal.Camera + member=AccessCamera + peer=(name=org.freedesktop.portal.Desktop, label=xdg-desktop-portal), + dbus send bus=session path=/org/freedesktop/portal/desktop + interface=org.freedesktop.portal.Camera + member=OpenPipeWireRemote + peer=(name=org.freedesktop.portal.Desktop, label=xdg-desktop-portal), @{exec_path} mr, @@ -23,8 +37,6 @@ profile snapshot @{exec_path} flags=(attach_disconnected) { owner @{user_pictures_dirs}/Camera/{,**} rw, owner @{user_videos_dirs}/Camera/{,**} rw, - @{sys}/devices/virtual/dmi/id/bios_vendor r, - include if exists } diff --git a/apparmor.d/profiles-s-z/solaar b/apparmor.d/profiles-s-z/solaar new file mode 100644 index 0000000000..bfb42b9f6f --- /dev/null +++ b/apparmor.d/profiles-s-z/solaar @@ -0,0 +1,45 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/solaar +profile solaar @{exec_path} flags=(attach_disconnected) { + include + include + include + include + include + include + include + include + include + include + include + + network netlink raw, + + @{exec_path} mr, + + @{sbin}/ldconfig ix, + @{bin}/git ix, + + owner @{user_config_dirs}/solaar/{,**} rw, + + owner /var/tmp/@{word8} rw, + owner @{tmp}/Solaar_@{rand8} rw, + owner @{tmp}/@{word8} rw, + + owner @{PROC}/@{pid}/cgroup r, + owner @{PROC}/@{pid}/mounts r, + + deny @{bin}/git x, + deny @{HOME}/@{word8} rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-s-z/spectre-meltdown-checker b/apparmor.d/profiles-s-z/spectre-meltdown-checker deleted file mode 100644 index e70a5c4995..0000000000 --- a/apparmor.d/profiles-s-z/spectre-meltdown-checker +++ /dev/null @@ -1,184 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2019-2021 Mikhail Morfikov -# Copyright (C) 2021-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - -abi , - -include - -@{exec_path} = /{,usr/}{,local/}bin/spectre-meltdown-checker{,.sh} -profile spectre-meltdown-checker @{exec_path} { - include - include - - # Needed to read the /dev/cpu/@{int}/msr device - capability sys_rawio, - - # Needed to read system logs - capability syslog, - - # Used by readlink - capability sys_ptrace, - ptrace (read), - - @{exec_path} r, - - @{bin}/ r, - @{bin}/{,@{multiarch}-}objdump rix, - @{bin}/{,@{multiarch}-}readelf rix, - @{bin}/{,@{multiarch}-}strings rix, - @{sh_path} rix, - @{bin}/{,e}grep rix, - @{bin}/{,g,m}awk rix, - @{bin}/base64 rix, - @{bin}/basename rix, - @{bin}/bunzip2 rix, - @{bin}/cat rix, - @{bin}/ccache rCx -> ccache, - @{bin}/cut rix, - @{bin}/date rix, - @{bin}/dd rix, - @{bin}/dirname rix, - @{bin}/dmesg rix, - @{bin}/find rix, - @{bin}/gunzip rix, - @{bin}/gzip rix, - @{bin}/head rix, - @{bin}/id rix, - @{bin}/iucode_tool rix, - @{bin}/kmod rCx -> kmod, - @{bin}/lzop rix, - @{bin}/mktemp rix, - @{bin}/mount rix, - @{bin}/nproc rix, - @{bin}/od rix, - @{bin}/perl rix, - @{bin}/pgrep rCx -> pgrep, - @{bin}/rdmsr rix, - @{bin}/readlink rix, - @{bin}/rm rix, - @{bin}/sed rix, - @{bin}/seq rix, - @{bin}/sort rix, - @{bin}/stat rix, - @{bin}/tail rix, - @{bin}/tr rix, - @{bin}/uname rix, - @{bin}/unzip rix, - @{bin}/xargs rix, - @{bin}/xz rix, - @{bin}/zstd rix, - - # To fetch MCE.db from the MCExtractor project - @{bin}/wget rCx -> mcedb, - @{bin}/sqlite3 rCx -> mcedb, - owner @{tmp}/mcedb-* rw, - owner @{tmp}/smc-* rw, - owner @{tmp}/{,smc-}intelfw-*/ rw, - owner @{tmp}/{,smc-}intelfw-*/fw.zip rw, - owner @{tmp}/{,smc-}intelfw-*/Intel-Linux-Processor-Microcode-Data-Files-{master,main}/ rw, - owner @{tmp}/{,smc-}intelfw-*/Intel-Linux-Processor-Microcode-Data-Files-{master,main}/** rw, - - owner @{HOME}/.mcedb rw, - - /tmp/ r, - owner @{tmp}/{config,kernel}-* rw, - - owner /dev/cpu/@{int}/cpuid r, - owner /dev/cpu/@{int}/msr rw, - owner /dev/kmsg r, - - /boot/ r, - /boot/{config,vmlinuz,System.map}-* r, - - @{sys}/devices/system/cpu/vulnerabilities/* r, - @{sys}/module/kvm_intel/parameters/ept r, - - @{PROC}/ r, - @{PROC}/config.gz r, - @{PROC}/cmdline r, - @{PROC}/kallsyms r, - @{PROC}/modules r, - - # find and denoise - @{PROC}/@{pids}/{status,exe} r, - @{PROC}/@{pids}/fd/ r, - @{PROC}/*/ r, - - /var/lib/dbus/machine-id r, - /etc/machine-id r, - - # For shell pwd - /root/ r, - /etc/ r, - - profile ccache { - include - - @{bin}/ccache mr, - - @{lib}/llvm-[0-9]*/bin/clang rix, - @{bin}/{,@{multiarch}-}gcc-[0-9]* rix, - @{bin}/{,@{multiarch}-}g++-[0-9]* rix, - - /media/ccache/*/** rw, - - /etc/debian_version r, - - include if exists - } - - profile pgrep { - include - include - - include if exists - } - - profile mcedb { - include - include - include - include - - deny capability net_admin, - - network inet dgram, - network inet6 dgram, - network inet stream, - network inet6 stream, - network netlink raw, - - @{bin}/wget mr, - @{bin}/sqlite3 mr, - - /etc/wgetrc r, - owner @{HOME}/.wget-hsts rwk, - owner @{HOME}/.mcedb rw, - - /tmp/ r, - owner @{tmp}/{,smc-}mcedb-* rwk, - owner @{tmp}/{,smc-}intelfw-*/fw.zip rw, - - /usr/share/publicsuffix/public_suffix_list.* r, - - include if exists - } - - profile kmod { - include - include - - capability sys_module, - - owner @{sys}/module/cpuid/** r, - owner @{sys}/module/msr/** r, - - include if exists - } - - include if exists -} - -# vim:syntax=apparmor diff --git a/apparmor.d/profiles-s-z/speech-dispatcher b/apparmor.d/profiles-s-z/speech-dispatcher index 652a7d9ed5..0267d68897 100644 --- a/apparmor.d/profiles-s-z/speech-dispatcher +++ b/apparmor.d/profiles-s-z/speech-dispatcher @@ -20,16 +20,20 @@ profile speech-dispatcher @{exec_path} { @{exec_path} mr, @{sh_path} ix, + @{lib}/speech-dispatcher-modules/* ix, @{lib}/speech-dispatcher/** r, @{lib}/speech-dispatcher/speech-dispatcher-modules/* ix, /etc/machine-id r, /etc/speech-dispatcher/{,**} r, + owner @{user_config_dirs}/speech-dispatcher/{,**} r, + owner @{run}/user/@{uid}/speech-dispatcher/ rw, owner @{run}/user/@{uid}/speech-dispatcher/** rwk, - owner @{user_config_dirs}/speech-dispatcher/{,**} r, + owner /dev/shm/sem.@{rand6} rw, + owner /dev/shm/sem.speechd-modules-dummy-@{int} rwl -> /dev/shm/sem.@{rand6}, include if exists } diff --git a/apparmor.d/profiles-s-z/spice-vdagent b/apparmor.d/profiles-s-z/spice-vdagent index 9562fec75f..1d97de454a 100644 --- a/apparmor.d/profiles-s-z/spice-vdagent +++ b/apparmor.d/profiles-s-z/spice-vdagent @@ -9,21 +9,19 @@ include @{exec_path} = @{bin}/spice-vdagent profile spice-vdagent @{exec_path} flags=(attach_disconnected) { include - include - include include - include - include - include - include - include - include - include - include - include - include + include + include + include + include + include include + include + include + include include + include + include dbus send bus=session path=/org/freedesktop/portal/desktop interface=org.freedesktop.portal.Realtime @@ -33,20 +31,20 @@ profile spice-vdagent @{exec_path} flags=(attach_disconnected) { dbus receive bus=session path=/ interface=org.freedesktop.DBus.Introspectable member=Introspect - peer=(name=:*, label=gnome-shell), + peer=(name=@{busname}, label=gnome-shell), @{exec_path} mr, - owner @{desktop_config_dirs}/user-dirs.dirs r, - owner @{user_config_dirs}/user-dirs.dirs r, + /etc/fstab r, + @{run}/mount/utab r, @{run}/spice-vdagentd/spice-vdagent-sock rw, - @{sys}/devices/virtual/dmi/id/product_name r, - @{sys}/devices/virtual/dmi/id/sys_vendor r, - + owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pids}/task/@{tid}/comm rw, + /dev/udmabuf rw, + include if exists } diff --git a/apparmor.d/profiles-s-z/spice-vdagentd b/apparmor.d/profiles-s-z/spice-vdagentd index bebfbe4198..9323e054d3 100644 --- a/apparmor.d/profiles-s-z/spice-vdagentd +++ b/apparmor.d/profiles-s-z/spice-vdagentd @@ -6,11 +6,12 @@ abi , include -@{exec_path} = @{bin}/spice-vdagentd +@{exec_path} = @{sbin}/spice-vdagentd profile spice-vdagentd @{exec_path} flags=(attach_disconnected) { include include - include + include + include capability sys_nice, @@ -24,7 +25,6 @@ profile spice-vdagentd @{exec_path} flags=(attach_disconnected) { @{PROC}/@{pids}/cgroup r, - /dev/uinput rw, /dev/vport@{int}p@{int} rw, include if exists diff --git a/apparmor.d/profiles-s-z/spotdl b/apparmor.d/profiles-s-z/spotdl new file mode 100644 index 0000000000..be31bb0d01 --- /dev/null +++ b/apparmor.d/profiles-s-z/spotdl @@ -0,0 +1,40 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 tpaau-17DB +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/spotdl +profile spotdl @{exec_path} { + include + include + include + include + include + + network inet dgram, + network inet6 dgram, + network inet stream, + network inet6 stream, + + @{exec_path} mr, + @{python_path} r, + + @{bin}/ffmpeg rPx, + @{bin}/ffprobe rPx, + + owner @{user_music_dirs}/{,**} rwk, + + owner @{HOME}/.spotdl/** rw, + + owner @{user_cache_dirs}/spotdl/{,**} rw, + owner @{user_config_dirs}/spotdl/{,**} rw, + + owner @{PROC}/@{pid}/fd/ r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-s-z/spotify b/apparmor.d/profiles-s-z/spotify index ef516a7d64..f48524de76 100644 --- a/apparmor.d/profiles-s-z/spotify +++ b/apparmor.d/profiles-s-z/spotify @@ -8,7 +8,8 @@ abi , include @{name} = spotify -@{lib_dirs} = /opt/spotify/ +@{domain} = org.chromium.Chromium +@{lib_dirs} = /opt/@{name}/ /usr/share/@{name}/ @{config_dirs} = @{user_config_dirs}/@{name} @{cache_dirs} = @{user_cache_dirs}/@{name} @@ -16,7 +17,18 @@ include profile spotify @{exec_path} flags=(attach_disconnected) { include include + include + include include + include + include + include + include + include + include + include + include + include network inet dgram, network inet6 dgram, @@ -24,16 +36,22 @@ profile spotify @{exec_path} flags=(attach_disconnected) { network inet6 stream, network netlink raw, + #aa:dbus talk bus=session name=org.freedesktop.portal.{d,D}esktop label=xdg-desktop-portal + + dbus send bus=session path=/org/freedesktop/portal/desktop + interface=org.freedesktop.portal.Secret + member=RetrieveSecret + peer=(name=org.freedesktop.portal.Desktop, label=xdg-desktop-portal), + @{exec_path} mrix, @{sh_path} mr, - @{bin}/grep rix, @{open_path} rPx -> child-open-strict, - /etc/machine-id r, + /usr/local/lib/spotify-adblock.so mr, + /etc/spotify-adblock/* r, - /var/lib/dbus/machine-id r, owner @{user_music_dirs}/{,**} r, @@ -42,20 +60,19 @@ profile spotify @{exec_path} flags=(attach_disconnected) { owner @{cache_dirs}/WidevineCdm/**/libwidevinecdm.so rm, owner @{config_dirs}/*/WidevineCdm/**/libwidevinecdm.so rm, - owner @{tmp}/.org.chromium.Chromium.@{rand6}/** rw, + @{sys}/devices/@{pci_bus}/uevent r, @{PROC}/@{pid}/net/unix r, - @{PROC}/pressure/* r, owner @{PROC}/@{pid}/clear_refs w, - owner @{PROC}/@{pid}/task/@{tid}/comm rw, /dev/tty rw, - deny @{sys}/bus/ r, - deny @{sys}/bus/*/devices/ r, - deny @{sys}/class/*/ r, - deny @{sys}/devices/@{pci}/usb@{int}/** r, - deny @{user_share_dirs}/gvfs-metadata/* r, + deny dbus bus=session interface=org.freedesktop.systemd1.Manager, + deny dbus bus=system interface=org.freedesktop.login1.Manager, + deny owner @{HOME}/.tmp* rw, + deny /var/tmp/ r, + deny @{PROC}/pressure/* r, + deny /dev/bus/usb/** w, include if exists } diff --git a/apparmor.d/profiles-s-z/ss b/apparmor.d/profiles-s-z/ss index a942cac4f5..2ce6b6b4d5 100644 --- a/apparmor.d/profiles-s-z/ss +++ b/apparmor.d/profiles-s-z/ss @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/ss +@{exec_path} = @{sbin}/ss profile ss @{exec_path} { include include diff --git a/apparmor.d/profiles-s-z/start-hyprland b/apparmor.d/profiles-s-z/start-hyprland new file mode 100644 index 0000000000..0fda42a09b --- /dev/null +++ b/apparmor.d/profiles-s-z/start-hyprland @@ -0,0 +1,23 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 You +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/start-hyprland +profile start-hyprland @{exec_path} { + include + + signal receive set=term peer=sddm, + signal send set=term peer=hyprland, + + @{bin}/Hyprland rPx, + + @{exec_path} mr, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-s-z/startx b/apparmor.d/profiles-s-z/startx index 34f6d47240..2270397324 100644 --- a/apparmor.d/profiles-s-z/startx +++ b/apparmor.d/profiles-s-z/startx @@ -43,7 +43,7 @@ profile startx @{exec_path} flags=(attach_disconnected) { owner @{tmp}/serverauth.* rw, /dev/ r, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-s-z/strawberry b/apparmor.d/profiles-s-z/strawberry index 6a337a66bb..ae22e1f1d8 100644 --- a/apparmor.d/profiles-s-z/strawberry +++ b/apparmor.d/profiles-s-z/strawberry @@ -21,6 +21,7 @@ profile strawberry @{exec_path} flags=(attach_disconnected,mediate_deleted) { include include include + include include include @@ -68,9 +69,8 @@ profile strawberry @{exec_path} flags=(attach_disconnected,mediate_deleted) { owner @{tmp}/.*/s rw, owner @{tmp}/*= w, owner @{tmp}/#@{int} rw, - owner @{tmp}/etilqs_@{hex16} rw, - owner @{tmp}/kdsingleapp-daemonspudguy-strawberry w, - owner @{tmp}/kdsingleapp-daemonspudguy-strawberry.lock rwk, + owner @{tmp}/kdsingleapp-*-strawberry w, + owner @{tmp}/kdsingleapp-*-strawberry.lock rwk, owner @{tmp}/qipc_{systemsem,sharedmemory}_*[a-f0-9]* rw, owner @{tmp}/strawberry-cover-@{rand6}.jpg rwl -> @{tmp}/#@{int}, owner @{tmp}/strawberry*[0-9] w, diff --git a/apparmor.d/profiles-s-z/su-rs b/apparmor.d/profiles-s-z/su-rs new file mode 100644 index 0000000000..e16505b6f2 --- /dev/null +++ b/apparmor.d/profiles-s-z/su-rs @@ -0,0 +1,24 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/su-rs @{lib}/cargo/bin/su + +profile su-rs @{exec_path} { + include + include + include + + @{exec_path} mr, + + @{bin}/@{shells} Ux, #aa:exclude RBAC + @{sbin}/nologin Px, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-s-z/sudo b/apparmor.d/profiles-s-z/sudo index b2074ba046..6c22bd9db4 100644 --- a/apparmor.d/profiles-s-z/sudo +++ b/apparmor.d/profiles-s-z/sudo @@ -17,6 +17,7 @@ profile sudo @{exec_path} flags=(attach_disconnected) { capability fowner, capability mknod, capability sys_ptrace, + capability kill, network inet dgram, network inet6 dgram, @@ -29,6 +30,8 @@ profile sudo @{exec_path} flags=(attach_disconnected) { @{lib}/** PUx, /opt/*/** PUx, /snap/snapd/@{int}@{bin}/snap rPUx, + @{user_bin_dirs}/** PUx, + @{user_share_dirs}/pipx/venvs/*/bin/* rPUx, /etc/default/locale r, diff --git a/apparmor.d/profiles-s-z/sudo-rs b/apparmor.d/profiles-s-z/sudo-rs new file mode 100644 index 0000000000..1c30208778 --- /dev/null +++ b/apparmor.d/profiles-s-z/sudo-rs @@ -0,0 +1,36 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/sudo-rs @{lib}/cargo/bin/sudo + +profile sudo-rs @{exec_path} { + include + include + include + + capability sys_ptrace, # optional: no audit + + ptrace read, + + signal send set=(winch, hup, term), + + @{exec_path} mr, + @{bin}/env ix, + @{bin}/tee m, + + @{bin}/@{shells} rUx, + @{lib}/** PUx, + /opt/*/** PUx, + /snap/snapd/@{int}@{bin}/snap rPUx, + @{user_bin_dirs}/** PUx, + @{user_share_dirs}/pipx/venvs/*/bin/* rPUx, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-s-z/superproductivity b/apparmor.d/profiles-s-z/superproductivity index c0b940478d..959dffc163 100644 --- a/apparmor.d/profiles-s-z/superproductivity +++ b/apparmor.d/profiles-s-z/superproductivity @@ -6,7 +6,8 @@ abi , include -@{name} = super{p,P}roductivity +@{name} = super{p,P}roductivity Super?Productivity +@{domain} = org.chromium.Chromium @{lib_dirs} = /opt/@{name} @{config_dirs} = @{user_config_dirs}/@{name} @{cache_dirs} = @{user_cache_dirs}/@{name} @@ -15,8 +16,12 @@ include profile superproductivity @{exec_path} flags=(attach_disconnected) { include include - include + include + include include + include + include + include network inet stream, network inet6 stream, @@ -26,10 +31,14 @@ profile superproductivity @{exec_path} flags=(attach_disconnected) { @{exec_path} mrix, - @{bin}/speech-dispatcher rPx, - @{open_path} rPx -> child-open-strict, + @{sh_path} rix, + @{bin}/gdbus rix, + @{bin}/speech-dispatcher rPx, + @{bin}/which{,.debianutils} rix, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, + @{open_path} rPx -> child-open-strict, + + owner @{run}/user/@{uid}/speech-dispatcher/speechd.sock rw, include if exists } diff --git a/apparmor.d/profiles-s-z/switcheroo-control b/apparmor.d/profiles-s-z/switcheroo-control index e1b9ab7de7..c1fd317c8b 100644 --- a/apparmor.d/profiles-s-z/switcheroo-control +++ b/apparmor.d/profiles-s-z/switcheroo-control @@ -12,6 +12,7 @@ profile switcheroo-control @{exec_path} flags=(attach_disconnected) { include capability net_admin, + capability sys_admin, capability sys_nice, network netlink raw, @@ -20,16 +21,18 @@ profile switcheroo-control @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, + / r, + @{run}/udev/data/+drm:card@{int}-* r, # for screen outputs @{run}/udev/data/+pci:* r, # Identifies all PCI devices (CPU, GPU, Network, Disks, USB, etc.) - @{run}/udev/data/c226:@{int} r, # for /dev/dri/card* + @{run}/udev/data/c226:@{int} r, # For DRI card /dev/dri/card@{int} @{sys}/bus/ r, @{sys}/class/ r, @{sys}/class/drm/ r, + @{sys}/devices/**/uevent r, @{sys}/devices/@{pci}/boot_vga r, - @{sys}/devices/@{pci}/uevent r, @{sys}/devices/virtual/**/uevent r, include if exists diff --git a/apparmor.d/profiles-s-z/swtpm b/apparmor.d/profiles-s-z/swtpm index 783e582379..9981a14d38 100644 --- a/apparmor.d/profiles-s-z/swtpm +++ b/apparmor.d/profiles-s-z/swtpm @@ -9,23 +9,42 @@ include @{exec_path} = @{bin}/swtpm profile swtpm @{exec_path} { include + include - signal (receive) set=(term) peer=libvirtd, + audit capability chown, + audit capability dac_override, + audit capability dac_read_search, + audit capability fowner, + audit capability fsetid, + audit capability setgid, + audit capability setuid, + audit capability sys_admin, + + network inet stream, + network inet6 stream, + + signal receive set=term peer=libvirtd, + + unix (send receive) type=stream peer=(label=swtpm_setup), + unix (send receive) type=stream peer=(label=libvirt-*), @{exec_path} mr, - /var/lib/libvirt/swtpm/@{uuid}/tpm2/.lock wk, - /var/lib/libvirt/swtpm/@{uuid}/tpm2/*.permall rw, + owner /var/lib/libvirt/swtpm/{,**} rwk, + owner /var/lib/swtpm/{,**} rwk, + owner /var/log/swtpm/libvirt/qemu/*-swtpm.log rw, - /var/log/swtpm/libvirt/qemu/*-swtpm.log w, + @{run}/libvirt/qemu/swtpm/*.pid rwk, + @{run}/libvirt/qemu/swtpm/*.sock rwk, + owner @{run}/swtpm/sock rw, + owner @{run}/user/@{uid}/libvirt/qemu/run/swtpm/*.pid rwk, + owner @{run}/user/@{uid}/libvirt/qemu/run/swtpm/*.sock rwk, - /tmp/.swtpm_setup.pidfile.* rw, + /tmp/.swtpm_setup.pidfile.@{rand6} rw, /tmp/@{int}/.lock rwk, - /tmp/@{int}/TMP* rw, /tmp/@{int}/vtpm.sock rw, - @{run}/libvirt/qemu/swtpm/*.sock w, - @{run}/libvirt/qemu/swtpm/*.pid w, + owner /dev/vtpmx rw, include if exists } diff --git a/apparmor.d/profiles-s-z/swtpm_ioctl b/apparmor.d/profiles-s-z/swtpm_ioctl index f1e41aa6ed..98349cda22 100644 --- a/apparmor.d/profiles-s-z/swtpm_ioctl +++ b/apparmor.d/profiles-s-z/swtpm_ioctl @@ -15,6 +15,8 @@ profile swtpm_ioctl @{exec_path} { @{exec_path} mr, + @{run}/libvirt/qemu/swtpm/*.sock rw, + include if exists } diff --git a/apparmor.d/profiles-s-z/swtpm_setup b/apparmor.d/profiles-s-z/swtpm_setup index 08ee1532e5..c1e88fb44c 100644 --- a/apparmor.d/profiles-s-z/swtpm_setup +++ b/apparmor.d/profiles-s-z/swtpm_setup @@ -11,6 +11,8 @@ profile swtpm_setup @{exec_path} { include include + unix (send receive) type=stream peer=(label=swtpm), + @{exec_path} mr, @{bin}/swtpm rPx, @@ -21,9 +23,9 @@ profile swtpm_setup @{exec_path} { /var/log/swtpm/{,**} w, /var/lib/libvirt/swtpm/@{uuid}/tpm2/ r, - owner @{tmp}/swtpm_setup.certs.*/ w, - owner @{tmp}/swtpm_setup.certs.*/*.cert rw, - owner @{tmp}/.swtpm_setup.pidfile* rw, + owner @{tmp}/.swtpm_setup.pidfile.@{rand6} rw, + owner @{tmp}/swtpm_setup.certs.@{rand6}/ w, + owner @{tmp}/swtpm_setup.certs.@{rand6}/*.cert rw, include if exists } diff --git a/apparmor.d/profiles-s-z/syncoid b/apparmor.d/profiles-s-z/syncoid index 821a3fd638..fc30c5fd69 100644 --- a/apparmor.d/profiles-s-z/syncoid +++ b/apparmor.d/profiles-s-z/syncoid @@ -15,7 +15,7 @@ profile syncoid @{exec_path} flags=(complain) { @{exec_path} mr, @{sh_path} rix, - @{bin}/grep rix, + @{bin}/{,e}grep rix, @{bin}/mbuffer rix, @{bin}/perl rix, @{bin}/ps rPx, @@ -25,8 +25,6 @@ profile syncoid @{exec_path} flags=(complain) { /etc/mbuffer.rc r, - @{PROC}/@{pids}/maps r, - include if exists } diff --git a/apparmor.d/profiles-s-z/syncthing b/apparmor.d/profiles-s-z/syncthing index d03ece9e4b..a4bd163c17 100644 --- a/apparmor.d/profiles-s-z/syncthing +++ b/apparmor.d/profiles-s-z/syncthing @@ -8,10 +8,12 @@ abi , include @{exec_path} = @{bin}/syncthing -profile syncthing @{exec_path} { +profile syncthing @{exec_path} flags=(attach_disconnected) { include include + include include + include include network inet dgram, @@ -25,10 +27,6 @@ profile syncthing @{exec_path} { @{open_path} rPx -> child-open, @{bin}/ip rix, - /usr/share/mime/{,**} r, - - /etc/mime.types r, - @{HOME}/ r, @{HOME}/** rwk, @@ -36,10 +34,14 @@ profile syncthing @{exec_path} { @{user_sync_dirs}/{,**} rw, @{PROC}/@{pids}/net/route r, + @{PROC}/bus/pci/devices r, + @{PROC}/modules r, @{PROC}/sys/kernel/osrelease r, @{PROC}/sys/net/core/somaxconn r, owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/mountinfo r, + owner @{PROC}/@{pid}/stat r, + owner @{PROC}/@{pid}/statm r, include if exists } diff --git a/apparmor.d/profiles-s-z/sysstat-sa b/apparmor.d/profiles-s-z/sysstat-sa index 37f5e3ca12..8bb38820a1 100644 --- a/apparmor.d/profiles-s-z/sysstat-sa +++ b/apparmor.d/profiles-s-z/sysstat-sa @@ -17,13 +17,14 @@ profile sysstat-sa @{exec_path} { @{sh_path} rix, @{bin}/date ix, @{bin}/find ix, - @{bin}/grep ix, + @{bin}/{,e}grep ix, @{bin}/rm ix, @{bin}/sar.sysstat ix, @{bin}/xargs ix, @{lib}/sysstat/sadc Px, /etc/sysstat/sysstat r, + /etc/sysstat/sysstat.ioconf r, /var/log/sysstat/ r, /var/log/sysstat/** rw, diff --git a/apparmor.d/profiles-s-z/sysstat-sadc b/apparmor.d/profiles-s-z/sysstat-sadc index e076f313cb..63e9096ca5 100644 --- a/apparmor.d/profiles-s-z/sysstat-sadc +++ b/apparmor.d/profiles-s-z/sysstat-sadc @@ -10,6 +10,7 @@ include profile sysstat-sadc @{exec_path} { include include + include capability sys_admin, @@ -21,18 +22,17 @@ profile sysstat-sadc @{exec_path} { /var/log/sysstat/{,**} rwk, @{sys}/bus/i2c/devices/ r, + @{sys}/bus/usb/devices/ r, @{sys}/class/fc_host/ r, - @{sys}/class/hwmon/ r, @{sys}/class/i2c-adapter/ r, - @{sys}/devices/@{pci}/i2c-@{int}/name r, - @{sys}/devices/@{pci}/net/*/duplex r, - @{sys}/devices/**/net/*/duplex r, - @{sys}/devices/**/net/*/speed r, - @{sys}/devices/virtual/net/*/duplex r, - @{sys}/devices/virtual/net/*/speed r, + @{sys}/class/power_supply/ r, + @{sys}/devices/**/duplex r, + @{sys}/devices/**/name r, + @{sys}/devices/**/speed r, @{PROC}/@{pid}/net/* r, @{PROC}/diskstats r, + @{PROC}/interrupts r, @{PROC}/loadavg r, @{PROC}/pressure/cpu r, @{PROC}/pressure/io r, diff --git a/apparmor.d/profiles-s-z/system-config-printer b/apparmor.d/profiles-s-z/system-config-printer index 84f6d52d32..9c7ed77c85 100644 --- a/apparmor.d/profiles-s-z/system-config-printer +++ b/apparmor.d/profiles-s-z/system-config-printer @@ -11,10 +11,8 @@ include @{exec_path} += /usr/share/system-config-printer/system-config-printer.py profile system-config-printer @{exec_path} flags=(complain) { include - include - include - include - include + include + include include include include @@ -52,7 +50,7 @@ profile system-config-printer @{exec_path} flags=(complain) { owner @{PROC}/@{pid}/mounts r, owner @{PROC}/@{pid}/stat r, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-s-z/tasksel b/apparmor.d/profiles-s-z/tasksel index 64b3ed4ad2..8a33649a0c 100644 --- a/apparmor.d/profiles-s-z/tasksel +++ b/apparmor.d/profiles-s-z/tasksel @@ -10,73 +10,33 @@ include @{exec_path} = @{bin}/tasksel profile tasksel @{exec_path} flags=(complain) { include - include + include @{exec_path} r, - @{sh_path} rix, - @{bin}/tempfile rix, - @{lib}/tasksel/tasksel-debconf rix, - - @{lib}/tasksel/tests/* rCx -> tasksel-tests, - - # Think what to do about this (#FIXME#) - /usr/share/debconf/frontend rPx, - #/usr/share/debconf/frontend rCx -> frontend, + @{bin}/tempfile ix, + @{lib}/tasksel/tasksel-debconf ix, + @{lib}/tasksel/tests/* Cx -> tasksel-tests, # Do not strip env to avoid errors like the following: # ERROR: ld.so: object 'libfakeroot-sysv.so' from LD_PRELOAD cannot be preloaded (cannot open # shared object file): ignored. - @{bin}/dpkg-query rpx, + @{bin}/dpkg-query px, # - @{bin}/apt-cache rPx, - - @{bin}/debconf-apt-progress rPx, - - /usr/share/tasksel/** r, - - /usr/share/debconf/confmodule r, + @{bin}/apt-cache Px, + @{bin}/debconf-apt-progress Px, - owner @{tmp}/file* w, + /usr/share/tasksel/{,**} r, profile tasksel-tests flags=(complain) { include - @{lib}/tasksel/tests/* r, @{sh_path} rix, + @{lib}/tasksel/tests/* r, include if exists } - profile frontend flags=(complain) { - include - include - include - include - - /usr/share/debconf/frontend r, - - @{bin}/tasksel rPx, - - @{sh_path} rix, - @{bin}/stty rix, - @{bin}/locale rix, - - # The following is needed when debconf uses dialog/whiptail frontend. - @{bin}/whiptail rPx, - owner @{tmp}/file* w, - - /usr/share/debconf/confmodule r, - - /etc/debconf.conf r, - owner /var/cache/debconf/{config,passwords,templates}.dat{,-new,-old} rwk, - /usr/share/debconf/templates/adequate.templates r, - - /etc/shadow r, - - include if exists - } - include if exists } diff --git a/apparmor.d/profiles-s-z/telegram-desktop b/apparmor.d/profiles-s-z/telegram-desktop index d967f42294..349cab595a 100644 --- a/apparmor.d/profiles-s-z/telegram-desktop +++ b/apparmor.d/profiles-s-z/telegram-desktop @@ -7,14 +7,12 @@ abi , include -@{exec_path} = @{bin}/telegram-desktop +@{exec_path} = @{bin}/telegram-desktop @{bin}/Telegram /opt/Telegram/Telegram profile telegram-desktop @{exec_path} { include include include - include - include - include + include include include include @@ -35,29 +33,27 @@ profile telegram-desktop @{exec_path} { network netlink dgram, network netlink raw, - @{exec_path} mr, + @{exec_path} mrix, @{sh_path} rix, @{open_path} rPx -> child-open-strict, + @{bin}/systemd-detect-virt rPx, owner @{user_share_dirs}/TelegramDesktop/ rw, owner @{user_share_dirs}/TelegramDesktop/** rwlk -> @{user_share_dirs}/TelegramDesktop/**, owner @{user_config_dirs}/autostart/telegramdesktop.desktop rw, + owner @{user_config_dirs}/autostart/org.telegram.desktop._@{hex32}.desktop{,.@{rand6}} rw, owner @{tmp}/@{hex32}-?@{uuid}? rwk, audit owner /dev/shm/#@{int} rw, - @{sys}/kernel/mm/transparent_hugepage/enabled r, - owner @{PROC}/@{pid}/cmdline r, owner @{PROC}/@{pid}/fd/ r, owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/mounts r, owner @{PROC}/@{pid}/task/@{tid}/comm rw, - owner /dev/tty@{int} rw, - include if exists } diff --git a/apparmor.d/profiles-s-z/terminator b/apparmor.d/profiles-s-z/terminator index 679a0fd32a..948a0f8e26 100644 --- a/apparmor.d/profiles-s-z/terminator +++ b/apparmor.d/profiles-s-z/terminator @@ -9,12 +9,12 @@ include @{exec_path} = @{bin}/terminator profile terminator @{exec_path} flags=(attach_disconnected) { include - include - include - include + include include include include + include + include include include include @@ -25,7 +25,12 @@ profile terminator @{exec_path} flags=(attach_disconnected) { signal send set=hup peer=unconfined, - #aa:dbus own bus=session name=net.tenshu.Terminator@{hex} + #aa:dbus own bus=session name=net.tenshu.Terminator2 + + dbus send bus=session path=/org/freedesktop/systemd1 + interface=org.freedesktop.systemd1.Manager + member=StartTransientUnit + peer=(name=org.freedesktop.systemd1, label="@{p_systemd_user}"), @{exec_path} mr, @@ -63,8 +68,6 @@ profile terminator @{exec_path} flags=(attach_disconnected) { /dev/dri/card@{int} rw, /dev/ptmx rw, - deny @{user_share_dirs}/gvfs-metadata/{,*} r, - include if exists } diff --git a/apparmor.d/profiles-s-z/texstudio b/apparmor.d/profiles-s-z/texstudio new file mode 100644 index 0000000000..710144ea9e --- /dev/null +++ b/apparmor.d/profiles-s-z/texstudio @@ -0,0 +1,48 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 valoq +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/texstudio +profile texstudio @{exec_path} { + include + include + include + include + include + include + include + + @{exec_path} mr, + + @{bin}/bibtex ix, + @{bin}/pdflatex ix, + @{bin}/pdftex ix, + @{bin}/kpsewhich ix, + @{bin}/gsettings ix, + @{bin}/which{,.debianutils} ix, + + /usr/share/texmf-dist/{,**} r, + /usr/share/doc/texstudio/{,**} r, + /usr/share/hunspell/{,**} r, + /usr/share/texstudio/{,**} r, + + /etc/texmf/{,**} r, + /etc/machine-id r, + + /var/lib/texmf/{,**} r, + + owner @{user_config_dirs}/texstudio/{,**} rwlk, + owner /tmp/qtsingleapp-TeXstu-** rw, + owner /tmp/qtsingleapp-TeXstu-**-lockfile rwk, + + ## silencer + deny owner /usr/share/hunspell/en_US-large.ign w, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-s-z/tftp b/apparmor.d/profiles-s-z/tftp index 33f6fe6dc9..bb0a1c37b3 100644 --- a/apparmor.d/profiles-s-z/tftp +++ b/apparmor.d/profiles-s-z/tftp @@ -10,9 +10,15 @@ include @{exec_path} = @{bin}/tftp profile tftp @{exec_path} { include - include + include include + network inet dgram, + network inet stream, + network inet6 dgram, + network inet6 stream, + network netlink raw, + @{exec_path} mr, include if exists diff --git a/apparmor.d/profiles-s-z/thermald b/apparmor.d/profiles-s-z/thermald index fe30e6da82..988918f50d 100644 --- a/apparmor.d/profiles-s-z/thermald +++ b/apparmor.d/profiles-s-z/thermald @@ -8,12 +8,13 @@ abi , include -@{exec_path} = @{bin}/thermald +@{exec_path} = @{sbin}/thermald profile thermald @{exec_path} flags=(attach_disconnected) { include include - include - include + include + include + include capability sys_boot, @@ -24,11 +25,9 @@ profile thermald @{exec_path} flags=(attach_disconnected) { /etc/thermald/{,*} r, owner @{run}/thermald/ rw, - owner @{run}/thermald/thd_preference.conf rw, - owner @{run}/thermald/thd_preference.conf.save w, + owner @{run}/thermald/** rw, owner @{run}/thermald/thermald.pid rwk, - @{sys}/class/hwmon/ r, @{sys}/class/thermal/ r, @{sys}/devices/platform/ r, @{sys}/devices/platform/** r, @@ -44,9 +43,6 @@ profile thermald @{exec_path} flags=(attach_disconnected) { @{sys}/devices/@{pci}/power_limits/power_limit_@{int}_tmax_us r, @{sys}/devices/@{pci}/power_limits/power_limit_@{int}_tmin_us r, - @{sys}/devices/**/hwmon@{int}/ r, - @{sys}/devices/**/hwmon@{int}/name r, - @{sys}/devices/**/hwmon@{int}/temp@{int}_{max,crit} r, @{sys}/devices/**/path r, @{sys}/devices/platform/*/uuids/current_uuid rw, diff --git a/apparmor.d/profiles-s-z/thinkfan b/apparmor.d/profiles-s-z/thinkfan index ddf7e1ff29..6165f2fb44 100644 --- a/apparmor.d/profiles-s-z/thinkfan +++ b/apparmor.d/profiles-s-z/thinkfan @@ -10,16 +10,14 @@ include @{exec_path} = @{bin}/thinkfan profile thinkfan @{exec_path} { include + include + include @{exec_path} mr, /etc/thinkfan.conf r, /etc/thinkfan.yaml r, - @{sys}/devices/**/hwmon/**/pwm@{int} rw, - @{sys}/devices/**/hwmon/**/pwm@{int}_enable rw, - @{sys}/devices/**/hwmon/**/temp@{int}_input r, - @{PROC}/acpi/ibm/thermal r, @{PROC}/acpi/ibm/fan rw, diff --git a/apparmor.d/profiles-s-z/thunderbird b/apparmor.d/profiles-s-z/thunderbird index 02046580ca..cead62dad2 100644 --- a/apparmor.d/profiles-s-z/thunderbird +++ b/apparmor.d/profiles-s-z/thunderbird @@ -13,7 +13,7 @@ include @{cache_dirs} = @{user_cache_dirs}/@{name}/ @{exec_path} = @{bin}/@{name} @{lib_dirs}/@{name} -profile thunderbird @{exec_path} { +profile thunderbird @{exec_path} flags=(attach_disconnected) { include include include @@ -23,8 +23,15 @@ profile thunderbird @{exec_path} { @{exec_path} mrix, - @{lib_dirs}/glxtest rPx, - @{lib_dirs}/vaapitest rPx, + @{lib_dirs}/glxtest rPx -> thunderbird//&thunderbird-glxtest, + @{lib_dirs}/vaapitest rPx -> thunderbird//&thunderbird-vaapitest, + + #aa:only apparmor<5.0 + # glycin-loaders sandboxed profile stack + include + signal (send receive) set=kill peer=glycin//&thunderbird, + @{bin}/bwrap Px -> thunderbird//&glycin, + @{lib}/glycin-loaders/@{d}+/glycin-* Px -> thunderbird//&glycin//&glycin//loaders, @{lib}/@{multiarch}/qt5/plugins/kf5/org.kde.kwindowsystem.platforms/KF5WindowSystemKWaylandPlugin.so mr, @{lib}/@{multiarch}/qt5/plugins/kf5/org.kde.kwindowsystem.platforms/KF5WindowSystemX11Plugin.so mr, @@ -55,9 +62,10 @@ profile thunderbird @{exec_path} { owner @{tmp}/MozillaMailnews/ rw, owner @{tmp}/MozillaMailnews/*.msf rw, - owner @{tmp}/nscopy.tmp rw, - owner @{tmp}/nsemail{,-@{int}}.eml rw, - owner @{tmp}/nsma{,-@{int}} rw, + owner @{tmp}/ns* rw, + owner @{tmp}/org.mozilla.thunderbird/ w, + owner @{tmp}/org.mozilla.thunderbird/.parentlock wk, + owner @{tmp}/org.mozilla.thunderbird/lock w, owner @{tmp}/pid-@{pid}/{,**} w, owner @{tmp}/remote-settings-startup-bundle- rw, diff --git a/apparmor.d/profiles-s-z/thunderbird-glxtest b/apparmor.d/profiles-s-z/thunderbird-glxtest index 626896a09c..81f506e9b1 100644 --- a/apparmor.d/profiles-s-z/thunderbird-glxtest +++ b/apparmor.d/profiles-s-z/thunderbird-glxtest @@ -11,18 +11,24 @@ include @{config_dirs} = @{HOME}/.@{name}/ @{exec_path} = @{lib_dirs}/glxtest -profile thunderbird-glxtest @{exec_path} { +profile thunderbird-glxtest @{exec_path} flags=(attach_disconnected) { include + include include include + include include - include + + network netlink raw, @{exec_path} mr, + / r, + owner @{config_dirs}/*/.parentlock rw, owner @{tmp}/thunderbird/.parentlock rw, + owner @{tmp}/org.mozilla.thunderbird/.parentlock rw, owner @{PROC}/@{pid}/cmdline r, diff --git a/apparmor.d/profiles-s-z/thunderbird-vaapitest b/apparmor.d/profiles-s-z/thunderbird-vaapitest index c93d14bd72..3de90eadda 100644 --- a/apparmor.d/profiles-s-z/thunderbird-vaapitest +++ b/apparmor.d/profiles-s-z/thunderbird-vaapitest @@ -20,6 +20,7 @@ profile thunderbird-vaapitest @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, + owner @{tmp}/org.mozilla.thunderbird/.parentlock w, owner @{tmp}/thunderbird/.parentlock rw, deny @{cache_dirs}/*/startupCache/** r, diff --git a/apparmor.d/profiles-s-z/tickrs b/apparmor.d/profiles-s-z/tickrs new file mode 100644 index 0000000000..131e1102b5 --- /dev/null +++ b/apparmor.d/profiles-s-z/tickrs @@ -0,0 +1,32 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Zane Zakraisek +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/tickrs +profile tickrs @{exec_path} { + include + include + include + include + + network inet dgram, + network inet6 dgram, + network inet stream, + network inet6 stream, + network netlink raw, + + @{exec_path} mr, + + owner @{user_config_dirs}/tickrs/{,**} rw, + + @{sys}/fs/cgroup/**/cpu.max r, + owner @{PROC}/@{pid}/cgroup r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-s-z/tint2 b/apparmor.d/profiles-s-z/tint2 index 8b6f0dc453..c7ad54d286 100644 --- a/apparmor.d/profiles-s-z/tint2 +++ b/apparmor.d/profiles-s-z/tint2 @@ -57,7 +57,7 @@ profile tint2 @{exec_path} { owner @{PROC}/@{pid}/mountinfo r, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, owner @{HOME}/.xsession-errors w, include if exists diff --git a/apparmor.d/profiles-s-z/tint2conf b/apparmor.d/profiles-s-z/tint2conf index 737bc90f85..f82d19ec11 100644 --- a/apparmor.d/profiles-s-z/tint2conf +++ b/apparmor.d/profiles-s-z/tint2conf @@ -10,10 +10,7 @@ include @{exec_path} = @{bin}/tint2conf profile tint2conf @{exec_path} { include - include - include - include - include + include @{exec_path} mr, @@ -37,7 +34,7 @@ profile tint2conf @{exec_path} { /etc/fstab r, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-s-z/tlp b/apparmor.d/profiles-s-z/tlp index ff447e81e0..0bfc8eecdb 100644 --- a/apparmor.d/profiles-s-z/tlp +++ b/apparmor.d/profiles-s-z/tlp @@ -7,17 +7,20 @@ abi , include -@{exec_path} = @{bin}/tlp +@{exec_path} = @{sbin}/tlp profile tlp @{exec_path} flags=(attach_disconnected) { include include - include + include include include include include + include + include capability dac_read_search, + capability net_admin, capability sys_nice, capability sys_rawio, capability sys_tty_config, @@ -30,13 +33,13 @@ profile tlp @{exec_path} flags=(attach_disconnected) { @{bin}/cat rix, @{bin}/chmod rix, @{bin}/cp rix, - @{bin}/ethtool rix, + @{sbin}/ethtool rix, @{bin}/flock rix, - @{bin}/grep rix, - @{bin}/hdparm rPx, + @{bin}/{,e}grep rix, + @{sbin}/hdparm rPx, @{bin}/head rix, @{bin}/id rPx, - @{bin}/iw rPx, + @{sbin}/iw rPx, @{bin}/logger rix, @{bin}/mktemp rix, @{bin}/readlink rix, @@ -48,6 +51,7 @@ profile tlp @{exec_path} flags=(attach_disconnected) { @{bin}/tr rix, @{bin}/udevadm rCx -> udevadm, @{bin}/uname rix, + @{bin}/timeout rix, /usr/share/tlp/tlp-readconfs rix, / r, @@ -66,9 +70,11 @@ profile tlp @{exec_path} flags=(attach_disconnected) { owner @{run}/tlp/{,**} rw, owner @{run}/tlp/lock_tlp rwk, - @{run}/udev/data/+platform:* r, + @{run}/udev/data/+platform:* r, # Identifies onboard devices (laptop/board model, power controllers, thermal sensors) @{sys}/bus/pci/devices/ r, + @{sys}/bus/pci/drivers/*/ r, + @{sys}/bus/platform/devices/ r, @{sys}/class/drm/ r, @{sys}/class/net/ r, @{sys}/class/power_supply/ r, @@ -76,10 +82,11 @@ profile tlp @{exec_path} flags=(attach_disconnected) { @{sys}/devices/@{pci}/{,**/}power/control w, @{sys}/devices/@{pci}/**/host@{int}/**/link_power_management_policy w, @{sys}/devices/@{pci}/class r, + @{sys}/devices/**/@{uuid}/@{pci}/ r, + @{sys}/devices/**/@{uuid}/@{pci}//{,**/}power/control w, + @{sys}/devices/**/@{uuid}/@{pci}/class r, @{sys}/devices/**/net/**/uevent r, @{sys}/devices/system/cpu/cpufreq/policy@{int}/energy_performance_preference rw, - @{sys}/devices/virtual/dmi/id/product_version r, - @{sys}/devices/virtual/net/**/uevent r, @{sys}/firmware/acpi/platform_profile* rw, @{sys}/firmware/acpi/pm_profile* rw, @{sys}/module/*/parameters/power_save rw, @@ -104,7 +111,9 @@ profile tlp @{exec_path} flags=(attach_disconnected) { include include - @{run}/tlp/lock_tlp rw, + @{run}/tlp/lock_tlp rw, # file_inherit + + @{run}/udev/data/b@{int}:* r, # For block devices include if exists } diff --git a/apparmor.d/profiles-s-z/tomb b/apparmor.d/profiles-s-z/tomb index 0b35cff02d..df4258b8c4 100644 --- a/apparmor.d/profiles-s-z/tomb +++ b/apparmor.d/profiles-s-z/tomb @@ -21,13 +21,14 @@ profile tomb @{exec_path} { capability sys_rawio, signal send set=cont peer=gpg, + signal send set=cont peer=pinentry-*, ptrace read peer=@{p_systemd_user}, @{exec_path} mr, @{bin}/{,e,f}grep rix, - @{bin}/awk rix, + @{bin}/{m,g,}awk rix, @{bin}/basename rix, @{bin}/cat rix, @{bin}/chmod rix, @@ -41,14 +42,13 @@ profile tomb @{exec_path} { @{bin}/env rix, @{bin}/file rix, @{bin}/findmnt rix, - @{bin}/gawk rix, @{bin}/getent rix, @{bin}/gettext rix, + @{bin}/head rix, @{bin}/hostname rix, @{bin}/id rix, @{bin}/kill rix, @{bin}/locate rix, - @{bin}/losetup rix, @{bin}/ls rix, @{bin}/lsof rix, @{bin}/mkdir rix, @@ -65,24 +65,25 @@ profile tomb @{exec_path} { @{bin}/touch rix, @{bin}/tr rix, @{bin}/zsh rix, + @{sbin}/losetup rix, - @{bin}/btrfs rPx, - @{bin}/cryptsetup rPUx, - @{bin}/e2fsc rPUx, - @{bin}/fsck rPx, + @{sbin}/btrfs rPx, + @{sbin}/cryptsetup rPUx, + @{sbin}/e2fsck rPx, + @{sbin}/fsck rPx, @{bin}/gpg{,2} rPx, @{bin}/lsblk rPx, - @{bin}/mkfs.* rPUx, + @{sbin}/mkfs.* rPUx, @{bin}/mount rPx, @{bin}/pinentry rPx, @{bin}/pinentry-* rPx, @{bin}/qrencode rPx, - @{bin}/resize2fs rPx, + @{sbin}/resize2fs rPx, @{bin}/tomb-kdb-pbkdf2 rPUx, - @{bin}/tune2fs rPx, + @{sbin}/tune2fs rPx, @{bin}/umount rCx -> umount, @{bin}/updatedb.mlocate rPx, - @{bin}/zramctl rPx, + @{sbin}/zramctl rPx, /usr/share/file/** r, /usr/share/terminfo/** r, diff --git a/apparmor.d/profiles-s-z/torsocks b/apparmor.d/profiles-s-z/torsocks index c7c914387f..ad258189cc 100644 --- a/apparmor.d/profiles-s-z/torsocks +++ b/apparmor.d/profiles-s-z/torsocks @@ -19,7 +19,7 @@ profile torsocks @{exec_path} { @{sh_path} rix, @{bin}/* rPUx, @{lib}/uwt/uwtexec rPUx, - @{bin}/getcap rix, + @{sbin}/getcap rix, /etc/tor/torsocks.conf r, diff --git a/apparmor.d/profiles-s-z/totem b/apparmor.d/profiles-s-z/totem index 64ab228ba9..f23dfcdf80 100644 --- a/apparmor.d/profiles-s-z/totem +++ b/apparmor.d/profiles-s-z/totem @@ -10,17 +10,22 @@ include profile totem @{exec_path} flags=(attach_disconnected) { include include - include - include include include + include + include + include + include + include + include include network netlink raw, signal (send) set=(kill) peer=totem//bwrap, - #aa:dbus own bus=session name=org.mpris.MediaPlayer2.totem + #aa:dbus own bus=session name=org.gnome.Totem + #aa:dbus talk bus=session name=org.gnome.Nautilus label=nautilus #aa:dbus talk bus=session name=org.gnome.OnlineAccounts label=goa-daemon #aa:dbus talk bus=session name=org.gtk.vfs label="gvfsd{,-*}" @@ -45,6 +50,7 @@ profile totem @{exec_path} flags=(attach_disconnected) { owner @{user_cache_dirs}/gnome-desktop-thumbnailer/gstreamer-1.0/{,**} r, owner @{user_share_dirs}/grilo-plugins/ rw, owner @{user_share_dirs}/grilo-plugins/** rwlk, + owner @{user_share_dirs}/gvfs-metadata/* r, owner @{tmp}/flatpak-seccomp-@{rand6} rw, owner @{tmp}/gnome-desktop-thumbnailer-@{rand6}/{,**} rw, @@ -56,17 +62,18 @@ profile totem @{exec_path} flags=(attach_disconnected) { owner @{PROC}/@{pid}/mountinfo r, - deny @{user_share_dirs}/gvfs-metadata/* r, - profile bwrap flags=(attach_disconnected) { include - include + include include - include include include capability dac_override, + capability sys_ptrace, + + network inet dgram, + network inet6 dgram, @{bin}/bwrap mr, @{bin}/totem-video-thumbnailer rix, @@ -78,8 +85,11 @@ profile totem @{exec_path} flags=(attach_disconnected) { owner @{tmp}/flatpak-seccomp-@{rand6} rw, owner @{tmp}/gnome-desktop-file-to-thumbnail.* rw, owner @{tmp}/gnome-desktop-thumbnailer-@{rand6}/{,**} rw, + owner @{tmp}/gnome-desktop-thumbnailer.png rw, @{PROC}/sys/vm/mmap_min_addr r, + owner @{PROC}/@{pid}/mountinfo r, + owner @{PROC}/@{pid}/stat r, owner @{PROC}/@{pid}/task/@{tid}/comm w, /dev/ r, diff --git a/apparmor.d/profiles-s-z/transmission b/apparmor.d/profiles-s-z/transmission index ad219f1ab8..992a72419b 100644 --- a/apparmor.d/profiles-s-z/transmission +++ b/apparmor.d/profiles-s-z/transmission @@ -9,15 +9,14 @@ include @{exec_path} = @{bin}/transmission-{gtk,qt} profile transmission @{exec_path} flags=(attach_disconnected) { include - include - include - include - include - include + include + include include include include + include include + include include include include @@ -30,7 +29,6 @@ profile transmission @{exec_path} flags=(attach_disconnected) { #aa:dbus own bus=session name=com.transmissionbt.Transmission #aa:dbus own bus=session name=com.transmissionbt.transmission_* - #aa:dbus talk bus=session name=org.gtk.vfs label="gvfsd{,-*}" @{exec_path} mr, @@ -62,8 +60,6 @@ profile transmission @{exec_path} flags=(attach_disconnected) { owner @{PROC}/@{pid}/stat r, owner @{PROC}/@{pid}/task/@{tid}/comm rw, - deny @{user_share_dirs}/gvfs-metadata/* r, - include if exists } diff --git a/apparmor.d/profiles-s-z/u-d-c-print-pci-ids b/apparmor.d/profiles-s-z/u-d-c-print-pci-ids new file mode 100644 index 0000000000..2ae7f66ef3 --- /dev/null +++ b/apparmor.d/profiles-s-z/u-d-c-print-pci-ids @@ -0,0 +1,19 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{sbin}/u-d-c-print-pci-ids +profile u-d-c-print-pci-ids @{exec_path} { + include + + @{exec_path} mr, + @{sh_path} r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-s-z/ucf b/apparmor.d/profiles-s-z/ucf index 4fdbb5a523..2735d882af 100644 --- a/apparmor.d/profiles-s-z/ucf +++ b/apparmor.d/profiles-s-z/ucf @@ -10,18 +10,23 @@ include @{exec_path} = @{bin}/ucf profile ucf @{exec_path} { include + include include include - @{exec_path} r, + capability dac_read_search, + + mqueue getattr type=posix, + + @{exec_path} rix, @{sh_path} rix, @{bin}/{,e}grep rix, + @{bin}/{m,g,}awk rix, @{bin}/basename rix, @{bin}/cat rix, @{bin}/cp rix, @{bin}/dirname rix, - @{bin}/{m,g,}awk rix, @{bin}/getopt rix, @{bin}/id rix, @{bin}/md5sum rix, @@ -32,28 +37,35 @@ profile ucf @{exec_path} { @{bin}/sed rix, @{bin}/seq rix, @{bin}/stat rix, + @{bin}/stty rix, @{bin}/tr rix, - @{bin}/which{,.debianutils} rix, + @{bin}/which{,.debianutils} rix, @{bin}/dpkg-query rpx, @{bin}/dpkg-divert rPx, @{pager_path} rCx -> child-pager, - /usr/share/debconf/frontend rPx, # TODO: rCx -> debonc-frontend, - # For md5sum /usr/share/** r, # For writing new config files - /etc/** rw, + /etc/** rw, #aa:lint ignore=too-wide # For shell pwd / r, /root/ r, + /var/lib/dpkg/info/ucf.templates r, + owner /var/lib/ucf/** rw, - owner /tmp/tmp.@{rand10} r, + /tmp/@{rand10} r, + /tmp/grub.@{rand10} r, + /tmp/tmp.@{rand10} r, + + @{PROC}/@{pid}/mountinfo r, + + deny capability sys_admin, # optional: no audit include if exists } diff --git a/apparmor.d/profiles-s-z/ucfq b/apparmor.d/profiles-s-z/ucfq new file mode 100644 index 0000000000..bf65d66d0a --- /dev/null +++ b/apparmor.d/profiles-s-z/ucfq @@ -0,0 +1,27 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/ucfq +profile ucfq @{exec_path} { + include + include + + @{exec_path} mr, + + @{bin}/md5sum rix, + + /etc/ r, + /etc/default/ r, + /etc/default/grub r, + + /var/lib/ucf/* r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-s-z/ucfr b/apparmor.d/profiles-s-z/ucfr new file mode 100644 index 0000000000..3b9a518c62 --- /dev/null +++ b/apparmor.d/profiles-s-z/ucfr @@ -0,0 +1,43 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/ucfr +profile ucfr @{exec_path} { + include + include + + @{exec_path} mr, + + @{sh_path} r, + @{bin}/{,e}grep ix, + @{bin}/{m,g,}awk ix, + @{bin}/basename ix, + @{bin}/cp ix, + @{bin}/dirname ix, + @{bin}/getopt ix, + @{bin}/id ix, + @{bin}/mv ix, + @{bin}/readlink ix, + @{bin}/sed ix, + @{bin}/seq ix, + + /usr/share/ucf/{,**} r, + + /etc/ucf.conf r, + + / r, + + /var/lib/ucf/ r, + /var/lib/ucf/registry r, + /var/lib/ucf/registry.@{int} rw, + /var/lib/ucf/registry.tmp rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-s-z/udev-ata_id b/apparmor.d/profiles-s-z/udev-ata_id new file mode 100644 index 0000000000..d41629bed4 --- /dev/null +++ b/apparmor.d/profiles-s-z/udev-ata_id @@ -0,0 +1,25 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/udev/ata_id +profile udev-ata_id @{exec_path} { + include + include + + capability sys_rawio, + + @{exec_path} mr, + + /etc/udev/udev.conf r, + + / r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-s-z/udev-bcache-export-cached b/apparmor.d/profiles-s-z/udev-bcache-export-cached new file mode 100644 index 0000000000..e42b10c26e --- /dev/null +++ b/apparmor.d/profiles-s-z/udev-bcache-export-cached @@ -0,0 +1,23 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/udev/bcache-export-cached +profile udev-bcache-export-cached @{exec_path} { + include + include + + @{exec_path} mr, + + @{sh_path} rix, + @{bin}/{m,g,}awk rix, + @{sbin}/bcache-super-show rix, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-s-z/udev-bridge-network-interface b/apparmor.d/profiles-s-z/udev-bridge-network-interface new file mode 100644 index 0000000000..7e3ba52f97 --- /dev/null +++ b/apparmor.d/profiles-s-z/udev-bridge-network-interface @@ -0,0 +1,21 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/udev/bridge-network-interface +profile udev-bridge-network-interface @{exec_path} { + include + + @{exec_path} mr, + @{sh_path} r, + + /etc/default/bridge-utils r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-s-z/udev-cdrom_id b/apparmor.d/profiles-s-z/udev-cdrom_id new file mode 100644 index 0000000000..ecfc5d902b --- /dev/null +++ b/apparmor.d/profiles-s-z/udev-cdrom_id @@ -0,0 +1,26 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/udev/cdrom_id +profile udev-cdrom_id @{exec_path} { + include + + capability sys_rawio, + + @{exec_path} mr, + + / r, + + /etc/udev/udev.conf r, + + /dev/sr@{int} r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-s-z/udev-dmi-memory-id b/apparmor.d/profiles-s-z/udev-dmi-memory-id index 1d6580311f..19d859992d 100644 --- a/apparmor.d/profiles-s-z/udev-dmi-memory-id +++ b/apparmor.d/profiles-s-z/udev-dmi-memory-id @@ -14,6 +14,8 @@ profile udev-dmi-memory-id @{exec_path} { /etc/udev/udev.conf r, + / r, + @{sys}/firmware/dmi/tables/DMI r, @{sys}/firmware/dmi/tables/smbios_entry_point r, diff --git a/apparmor.d/profiles-s-z/udev-fido_id b/apparmor.d/profiles-s-z/udev-fido_id new file mode 100644 index 0000000000..9a264fabd1 --- /dev/null +++ b/apparmor.d/profiles-s-z/udev-fido_id @@ -0,0 +1,28 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/udev/fido_id +profile udev-fido_id @{exec_path} { + include + include + + @{exec_path} mr, + + /etc/udev/udev.conf r, + /etc/udev/udev.conf.d/{,**} r, + + / r, + + @{sys}/devices/@{pci}/report_descriptor r, + @{sys}/devices/platform/**/report_descriptor r, + @{sys}/devices/virtual/**/report_descriptor r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-s-z/udev-hdparm b/apparmor.d/profiles-s-z/udev-hdparm new file mode 100644 index 0000000000..bca98163b6 --- /dev/null +++ b/apparmor.d/profiles-s-z/udev-hdparm @@ -0,0 +1,28 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/udev/hdparm +profile udev-hdparm @{exec_path} { + include + + @{exec_path} mr, + + @{sh_path} rix, + @{bin}/{,e}grep rix, + @{bin}/sed rix, + @{bin}/udevadm rPx, + + /etc/hdparm.conf r, + + @{PROC}/cmdline r, + @{PROC}/mdstat r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-s-z/udev-probe-bcache b/apparmor.d/profiles-s-z/udev-probe-bcache new file mode 100644 index 0000000000..e02e070a84 --- /dev/null +++ b/apparmor.d/profiles-s-z/udev-probe-bcache @@ -0,0 +1,21 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{lib}/udev/probe-bcache +profile udev-probe-bcache @{exec_path} { + include + include + + capability sys_rawio, + + @{exec_path} mr, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-s-z/unhide-tcp b/apparmor.d/profiles-s-z/unhide-tcp index c4b30b8849..8827bca14b 100644 --- a/apparmor.d/profiles-s-z/unhide-tcp +++ b/apparmor.d/profiles-s-z/unhide-tcp @@ -22,7 +22,7 @@ profile unhide-tcp @{exec_path} { @{bin}/fuser rix, @{bin}/netstat rix, @{bin}/sed rix, - @{bin}/ss rix, + @{sbin}/ss rix, @{PROC}/@{pids}/net/tcp{,6} r, @{PROC}/@{pids}/net/udp{,6} r, diff --git a/apparmor.d/profiles-s-z/unix-chkpwd b/apparmor.d/profiles-s-z/unix-chkpwd index 85b99b8abd..a73eb594a0 100644 --- a/apparmor.d/profiles-s-z/unix-chkpwd +++ b/apparmor.d/profiles-s-z/unix-chkpwd @@ -7,13 +7,14 @@ abi , include -@{exec_path} = @{bin}/unix_chkpwd -profile unix-chkpwd @{exec_path} { +@{exec_path} = @{sbin}/unix_chkpwd +profile unix-chkpwd @{exec_path} flags=(attach_disconnected) { include include include capability audit_write, + capability dac_read_search, # To read shadow with 000 permissions. network netlink raw, @@ -26,8 +27,6 @@ profile unix-chkpwd @{exec_path} { @{run}/host/userdb/*.user r, @{run}/host/userdb/*.user-privileged r, - owner /dev/tty@{int} rw, - include if exists } diff --git a/apparmor.d/profiles-s-z/unmkinitramfs b/apparmor.d/profiles-s-z/unmkinitramfs index 6b5607ed17..c387049445 100644 --- a/apparmor.d/profiles-s-z/unmkinitramfs +++ b/apparmor.d/profiles-s-z/unmkinitramfs @@ -18,25 +18,22 @@ profile unmkinitramfs @{exec_path} { @{exec_path} r, @{sh_path} rix, + @{archive_path} rix, + @{bin}/{,3}cpio rix, @{bin}/{,e}grep rix, - @{bin}/bzip2 rix, @{bin}/cat rix, - @{bin}/cpio rix, @{bin}/dd rix, @{bin}/getopt rix, - @{bin}/gzip rix, @{bin}/lz4cat rix, @{bin}/lzma rix, @{bin}/lzop rix, @{bin}/mkdir rix, @{bin}/mktemp rix, @{bin}/rm rix, - @{bin}/xz rix, @{bin}/xzcat rix, - @{bin}/zstd rix, - /boot/ r, - owner /boot/initrd.img-* r, + @{efi}/ r, + owner @{efi}/initrd.img-* r, /tmp/ r, owner @{tmp}/initrd.img-* r, /mnt/ r, diff --git a/apparmor.d/profiles-s-z/update-alternatives b/apparmor.d/profiles-s-z/update-alternatives index 8f08b74fa0..da18008b63 100644 --- a/apparmor.d/profiles-s-z/update-alternatives +++ b/apparmor.d/profiles-s-z/update-alternatives @@ -23,6 +23,7 @@ profile update-alternatives @{exec_path} { /usr/** rw, /etc/**.dpkg-tmp rw, + /etc/pam.d/gdm-smartcard w, /etc/alternatives/* rw, /var/lib/dpkg/alternatives/ r, diff --git a/apparmor.d/profiles-s-z/update-ca-certificates b/apparmor.d/profiles-s-z/update-ca-certificates index b496777e94..9ff72ef2bb 100644 --- a/apparmor.d/profiles-s-z/update-ca-certificates +++ b/apparmor.d/profiles-s-z/update-ca-certificates @@ -7,10 +7,11 @@ abi , include -@{exec_path} = @{bin}/update-ca-certificates +@{exec_path} = @{sbin}/update-ca-certificates profile update-ca-certificates @{exec_path} { include include + include include @{exec_path} rmix, @@ -19,15 +20,18 @@ profile update-ca-certificates @{exec_path} { @{bin}/basename rix, @{bin}/cat rix, @{bin}/chmod rix, + @{bin}/dpkg-trigger rPx, @{bin}/find rix, @{bin}/flock rix, @{bin}/install rix, @{bin}/ln rix, + @{bin}/mkdir rix, @{bin}/mktemp rix, @{bin}/mv rix, @{bin}/openssl rix, @{bin}/readlink rix, @{bin}/rm rix, + @{bin}/run-parts rix, @{bin}/sed rix, @{bin}/sort rix, @{bin}/test rix, @@ -39,17 +43,21 @@ profile update-ca-certificates @{exec_path} { /etc/ca-certificates/update.d/ r, /etc/ca-certificates/update.d/* rix, - /usr/share/p11-kit/modules/{,*} r, - /etc/ r, /etc/ca-certificates.conf r, /etc/ssl/certs/ca-certificates.crt{,.new} rw, /etc/ssl/certs/*.pem rw, /etc/ssl/certs/@{hex}.@{d} rw, + /var/ r, + /var/lib/ r, + /var/lib/ca-certificates/ rwk, /var/lib/ca-certificates/** rw, + /var/lib/ca-certificates-java/ rwk, + /var/lib/ca-certificates-java/** rw, + / r, /tmp/ r, diff --git a/apparmor.d/profiles-s-z/update-ca-trust b/apparmor.d/profiles-s-z/update-ca-trust index c0f220919b..5044822bd7 100644 --- a/apparmor.d/profiles-s-z/update-ca-trust +++ b/apparmor.d/profiles-s-z/update-ca-trust @@ -9,6 +9,8 @@ include @{exec_path} = @{bin}/update-ca-trust profile update-ca-trust @{exec_path} { include + include + include include capability dac_read_search, @@ -22,7 +24,6 @@ profile update-ca-trust @{exec_path} { @{bin}/trust rix, / r, - /usr/share/p11-kit/modules/{,*} r, /etc/ca-certificates/extracted/** rw, /etc/ssl/certs/{,*} rw, diff --git a/apparmor.d/profiles-s-z/update-catalog b/apparmor.d/profiles-s-z/update-catalog new file mode 100644 index 0000000000..24c7681cfa --- /dev/null +++ b/apparmor.d/profiles-s-z/update-catalog @@ -0,0 +1,27 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{sbin}/update-catalog +profile update-catalog @{exec_path} { + include + include + include + + @{exec_path} mr, + + /etc/sgml/ r, + /etc/sgml/* r, + + /var/lib/sgml-base/*catalog rw, + /var/lib/sgml-base/*catalog.new rw, + /var/lib/sgml-base/*catalog.old w, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-s-z/update-cracklib b/apparmor.d/profiles-s-z/update-cracklib index 9bef23a77f..8f848b0ada 100644 --- a/apparmor.d/profiles-s-z/update-cracklib +++ b/apparmor.d/profiles-s-z/update-cracklib @@ -6,7 +6,7 @@ abi , include -@{exec_path} = @{bin}/update-cracklib +@{exec_path} = @{sbin}/update-cracklib profile update-cracklib @{exec_path} { include include @@ -16,12 +16,12 @@ profile update-cracklib @{exec_path} { @{exec_path} mr, @{sh_path} rix, - @{bin}/cracklib-format rix, - @{bin}/cracklib-packer rPx, + @{sbin}/cracklib-format rix, + @{sbin}/cracklib-packer rPx, @{bin}/env rix, @{bin}/file rix, @{bin}/find rix, - @{bin}/grep rix, + @{bin}/{,e}grep rix, @{bin}/gzip rix, @{bin}/install rix, @{bin}/install rix, diff --git a/apparmor.d/profiles-s-z/update-dlocatedb b/apparmor.d/profiles-s-z/update-dlocatedb index 2afe8a22f0..e9d92e421f 100644 --- a/apparmor.d/profiles-s-z/update-dlocatedb +++ b/apparmor.d/profiles-s-z/update-dlocatedb @@ -26,7 +26,7 @@ profile update-dlocatedb @{exec_path} { /usr/share/dlocate/updatedb rCx -> updatedb, @{bin}/dpkg rPx -> child-dpkg, - owner @{PROC}/@{pid}/fd/2 w, + owner @{PROC}/@{pid}/fd/@{int} w, /var/lib/dlocate/dpkg-list w, diff --git a/apparmor.d/profiles-s-z/update-info-dir b/apparmor.d/profiles-s-z/update-info-dir new file mode 100644 index 0000000000..62f693e895 --- /dev/null +++ b/apparmor.d/profiles-s-z/update-info-dir @@ -0,0 +1,35 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{sbin}/update-info-dir +profile update-info-dir @{exec_path} { + include + include + + capability dac_read_search, + + @{exec_path} mr, + + @{sh_path} r, + @{bin}/cp ix, + @{bin}/find ix, + @{bin}/install-info Px, + @{bin}/rm ix, + + /usr/share/info/ r, + /usr/share/info/dir rw, + /usr/share/info/dir.old w, + + /etc/environment r, + + / r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-s-z/update-initramfs b/apparmor.d/profiles-s-z/update-initramfs index 6948f28127..fe38df2859 100644 --- a/apparmor.d/profiles-s-z/update-initramfs +++ b/apparmor.d/profiles-s-z/update-initramfs @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/update-initramfs +@{exec_path} = @{sbin}/update-initramfs profile update-initramfs @{exec_path} { include include @@ -22,17 +22,23 @@ profile update-initramfs @{exec_path} { @{bin}/cat rix, @{bin}/{m,g,}awk rix, @{bin}/getopt rix, - @{bin}/ischroot rix, @{bin}/ln rix, @{bin}/mv rix, @{bin}/rm rix, @{bin}/sha1sum rix, @{bin}/sync rix, @{bin}/uname rix, + @{bin}/run-parts rix, @{bin}/dpkg-trigger rPx, + @{bin}/dracut rPUx, + @{bin}/ischroot rPx, + @{bin}/limine-mkinitcpio rPUx, @{bin}/linux-version rPx, - @{bin}/mkinitramfs rPx, + @{sbin}/mkinitramfs rPx, + + /etc/initramfs/post-update.d/ r, + /etc/initramfs/post-update.d/* rPUx, /var/lib/initramfs-tools/* w, @@ -47,9 +53,9 @@ profile update-initramfs @{exec_path} { owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/mounts r, - owner /boot/ r, - owner /boot/initrd.img-* rw, - owner /boot/initrd.img-*.dpkg-bak rwl -> /boot/initrd.img-*, + owner @{efi}/ r, + owner @{efi}/initrd.img-* rw, + owner @{efi}/initrd.img-*.dpkg-bak rwl -> @{efi}/initrd.img-*, include if exists } diff --git a/apparmor.d/profiles-s-z/update-pciids b/apparmor.d/profiles-s-z/update-pciids index d2e36ead0c..901dae9a0a 100644 --- a/apparmor.d/profiles-s-z/update-pciids +++ b/apparmor.d/profiles-s-z/update-pciids @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/update-pciids +@{exec_path} = @{sbin}/update-pciids profile update-pciids @{exec_path} { include include @@ -24,7 +24,7 @@ profile update-pciids @{exec_path} { @{bin}/chmod rix, @{bin}/echo rix, @{bin}/cat rix, - @{bin}/which{,.debianutils} rix, + @{bin}/which{,.debianutils} rix, @{bin}/bunzip2 rix, @{bin}/bzip2 rix, @{bin}/gzip rix, diff --git a/apparmor.d/profiles-s-z/update-secureboot-policy b/apparmor.d/profiles-s-z/update-secureboot-policy index e5ffca44f4..31a03ef7be 100644 --- a/apparmor.d/profiles-s-z/update-secureboot-policy +++ b/apparmor.d/profiles-s-z/update-secureboot-policy @@ -7,28 +7,24 @@ abi , include -@{exec_path} = @{bin}/update-secureboot-policy +@{exec_path} = @{sbin}/update-secureboot-policy profile update-secureboot-policy @{exec_path} { include - include + include @{exec_path} rm, - @{sh_path} rix, - @{bin}/{,m,g}awk rix, - @{bin}/dpkg-trigger rPx, - @{bin}/find rix, - @{bin}/id rix, - @{bin}/od rix, - @{bin}/sort rix, - @{bin}/touch rix, - @{bin}/wc rix, - /usr/share/debconf/frontend rPx, + @{bin}/{,m,g}awk ix, + @{bin}/dpkg-trigger Px, + @{bin}/find ix, + @{bin}/id ix, + @{bin}/od ix, + @{bin}/sort ix, + @{bin}/touch ix, + @{bin}/wc ix, / r, - /usr/share/debconf/confmodule r, - /var/lib/dkms/ r, /var/lib/shim-signed/dkms-list rw, diff --git a/apparmor.d/profiles-s-z/update-shells b/apparmor.d/profiles-s-z/update-shells new file mode 100644 index 0000000000..cbc7c1c7fb --- /dev/null +++ b/apparmor.d/profiles-s-z/update-shells @@ -0,0 +1,42 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{sbin}/update-shells +profile update-shells @{exec_path} { + include + include + include + + @{exec_path} mr, + + @{sh_path} r, + @{bin}/basename ix, + @{bin}/chmod ix, + @{bin}/chown ix, + @{bin}/dirname ix, + @{bin}/dpkg-realpath rix, + @{bin}/mv ix, + @{bin}/sync ix, + @{bin}/readlink ix, + + /usr/share/debianutils/shells r, + /usr/share/debianutils/shells.d/{,**} r, + /usr/share/dpkg/sh/dpkg-error.sh r, + + /etc/ r, + /etc/shells rw, + /etc/shells.tmp rw, + + /var/lib/ r, + /var/lib/shells.state rw, + /var/lib/shells.state.tmp rw, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-s-z/update-smart-drivedb b/apparmor.d/profiles-s-z/update-smart-drivedb index 2ce61cebfe..5ec8a45c0e 100644 --- a/apparmor.d/profiles-s-z/update-smart-drivedb +++ b/apparmor.d/profiles-s-z/update-smart-drivedb @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/update-smart-drivedb +@{exec_path} = @{sbin}/update-smart-drivedb profile update-smart-drivedb @{exec_path} { include include @@ -28,7 +28,7 @@ profile update-smart-drivedb @{exec_path} { @{bin}/cmp rix, @{bin}/ r, - @{bin}/smartctl rPx, + @{sbin}/smartctl rPx, @{bin}/gpg{,2} rCx -> gpg, @{bin}/wget rCx -> browse, @@ -64,6 +64,7 @@ profile update-smart-drivedb @{exec_path} { profile browse { include include + include include include @@ -78,7 +79,6 @@ profile update-smart-drivedb @{exec_path} { @{sh_path} rix, - /etc/mime.types r, /etc/mailcap r, /etc/lynx/* r, diff --git a/apparmor.d/profiles-s-z/updatedb-mlocate b/apparmor.d/profiles-s-z/updatedb-mlocate index 7a951b7e74..518a8d7df4 100644 --- a/apparmor.d/profiles-s-z/updatedb-mlocate +++ b/apparmor.d/profiles-s-z/updatedb-mlocate @@ -19,13 +19,13 @@ profile updatedb-mlocate @{exec_path} { @{exec_path} mr, - @{bin}/on_ac_power rPx, + @{sbin}/on_ac_power rPx, # For shell pwd / r, - /boot/ r, - /boot/**/ r, + @{efi}/ r, + @{efi}/**/ r, /home/ r, @{HOME}/ r, @@ -47,7 +47,7 @@ profile updatedb-mlocate @{exec_path} { /srv/**/ r, # Silence the noise - deny /efi/ r, + deny @{efi}/ r, deny /hugepages/ r, deny /lost+found/ r, deny /mnt/ r, diff --git a/apparmor.d/profiles-s-z/uupdate b/apparmor.d/profiles-s-z/uupdate index 8858a80f13..88a6cd4065 100644 --- a/apparmor.d/profiles-s-z/uupdate +++ b/apparmor.d/profiles-s-z/uupdate @@ -18,7 +18,7 @@ profile uupdate @{exec_path} flags=(complain) { @{sh_path} rix, @{bin}/basename rix, - @{bin}/which{,.debianutils} rix, + @{bin}/which{,.debianutils} rix, @{bin}/tr rix, @{bin}/{,e}grep rix, @{bin}/getopt rix, diff --git a/apparmor.d/profiles-s-z/v4l2-ctl b/apparmor.d/profiles-s-z/v4l2-ctl new file mode 100644 index 0000000000..ddb86b9a2d --- /dev/null +++ b/apparmor.d/profiles-s-z/v4l2-ctl @@ -0,0 +1,21 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Roman Beslik +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/v4l2-ctl +profile v4l2-ctl @{exec_path} { + include + include + include + include + + @{exec_path} mr, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-s-z/veracrypt b/apparmor.d/profiles-s-z/veracrypt index 6612846cde..42bf034312 100644 --- a/apparmor.d/profiles-s-z/veracrypt +++ b/apparmor.d/profiles-s-z/veracrypt @@ -7,15 +7,15 @@ abi , include @{exec_path} = @{bin}/veracrypt -profile veracrypt @{exec_path} { +profile veracrypt @{exec_path} flags=(attach_disconnected) { include - include - include + include include include include include include + include capability chown, capability dac_read_search, @@ -27,25 +27,25 @@ profile veracrypt @{exec_path} { @{exec_path} mrix, - @{sh_path} rix, - @{open_path} rPx -> child-open-help, - @{bin}/dmsetup rPx, - @{bin}/grep rix, - @{bin}/kmod rix, - @{bin}/ldconfig rix, - @{bin}/losetup rCx -> losetup, - @{bin}/mount rPx, - @{bin}/sudo rix, - @{bin}/umount rCx -> umount, - @{bin}/wc rix, + @{sh_path} rix, + @{open_path} rPx -> child-open-help, + @{sbin}/dmsetup rPx, + @{bin}/{,e}grep rix, + @{bin}/kmod rCx -> kmod, + @{sbin}/ldconfig rix, + @{sbin}/ldconfig.real ix, + @{sbin}/losetup rCx -> losetup, + @{bin}/mount rPx, + @{bin}/sudo rCx -> sudo, + @{bin}/umount rCx -> umount, + @{bin}/wc rix, @{file_explorers_path} rPx, - /home/ r, - # Mount points @{MOUNTS}/ rw, @{MOUNTS}/*/ rw, + /home/ r, owner @{HOME}/ r, owner @{HOME}/.VeraCrypt-lock-@{user} rwk, @@ -55,10 +55,10 @@ profile veracrypt @{exec_path} { /tmp/.veracrypt_*/ rw, /tmp/.veracrypt_*/** rwk, - @{sys}/module/compression r, - @{sys}/module/dm_mod/initstate r, + /dev/shm/ r, @{PROC}/partitions r, + owner @{PROC}/@{pid}/cgroup r, owner @{PROC}/@{pid}/mounts r, /dev/fuse rw, @@ -85,11 +85,37 @@ profile veracrypt @{exec_path} { capability sys_rawio, - @{bin}/losetup mr, + @{sbin}/losetup mr, include if exists } + profile kmod { + include + include + + @{sys}/module/compression r, + @{sys}/module/dm_mod/initstate r, + + include if exists + } + + profile sudo { + include + include + + capability sys_ptrace, + + ptrace read peer=veracrypt, + + @{bin}/veracrypt Px, + + @{HOME}/.VeraCrypt-lock-@{user} w, + @{user_config_dirs}/VeraCrypt/.show-request-queue r, + + include if exists + } + include if exists } diff --git a/apparmor.d/profiles-s-z/vesktop b/apparmor.d/profiles-s-z/vesktop index b4b63fe746..eaced30326 100644 --- a/apparmor.d/profiles-s-z/vesktop +++ b/apparmor.d/profiles-s-z/vesktop @@ -8,11 +8,12 @@ abi , include @{name} = vesktop +@{domain} = org.chromium.Chromium @{lib_dirs} = @{lib}/@{name} @{config_dirs} = @{user_config_dirs}/@{name} @{cache_dirs} = @{user_cache_dirs}/@{name} -@{exec_path} = @{bin}/vesktop +@{exec_path} = @{bin}/vesktop @{lib_dirs}/vesktop profile vesktop @{exec_path} flags=(attach_disconnected) { include include @@ -21,6 +22,7 @@ profile vesktop @{exec_path} flags=(attach_disconnected) { include include include + include network inet dgram, network inet6 dgram, @@ -28,23 +30,23 @@ profile vesktop @{exec_path} flags=(attach_disconnected) { network inet6 stream, network netlink raw, - @{exec_path} mr, + @{exec_path} mrix, @{bin}/speech-dispatcher rPx, - @{open_path} rPx -> child-open, + @{open_path} rPx -> child-open-strict, - owner /tmp/.org.chromium.Chromium.@{rand6} mr, + owner @{user_videos_dirs}/{,**} rwl, + owner @{user_pictures_dirs}/{,**} rwl, + + owner /tmp/.org.chromium.Chromium.* rwm, owner @{run}/user/@{uid}/discord-ipc-@{int} rw, @{sys}/devices/@{pci}/usb@{int}/**/interface r, - @{PROC}/@{pid}/cmdline r, - owner @{PROC}/@{pid}/task/@{tid}/comm rw, - owner /dev/ r, deny /dev/tty rw, - deny owner /dev/tty@{int} rw, + deny owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-s-z/vidcutter b/apparmor.d/profiles-s-z/vidcutter index 1460fb1a7a..f281048c47 100644 --- a/apparmor.d/profiles-s-z/vidcutter +++ b/apparmor.d/profiles-s-z/vidcutter @@ -28,7 +28,7 @@ profile vidcutter @{exec_path} { @{python_path} r, @{bin}/ r, - @{bin}/ldconfig rix, + @{sbin}/ldconfig rix, @{bin}/ffmpeg rPx, @{bin}/ffprobe rPx, @@ -66,7 +66,7 @@ profile vidcutter @{exec_path} { /dev/shm/#@{int} rw, /dev/disk/*/ r, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-s-z/virt-manager b/apparmor.d/profiles-s-z/virt-manager index 614084c715..a6a06c9ab8 100644 --- a/apparmor.d/profiles-s-z/virt-manager +++ b/apparmor.d/profiles-s-z/virt-manager @@ -12,15 +12,20 @@ include profile virt-manager @{exec_path} flags=(attach_disconnected) { include include + include include include include include include include + include + include include include include + include + include include include @@ -28,6 +33,11 @@ profile virt-manager @{exec_path} flags=(attach_disconnected) { network inet6 stream, network netlink raw, + unix type=stream peer=(label=libvirt-*), + unix type=stream peer=(label=libvirtd), + + #aa:dbus own bus=session name=org.virt-manager.virt-manager + @{exec_path} rix, @{sh_path} rix, @@ -39,13 +49,12 @@ profile virt-manager @{exec_path} flags=(attach_disconnected) { @{bin}/getfacl rix, @{bin}/setfacl rix, - @{bin}/libvirtd rPx, + @{sbin}/libvirtd rPx, @{bin}/ssh rPx, @{lib}/spice-client-glib-usb-acl-helper rPx, @{open_path} rPx -> child-open, - /usr/share/gtksourceview-4/{,**} r, /usr/share/ladspa/rdf/{,ladspa.rdfs} r, /usr/share/misc/*.ids r, /usr/share/osinfo/{,**} r, @@ -71,20 +80,19 @@ profile virt-manager @{exec_path} flags=(attach_disconnected) { owner @{user_cache_dirs}/virt-manager/{,**} rw, # User VM images + @{user_vm_dirs}/{,**} rw, owner @{user_share_dirs}/ r, owner @{user_share_dirs}/libvirt/{,**} rw, - owner @{user_vm_dirs}/{,**} rw, owner @{run}/user/@{uid}/libvirt/libvirtd.lock rwk, owner @{run}/user/@{uid}/libvirt/virtqemud.lock rwk, + @{run}/libvirt/libvirt-sock rw, @{run}/mount/utab r, @{run}/udev/data/c@{dynamic}:@{int} r, # For dynamic assignment range 234 to 254, 384 to 511 - @{sys}/devices/**/hwmon/**/{,name,temp*,fan*} r, + @{sys}/devices/@{pci_bus}/uevent r, @{sys}/devices/virtual/drm/ttm/uevent r, - @{sys}/fs/cgroup/user.slice/cpu.max r, - @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/cpu.max r, @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/session-@{word}.scope/cpu.max r, @{PROC}/@{pids}/net/route r, @@ -95,12 +103,8 @@ 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, include if exists } diff --git a/apparmor.d/profiles-s-z/vlc b/apparmor.d/profiles-s-z/vlc index d572ce9b8a..55c131c101 100644 --- a/apparmor.d/profiles-s-z/vlc +++ b/apparmor.d/profiles-s-z/vlc @@ -8,26 +8,24 @@ abi , include @{exec_path} = @{bin}/{c,}vlc -profile vlc @{exec_path} { +profile vlc @{exec_path} flags=(attach_disconnected,mediate_deleted) { include include - include - include - include - include - include - include - include + include include include include include include include - include + include + include include include + include + include include + include include network inet dgram, @@ -36,13 +34,11 @@ profile vlc @{exec_path} { network inet6 stream, network netlink raw, - #aa:dbus own bus=session name=org.mpris.MediaPlayer2.vlc - #aa:dbus talk bus=session name=org.mpris.MediaPlayer2.Player label=unconfined - @{exec_path} mrix, @{open_path} rPx -> child-open-help, @{bin}/xdg-screensaver rPx, + @{bin}/proxy Cx -> proxy, /usr/share/vlc/{,**} r, @@ -75,23 +71,24 @@ profile vlc @{exec_path} { @{run}/mount/utab r, - @{sys}/devices/virtual/dmi/id/board_name r, - @{sys}/devices/virtual/dmi/id/board_vendor r, - @{sys}/devices/virtual/dmi/id/board_version r, - @{sys}/devices/virtual/dmi/id/product_name r, - @{sys}/devices/virtual/dmi/id/product_version r, - @{sys}/devices/virtual/dmi/id/sys_vendor r, - /dev/shm/#@{int} rw, /dev/snd/ r, /dev/tty r, - /dev/video@{int} rw, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, # Silencer deny @{lib}/@{multiarch}/vlc/{,**} w, deny @{user_share_dirs}/gvfs-metadata/{*,} r, + profile proxy { + include + include + + @{bin}/proxy mr, + + include if exists + } + include if exists } diff --git a/apparmor.d/profiles-s-z/vnstat b/apparmor.d/profiles-s-z/vnstat index edce318402..41fe8cc16a 100644 --- a/apparmor.d/profiles-s-z/vnstat +++ b/apparmor.d/profiles-s-z/vnstat @@ -11,6 +11,7 @@ include profile vnstat @{exec_path} { include include + include capability chown, capability dac_override, @@ -43,8 +44,7 @@ profile vnstat @{exec_path} { deny @{PROC}/uptime r, deny @{PROC}/diskstats r, deny @{PROC}/loadavg r, - deny @{sys}/devices/**/hwmon/**/temp*_input r, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, deny network inet dgram, deny network inet6 dgram, diff --git a/apparmor.d/profiles-s-z/volumeicon b/apparmor.d/profiles-s-z/volumeicon index e354c3cbd4..c76dc1562f 100644 --- a/apparmor.d/profiles-s-z/volumeicon +++ b/apparmor.d/profiles-s-z/volumeicon @@ -32,7 +32,7 @@ profile volumeicon @{exec_path} { owner @{user_config_dirs}/volumeicon/ rw, owner @{user_config_dirs}/volumeicon/volumeicon* rw, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-s-z/vsftpd b/apparmor.d/profiles-s-z/vsftpd index 2b6af35615..8fe33af50e 100644 --- a/apparmor.d/profiles-s-z/vsftpd +++ b/apparmor.d/profiles-s-z/vsftpd @@ -12,7 +12,7 @@ profile vsftpd @{exec_path} { include include include - include + include include # To be able to listen on ports < 1024 @@ -41,6 +41,12 @@ profile vsftpd @{exec_path} { capability dac_read_search, # If session_support=YES, vsftpd will also try and update utmp and wtmp + network inet dgram, + network inet stream, + network inet6 dgram, + network inet6 stream, + network netlink raw, + @{exec_path} mr, # To validate allowed users shells diff --git a/apparmor.d/profiles-s-z/w3m b/apparmor.d/profiles-s-z/w3m index ade896ea53..5a8393f513 100644 --- a/apparmor.d/profiles-s-z/w3m +++ b/apparmor.d/profiles-s-z/w3m @@ -11,6 +11,7 @@ include profile w3m @{exec_path} { include include + include include include include @@ -29,7 +30,6 @@ profile w3m @{exec_path} { /usr/share/terminfo/{,**} r, - /etc/mime.types r, /etc/w3m/{,**} r, owner @{HOME}/.w3m/{,**} rw, diff --git a/apparmor.d/profiles-s-z/waybar b/apparmor.d/profiles-s-z/waybar index b8d1d53261..52b9b60fe2 100644 --- a/apparmor.d/profiles-s-z/waybar +++ b/apparmor.d/profiles-s-z/waybar @@ -12,9 +12,11 @@ profile waybar @{exec_path} flags=(attach_disconnected) { include include include + include include include include + include network inet dgram, network inet6 dgram, @@ -23,15 +25,12 @@ profile waybar @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, /etc/machine-id r, + /etc/timezone r, owner @{user_config_dirs}/waybar/{,**} r, @{sys}/devices/@{pci}/uevent r, @{sys}/devices/system/cpu/present r, - @{sys}/devices/virtual/dmi/id/bios_vendor r, - @{sys}/devices/virtual/dmi/id/board_vendor r, - @{sys}/devices/virtual/dmi/id/product_name r, - @{sys}/devices/virtual/dmi/id/sys_vendor r, @{sys}/devices/virtual/dmi/id/uevent r, @{PROC}/@{pid}/net/dev r, @@ -40,7 +39,7 @@ profile waybar @{exec_path} flags=(attach_disconnected) { /dev/rfkill r, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-s-z/wechat b/apparmor.d/profiles-s-z/wechat old mode 100755 new mode 100644 index e23d4db43e..f6409fd906 --- a/apparmor.d/profiles-s-z/wechat +++ b/apparmor.d/profiles-s-z/wechat @@ -7,6 +7,7 @@ abi , include @{name} = wechat +@{domain} = org.chromium.Chromium @{lib_dirs} = /opt/wechat/ @{config_dirs} = @{user_config_dirs}/@{name} @{cache_dirs} = @{user_cache_dirs}/@{name} @@ -14,10 +15,9 @@ include @{exec_path} = @{lib_dirs}/wechat profile wechat @{exec_path} flags=(attach_disconnected) { include - include include include - include + include network netlink raw, network netlink dgram, @@ -28,14 +28,13 @@ profile wechat @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, - @{sh_path} rix, - @{lib_dirs}/crashpad_handler ix, - @{bin}/mkdir ix, - @{bin}/gawk rix, - @{bin}/lsblk rPx, - @{bin}/ip rix, - @{bin}/xdg-user-dir rix, - @{open_path} rpx -> child-open-strict, + @{sh_path} rix, + @{bin}/{m,g,}awk rix, + @{bin}/ip rix, + @{bin}/lsblk Px, + @{bin}/mkdir rix, + @{bin}/xdg-user-dir rix, + @{open_path} Px -> child-open-strict, owner @{HOME}/.xwechat/{,**} rwk, owner @{user_documents_dirs}/xwechat_files/{,**} rwk, diff --git a/apparmor.d/profiles-s-z/wechat-appimage b/apparmor.d/profiles-s-z/wechat-appimage index 88c44287d5..5f437fc18a 100755 --- a/apparmor.d/profiles-s-z/wechat-appimage +++ b/apparmor.d/profiles-s-z/wechat-appimage @@ -7,6 +7,7 @@ abi , include @{name} = wechat-appimage +@{domain} = org.chromium.Chromium @{lib_dirs} = /opt/wechat-appimage/ @{config_dirs} = @{user_config_dirs}/@{name} @{cache_dirs} = @{user_cache_dirs}/@{name} @@ -14,10 +15,11 @@ include @{exec_path} = @{bin}/wechat @{lib_dirs}/wechat-appimage.Appimage /tmp/.mount_wechat??????/user/bin/wechat profile wechat-appimage @{exec_path} flags=(attach_disconnected) { include - include include include - include + include + include + include network netlink raw, network netlink dgram, @@ -32,36 +34,25 @@ profile wechat-appimage @{exec_path} flags=(attach_disconnected) { @{exec_path} r, - @{sh_path} rix, - @{lib_dirs}/wechat-appimage.AppImage ix, - /tmp/.mount_wechat??????/AppRun ix, - @{bin}/mkdir ix, - @{bin}/gawk rix, - @{bin}/lsblk rPx, - @{bin}/ip rix, - @{bin}/xdg-user-dir rix, - @{tmp}/.mount_wechat@{word6}/opt/wechat/{,**} ix, - @{tmp}/.mount_wechat@{word6}/usr/bin/wechat ix, - @{open_path} rpx -> child-open-strict, + @{sh_path} rix, + @{bin}/dirname rix, + @{bin}/fusermount{,3} Cx -> fusermount, + @{bin}/lsblk Px, + @{bin}/xdg-user-dir rix, + @{bin}/ip rix, + @{lib_dirs}/wechat-appimage.AppImage ix, + @{open_path} Px -> child-open-strict, @{bin}/fusermount{,3} Cx -> fusermount, @{bin}/dirname rix, @{bin}/readlink rix, - @{bin}/ r, - @{bin}/*/ r, - /usr/local/bin/ r, - /usr/local/sbin/ r, - - /etc/machine-id r, - - @{tmp}/.mount_wechat@{word6}/AppRun r, - @{tmp}/.mount_wechat@{word6}/ rw, - @{tmp}/.mount_wechat@{word6}/opt/wechat/{,**} mr, - - owner /var/tmp/etilqs_* rw, + @{tmp}/.mount_wechat@{word6}/opt/wechat/{,**} ix, + @{tmp}/.mount_wechat@{word6}/usr/bin/wechat ix, + @{tmp}/.mount_wechat@{word6}/AppRun ix, @{HOME}/.xwechat/{,**} rwk, + owner @{user_documents_dirs}/xwechat_files/{,**} rwk, /dev/fuse rw, diff --git a/apparmor.d/profiles-s-z/wechat-universal b/apparmor.d/profiles-s-z/wechat-universal index 21e1eee10b..dacbc6e41e 100644 --- a/apparmor.d/profiles-s-z/wechat-universal +++ b/apparmor.d/profiles-s-z/wechat-universal @@ -7,6 +7,7 @@ abi , include @{name} = wechat-universal +@{domain} = org.chromium.Chromium @{lib_dirs} = /opt/wechat-universal/ @{config_dirs} = @{user_config_dirs}/@{name} @{cache_dirs} = @{user_cache_dirs}/@{name} @@ -14,11 +15,10 @@ include @{exec_path} = @{bin}/wechat-universal @{lib_dirs}/wechat profile wechat-universal @{exec_path} flags=(attach_disconnected) { include - include include + include include - include - include + include network netlink raw, network netlink dgram, @@ -29,25 +29,21 @@ profile wechat-universal @{exec_path} flags=(attach_disconnected) { @{exec_path} mrix, - @{sh_path} rix, - @{lib}/wechat-universal/common.sh ix, - @{bin}/sed ix, - @{bin}/ln ix, - @{bin}/mkdir ix, - @{bin}/lsblk Px, - @{bin}/bwrap rix, - @{bin}/xdg-user-dir rix, - @{lib_dirs}/crashpad_handler ix, - @{open_path} rPx -> child-open-strict, + @{sh_path} rix, + @{bin}/bwrap rix, + @{bin}/ln ix, + @{bin}/lsblk Px, + @{bin}/sed ix, + @{bin}/xdg-user-dir rix, + @{lib}/wechat-appimage.AppImage ix, + @{open_path} Px -> child-open-strict, /etc/lsb-release r, - /etc/machine-id r, - owner @{HOME}/@{XDG_DOCUMENTS_DIR}/WeChat_Data/{,**} rwk, + owner @{user_documents_dirs}/WeChat_Data/{,**} rwk, owner @{HOME}/.xwechat/{,**} rwk, owner @{HOME}/.sys1og.conf rw, - @{att}/@{run}/systemd/inhibit/@{int}.ref rw, @{run}/utmp r, @{PROC}/@{pid}/net/route r, diff --git a/apparmor.d/profiles-s-z/wemeet b/apparmor.d/profiles-s-z/wemeet index 4f40ef746d..e943228bd7 100644 --- a/apparmor.d/profiles-s-z/wemeet +++ b/apparmor.d/profiles-s-z/wemeet @@ -6,15 +6,17 @@ abi , include +@{domain} = org.chromium.Chromium + @{exec_path} = @{bin}/wemeet @{exec_path} += /opt/wemeet/bin/wemeetapp @{exec_path} += /opt/wemeet/bin/QtWebEngineProcess profile wemeet @{exec_path} flags=(attach_disconnected) { include - include include - include + include include + include include include include diff --git a/apparmor.d/profiles-s-z/whatis b/apparmor.d/profiles-s-z/whatis index 43fa8ff095..3febd0b0bd 100644 --- a/apparmor.d/profiles-s-z/whatis +++ b/apparmor.d/profiles-s-z/whatis @@ -13,7 +13,7 @@ profile whatis @{exec_path} { include @{exec_path} mr, - @{bin}/grep rix, + @{bin}/{,e}grep rix, /usr/{,**/}man/{,**/}{,whatis} r, diff --git a/apparmor.d/profiles-s-z/whdd b/apparmor.d/profiles-s-z/whdd index cc4ae2959f..41541ea84c 100644 --- a/apparmor.d/profiles-s-z/whdd +++ b/apparmor.d/profiles-s-z/whdd @@ -25,7 +25,7 @@ profile whdd @{exec_path} { @{bin}/tr rix, # To read SMART attributes - @{bin}/smartctl rPx, + @{sbin}/smartctl rPx, owner @{PROC}/@{pid}/mounts r, @{PROC}/partitions r, diff --git a/apparmor.d/profiles-s-z/which b/apparmor.d/profiles-s-z/which index 855db3f4bc..934a91da5f 100644 --- a/apparmor.d/profiles-s-z/which +++ b/apparmor.d/profiles-s-z/which @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/which{.debianutils,} +@{exec_path} = @{bin}/which{,.debianutils} profile which @{exec_path} flags=(attach_disconnected) { include include @@ -17,7 +17,9 @@ profile which @{exec_path} flags=(attach_disconnected) { @{sh_path} rix, @{bin}/ r, + @{sbin}/ r, @{bin}/**/ r, + @{sbin}/**/ r, @{lib}/ r, @{lib}/**/ r, /opt/**/bin/ r, @@ -29,8 +31,9 @@ profile which @{exec_path} flags=(attach_disconnected) { owner @{HOME}/{.,}go/bin/ r, owner @{user_bin_dirs}/ r, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, + deny @{user_share_dirs}/gnome-shell/session.gvdb rw, deny @{user_share_dirs}/gvfs-metadata/* r, include if exists diff --git a/apparmor.d/profiles-s-z/whiptail b/apparmor.d/profiles-s-z/whiptail index a7b98ebee1..a42a63312e 100644 --- a/apparmor.d/profiles-s-z/whiptail +++ b/apparmor.d/profiles-s-z/whiptail @@ -8,7 +8,7 @@ abi , include @{exec_path} = @{bin}/whiptail -profile whiptail @{exec_path} flags=(complain) { +profile whiptail @{exec_path} { include include @@ -16,9 +16,9 @@ profile whiptail @{exec_path} flags=(complain) { @{exec_path} mr, - /etc/newt/palette.* r, + /usr/share/terminfo/** r, - owner @{tmp}/gpm* w, + /etc/newt/palette.* r, include if exists } diff --git a/apparmor.d/profiles-s-z/whoami b/apparmor.d/profiles-s-z/whoami index 3fc9e26b44..11c763474f 100644 --- a/apparmor.d/profiles-s-z/whoami +++ b/apparmor.d/profiles-s-z/whoami @@ -8,7 +8,7 @@ abi , include @{exec_path} = @{bin}/whoami -profile whoami @{exec_path} { +profile whoami @{exec_path} flags=(attach_disconnected) { include include include diff --git a/apparmor.d/groups/virt/cni-bandwidth b/apparmor.d/profiles-s-z/whois similarity index 61% rename from apparmor.d/groups/virt/cni-bandwidth rename to apparmor.d/profiles-s-z/whois index 3192c70510..a1549db033 100644 --- a/apparmor.d/groups/virt/cni-bandwidth +++ b/apparmor.d/profiles-s-z/whois @@ -1,14 +1,15 @@ # apparmor.d - Full set of apparmor profiles -# Copyright (C) 2022 Jeroen Rijken +# Copyright (C) 2025 valoq # SPDX-License-Identifier: GPL-2.0-only abi , include -@{exec_path} = @{lib}/cni/bandwidth /opt/cni/bin/bandwidth -profile cni-bandwidth @{exec_path} { +@{exec_path} = @{bin}/whois +profile whois @{exec_path} { include + include network inet dgram, network inet6 dgram, @@ -18,7 +19,9 @@ profile cni-bandwidth @{exec_path} { @{exec_path} mr, - include if exists + /etc/whois.conf r, + + include if exists } # vim:syntax=apparmor diff --git a/apparmor.d/profiles-s-z/whoopsie b/apparmor.d/profiles-s-z/whoopsie new file mode 100644 index 0000000000..8a2c839045 --- /dev/null +++ b/apparmor.d/profiles-s-z/whoopsie @@ -0,0 +1,43 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/whoopsie +profile whoopsie @{exec_path} { + include + include + include + + capability setgid, + capability setuid, + + network inet dgram, + network inet stream, + network inet6 dgram, + network inet6 dgram, + network netlink raw, + + @{exec_path} mr, + + /var/crash/ r, + + /var/lib/whoopsie/ rw, + /var/lib/whoopsie/whoopsie-id rw, + /var/lib/whoopsie/whoopsie-id.@{rand6} rw, + + /var/crash/*.@{uid}.crash r, + owner /var/crash/*.@{uid}.uploaded rw, + + owner @{run}/lock/whoopsie/ rw, + owner @{run}/lock/whoopsie/lock rwk, + + @{sys}/devices/virtual/dmi/id/product_uuid r, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-s-z/whoopsie-preferences b/apparmor.d/profiles-s-z/whoopsie-preferences new file mode 100644 index 0000000000..200653f0db --- /dev/null +++ b/apparmor.d/profiles-s-z/whoopsie-preferences @@ -0,0 +1,41 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/whoopsie-preferences +profile whoopsie-preferences @{exec_path} { + include + include + include + include + + capability net_admin, + + #aa:dbus own bus=system name=com.ubuntu.WhoopsiePreferences + + @{exec_path} mr, + + @{bin}/systemctl Cx -> systemctl, + + /etc/whoopsie rw, + /etc/whoopsie.@{rand6} rw, + + /var/lib/whoopsie/whoopsie-id r, + + profile systemctl { + include + include + + capability net_admin, + + include if exists + } + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-s-z/wireshark b/apparmor.d/profiles-s-z/wireshark index c29543d6b8..9ddc908f7c 100644 --- a/apparmor.d/profiles-s-z/wireshark +++ b/apparmor.d/profiles-s-z/wireshark @@ -11,8 +11,6 @@ include @{exec_path} = @{bin}/wireshark profile wireshark @{exec_path} { include - include - include include include include @@ -59,7 +57,7 @@ profile wireshark @{exec_path} { @{PROC}/@{pid}/mounts r, owner /dev/shm/#@{int} rw, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-s-z/wpa-action b/apparmor.d/profiles-s-z/wpa-action index 136caa781b..b6764ba0ee 100644 --- a/apparmor.d/profiles-s-z/wpa-action +++ b/apparmor.d/profiles-s-z/wpa-action @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/wpa_action +@{exec_path} = @{sbin}/wpa_action profile wpa-action @{exec_path} { include @@ -17,7 +17,7 @@ profile wpa-action @{exec_path} { @{exec_path} mr, - @{bin}/wpa_cli rPx, + @{sbin}/wpa_cli rPx, @{sh_path} rix, @{bin}/{,e}grep rix, diff --git a/apparmor.d/profiles-s-z/wpa-cli b/apparmor.d/profiles-s-z/wpa-cli index 11da651797..eb4efeee91 100644 --- a/apparmor.d/profiles-s-z/wpa-cli +++ b/apparmor.d/profiles-s-z/wpa-cli @@ -7,13 +7,13 @@ abi , include -@{exec_path} = @{bin}/wpa_cli +@{exec_path} = @{sbin}/wpa_cli profile wpa-cli @{exec_path} { include @{exec_path} mr, - @{bin}/wpa_action rPx, + @{sbin}/wpa_action rPx, /etc/inputrc r, diff --git a/apparmor.d/profiles-s-z/wpa-gui b/apparmor.d/profiles-s-z/wpa-gui index f833c812e6..8ccf972faf 100644 --- a/apparmor.d/profiles-s-z/wpa-gui +++ b/apparmor.d/profiles-s-z/wpa-gui @@ -24,7 +24,7 @@ profile wpa-gui @{exec_path} { owner @{PROC}/@{pid}/cmdline r, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-s-z/wpa-supplicant b/apparmor.d/profiles-s-z/wpa-supplicant index 23f77f8408..2a987c789c 100644 --- a/apparmor.d/profiles-s-z/wpa-supplicant +++ b/apparmor.d/profiles-s-z/wpa-supplicant @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/wpa_supplicant +@{exec_path} = @{sbin}/wpa_supplicant profile wpa-supplicant @{exec_path} flags=(attach_disconnected) { include include @@ -20,6 +20,7 @@ profile wpa-supplicant @{exec_path} flags=(attach_disconnected) { capability mknod, capability net_admin, capability net_raw, + capability sys_admin, # optional: no audit capability sys_module, network inet dgram, @@ -42,6 +43,7 @@ profile wpa-supplicant @{exec_path} flags=(attach_disconnected) { @{user_config_dirs}/cat_installer/*.pem r, owner @{run}/wpa_supplicant/{,**} rw, + owner @{run}/netplan/* r, @{sys}/devices/@{pci}/ieee*/phy@{int}/name r, diff --git a/apparmor.d/profiles-s-z/wrmsr b/apparmor.d/profiles-s-z/wrmsr index 7de522fc8c..6ef05cc0fd 100644 --- a/apparmor.d/profiles-s-z/wrmsr +++ b/apparmor.d/profiles-s-z/wrmsr @@ -7,7 +7,7 @@ abi , include -@{exec_path} = @{bin}/wrmsr +@{exec_path} = @{sbin}/wrmsr profile wrmsr @{exec_path} { include diff --git a/apparmor.d/profiles-s-z/wsdd b/apparmor.d/profiles-s-z/wsdd index 20575b2a89..f06bbe844c 100644 --- a/apparmor.d/profiles-s-z/wsdd +++ b/apparmor.d/profiles-s-z/wsdd @@ -9,9 +9,14 @@ include @{exec_path} = @{bin}/wsdd profile wsdd @{exec_path} { include + include include include + # wsdd can create its own chroot as a built-in security mechanism. + # This is used by default in the systemd wsdd-server service. + capability sys_chroot, + network inet dgram, network inet stream, network inet6 dgram, @@ -27,7 +32,11 @@ profile wsdd @{exec_path} { owner /var/lib/libuuid/clock.txt rw, - owner @{run}/user/@{uid}/gvfsd/wsdd w, + @{run}/uuidd/request rw, + owner @{run}/user/@{uid}/wsdd w, + owner @{run}/user/@{uid}/*/wsdd w, + + owner @{PROC}/@{pid}/mounts r, include if exists } diff --git a/apparmor.d/profiles-s-z/xarchiver b/apparmor.d/profiles-s-z/xarchiver index 0037700082..51abaa628a 100644 --- a/apparmor.d/profiles-s-z/xarchiver +++ b/apparmor.d/profiles-s-z/xarchiver @@ -11,13 +11,10 @@ include profile xarchiver @{exec_path} { include include - include - include - include - include + include include - include include + include @{exec_path} mrix, @@ -28,18 +25,7 @@ profile xarchiver @{exec_path} { @{bin}/cp rix, # Archivers - @{bin}/7z rix, - @{lib}/p7zip/7z rix, - @{bin}/unrar-nonfree rix, - @{bin}/zip rix, - @{bin}/unzip rix, - @{bin}/tar rix, - @{bin}/xz rix, - @{bin}/bzip2 rix, - @{bin}/cpio rix, - @{bin}/gzip rix, - @{bin}/zstd rix, - # For deb packages + @{archive_path} rix, @{bin}/{,@{multiarch}-}ar rix, @{open_path} rPx -> child-open, @@ -51,20 +37,17 @@ profile xarchiver @{exec_path} { owner @{HOME}/.bz2 rw, - / r, - /home/ r, - #owner @{HOME}/ r, - #owner @{HOME}/** rw, - @{MOUNTS}/ r, - @{MOUNTS}/** rw, - /tmp/ r, + #aa:lint ignore=too-wide + # Full access to user's data + @{MOUNTS}/** rw, + owner @{HOME}/** rw, owner @{tmp}/** rw, @{PROC}/@{pid}/mountinfo r, @{PROC}/@{pid}/mounts r, owner @{PROC}/@{pid}/fd/ r, - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-s-z/xauth b/apparmor.d/profiles-s-z/xauth index e1a4199db3..c4d6f0b57e 100644 --- a/apparmor.d/profiles-s-z/xauth +++ b/apparmor.d/profiles-s-z/xauth @@ -42,6 +42,11 @@ profile xauth @{exec_path} { owner @{run}/user/@{uid}/xauth_@{rand6}-c w, owner @{run}/user/@{uid}/xauth_@{rand6}-l wl, + owner @{tmp}/xvfb-run.@{rand6}/Xauthority-c w, + owner @{tmp}/xvfb-run.@{rand6}/Xauthority-l wl -> @{tmp}/xvfb-run.@{rand6}/Xauthority-c, + owner @{tmp}/xvfb-run.@{rand6}/Xauthority-n rw, + owner @{tmp}/xvfb-run.@{rand6}/Xauthority rwl -> @{tmp}/xvfb-run.@{rand6}/Xauthority-n, + include if exists } diff --git a/apparmor.d/profiles-s-z/xautolock b/apparmor.d/profiles-s-z/xautolock index cb94265835..d80682bfb8 100644 --- a/apparmor.d/profiles-s-z/xautolock +++ b/apparmor.d/profiles-s-z/xautolock @@ -26,7 +26,7 @@ profile xautolock @{exec_path} { owner @{HOME}/.Xauthority r, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, include if exists } diff --git a/apparmor.d/profiles-s-z/xbrlapi b/apparmor.d/profiles-s-z/xbrlapi index 4ce252e107..b2f94975fb 100644 --- a/apparmor.d/profiles-s-z/xbrlapi +++ b/apparmor.d/profiles-s-z/xbrlapi @@ -16,6 +16,8 @@ profile xbrlapi @{exec_path} flags=(attach_disconnected) { @{exec_path} mr, + owner @{HOME}/.xsession-errors w, + include if exists } diff --git a/apparmor.d/profiles-s-z/xinit b/apparmor.d/profiles-s-z/xinit index a332bd20b9..ed6fbc2d70 100644 --- a/apparmor.d/profiles-s-z/xinit +++ b/apparmor.d/profiles-s-z/xinit @@ -35,7 +35,7 @@ profile xinit @{exec_path} { @{bin}/tail rix, @{bin}/tempfile rix, @{bin}/touch rix, - @{bin}/which{,.debianutils} rix, + @{bin}/which{,.debianutils} rix, /etc/X11/xinit/xinitrc rix, /etc/X11/xinit/xserverrc rix, @@ -85,7 +85,7 @@ profile xinit @{exec_path} { /etc/X11/Xresources/ r, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, owner @{HOME}/.xsession-errors w, include if exists diff --git a/apparmor.d/profiles-s-z/xournalpp b/apparmor.d/profiles-s-z/xournalpp new file mode 100644 index 0000000000..331fb5e380 --- /dev/null +++ b/apparmor.d/profiles-s-z/xournalpp @@ -0,0 +1,41 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 valoq +# SPDX-License-Identifier: GPL-2.0-only + +abi , + +include + +@{exec_path} = @{bin}/xournalpp +profile xournalpp @{exec_path} { + include + include + include + include + include + include + include + include + include + + @{exec_path} mr, + + @{open_path} rPx -> child-open-browsers, + + /usr/share/xournalpp/** r, + + /etc/machine-id r, + /etc/pipewire/jack.conf.d/ r, + + owner @{user_config_dirs}/xournalpp/{,**} rw, + owner @{user_cache_dirs}/xournalpp/{,**} rw, + + owner @{PROC}/@{pid}/task/@{tid}/comm rw, + + /dev/snd/controlC@{int} w, + /dev/snd/pcmC@{int}D@{int}[cp] w, + + include if exists +} + +# vim:syntax=apparmor diff --git a/apparmor.d/profiles-s-z/xray b/apparmor.d/profiles-s-z/xray index 79c3104dc4..c935eb9f04 100644 --- a/apparmor.d/profiles-s-z/xray +++ b/apparmor.d/profiles-s-z/xray @@ -10,11 +10,14 @@ include profile xray @{exec_path} flags=(attach_disconnected) { include include + include + include network inet dgram, + network inet6 dgram, network inet stream, + network inet6 stream, network inet raw, - network inet6 dgram, network inet6 raw, network netlink raw, @@ -23,8 +26,13 @@ profile xray @{exec_path} flags=(attach_disconnected) { /etc/xray/{,*} r, /usr/share/xray/**.dat r, /usr/share/v2ray/**.dat r, + /var/log/xray/*.log rw, + + @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/session-@{word}.scope/cpu.max r, - @{PROC}/sys/net/core/somaxconn r, + @{PROC}/sys/net/core/somaxconn r, + owner @{PROC}/@{pid}/mountinfo r, + owner @{PROC}/@{pid}/cgroup r, include if exists } diff --git a/apparmor.d/profiles-s-z/xsane-gimp b/apparmor.d/profiles-s-z/xsane-gimp index 41ac0b973c..633035a1b5 100644 --- a/apparmor.d/profiles-s-z/xsane-gimp +++ b/apparmor.d/profiles-s-z/xsane-gimp @@ -1,5 +1,6 @@ # apparmor.d - Full set of apparmor profiles # Copyright (C) 2024 Roman Beslik +# Copyright (C) 2024-2025 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only abi , @@ -10,27 +11,32 @@ include profile xsane-gimp @{exec_path} { include include - include - - signal (receive) set=(term, kill) peer=gimp, + include network inet dgram, network inet6 dgram, network netlink raw, + signal receive set=(term, kill) peer=gimp, + @{exec_path} mr, + @{system_share_dirs}/gimp/{,**} r, @{system_share_dirs}/sane/xsane/{,**} r, - @{system_share_dirs}/snmp/mibs/{,**} r, # network + @{system_share_dirs}/snmp/mibs/{,**} r, + /etc/sane.d/{,**} r, + owner @{HOME}/.sane/{,**} rw, owner @{tmp}/xsane-*-@{rand6} rw, - @{sys}/devices/@{pci}/{model,type,vendor} r, - @{PROC}/sys/dev/parport/{,parport@{int}/{base-addr,irq}} r, - # SCSI @{sys}/bus/scsi/devices/ r, + @{sys}/devices/@{pci}/{model,type,vendor} r, + @{PROC}/scsi/scsi r, + @{PROC}/sys/dev/parport/ r, + @{PROC}/sys/dev/parport/parport@{int}/base-addr r, + @{PROC}/sys/dev/parport/parport@{int}/irq r, include if exists } diff --git a/apparmor.d/profiles-s-z/xsel b/apparmor.d/profiles-s-z/xsel index 05b93fed98..4b4e3f112e 100644 --- a/apparmor.d/profiles-s-z/xsel +++ b/apparmor.d/profiles-s-z/xsel @@ -20,7 +20,7 @@ profile xsel @{exec_path} { owner @{user_cache_dirs}/xsel.log rw, # file_inherit - owner /dev/tty@{int} rw, + owner /dev/tty@{u8} rw, owner @{HOME}/.xsession-errors w, include if exists diff --git a/apparmor.d/profiles-s-z/youtube-dl b/apparmor.d/profiles-s-z/youtube-dl index d618a0db19..96d261b0b6 100644 --- a/apparmor.d/profiles-s-z/youtube-dl +++ b/apparmor.d/profiles-s-z/youtube-dl @@ -13,13 +13,11 @@ profile youtube-dl @{exec_path} { include include include - include - include + include include include include include - include network inet dgram, network inet6 dgram, @@ -38,14 +36,12 @@ profile youtube-dl @{exec_path} { @{bin}/ r, @{bin}/{,@{multiarch}-}gcc-[0-9]* rix, @{bin}/git rix, - @{bin}/ldconfig rix, + @{sbin}/ldconfig rix, @{bin}/rtmpdump rix, @{bin}/uname rix, @{lib}/git{,-core}/git rix, @{lib}/llvm-[0-9]*/bin/clang rix, - /etc/mime.types r, - owner @{HOME}/ r, owner @{user_music_dirs}/{,**} rw, owner @{user_videos_dirs}/{,**} rw, diff --git a/apparmor.d/profiles-s-z/yt-dlp b/apparmor.d/profiles-s-z/yt-dlp index ffa78eda39..0f232f55c4 100644 --- a/apparmor.d/profiles-s-z/yt-dlp +++ b/apparmor.d/profiles-s-z/yt-dlp @@ -33,6 +33,8 @@ profile yt-dlp @{exec_path} { @{bin}/ffmpeg rPx, @{bin}/ffprobe rPx, + @{bin}/deno rPx, + /etc/magic r, owner @{user_music_dirs}/{,**} rwk, diff --git a/apparmor.d/profiles-s-z/ytdl b/apparmor.d/profiles-s-z/ytdl index 12fd657c30..b14c8d1e08 100644 --- a/apparmor.d/profiles-s-z/ytdl +++ b/apparmor.d/profiles-s-z/ytdl @@ -10,6 +10,7 @@ include @{exec_path} = @{bin}/ytdl profile ytdl @{exec_path} { include + include include include include @@ -27,11 +28,9 @@ profile ytdl @{exec_path} { @{python_path} r, @{bin}/ r, - @{bin}/ldconfig rix, + @{sbin}/ldconfig rix, @{bin}/uname rix, - /etc/mime.types r, - owner @{HOME}/ r, owner @{user_music_dirs}/{,**} rw, owner @{user_videos_dirs}/{,**} rw, diff --git a/apparmor.d/profiles-s-z/zathura b/apparmor.d/profiles-s-z/zathura index 5d0d1a745b..c95eb17c24 100644 --- a/apparmor.d/profiles-s-z/zathura +++ b/apparmor.d/profiles-s-z/zathura @@ -18,11 +18,12 @@ profile zathura @{exec_path} { @{exec_path} mr, /usr/share/file/{,**} r, - /usr/share/poppler/{,**} r, /etc/xdg/{,**} r, /etc/zathurarc r, + /var/empty/ r, + owner @{user_config_dirs}/zathura/** r, owner @{user_share_dirs}/zathura/ r, owner @{user_share_dirs}/zathura/** rwk, diff --git a/apparmor.d/profiles-s-z/zed b/apparmor.d/profiles-s-z/zed index bb160a5e55..893cead5b6 100644 --- a/apparmor.d/profiles-s-z/zed +++ b/apparmor.d/profiles-s-z/zed @@ -23,7 +23,7 @@ profile zed @{exec_path} { @{bin}/diff rix, @{bin}/expr rix, @{bin}/flock rix, - @{bin}/grep rix, + @{bin}/{,e}grep rix, @{bin}/hostname rix, @{bin}/logger rix, @{bin}/ls rix, @@ -46,6 +46,7 @@ profile zed @{exec_path} { owner @{tmp}/tmp.* rw, @{sys}/bus/pci/slots/ r, + @{sys}/bus/pci/slots/@{int}-@{int}/address r, @{sys}/bus/pci/slots/@{int}/address r, @{sys}/module/zfs/parameters/zfs_zevent_len_max rw, diff --git a/apparmor.d/profiles-s-z/zenmap b/apparmor.d/profiles-s-z/zenmap index f4dc9fc774..fb0701fd18 100644 --- a/apparmor.d/profiles-s-z/zenmap +++ b/apparmor.d/profiles-s-z/zenmap @@ -10,10 +10,7 @@ include @{exec_path} = @{bin}/{zenmap,nmapfe} profile zenmap @{exec_path} { include - include - include - include - include + include include include @@ -24,6 +21,10 @@ profile zenmap @{exec_path} { @{bin}/nmap rPx, + /etc/fstab r, + + /usr/share/zenmap/** r, + owner @{HOME}/ r, owner @{HOME}/.zenmap/ rw, owner @{HOME}/.zenmap/** rwk, @@ -33,10 +34,6 @@ profile zenmap @{exec_path} { owner @{PROC}/@{pid}/mountinfo r, owner @{PROC}/@{pid}/mounts r, - /etc/fstab r, - - /usr/share/zenmap/** r, - owner @{tmp}/* rw, owner @{tmp}/zenmap-stdout-* rw, diff --git a/apparmor.d/profiles-s-z/zfs b/apparmor.d/profiles-s-z/zfs index e28a2e439d..a4608ca447 100644 --- a/apparmor.d/profiles-s-z/zfs +++ b/apparmor.d/profiles-s-z/zfs @@ -6,7 +6,7 @@ abi , include -@{exec_path} = /{usr/,}{local/,}{s,}bin/zfs +@{exec_path} = @{bin}/zfs profile zfs @{exec_path} { include include @@ -23,10 +23,12 @@ profile zfs @{exec_path} { # Sanoid generates temorary files with random names including underscores, directly under /tmp. # https://github.com/jimsalterjrs/sanoid/issues/758 - /tmp/* rw, + /tmp/@{word10} rw, @{run}/zfs-list.cache@* rw, + @{sys}/module/zfs/*/ r, + @{PROC}/@{pids}/mounts r, @{PROC}/sys/fs/pipe-max-size r, diff --git a/apparmor.d/profiles-s-z/zpool b/apparmor.d/profiles-s-z/zpool index 2cb997fd74..d9ffaed74a 100644 --- a/apparmor.d/profiles-s-z/zpool +++ b/apparmor.d/profiles-s-z/zpool @@ -6,17 +6,19 @@ abi , include -@{exec_path} = /{usr/,}{local/,}{s,}bin/zpool +@{exec_path} = @{bin}/zpool profile zpool @{exec_path} { include include capability sys_admin, + mount fstype=zfs options=(rw noatime) -> @{MOUNTS}/, + @{exec_path} mr, @{sh_path} rix, - /{usr/,}{local/,}lib/zfs-linux/zpool.d/* rix, + @{lib}/zfs-linux/zpool.d/* rix, /usr/share/zfs/{,**} r, @@ -31,13 +33,14 @@ profile zpool @{exec_path} { @{sys}/module/zfs/** r, @{sys}/bus/pci/slots/ r, + @{sys}/bus/pci/slots/@{int}-@{int}/address r, @{sys}/bus/pci/slots/@{int}/address r, @{PROC}/@{pids}/mountinfo r, @{PROC}/@{pids}/mounts r, @{PROC}/sys/kernel/spl/hostid r, - /dev/pts/@{int} rw, + /dev/pts/@{u16} rw, /dev/zfs rw, include if exists diff --git a/apparmor.d/profiles-s-z/zsysd b/apparmor.d/profiles-s-z/zsysd index 8ac23a07c1..7a67c35964 100644 --- a/apparmor.d/profiles-s-z/zsysd +++ b/apparmor.d/profiles-s-z/zsysd @@ -10,7 +10,7 @@ include profile zsysd @{exec_path} flags=(complain) { include include - include + include include capability sys_ptrace, @@ -20,14 +20,13 @@ profile zsysd @{exec_path} flags=(complain) { /{usr/,}{local/,}{s,}bin/zfs rPx, /{usr/,}{local/,}{s,}bin/zpool rPx, # ALLOWED zsysd exec /usr/sbin/update-grub info="no new privs" comm=zsysd requested_mask=x denied_mask=x error=-1 - @{bin}/update-grub rPx, + @{sbin}/update-grub rPx, /etc/hostid r, /etc/zsys.conf r, /var/log/unattended-upgrades/unattended-upgrades-dpkg.log rw, - @{run}/systemd/notify rw, @{run}/unattended-upgrades.pid r, @{run}/zsys-snapshot.unattended-upgrades rw, @{run}/zsysd.sock rw, @@ -37,7 +36,7 @@ profile zsysd @{exec_path} flags=(complain) { @{PROC}/cmdline r, @{PROC}/sys/kernel/spl/hostid r, - /dev/pts/@{int} rw, + /dev/pts/@{u16} rw, /dev/zfs rw, include if exists diff --git a/apparmor.d/tunables/alias.d/coreutils b/apparmor.d/tunables/alias.d/coreutils new file mode 100644 index 0000000000..d17d2de1b0 --- /dev/null +++ b/apparmor.d/tunables/alias.d/coreutils @@ -0,0 +1,112 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# In ubuntu 25.10, as gnutils and uutils are available, classic install paths +# are now link to one of these two implementations. To avoid breaking profiles, +# we provide aliases for all the coreutils names to their gnu* counterpart. + + alias /{,usr/}bin/dd -> /usr/bin/gnudd, + alias /{,usr/}bin/tee -> /usr/bin/gnutee, + alias /{,usr/}bin/paste -> /usr/bin/gnupaste, + alias /{,usr/}bin/sha256sum -> /usr/bin/gnusha256sum, + alias /{,usr/}bin/env -> /usr/bin/gnuenv, + alias /{,usr/}bin/expr -> /usr/bin/gnuexpr, + alias /{,usr/}bin/sleep -> /usr/bin/gnusleep, + alias /{,usr/}bin/shred -> /usr/bin/gnushred, + alias /{,usr/}bin/dircolors -> /usr/bin/gnudircolors, + alias /{,usr/}bin/nohup -> /usr/bin/gnunohup, + alias /{,usr/}bin/stty -> /usr/bin/gnustty, + alias /{,usr/}bin/sha384sum -> /usr/bin/gnusha384sum, + alias /{,usr/}bin/pr -> /usr/bin/gnupr, + alias /{,usr/}bin/nice -> /usr/bin/gnunice, + alias /{,usr/}bin/basenc -> /usr/bin/gnubasenc, + alias /{,usr/}bin/sha224sum -> /usr/bin/gnusha224sum, + alias /{,usr/}bin/unexpand -> /usr/bin/gnuunexpand, + alias /{,usr/}bin/logname -> /usr/bin/gnulogname, + alias /{,usr/}bin/uniq -> /usr/bin/gnuuniq, + alias /{,usr/}bin/chown -> /usr/bin/gnuchown, + alias /{,usr/}bin/vdir -> /usr/bin/gnuvdir, + alias /{,usr/}bin/printf -> /usr/bin/gnuprintf, + alias /{,usr/}bin/true -> /usr/bin/gnutrue, + alias /{,usr/}bin/groups -> /usr/bin/gnugroups, + alias /{,usr/}bin/printenv -> /usr/bin/gnuprintenv, + alias /{,usr/}bin/truncate -> /usr/bin/gnutruncate, + alias /{,usr/}bin/md5sum -> /usr/bin/gnumd5sum, + alias /{,usr/}bin/pinky -> /usr/bin/gnupinky, + alias /{,usr/}bin/rm -> /usr/bin/gnurm, + alias /{,usr/}bin/cat -> /usr/bin/gnucat, + alias /{,usr/}bin/tac -> /usr/bin/gnutac, + alias /{,usr/}bin/b2sum -> /usr/bin/gnub2sum, + alias /{,usr/}bin/seq -> /usr/bin/gnuseq, + alias /{,usr/}bin/cut -> /usr/bin/gnucut, + alias /{,usr/}bin/csplit -> /usr/bin/gnucsplit, + alias /{,usr/}bin/split -> /usr/bin/gnusplit, + alias /{,usr/}bin/realpath -> /usr/bin/gnurealpath, + alias /{,usr/}bin/ptx -> /usr/bin/gnuptx, + alias /{,usr/}bin/who -> /usr/bin/gnuwho, + alias /{,usr/}bin/whoami -> /usr/bin/gnuwhoami, + alias /{,usr/}bin/cksum -> /usr/bin/gnucksum, + alias /{,usr/}bin/ls -> /usr/bin/gnuls, + alias /{,usr/}bin/runcon -> /usr/bin/gnuruncon, + alias /{,usr/}bin/arch -> /usr/bin/gnuarch, + alias /{,usr/}bin/head -> /usr/bin/gnuhead, + alias /{,usr/}bin/date -> /usr/bin/gnudate, + alias /{,usr/}bin/wc -> /usr/bin/gnuwc, + alias /{,usr/}bin/mktemp -> /usr/bin/gnumktemp, + alias /{,usr/}bin/pathchk -> /usr/bin/gnupathchk, + alias /{,usr/}bin/mkfifo -> /usr/bin/gnumkfifo, + alias /{,usr/}bin/du -> /usr/bin/gnudu, + alias /{,usr/}bin/cp -> /usr/bin/gnucp, + alias /{,usr/}bin/tty -> /usr/bin/gnutty, + alias /{,usr/}bin/sync -> /usr/bin/gnusync, + alias /{,usr/}bin/fold -> /usr/bin/gnufold, + alias /{,usr/}bin/users -> /usr/bin/gnuusers, + alias /{,usr/}bin/dirname -> /usr/bin/gnudirname, + alias /{,usr/}bin/nproc -> /usr/bin/gnunproc, + alias /{,usr/}bin/sort -> /usr/bin/gnusort, + alias /{,usr/}bin/[ -> /usr/bin/gnu[, + alias /{,usr/}bin/base64 -> /usr/bin/gnubase64, + alias /{,usr/}bin/od -> /usr/bin/gnuod, + alias /{,usr/}bin/tr -> /usr/bin/gnutr, + alias /{,usr/}bin/join -> /usr/bin/gnujoin, + alias /{,usr/}bin/sha512sum -> /usr/bin/gnusha512sum, + alias /{,usr/}bin/false -> /usr/bin/gnufalse, + alias /{,usr/}bin/expand -> /usr/bin/gnuexpand, + alias /{,usr/}bin/base32 -> /usr/bin/gnubase32, + alias /{,usr/}bin/chmod -> /usr/bin/gnuchmod, + alias /{,usr/}bin/rmdir -> /usr/bin/gnurmdir, + alias /{,usr/}bin/factor -> /usr/bin/gnufactor, + alias /{,usr/}bin/mknod -> /usr/bin/gnumknod, + alias /{,usr/}bin/chcon -> /usr/bin/gnuchcon, + alias /{,usr/}bin/basename -> /usr/bin/gnubasename, + alias /{,usr/}bin/chgrp -> /usr/bin/gnuchgrp, + alias /{,usr/}bin/sha1sum -> /usr/bin/gnusha1sum, + alias /{,usr/}bin/ln -> /usr/bin/gnuln, + alias /{,usr/}bin/tsort -> /usr/bin/gnutsort, + alias /{,usr/}bin/echo -> /usr/bin/gnuecho, + alias /{,usr/}bin/timeout -> /usr/bin/gnutimeout, + alias /{,usr/}bin/dir -> /usr/bin/gnudir, + alias /{,usr/}bin/numfmt -> /usr/bin/gnunumfmt, + alias /{,usr/}bin/touch -> /usr/bin/gnutouch, + alias /{,usr/}bin/mv -> /usr/bin/gnumv, + alias /{,usr/}bin/sum -> /usr/bin/gnusum, + alias /{,usr/}bin/stat -> /usr/bin/gnustat, + alias /{,usr/}bin/yes -> /usr/bin/gnuyes, + alias /{,usr/}bin/install -> /usr/bin/gnuinstall, + alias /{,usr/}bin/readlink -> /usr/bin/gnureadlink, + alias /{,usr/}bin/pwd -> /usr/bin/gnupwd, + alias /{,usr/}bin/tail -> /usr/bin/gnutail, + alias /{,usr/}bin/stdbuf -> /usr/bin/gnustdbuf, + alias /{,usr/}bin/comm -> /usr/bin/gnucomm, + alias /{,usr/}bin/shuf -> /usr/bin/gnushuf, + alias /{,usr/}bin/uname -> /usr/bin/gnuuname, + alias /{,usr/}bin/test -> /usr/bin/gnutest, + alias /{,usr/}bin/mkdir -> /usr/bin/gnumkdir, + alias /{,usr/}bin/link -> /usr/bin/gnulink, + alias /{,usr/}bin/df -> /usr/bin/gnudf, + alias /{,usr/}bin/unlink -> /usr/bin/gnuunlink, + alias /{,usr/}bin/hostid -> /usr/bin/gnuhostid, + alias /{,usr/}bin/fmt -> /usr/bin/gnufmt, + alias /{,usr/}bin/id -> /usr/bin/gnuid, + alias /{,usr/}bin/nl -> /usr/bin/gnunl, diff --git a/apparmor.d/tunables/alias.d/uutils b/apparmor.d/tunables/alias.d/uutils new file mode 100644 index 0000000000..d82a6d5c3b --- /dev/null +++ b/apparmor.d/tunables/alias.d/uutils @@ -0,0 +1,123 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# In ubuntu 25.10, as gnutils and uutils are available, classic install paths +# are now link to one of these two implementations. To avoid breaking profiles, +# we provide aliases for all the coreutils names to their rust counterpart. + + alias /{,usr/}bin/sudo -> /usr/lib/cargo/bin/sudo, + alias /{,usr/}bin/mv -> /usr/lib/cargo/bin/coreutils/mv, + alias /{,usr/}bin/mkfifo -> /usr/lib/cargo/bin/coreutils/mkfifo, + alias /{,usr/}bin/dirname -> /usr/lib/cargo/bin/coreutils/dirname, + alias /{,usr/}bin/chown -> /usr/lib/cargo/bin/coreutils/chown, + alias /{,usr/}bin/whoami -> /usr/lib/cargo/bin/coreutils/whoami, + alias /{,usr/}bin/touch -> /usr/lib/cargo/bin/coreutils/touch, + alias /{,usr/}bin/expand -> /usr/lib/cargo/bin/coreutils/expand, + alias /{,usr/}bin/sha3sum -> /usr/lib/cargo/bin/coreutils/sha3sum, + alias /{,usr/}bin/od -> /usr/lib/cargo/bin/coreutils/od, + alias /{,usr/}bin/sum -> /usr/lib/cargo/bin/coreutils/sum, + alias /{,usr/}bin/fmt -> /usr/lib/cargo/bin/coreutils/fmt, + alias /{,usr/}bin/sync -> /usr/lib/cargo/bin/coreutils/sync, + alias /{,usr/}bin/dd -> /usr/lib/cargo/bin/coreutils/dd, + alias /{,usr/}bin/comm -> /usr/lib/cargo/bin/coreutils/comm, + alias /{,usr/}bin/chgrp -> /usr/lib/cargo/bin/coreutils/chgrp, + alias /{,usr/}bin/cksum -> /usr/lib/cargo/bin/coreutils/cksum, + alias /{,usr/}bin/dir -> /usr/lib/cargo/bin/coreutils/dir, + alias /{,usr/}bin/relpath -> /usr/lib/cargo/bin/coreutils/relpath, + alias /{,usr/}bin/base32 -> /usr/lib/cargo/bin/coreutils/base32, + alias /{,usr/}bin/ls -> /usr/lib/cargo/bin/coreutils/ls, + alias /{,usr/}bin/uniq -> /usr/lib/cargo/bin/coreutils/uniq, + alias /{,usr/}bin/tee -> /usr/lib/cargo/bin/coreutils/tee, + alias /{,usr/}bin/install -> /usr/lib/cargo/bin/coreutils/install, + alias /{,usr/}bin/link -> /usr/lib/cargo/bin/coreutils/link, + alias /{,usr/}bin/join -> /usr/lib/cargo/bin/coreutils/join, + alias /{,usr/}bin/cut -> /usr/lib/cargo/bin/coreutils/cut, + alias /{,usr/}bin/sha3-512sum -> /usr/lib/cargo/bin/coreutils/sha3-512sum, + alias /{,usr/}bin/basename -> /usr/lib/cargo/bin/coreutils/basename, + alias /{,usr/}bin/unlink -> /usr/lib/cargo/bin/coreutils/unlink, + alias /{,usr/}bin/true -> /usr/lib/cargo/bin/coreutils/true, + alias /{,usr/}bin/pinky -> /usr/lib/cargo/bin/coreutils/pinky, + alias /{,usr/}bin/logname -> /usr/lib/cargo/bin/coreutils/logname, + alias /{,usr/}bin/truncate -> /usr/lib/cargo/bin/coreutils/truncate, + alias /{,usr/}bin/stat -> /usr/lib/cargo/bin/coreutils/stat, + alias /{,usr/}bin/pwd -> /usr/lib/cargo/bin/coreutils/pwd, + alias /{,usr/}bin/id -> /usr/lib/cargo/bin/coreutils/id, + alias /{,usr/}bin/test -> /usr/lib/cargo/bin/coreutils/test, + alias /{,usr/}bin/realpath -> /usr/lib/cargo/bin/coreutils/realpath, + alias /{,usr/}bin/sha384sum -> /usr/lib/cargo/bin/coreutils/sha384sum, + alias /{,usr/}bin/nl -> /usr/lib/cargo/bin/coreutils/nl, + alias /{,usr/}bin/runcon -> /usr/lib/cargo/bin/coreutils/runcon, + alias /{,usr/}bin/rm -> /usr/lib/cargo/bin/coreutils/rm, + alias /{,usr/}bin/cat -> /usr/lib/cargo/bin/coreutils/cat, + alias /{,usr/}bin/dircolors -> /usr/lib/cargo/bin/coreutils/dircolors, + alias /{,usr/}bin/du -> /usr/lib/cargo/bin/coreutils/du, + alias /{,usr/}bin/printf -> /usr/lib/cargo/bin/coreutils/printf, + alias /{,usr/}bin/printenv -> /usr/lib/cargo/bin/coreutils/printenv, + alias /{,usr/}bin/mktemp -> /usr/lib/cargo/bin/coreutils/mktemp, + alias /{,usr/}bin/shake128sum -> /usr/lib/cargo/bin/coreutils/shake128sum, + alias /{,usr/}bin/ptx -> /usr/lib/cargo/bin/coreutils/ptx, + alias /{,usr/}bin/uname -> /usr/lib/cargo/bin/coreutils/uname, + alias /{,usr/}bin/md5sum -> /usr/lib/cargo/bin/coreutils/md5sum, + alias /{,usr/}bin/rmdir -> /usr/lib/cargo/bin/coreutils/rmdir, + alias /{,usr/}bin/sha3-384sum -> /usr/lib/cargo/bin/coreutils/sha3-384sum, + alias /{,usr/}bin/expr -> /usr/lib/cargo/bin/coreutils/expr, + alias /{,usr/}bin/factor -> /usr/lib/cargo/bin/coreutils/factor, + alias /{,usr/}bin/arch -> /usr/lib/cargo/bin/coreutils/arch, + alias /{,usr/}bin/numfmt -> /usr/lib/cargo/bin/coreutils/numfmt, + alias /{,usr/}bin/[ -> /usr/lib/cargo/bin/coreutils/[, + alias /{,usr/}bin/echo -> /usr/lib/cargo/bin/coreutils/echo, + alias /{,usr/}bin/tail -> /usr/lib/cargo/bin/coreutils/tail, + alias /{,usr/}bin/chmod -> /usr/lib/cargo/bin/coreutils/chmod, + alias /{,usr/}bin/sort -> /usr/lib/cargo/bin/coreutils/sort, + alias /{,usr/}bin/pathchk -> /usr/lib/cargo/bin/coreutils/pathchk, + alias /{,usr/}bin/shake256sum -> /usr/lib/cargo/bin/coreutils/shake256sum, + alias /{,usr/}bin/who -> /usr/lib/cargo/bin/coreutils/who, + alias /{,usr/}bin/mkdir -> /usr/lib/cargo/bin/coreutils/mkdir, + alias /{,usr/}bin/cp -> /usr/lib/cargo/bin/coreutils/cp, + alias /{,usr/}bin/date -> /usr/lib/cargo/bin/coreutils/date, + alias /{,usr/}bin/hashsum -> /usr/lib/cargo/bin/coreutils/hashsum, + alias /{,usr/}bin/basenc -> /usr/lib/cargo/bin/coreutils/basenc, + alias /{,usr/}bin/tsort -> /usr/lib/cargo/bin/coreutils/tsort, + alias /{,usr/}bin/hostid -> /usr/lib/cargo/bin/coreutils/hostid, + alias /{,usr/}bin/sleep -> /usr/lib/cargo/bin/coreutils/sleep, + alias /{,usr/}bin/pr -> /usr/lib/cargo/bin/coreutils/pr, + alias /{,usr/}bin/ln -> /usr/lib/cargo/bin/coreutils/ln, + alias /{,usr/}bin/sha256sum -> /usr/lib/cargo/bin/coreutils/sha256sum, + alias /{,usr/}bin/nohup -> /usr/lib/cargo/bin/coreutils/nohup, + alias /{,usr/}bin/unexpand -> /usr/lib/cargo/bin/coreutils/unexpand, + alias /{,usr/}bin/nproc -> /usr/lib/cargo/bin/coreutils/nproc, + alias /{,usr/}bin/csplit -> /usr/lib/cargo/bin/coreutils/csplit, + alias /{,usr/}bin/sha3-224sum -> /usr/lib/cargo/bin/coreutils/sha3-224sum, + alias /{,usr/}bin/env -> /usr/lib/cargo/bin/coreutils/env, + alias /{,usr/}bin/fold -> /usr/lib/cargo/bin/coreutils/fold, + alias /{,usr/}bin/groups -> /usr/lib/cargo/bin/coreutils/groups, + alias /{,usr/}bin/nice -> /usr/lib/cargo/bin/coreutils/nice, + alias /{,usr/}bin/readlink -> /usr/lib/cargo/bin/coreutils/readlink, + alias /{,usr/}bin/shuf -> /usr/lib/cargo/bin/coreutils/shuf, + alias /{,usr/}bin/head -> /usr/lib/cargo/bin/coreutils/head, + alias /{,usr/}bin/stdbuf -> /usr/lib/cargo/bin/coreutils/stdbuf, + alias /{,usr/}bin/wc -> /usr/lib/cargo/bin/coreutils/wc, + alias /{,usr/}bin/tac -> /usr/lib/cargo/bin/coreutils/tac, + alias /{,usr/}bin/base64 -> /usr/lib/cargo/bin/coreutils/base64, + alias /{,usr/}bin/sha224sum -> /usr/lib/cargo/bin/coreutils/sha224sum, + alias /{,usr/}bin/timeout -> /usr/lib/cargo/bin/coreutils/timeout, + alias /{,usr/}bin/sha1sum -> /usr/lib/cargo/bin/coreutils/sha1sum, + alias /{,usr/}bin/df -> /usr/lib/cargo/bin/coreutils/df, + alias /{,usr/}bin/tty -> /usr/lib/cargo/bin/coreutils/tty, + alias /{,usr/}bin/false -> /usr/lib/cargo/bin/coreutils/false, + alias /{,usr/}bin/split -> /usr/lib/cargo/bin/coreutils/split, + alias /{,usr/}bin/yes -> /usr/lib/cargo/bin/coreutils/yes, + alias /{,usr/}bin/b2sum -> /usr/lib/cargo/bin/coreutils/b2sum, + alias /{,usr/}bin/sha3-256sum -> /usr/lib/cargo/bin/coreutils/sha3-256sum, + alias /{,usr/}bin/chroot -> /usr/lib/cargo/bin/coreutils/chroot, + alias /{,usr/}bin/mknod -> /usr/lib/cargo/bin/coreutils/mknod, + alias /{,usr/}bin/vdir -> /usr/lib/cargo/bin/coreutils/vdir, + alias /{,usr/}bin/chcon -> /usr/lib/cargo/bin/coreutils/chcon, + alias /{,usr/}bin/shred -> /usr/lib/cargo/bin/coreutils/shred, + alias /{,usr/}bin/stty -> /usr/lib/cargo/bin/coreutils/stty, + alias /{,usr/}bin/tr -> /usr/lib/cargo/bin/coreutils/tr, + alias /{,usr/}bin/sha512sum -> /usr/lib/cargo/bin/coreutils/sha512sum, + alias /{,usr/}bin/seq -> /usr/lib/cargo/bin/coreutils/seq, + alias /{,usr/}bin/users -> /usr/lib/cargo/bin/coreutils/users, + alias /{,usr/}bin/paste -> /usr/lib/cargo/bin/coreutils/paste, diff --git a/apparmor.d/tunables/home.d/apparmor.d b/apparmor.d/tunables/home.d/apparmor.d index c791f53763..dacb7228e2 100644 --- a/apparmor.d/tunables/home.d/apparmor.d +++ b/apparmor.d/tunables/home.d/apparmor.d @@ -21,8 +21,6 @@ # Define extended user directories not defined in the XDG standard but commonly # used in profiles -@{XDG_SCREENSHOTS_DIR}="Pictures/Screenshots" -@{XDG_WALLPAPERS_DIR}="Pictures/Wallpapers" @{XDG_BOOKS_DIR}="Books" @{XDG_GAMES_DIR}="Games" @{XDG_PROJECTS_DIR}="Projects" @@ -74,4 +72,7 @@ @{user_passwordstore_dirs}=@{HOME}/@{XDG_PASSWORDSTORE_DIR} @{MOUNTS}/@{XDG_PASSWORDSTORE_DIR} @{user_private_dirs}=@{HOME}/@{XDG_PRIVATE_DIR} @{MOUNTS}/@{XDG_PRIVATE_DIR} +# Similar system-wide paths +@{system_games_dirs}=/usr/games /var/lib/games + # vim:syntax=apparmor diff --git a/apparmor.d/tunables/multiarch.d/base b/apparmor.d/tunables/multiarch.d/base index 9661b1e513..6691e78266 100644 --- a/apparmor.d/tunables/multiarch.d/base +++ b/apparmor.d/tunables/multiarch.d/base @@ -91,3 +91,7 @@ @{word16}=@{word8}@{word8} @{word32}=@{word16}@{word16} @{word64}=@{word32}@{word32} + +# Shortcut for PCI device +@{pci_bus}=pci@{hex4}:@{hex2} + diff --git a/apparmor.d/tunables/multiarch.d/extensions b/apparmor.d/tunables/multiarch.d/extensions index d7f7450aa2..9e4cedad15 100644 --- a/apparmor.d/tunables/multiarch.d/extensions +++ b/apparmor.d/tunables/multiarch.d/extensions @@ -432,6 +432,11 @@ @{image_ext} += [xX][wW][dD] # xwd @{image_ext} += [xX][yY][zZ][eE] # xyze +# Icons +@{icon_ext} = [pP][nN][gG] # png +@{icon_ext} += [iI][cC][oO] # ico +@{icon_ext} += [sS][vV][gG] # svg + # Models @{model_ext} = [bB][aA][rR][yY] # bary @{model_ext} += [bB][sS][pP] # bsp diff --git a/apparmor.d/tunables/multiarch.d/paths b/apparmor.d/tunables/multiarch.d/paths index 733f8925c7..4d1fb5ee01 100644 --- a/apparmor.d/tunables/multiarch.d/paths +++ b/apparmor.d/tunables/multiarch.d/paths @@ -12,10 +12,22 @@ # Coreutils programs that should not have dedicated profile @{coreutils_path} = @{bin}/@{coreutils} +@{coreutils_path} += @{bin}/gnu@{coreutils} #aa:only ubuntu +@{coreutils_path} += @{lib}/cargo/bin/coreutils/@{coreutils} #aa:only ubuntu # Python interpreters @{python_path} = @{bin}/@{python_name} +# ldd (List Dynamic Dependencies) and dynamic linker/loader +@{ldd_path} = @{bin}/ldd @{bin}/ld +@{ldd_path} += @{lib}/ld-linux-@{arch}.so{,.*} @{lib}/ld-linux.so{,.*} +@{ldd_path} += @{lib}/@{multiarch}/ld-linux-@{arch}.so{,.*} + +# Gstreamer plugin scanner +@{gstreamer_path} = @{lib}/@{multiarch}/gstreamer1.0/gstreamer-1.0/gst-plugin-scanner +@{gstreamer_path} += @{lib}/@{multiarch}/gstreamer-1.0/gst-plugin-scanner +@{gstreamer_path} += @{lib}/gstreamer-1.0/gst-plugin-scanner + # Browsers @{brave_path} = @{brave_lib_dirs}/@{brave_name} @{chrome_path} = @{opera_lib_dirs}/@{chrome_name} @@ -31,7 +43,7 @@ # Emails @{thunderbird_path} = @{bin}/@{thunderbird_name} @{thunderbird_lib_dirs}/@{thunderbird_name} -@{emails_path} = @{thunderbird_path} @{bin}/@{emails_names} +@{emails_path} = @{thunderbird_path} @{bin}/@{emails_names} "/opt/proton-mail/Proton Mail" # Open @{open_path} = @{bin}/@{open_names} @@ -67,6 +79,12 @@ @{help_path} = @{bin}/@{help_names} # Terminal emulator -@{terminal_path} = @{bin}/@{offices_names} +@{terminal_path} = @{bin}/@{terminal_names} + +# Backup +@{backup_path} = @{bin}/@{backup_names} @{lib}/deja-dup/deja-dup-monitor + +# Archives +@{archive_path} = @{bin}/@{archive_names} @{lib}/p7zip/7z @{lib}/7zip/7z # vim:syntax=apparmor diff --git a/apparmor.d/tunables/multiarch.d/profiles b/apparmor.d/tunables/multiarch.d/profiles index d18030d689..51efc84f90 100644 --- a/apparmor.d/tunables/multiarch.d/profiles +++ b/apparmor.d/tunables/multiarch.d/profiles @@ -8,27 +8,75 @@ # All variables that refer to a profile name should be prefixed with `p_` # Name of the systemd profiles. Can be `unconfined` or `systemd`, `systemd-user` -@{p_systemd}=unconfined +@{p_sd}=unconfined +@{p_sdu}=unconfined @{p_systemd_user}=unconfined +@{p_systemd}=unconfined # Name of the dbus daemon profiles @{p_dbus_accessibility}=dbus-accessibility -#aa:only apparmor4.1 -@{p_dbus_system}=dbus-system//&unconfined -@{p_dbus_session}=dbus-session//&unconfined +#aa:only apparmor>=4.1 +@{p_dbus_system}={dbus-system,unconfined} +@{p_dbus_session}={dbus-session,unconfined} -#aa:exclude apparmor4.1 +#aa:only apparmor<4.1 @{p_dbus_system}=dbus-system @{p_dbus_session}=dbus-session +@{p_accounts_daemon}=accounts-daemon +@{p_apt_news}=apt_news @{p_at_spi2_registryd}=at-spi2-registryd +@{p_avahi_daemon}=avahi-daemon +@{p_bluetoothd}=bluetoothd @{p_colord}=colord +@{p_e2scrub_all}=e2scrub_all +@{p_e2scrub}=e2scrub +@{p_file_roller}=file-roller +@{p_fprintd}=fprintd +@{p_fwupd}=fwupd +@{p_fwupdmgr}=fwupdmgr +@{p_geoclue}=geoclue +@{p_gnome_session}={gnome-session-binary,gnome-session-service} @{p_gnome_shell}=gnome-shell +@{p_gsd_media_keys}=gsd-media-keys +@{p_irqbalance}=irqbalance +@{p_logrotate}=logrotate +@{p_ModemManager}=ModemManager +@{p_nm_priv_helper}=nm-priv-helper @{p_packagekitd}=packagekitd +@{p_pcscd}=pcscd +@{p_polkitd}=polkitd +@{p_power_profiles_daemon}=power-profiles-daemon +@{p_rsyslogd}=rsyslogd +@{p_rtkit_daemon}=rtkit-daemon @{p_snap}=snap +@{p_systemd_coredump}=systemd-coredump +@{p_systemd_homed}=systemd-homed +@{p_systemd_hostnamed}=systemd-hostnamed +@{p_systemd_importd}=systemd-importd +@{p_systemd_initctl}=systemd-initctl +@{p_systemd_journal_remote}=systemd-journal-remote +@{p_systemd_journald}=systemd-journald +@{p_systemd_localed}=systemd-localed @{p_systemd_logind}=systemd-logind +@{p_systemd_networkd}=systemd-networkd +@{p_systemd_oomd}=systemd-oomd +@{p_systemd_resolved}=systemd-resolved +@{p_systemd_rfkill}=systemd-rfkill +@{p_systemd_timedated}=systemd-timedated +@{p_systemd_timesyncd}=systemd-timesyncd +@{p_systemd_userdbd}=systemd-userdbd +@{p_upowerd}=upowerd @{p_xdg_desktop_portal}=xdg-desktop-portal -@{p_gsd_media_keys}=gsd-media-keys -@{p_rtkit_daemon}=rtkit-daemon + +# Profiles Patterns +# Fit to an action that can be handled by multiple profiles depending on the +# software installed and the distribution + +# Notification +@{pp_notification}={plasmashell,gjs} +@{pp_app_indicator}={plasmashell,gnome-shell} +@{pp_dbusmenu}={plasmashell,nautilus,gnome-shell} +@{pp_mpris}={plasmashell,mpris-proxy,gnome-shell,gsd-media-keys,gnome-extension-gsconnect} # vim:syntax=apparmor diff --git a/apparmor.d/tunables/multiarch.d/programs b/apparmor.d/tunables/multiarch.d/programs index 3611178a22..dd5db56841 100644 --- a/apparmor.d/tunables/multiarch.d/programs +++ b/apparmor.d/tunables/multiarch.d/programs @@ -4,10 +4,10 @@ # Define some some commonly used programs. This is not an exhaustive list. # It is meant to label programs to easily provide access in profiles. - +# # All variables that refer to a program name should have the `_name` suffix. # variables that refer to a list of progran should have the `_names` suffix. -# @{sh}, @{shells}, and @{coreutils} are the only exceptions. +# `@{sh}`, `@{shells}`, and `@{coreutils}` are the only exceptions. # Default distribution shells @{sh} = sh bash dash @@ -16,7 +16,8 @@ @{shells} = sh zsh bash dash fish rbash ksh tcsh csh # Coreutils programs that should not have dedicated profile. Also includes findutils and diffutils. -@{coreutils} = {,g,m}awk b2sum base32 base64 basename basenc cat chcon chgrp chmod chown +# The remaining coreutils programs should have profile present in the utils group. +@{coreutils} = \[ {,g,m}awk b2sum base32 base64 basename basenc cat chcon chgrp chmod chown @{coreutils} += cksum cmp comm cp csplit cut date dd df dir dircolors dirname diff diff3 du echo env expand @{coreutils} += expr factor false find fmt fold {,e,f}grep head hostid id install join link @{coreutils} += ln locate logname ls md5sum mkdir mkfifo mknod mktemp mv nice nl nohup nproc numfmt @@ -24,6 +25,20 @@ @{coreutils} += runcon sdiff sed seq sha1sum sha224sum sha256sum sha384sum sha512sum shred shuf sleep @{coreutils} += sort split stat stdbuf stty sum tac tail tee test timeout touch tr true @{coreutils} += truncate tsort tty uname unexpand uniq unlink updatedb vdir wc who whoami xargs yes +@{coreutils} += which{,.debianutils} + +# Various development tools +# +# It is mostly used to easily define folder access in development tools profiles, +# not to allow execution. +# +# !!! warning +# +# Sensitive tools like git/ssh/gpg should not be included in `@{devtools}`. +# This should only contains core development tools like compilers, analysis tools, linters, debuggers etc. +# +@{devtools} = ansible cargo dlv gem go just node npm pip pyright python ruby +@{devtools} += rust typescript yarn docker uv pytest # Python interpreters @{python_version} = 3 3.[0-9] 3.1[0-9] @@ -33,7 +48,7 @@ @{open_names} = exo-open xdg-open gio kde-open gio-launch-desktop # Editors -@{editor_names} = sensible-editor vim{,.*} vimtutor vim-nox11 nvim nano +@{editor_names} = nano nvim sensible-editor vim* @{editor_ui_names} = gnome-text-editor gedit mousepad # Pager @@ -67,7 +82,7 @@ @{thunderbird_name} = thunderbird{,-bin} @{thunderbird_lib_dirs} = @{lib}/@{thunderbird_name} -@{emails_names} = evolution geary +@{emails_names} = evolution geary proton-mail # File explorers @{file_explorers_names} = dolphin nautilus thunar @@ -76,7 +91,7 @@ @{text_editors_names} = code gedit mousepad gnome-text-editor zeditor zedit zed-cli # Document viewers -@{document_viewers_names} = evince okular *{F,f}oliate YACReader +@{document_viewers_names} = evince papers okular *{F,f}oliate YACReader # Image viewers @{image_viewers_names} = eog loupe ristretto @@ -85,12 +100,22 @@ @{archive_viewers_names} = engrampa file-roller xarchiver # Office suites -@{offices_names} = libreoffice soffice +@{offices_names} = libreoffice soffice wps # Help @{help_names} = yelp # Terminal emulator -@{terminal_name} = kgx terminator konsole +@{terminal_names} = xdg-terminal-exec kgx terminator konsole ptyxis ghostty + +# Backup +@{backup_names} = deja-dup borg + +# Archives +@{archive_names} = 7z 7zz ar bunzip2 bzip2 cpio gunzip gzip lzip rar tar unrar unrar-nonfree unzip xz zip zstd + +# Steam +@{steam_share_dirs} = @{user_share_dirs}/Steam @{HOME}/.steam/debian-installation +@{steam_lib_dirs} = @{steam_share_dirs}/ubuntu@{int2}_{32,64} # vim:syntax=apparmor diff --git a/apparmor.d/tunables/multiarch.d/state b/apparmor.d/tunables/multiarch.d/state new file mode 100644 index 0000000000..d4e3298ca6 --- /dev/null +++ b/apparmor.d/tunables/multiarch.d/state @@ -0,0 +1,95 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# System states +# +# Current system states. All of the variables depend on the running state and +# are thus expected to be configured by a program at runtime. +# +# All variables that depends on the running state should be uppercase. + + +# Apparmor version +# ---------------- + +# AppArmor ABI +@{ABI} = 5 + +# AppArmor version +@{VERSION} = 5 + + +# Security level +# -------------- + +# The targeted security level of the system. These are experimental and subject to change. +# Supported values are: +# - 0: default +# - 1: strict +# - 2: fsp +# - 3: extreme +# +# See https://apparmor.pujol.io/security/architecture/#security-levels +@{LEVEL} = 0 + +# Either or not role-based access control is enabled on the system. +# Supported values are: true, false +#${RBAC} = false + +# Either or not Full system policies is enabled on the system. +# If enabled, @{LEVEL} should be set to 2 or higher. +# Supported values are: true, false +#${FSP} = false + +# Either or not the system is running in test mode. +# Supported values are: true, false +# ${TEST} = false + + +# Distribution information +# ------------------------ + +# The OS family. Supported family values are: apt, pacman, zypper +# It is a preferred way to check for the distribution. +@{OS_FAMILY} = pacman + +# The OS ID. It is the value of the ID field in /etc/os-release. +@{OS_ID} = arch + +# The OS version. It is the value of the VERSION_ID field in /etc/os-release. +@{OS_VERSION_ID} = rolling + + +# Desktop +# ------- + +# The list of desktop environments installed on the system. +# Supported values are: gnome, kde, xfce, cosmic, none +@{DE} = gnome + +# The list of display managers installed on the system. +# Supported values are: gdm, sddm, lightdm, none +@{DM} = gdm + +# The display server in use. +# Supported values are: wayland, x11, none +@{DS} = wayland + + +# Sysctl +# ------ +# +# Provide variables for some of the sysctl settings. +# +# All variables that refer to a sysctl config should have the `sysctl_` prefix. +# +# !!! warning +# +# **It is experimental**, both variables and values may be automatically set +# set in the future. +# + +#${sysctl_kernel_unprivileged_userns_clone} = true + +# vim:syntax=apparmor diff --git a/apparmor.d/tunables/multiarch.d/system b/apparmor.d/tunables/multiarch.d/system index 11fc6c2a87..2ae30b47f5 100644 --- a/apparmor.d/tunables/multiarch.d/system +++ b/apparmor.d/tunables/multiarch.d/system @@ -14,19 +14,23 @@ @{MOUNTS}=@{MOUNTDIRS}/*/ @{run}/user/@{uid}/gvfs/ # Common places for binaries and libraries across distributions -@{bin}=/{,usr/}{,s}bin -@{sbin}=/{,usr/}sbin +@{bin}=/{,usr/}bin +@{sbin}=/{,usr/}sbin #aa:only apt zypper +@{sbin}=/{,usr/}{,s}bin #aa:only pacman @{lib}=/{,usr/}lib{,exec,32,64} # Common places for temporary files +# /tmp/user/@{uid}/ is needed when using .... (default on Debian) @{tmp}=/tmp/ /tmp/user/@{uid}/ +# Common places for EFI +@{efi}=/boot/ /efi/ /boot/efi/ # System Variables # ---------------- # Common architecture names -@{arch}=x86_64 amd64 i386 i686 +@{arch}=x86{_,-}64 x64 amd64 i386 i686 # Dbus unique name @{busname}=:1.@{u16} :not.active.yet @@ -34,8 +38,11 @@ # Unix dbus address prefix @{udbus}=@{h}{@{h},}{@{h},}{@{h},}{@{h},}{@{h},}{@{h},}{@{h},}{@{h},}{@{h},}{@{h},}{@{h},}{@{h},}{@{h},}{@{h},}{@{h},} +# dbus-broker special addresses +@{udbus}+=@{int12}@{int} + # Universally unique identifier -@{uuid}=@{h}@{h}@{h}@{h}@{h}@{h}@{h}@{h}[-_]@{h}@{h}@{h}@{h}[-_]@{h}@{h}@{h}@{h}[-_]@{h}@{h}@{h}@{h}[-_]@{h}@{h}@{h}@{h}@{h}@{h}@{h}@{h}@{h}@{h}@{h}@{h} +@{uuid}=@{hex8}[-_]@{hex4}[-_]@{hex4}[-_]@{hex4}[-_]@{hex12} # Username & group valid characters @{user}=[a-zA-Z_]{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},} @@ -44,26 +51,28 @@ # Semantic version @{version}=@{u16}{.@{u16},}{.@{u16},}{{-,_}@{rand},} +#aa:only opensuse # OpenSUSE does not have the same multiarch structure -@{multiarch}+=*-suse-linux* #aa:only opensuse +@{multiarch}+=*-suse-linux* # System Internal # --------------- +@{pci_bus}=pci@{hex4}:@{hex2} + # Shortcut for PCI device -@{pci_id}=@{h}@{h}@{h}@{h}:@{h}@{h}:@{h}@{h}.@{h} -@{pci_bus}=pci@{h}@{h}@{h}@{h}:@{h}@{h} +@{pci_id}=@{hex4}:@{hex2}:@{hex2}.@{h} @{pci}=@{pci_bus}/**/ # Udev data dynamic assignment ranges +# See https://raw.githubusercontent.com/torvalds/linux/master/Documentation/admin-guide/devices.txt @{dynamic}=23[4-9] 24[0-9] 25[0-4] # range 234 to 254 @{dynamic}+=38[4-9] 39[0-9] 4[0-9][0-9] 50[0-9] 51[0-1] # range 384 to 511 -# Attachment path for attach_disconnected.path flag. -# Automatically generated and set in profile preamble on ABI4. Disabled on ABI3. -@{att}=/ - -alias // -> /, +# Default attachment path when re-attached path disconnected path is ignored. +# Disabled on abi3 and Ubuntu 25.04+ +# See https://apparmor.pujol.io/development/internal/#re-attached-path +@{att}="" # vim:syntax=apparmor diff --git a/apparmor.d/tunables/multiarch.d/system-users b/apparmor.d/tunables/multiarch.d/system-users index 885913da3f..4fd647ef9a 100644 --- a/apparmor.d/tunables/multiarch.d/system-users +++ b/apparmor.d/tunables/multiarch.d/system-users @@ -4,32 +4,81 @@ # Define some extra paths for some commonly used system user -# Full path of the GDM configuration directories -@{GDM_HOME}=/var/lib/gdm{,3}/ -@{gdm_cache_dirs}=@{GDM_HOME}/.cache/ -@{gdm_config_dirs}=@{GDM_HOME}/.config/ -@{gdm_local_dirs}=@{GDM_HOME}/.local/ -@{gdm_share_dirs}=@{GDM_HOME}/.local/share/ - -# Full path of the SDDM configuration directories -@{SDDM_HOME}=/var/lib/sddm/ -@{sddm_cache_dirs}=@{SDDM_HOME}/.cache/ -@{sddm_config_dirs}=@{SDDM_HOME}/.config/ -@{sddm_local_dirs}=@{SDDM_HOME}/.local/ -@{sddm_share_dirs}=@{SDDM_HOME}/.local/share/ - -# Full path of the LIGHTDM configuration directories -@{LIGHTDM_HOME}=/var/lib/lightdm/ -@{lightdm_cache_dirs}=@{LIGHTDM_HOME}/.cache/ -@{lightdm_config_dirs}=@{LIGHTDM_HOME}/.config/ -@{lightdm_local_dirs}=@{LIGHTDM_HOME}/.local/ -@{lightdm_share_dirs}=@{LIGHTDM_HOME}/.local/share/ - -# Full path of all DE configuration directories -@{DESKTOP_HOME}=@{GDM_HOME} @{SDDM_HOME} @{LIGHTDM_HOME} -@{desktop_cache_dirs}=@{gdm_cache_dirs} @{sddm_cache_dirs} @{lightdm_cache_dirs} -@{desktop_config_dirs}=@{gdm_config_dirs} @{sddm_config_dirs} @{lightdm_config_dirs} -@{desktop_local_dirs}=@{gdm_local_dirs} @{sddm_local_dirs} @{lightdm_local_dirs} -@{desktop_share_dirs}=@{gdm_share_dirs} @{sddm_share_dirs} @{lightdm_share_dirs} +@{DESKTOP_HOME}="" +@{desktop_cache_dirs}="" +@{desktop_config_dirs}="" +@{desktop_local_dirs}="" +@{desktop_share_dirs}="" +@{desktop_state_dirs}="" + +# if "gnome" in @{DE} { + + # Full path of the GDM configuration directories + @{GDM_HOME}=/var/lib/gdm{,3}/ @{run}/gdm{,3}/home/gdm-greeter/ @{run}/gdm{,3}/home/gnome-initial-setup*/ + @{gdm_cache_dirs}=@{GDM_HOME}/.cache/ + @{gdm_config_dirs}=@{GDM_HOME}/.config/ @{GDM_HOME}/seat@{int}/config/ + @{gdm_local_dirs}=@{GDM_HOME}/.local/ + @{gdm_share_dirs}=@{GDM_HOME}/.local/share/ + @{gdm_state_dirs}=@{GDM_HOME}/.local/state/ @{GDM_HOME}/seat@{int}/state/ + + @{DESKTOP_HOME}+=@{GDM_HOME} + @{desktop_cache_dirs}+=@{gdm_cache_dirs} + @{desktop_config_dirs}+=@{gdm_config_dirs} + @{desktop_local_dirs}+=@{gdm_local_dirs} + @{desktop_share_dirs}+=@{gdm_share_dirs} + @{desktop_state_dirs}+=@{gdm_state_dirs} + +# } else if "kde" in @{DE} { + + # Full path of the SDDM configuration directories + @{SDDM_HOME}=/var/lib/sddm/ /var/lib/plasmalogin + @{sddm_cache_dirs}=@{SDDM_HOME}/.cache/ + @{sddm_config_dirs}=@{SDDM_HOME}/.config/ + @{sddm_local_dirs}=@{SDDM_HOME}/.local/ + @{sddm_share_dirs}=@{SDDM_HOME}/.local/share/ + @{sddm_state_dirs}=@{SDDM_HOME}/.local/state/ + + @{DESKTOP_HOME}+=@{SDDM_HOME} + @{desktop_cache_dirs}+=@{sddm_cache_dirs} + @{desktop_config_dirs}+=@{sddm_config_dirs} + @{desktop_local_dirs}+=@{sddm_local_dirs} + @{desktop_share_dirs}+=@{sddm_share_dirs} + @{desktop_state_dirs}+=@{sddm_state_dirs} + +# } else if "xfce" in @{DE} { + + # Full path of the LIGHTDM configuration directories + @{LIGHTDM_HOME}=/var/lib/lightdm/ + @{lightdm_cache_dirs}=@{LIGHTDM_HOME}/.cache/ + @{lightdm_config_dirs}=@{LIGHTDM_HOME}/.config/ + @{lightdm_local_dirs}=@{LIGHTDM_HOME}/.local/ + @{lightdm_share_dirs}=@{LIGHTDM_HOME}/.local/share/ + @{lightdm_state_dirs}=@{LIGHTDM_HOME}/.local/state/ + + @{DESKTOP_HOME}+=@{LIGHTDM_HOME} + @{desktop_cache_dirs}+=@{lightdm_cache_dirs} + @{desktop_config_dirs}+=@{lightdm_config_dirs} + @{desktop_local_dirs}+=@{lightdm_local_dirs} + @{desktop_share_dirs}+=@{lightdm_share_dirs} + @{desktop_state_dirs}+=@{lightdm_state_dirs} + +# } else if "cosmic" in @{DE} { + +# # Full path of the Cosmic configuration directories +# @{COSMIC_HOME}=/var/lib/cosmic-greeter/ +# @{cosmic_cache_dirs}=@{COSMIC_HOME}/.cache/ +# @{cosmic_config_dirs}=@{COSMIC_HOME}/.config/ +# @{cosmic_local_dirs}=@{COSMIC_HOME}/.local/ +# @{cosmic_share_dirs}=@{COSMIC_HOME}/.local/share/ +# @{cosmic_state_dirs}=@{COSMIC_HOME}/.local/state/ + +# @{DESKTOP_HOME}+=@{COSMIC_HOME} +# @{desktop_cache_dirs}+=@{cosmic_cache_dirs} +# @{desktop_config_dirs}+=@{cosmic_config_dirs} +# @{desktop_local_dirs}+=@{cosmic_local_dirs} +# @{desktop_share_dirs}+=@{cosmic_share_dirs} +# @{desktop_state_dirs}+=@{cosmic_state_dirs} + +# } # vim:syntax=apparmor diff --git a/apparmor.d/tunables/xdg-user-dirs.d/apparmor.d b/apparmor.d/tunables/xdg-user-dirs.d/apparmor.d index 52be8b9205..3bc4007ead 100644 --- a/apparmor.d/tunables/xdg-user-dirs.d/apparmor.d +++ b/apparmor.d/tunables/xdg-user-dirs.d/apparmor.d @@ -13,6 +13,11 @@ #aa:only whonix @{XDG_DOWNLOAD_DIR}+=".tb/tor-browser/Browser/Downloads" +# Define more extended user directories not defined in the XDG standard but commonly +# used in profiles +@{XDG_SCREENSHOTS_DIR}=@{XDG_PICTURES_DIR}/Screenshots +@{XDG_WALLPAPERS_DIR}=@{XDG_PICTURES_DIR}/Wallpapers + # Other user directories @{user_desktop_dirs}=@{HOME}/@{XDG_DESKTOP_DIR} @{MOUNTS}/@{XDG_DESKTOP_DIR} @{user_download_dirs}=@{HOME}/@{XDG_DOWNLOAD_DIR} @{MOUNTS}/@{XDG_DOWNLOAD_DIR} diff --git a/cmd/aa-log/main.go b/cmd/aa-log/main.go index ccd6e9cca1..289988a6d8 100644 --- a/cmd/aa-log/main.go +++ b/cmd/aa-log/main.go @@ -15,7 +15,7 @@ import ( "github.com/roddhjav/apparmor.d/pkg/logs" ) -const usage = `aa-log [-h] [--systemd] [--file file] [--rules | --raw] [--since] [profile] +const usage = `aa-log [-h] [--systemd] [--file file] [--load] [--rules | --raw] [--since] [--namespace] [profile] Review AppArmor generated messages in a colorful way. It supports logs from auditd, systemd, syslog as well as dbus session events. @@ -24,49 +24,88 @@ const usage = `aa-log [-h] [--systemd] [--file file] [--rules | --raw] [--since] Default logs are read from '/var/log/audit/audit.log'. Other files in '/var/log/audit/' can easily be checked: 'aa-log -f 1' parses 'audit.log.1' + Use 'aa-log -f -' to read from standard input. + + Logs written with 'aa-log' can be read again with 'aa-log -l'. Options: -h, --help Show this help message and exit. -f, --file FILE Set a logfile or a suffix to the default log file. -s, --systemd Parse systemd logs from journalctl. + -n, --namespace NS Filter the logs to the specified namespace. -r, --rules Convert the log into AppArmor rules. -R, --raw Print the raw log without any formatting. + -b, --boot NUM Show entries from the specified boot. -S, --since DATE Show entries not older than the specified date. + -l, --load Load logs from the default aa-log output. ` // Command line options var ( - help bool - rules bool - path string - systemd bool - raw bool - since string + help bool + rules bool + path string + systemd bool + namespace string + raw bool + boot string + since string + load bool ) -func aaLog(logger string, path string, profile string) error { +func init() { + flag.BoolVar(&help, "h", false, "Show this help message and exit.") + flag.BoolVar(&help, "help", false, "Show this help message and exit.") + flag.StringVar(&path, "f", "", "Set a logfile or a suffix to the default log file.") + flag.StringVar(&path, "file", "", "Set a logfile or a suffix to the default log file.") + flag.BoolVar(&systemd, "s", false, "Parse systemd logs from journalctl.") + flag.BoolVar(&systemd, "systemd", false, "Parse systemd logs from journalctl.") + flag.BoolVar(&rules, "r", false, "Convert the log into AppArmor rules.") + flag.BoolVar(&rules, "rules", false, "Convert the log into AppArmor rules.") + flag.BoolVar(&raw, "R", false, "Print the raw log without any formatting.") + flag.BoolVar(&raw, "raw", false, "Print the raw log without any formatting.") + flag.StringVar(&boot, "b", "", "Show entries from the specified boot.") + flag.StringVar(&boot, "boot", "", "Show entries from the specified boot.") + flag.StringVar(&since, "S", "", "Display logs since the START time.") + flag.StringVar(&since, "since", "", "Display logs since the START time.") + flag.BoolVar(&load, "l", false, "Load logs from the default aa-log output.") + flag.BoolVar(&load, "load", false, "Load logs from the default aa-log output.") + flag.StringVar(&namespace, "n", "", "Filter the logs to the specified namespace") + flag.StringVar(&namespace, "namespace", "", "Filter the logs to the specified namespace") +} + +func aaLog(logger string, path string, profile string, namespace string, rules bool, raw bool, load bool) error { var err error var file io.Reader + start := timeNow() switch logger { case "auditd": file, err = logs.GetAuditLogs(path) case "systemd": - file, err = logs.GetJournalctlLogs(path, since, !slices.Contains(logs.LogFiles, path)) + file, err = logs.GetJournalctlLogs(path, boot, since, !slices.Contains(logs.LogFiles, path)) default: err = fmt.Errorf("logger %s not supported", logger) } if err != nil { return err } + endRead := timeNow() if raw { - fmt.Print(strings.Join(logs.GetApparmorLogs(file, profile), "\n") + "\n") + fmt.Print(strings.Join(logs.GetApparmorLogs(file, profile, namespace), "\n") + "\n") return nil } - aaLogs := logs.New(file, profile) + var aaLogs logs.AppArmorLogs + if load { + aaLogs = logs.Load(file, profile, namespace) + } else { + aaLogs = logs.New(file, profile, namespace) + } + + endParse := timeNow() if rules { profiles := aaLogs.ParseToProfiles() for _, p := range profiles { @@ -78,24 +117,12 @@ func aaLog(logger string, path string, profile string) error { } else { fmt.Print(aaLogs.String()) } + if withTime { + printTiming(start, endRead, endParse, timeNow()) + } return nil } -func init() { - flag.BoolVar(&help, "h", false, "Show this help message and exit.") - flag.BoolVar(&help, "help", false, "Show this help message and exit.") - flag.StringVar(&path, "f", "", "Set a logfile or a suffix to the default log file.") - flag.StringVar(&path, "file", "", "Set a logfile or a suffix to the default log file.") - flag.BoolVar(&systemd, "s", false, "Parse systemd logs from journalctl.") - flag.BoolVar(&systemd, "systemd", false, "Parse systemd logs from journalctl.") - flag.BoolVar(&rules, "r", false, "Convert the log into AppArmor rules.") - flag.BoolVar(&rules, "rules", false, "Convert the log into AppArmor rules.") - flag.BoolVar(&raw, "R", false, "Print the raw log without any formatting.") - flag.BoolVar(&raw, "raw", false, "Print the raw log without any formatting.") - flag.StringVar(&since, "S", "", "Display logs since the START time.") - flag.StringVar(&since, "since", "", "Display logs since the START time.") -} - func main() { flag.Usage = func() { fmt.Print(usage) } flag.Parse() @@ -104,9 +131,10 @@ func main() { os.Exit(0) } - profile := "" - if len(flag.Args()) >= 1 { - profile = flag.Args()[0] + profile := flag.Arg(0) + + if boot != "" { + systemd = true } logger := "auditd" @@ -114,10 +142,13 @@ func main() { logger = "systemd" } - path = logs.SelectLogFile(path) - err := aaLog(logger, path, profile) + path, err := logs.SelectLogFile(path) if err != nil { - fmt.Println(err) + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + if err = aaLog(logger, path, profile, namespace, rules, raw, load); err != nil { + fmt.Fprintln(os.Stderr, err) os.Exit(1) } } diff --git a/cmd/aa-log/main_test.go b/cmd/aa-log/main_test.go index fb93386753..f60b0a8a71 100644 --- a/cmd/aa-log/main_test.go +++ b/cmd/aa-log/main_test.go @@ -15,58 +15,74 @@ var ( func Test_app(t *testing.T) { tests := []struct { - name string - logger string - path string - profile string - rules bool - wantErr bool + name string + logger string + path string + profile string + namespace string + rules bool + raw bool + load bool + wantErr bool }{ { name: "Test audit.log", logger: "auditd", path: filepath.Join(testdata, "audit.log"), - profile: "", rules: false, + raw: false, + load: false, wantErr: false, }, { name: "Test audit.log to rules", logger: "auditd", path: filepath.Join(testdata, "audit.log"), - profile: "", rules: true, + raw: false, + load: false, wantErr: false, }, { name: "Test Dbus Session", logger: "systemd", path: filepath.Join(testdata, "systemd.log"), - profile: "", rules: false, + raw: true, + load: false, wantErr: false, }, { name: "No logfile", logger: "auditd", path: filepath.Join(testdata, "log"), - profile: "", rules: false, + raw: false, + load: false, wantErr: true, }, + { + name: "Test loading aa-log", + logger: "auditd", + path: filepath.Join(testdata, "aa-log"), + rules: false, + raw: false, + load: true, + wantErr: false, + }, { name: "Logger not supported", logger: "raw", path: filepath.Join(testdata, "audit.log"), - profile: "", rules: false, + raw: true, + load: false, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - rules = tt.rules - if err := aaLog(tt.logger, tt.path, tt.profile); (err != nil) != tt.wantErr { + if err := aaLog(tt.logger, tt.path, tt.profile, tt.namespace, tt.rules, tt.raw, tt.load); (err != nil) != tt.wantErr { t.Errorf("aaLog() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/cmd/aa-log/timing_dev.go b/cmd/aa-log/timing_dev.go new file mode 100644 index 0000000000..1e1a753860 --- /dev/null +++ b/cmd/aa-log/timing_dev.go @@ -0,0 +1,35 @@ +//go:build dev + +package main + +import ( + "fmt" + "time" +) + +const withTime = true + +func timeNow() time.Time { + return time.Now() +} + +func printTiming(start, endRead, endParse, end time.Time) { + printDuration := func(d time.Duration) string { + if d >= time.Minute { + return fmt.Sprintf("%.2fmin", d.Minutes()) + } else if d >= time.Second { + return fmt.Sprintf("%.2fs", d.Seconds()) + } else if d >= time.Millisecond { + return fmt.Sprintf("%.2fms", float64(d.Microseconds())/1000) + } + return fmt.Sprintf("%.2fµs", float64(d.Nanoseconds())/1000) + } + readDur := endRead.Sub(start) + parseDur := endParse.Sub(endRead) + printDur := end.Sub(endParse) + totalDur := end.Sub(start) + fmt.Printf("\x1b[3;97m( Read %s | Parse %s | Print %s | Total %s )\x1b[0m\n", + printDuration(readDur), printDuration(parseDur), + printDuration(printDur), printDuration(totalDur), + ) +} diff --git a/cmd/aa-log/timing_release.go b/cmd/aa-log/timing_release.go new file mode 100644 index 0000000000..d768c4188a --- /dev/null +++ b/cmd/aa-log/timing_release.go @@ -0,0 +1,13 @@ +//go:build !dev + +package main + +import "time" + +const withTime = false + +func timeNow() time.Time { + return time.Time{} +} + +func printTiming(start, endRead, endParse, end time.Time) {} diff --git a/cmd/aa-mode/main.go b/cmd/aa-mode/main.go new file mode 100644 index 0000000000..b842ca808c --- /dev/null +++ b/cmd/aa-mode/main.go @@ -0,0 +1,136 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package main + +import ( + "flag" + "fmt" + "os" + + "github.com/roddhjav/apparmor.d/pkg/aa" + "github.com/roddhjav/apparmor.d/pkg/logging" + "github.com/roddhjav/apparmor.d/pkg/paths" + "github.com/roddhjav/apparmor.d/pkg/util" +) + +const usage = `aa-mode [-h] (-e|-c|-k|-a|-u|-p) [profiles...] + + Switch the given program to an AppArmor mode. + + If a profile name is given without a path, it is looked up in '/etc/apparmor.d/'. + If a directory is given, all profiles in it are processed recursively. + +Options: + -h, --help Show this help message and exit. + -e, --enforce Set the profile in enforce mode. + -c, --complain Set the profile in complain mode. + -k, --kill Set the profile in kill mode. + -a, --default-allow Set the profile in default_allow mode. + -u, --unconfined Set the profile in unconfined mode. + -p, --prompt Set the profile in prompt mode. + --no-reload Do not reload the profile after modifying it. + +` + +var ( + help bool + enforce bool + complain bool + kill bool + defaultAllow bool + unconfined bool + prompt bool + noReload bool +) + +func init() { + flag.BoolVar(&help, "h", false, "Show this help message and exit.") + flag.BoolVar(&help, "help", false, "Show this help message and exit.") + flag.BoolVar(&enforce, "e", false, "Set the profile in enforce mode.") + flag.BoolVar(&enforce, "enforce", false, "Set the profile in enforce mode.") + flag.BoolVar(&complain, "c", false, "Set the profile in complain mode.") + flag.BoolVar(&complain, "complain", false, "Set the profile in complain mode.") + flag.BoolVar(&kill, "k", false, "Set the profile in kill mode.") + flag.BoolVar(&kill, "kill", false, "Set the profile in kill mode.") + flag.BoolVar(&defaultAllow, "a", false, "Set the profile in default_allow mode.") + flag.BoolVar(&defaultAllow, "default-allow", false, "Set the profile in default_allow mode.") + flag.BoolVar(&unconfined, "u", false, "Set the profile in unconfined mode.") + flag.BoolVar(&unconfined, "unconfined", false, "Set the profile in unconfined mode.") + flag.BoolVar(&prompt, "p", false, "Set the profile in prompt mode.") + flag.BoolVar(&prompt, "prompt", false, "Set the profile in prompt mode.") + flag.BoolVar(&noReload, "no-reload", false, "Do not reload the profile after modifying it.") +} + +func selectedMode() (string, error) { + flagsByMode := map[string]bool{ + "enforce": enforce, + "complain": complain, + "kill": kill, + "default_allow": defaultAllow, + "unconfined": unconfined, + "prompt": prompt, + } + var selected string + for _, mode := range util.ProfileModes { + if !flagsByMode[mode] { + continue + } + if selected != "" { + return "", fmt.Errorf("only one mode can be set, got %s and %s", selected, mode) + } + selected = mode + } + if selected == "" { + return "", fmt.Errorf("a mode must be set") + } + return selected, nil +} + +func aaSetMode(files paths.PathList, mode string) error { + modified := paths.PathList{} + for _, file := range files { + profile, err := file.ReadFileAsString() + if err != nil { + return err + } + if util.IsUnconfined(profile) { + logging.Warning("skipping %s: profile is in unconfined mode", file) + continue + } + profile, err = util.SetMode(profile, mode) + if err != nil { + return err + } + if err = file.WriteFile([]byte(profile)); err != nil { + return err + } + modified = append(modified, file) + } + if noReload { + return nil + } + return util.ReloadProfiles(modified) +} + +func main() { + flag.Usage = func() { fmt.Print(usage) } + flag.Parse() + if help || flag.NArg() < 1 { + flag.Usage() + os.Exit(0) + } + + mode, err := selectedMode() + if err != nil { + logging.Fatal("%s", err.Error()) + } + files, err := paths.PathListFromArgs(flag.Args(), aa.MagicRoot) + if err != nil { + logging.Fatal("%s", err.Error()) + } + if err = aaSetMode(files, mode); err != nil { + logging.Fatal("%s", err.Error()) + } +} diff --git a/cmd/aa-mode/main_test.go b/cmd/aa-mode/main_test.go new file mode 100644 index 0000000000..ebd45d1826 --- /dev/null +++ b/cmd/aa-mode/main_test.go @@ -0,0 +1,162 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package main + +import ( + "os" + "testing" + + "github.com/roddhjav/apparmor.d/pkg/paths" +) + +func tempDir(t *testing.T) *paths.Path { + t.Helper() + if err := os.MkdirAll("/tmp/tests", 0o755); err != nil { + t.Fatalf("mkdir /tmp/tests: %v", err) + } + t.Setenv("TMPDIR", "/tmp/tests") + return paths.New(t.TempDir()) +} + +func resetFlags(t *testing.T) { + t.Helper() + enforce, complain, kill = false, false, false + defaultAllow, unconfined, prompt = false, false, false + noReload = true +} + +func TestSelectedMode(t *testing.T) { + tests := []struct { + name string + setup func() + want string + wantErr bool + }{ + { + name: "enforce", + setup: func() { enforce = true }, + want: "enforce", + }, + { + name: "complain", + setup: func() { complain = true }, + want: "complain", + }, + { + name: "kill", + setup: func() { kill = true }, + want: "kill", + }, + { + name: "default_allow", + setup: func() { defaultAllow = true }, + want: "default_allow", + }, + { + name: "unconfined", + setup: func() { unconfined = true }, + want: "unconfined", + }, + { + name: "prompt", + setup: func() { prompt = true }, + want: "prompt", + }, + { + name: "no mode set", + setup: func() {}, + wantErr: true, + }, + { + name: "two modes set", + setup: func() { enforce = true; complain = true }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + resetFlags(t) + tt.setup() + got, err := selectedMode() + if (err != nil) != tt.wantErr { + t.Fatalf("selectedMode() error = %v, wantErr %v", err, tt.wantErr) + } + if err == nil && got != tt.want { + t.Errorf("selectedMode() = %q, want %q", got, tt.want) + } + }) + } +} + +func TestAaSetMode(t *testing.T) { + tests := []struct { + name string + profile string + mode string + want string + wantErr bool + }{ + { + name: "add complain to unflagged profile", + profile: "profile foo /usr/bin/foo {\n}\n", + mode: "complain", + want: "profile foo /usr/bin/foo flags=(complain) {\n}\n", + }, + { + name: "replace complain with kill", + profile: "profile foo /usr/bin/foo flags=(complain) {\n}\n", + mode: "kill", + want: "profile foo /usr/bin/foo flags=(kill) {\n}\n", + }, + { + name: "enforce removes mode flag", + profile: "profile foo /usr/bin/foo flags=(complain) {\n}\n", + mode: "enforce", + want: "profile foo /usr/bin/foo {\n}\n", + }, + { + name: "unknown mode errors", + profile: "profile foo /usr/bin/foo {\n}\n", + mode: "bogus", + wantErr: true, + }, + { + name: "unconfined profile is never modified", + profile: "profile foo /usr/bin/foo flags=(unconfined) {\n}\n", + mode: "complain", + want: "profile foo /usr/bin/foo flags=(unconfined) {\n}\n", + }, + { + name: "unconfined profile preserved even when setting unconfined", + profile: "profile foo /usr/bin/foo flags=(attach_disconnected, unconfined) {\n}\n", + mode: "unconfined", + want: "profile foo /usr/bin/foo flags=(attach_disconnected, unconfined) {\n}\n", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + resetFlags(t) + path := tempDir(t).Join("foo") + if err := path.WriteFile([]byte(tt.profile)); err != nil { + t.Fatalf("write profile: %v", err) + } + err := aaSetMode(paths.PathList{path}, tt.mode) + if (err != nil) != tt.wantErr { + t.Fatalf("aaSetMode() error = %v, wantErr %v", err, tt.wantErr) + } + if tt.wantErr { + return + } + got, err := path.ReadFileAsString() + if err != nil { + t.Fatalf("read profile: %v", err) + } + if got != tt.want { + t.Errorf("profile content = %q, want %q", got, tt.want) + } + }) + } +} + diff --git a/cmd/aa/main.go b/cmd/aa/main.go index 5d32e93314..ba066b914f 100644 --- a/cmd/aa/main.go +++ b/cmd/aa/main.go @@ -1,5 +1,5 @@ // apparmor.d - Full set of apparmor profiles -// Copyright (C) 2024 Alexandre Pujol +// Copyright (C) 2021-2026 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only package main @@ -15,51 +15,29 @@ import ( "github.com/roddhjav/apparmor.d/pkg/paths" ) -const usage = `aa [-h] [--lint | --format | --tree] [-s] [-F file] [profiles...] +const usage = `aa [-h] [profiles...] - Various AppArmor profiles development tools + Various unprivileged AppArmor profiles tools. + +Command: + lint Lint the AppArmor profiles. + format Format the AppArmor profiles. + tree Generate a tree of visited profiles. Options: - -h, --help Show this help message and exit. - -f, --format Format the AppArmor profiles. - -l, --lint Lint the AppArmor profiles. - -t, --tree Generate a tree of visited profiles. - -F, --file FILE Set a logfile or a suffix to the default log file. - -s, --systemd Parse systemd logs from journalctl. + -h, --help Show this help message and exit. ` // Command line options var ( help bool - path string - systemd bool - lint bool - format bool - tree bool -) - -type kind uint8 - -const ( - isProfile kind = iota - isAbstraction - isTunable + command string ) func init() { flag.BoolVar(&help, "h", false, "Show this help message and exit.") flag.BoolVar(&help, "help", false, "Show this help message and exit.") - flag.BoolVar(&lint, "l", false, "Lint the AppArmor profiles.") - flag.BoolVar(&lint, "lint", false, "Lint the AppArmor profiles.") - flag.BoolVar(&format, "f", false, "Format the AppArmor profiles.") - flag.BoolVar(&format, "format", false, "Format the AppArmor profiles.") - flag.BoolVar(&tree, "t", false, "Generate a tree of visited profiles.") - flag.BoolVar(&tree, "tree", false, "Generate a tree of visited profiles.") - flag.StringVar(&path, "F", "", "Set a logfile or a suffix to the default log file.") - flag.StringVar(&path, "file", "", "Set a logfile or a suffix to the default log file.") - flag.BoolVar(&systemd, "s", false, "Parse systemd logs from journalctl.") - flag.BoolVar(&systemd, "systemd", false, "Parse systemd logs from journalctl.") } func getIndentationLevel(input string) int { @@ -75,13 +53,13 @@ func getIndentationLevel(input string) int { return level } -func parse(kind kind, profile string) (aa.ParaRules, []string, error) { +func parse(kind aa.FileKind, profile string) (aa.ParaRules, []string, error) { var raw string paragraphs := []string{} rulesByParagraph := aa.ParaRules{} switch kind { - case isTunable, isProfile: + case aa.TunableKind, aa.ProfileKind: f := &aa.AppArmorProfileFile{} nb, err := f.Parse(profile) if err != nil { @@ -90,7 +68,7 @@ func parse(kind kind, profile string) (aa.ParaRules, []string, error) { lines := strings.Split(profile, "\n") raw = strings.Join(lines[nb:], "\n") - case isAbstraction: + case aa.AbstractionKind: raw = profile } @@ -103,7 +81,7 @@ func parse(kind kind, profile string) (aa.ParaRules, []string, error) { return rulesByParagraph, paragraphs, nil } -func formatFile(kind kind, profile string) (string, error) { +func formatFile(kind aa.FileKind, profile string) (string, error) { rulesByParagraph, paragraphs, err := parse(kind, profile) if err != nil { return "", err @@ -111,40 +89,27 @@ func formatFile(kind kind, profile string) (string, error) { for idx, rules := range rulesByParagraph { aa.IndentationLevel = getIndentationLevel(paragraphs[idx]) rules = rules.Merge().Sort().Format() - profile = strings.ReplaceAll(profile, paragraphs[idx], rules.String()+"\n") + fmt.Print(rules.String() + "\n") } return profile, nil } -// getKind checks if the file is a full apparmor profile file or an -// included (abstraction or tunable) file. -func getKind(file *paths.Path) kind { - dirname := file.Parent().String() - switch { - case strings.Contains(dirname, "abstractions"): - return isAbstraction - case strings.Contains(dirname, "tunables"): - return isTunable - default: - return isProfile - } -} - func aaFormat(files paths.PathList) error { for _, file := range files { if !file.Exist() { return nil } - profile, err := file.ReadFileAsString() + + raw, err := file.ReadFileAsString() if err != nil { return err } - profile, err = formatFile(getKind(file), profile) + raw, err = formatFile(aa.KindFromPath(file), raw) if err != nil { return err } - if err := file.WriteFile([]byte(profile)); err != nil { + if err := file.WriteFile([]byte(raw)); err != nil { return err } logging.Success("Formatted: %s", file) @@ -152,31 +117,15 @@ func aaFormat(files paths.PathList) error { return nil } -func aaTree() error { +func aaLint(files paths.PathList) error { + for _, file := range files { + fmt.Printf("wip: %v\n", file) + } return nil } -func pathsFromArgs() (paths.PathList, error) { - res := paths.PathList{} - for _, arg := range flag.Args() { - path := paths.New(arg) - switch { - case !path.Exist(): - return nil, fmt.Errorf("file %s not found", path) - case path.IsDir(): - files, err := path.ReadDirRecursiveFiltered(nil, - paths.FilterOutDirectories(), - paths.FilterOutNames("README.md"), - ) - if err != nil { - return nil, err - } - res = append(res, files...) - case path.Exist(): - res = append(res, path) - } - } - return res, nil +func aaTree() error { + return nil } func main() { @@ -186,24 +135,39 @@ func main() { flag.Usage() os.Exit(0) } + if len(flag.Args()) < 1 { + flag.Usage() + os.Exit(1) + } + + command = flag.Args()[0] + if err := flag.CommandLine.Parse(flag.Args()[1:]); err != nil { + logging.Fatal("%s", err.Error()) + } var err error var files paths.PathList - switch { - case lint: + switch command { + case "lint": + files, err = paths.PathListFromArgs(flag.Args(), aa.MagicRoot) + if err != nil { + logging.Fatal("%s", err.Error()) + } + err = aaLint(files) - case format: - files, err = pathsFromArgs() + case "format": + files, err = paths.PathListFromArgs(flag.Args(), aa.MagicRoot) if err != nil { logging.Fatal("%s", err.Error()) } err = aaFormat(files) - case tree: + case "tree": err = aaTree() default: flag.Usage() + os.Exit(1) } if err != nil { diff --git a/cmd/prebuild/main.go b/cmd/prebuild/main.go index fab6b8f350..205677b9b8 100644 --- a/cmd/prebuild/main.go +++ b/cmd/prebuild/main.go @@ -5,69 +5,61 @@ package main import ( + "github.com/roddhjav/apparmor.d/pkg/builder" + "github.com/roddhjav/apparmor.d/pkg/configure" + "github.com/roddhjav/apparmor.d/pkg/paths" "github.com/roddhjav/apparmor.d/pkg/prebuild" - "github.com/roddhjav/apparmor.d/pkg/prebuild/builder" "github.com/roddhjav/apparmor.d/pkg/prebuild/cli" - "github.com/roddhjav/apparmor.d/pkg/prebuild/prepare" + "github.com/roddhjav/apparmor.d/pkg/runtime" + "github.com/roddhjav/apparmor.d/pkg/tasks" ) // Cli arguments have priority over the settings entered here -func init() { +func configInit() *tasks.TaskConfig { + c := tasks.NewTaskConfig(cli.GetPrebuildRoot()) + // Define the default ABI - prebuild.ABI = 4 + c.ABI = 4 // Define the default version - prebuild.Version = 4.0 - - // Define the tasks applied by default - prepare.Register( - "synchronise", // Initialize a new clean apparmor.d build directory - "ignore", // Ignore profiles and files from dist/ignore - "merge", // Merge profiles (from group/, profiles-*-*/) to a unified apparmor.d directory - "configure", // Set distribution specificities - "setflags", // Set flags as definied in dist/flags - "overwrite", // Overwrite dummy upstream profiles - "systemd-default", // Set systemd unit drop in files for dbus profiles - ) - - // Build tasks applied by default - builder.Register( - "userspace", // Resolve variable in profile attachments - "hotfix", // Temporary fix for #74, #80 & #235 - ) - - // Compatibility with AppArmor 3 - switch prebuild.Distribution { + c.Version = 4.1 + + // Matrix of ABI/Apparmor version to integrate with + switch tasks.Distribution { + case "opensuse": + c.ABI = 5 + c.Version = 5.0 + case "arch": case "ubuntu": - switch prebuild.Release["VERSION_CODENAME"] { + switch tasks.Release["VERSION_CODENAME"] { case "jammy": - prebuild.ABI = 3 - prebuild.Version = 3.0 - case "noble", "oracular": - prebuild.ABI = 4 - prebuild.Version = 4.0 - case "plucky": - prebuild.ABI = 4 - prebuild.Version = 4.1 + c.ABI = 3 + c.Version = 3.0 + case "noble": + c.ABI = 4 + c.Version = 4.0 + case "questing": + c.ABI = 4 + c.Version = 4.0 + case "resolute": + c.ABI = 5 + c.Version = 5.0 } case "debian": - switch prebuild.Release["VERSION_CODENAME"] { + switch tasks.Release["VERSION_CODENAME"] { case "bullseye", "bookworm": - prebuild.ABI = 3 - prebuild.Version = 3.0 - case "trixie", "sid": - prebuild.ABI = 4 - prebuild.Version = 4.1 + c.ABI = 3 + c.Version = 3.0 } case "whonix": - prebuild.ABI = 3 - prebuild.Version = 3.0 + c.ABI = 3 + c.Version = 3.0 - // Hide rewrittem Whonix profiles + // Hide rewritten Whonix profiles prebuild.Hide += `/etc/apparmor.d/abstractions/base.d/kicksecure /etc/apparmor.d/home.tor-browser.firefox /etc/apparmor.d/tunables/homsanitycheck @@ -81,9 +73,47 @@ func init() { /etc/apparmor.d/whonix-firewall ` } + return c } func main() { - cli.Configure() - cli.Prebuild() + cli.ParseFlags() + c := configInit() + r := runtime.NewRunners(c) + + // Add default configure tasks + r.Configures. + // Initialize a new clean apparmor.d build directory + Add(configure.NewSynchronise( + []*paths.Path{paths.New("apparmor.d"), paths.New("share")}, + )). + + // Ignore profiles and files from dist/ignore + Add(configure.NewIgnore()). + + // Merge profiles (from group/, profiles-*-*/) to a unified apparmor.d directory + Add(configure.NewMerge()). + + // Set distribution specificities + Add(configure.NewConfigure()). + + // Overwrite dummy upstream profile + Add(configure.NewOverwrite(false)). + + // Set systemd unit drop in files for dbus profiles + Add(configure.NewSystemdDefault()) + + // Default build tasks + r.Builders. + // Resolve variable in profile attachments + Add(builder.NewUserspace()). + + // Temporary fix for #74, #80 & #235 + Add(builder.NewHotFix()). + + // Use base-strict as base abstraction + Add(builder.NewBaseStrict()) + + r = cli.Configure(r) + cli.Prebuild(r) } diff --git a/cmd/prebuild/main_test.go b/cmd/prebuild/main_test.go deleted file mode 100644 index d3c28f0253..0000000000 --- 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.hide b/debian/apparmor.d.hide deleted file mode 100644 index 20725a1338..0000000000 --- a/debian/apparmor.d.hide +++ /dev/null @@ -1 +0,0 @@ -# This file is generated by "make", all edit will be lost. diff --git a/debian/changelog b/debian/changelog index 4ba7f268c2..a1e5c7ef60 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,51 @@ +apparmor.d (0.4907.0-1) stable; urgency=medium + + * Release apparmor.d v0.4907.0 + + -- Alexandre Pujol Fri, 03 Apr 2026 00:28:39 +0200 + +apparmor.d (0.4906-1) stable; urgency=medium + + * Release apparmor.d v0.4906 + + -- Alexandre Pujol Sat, 21 Mar 2026 00:42:01 +0100 + +apparmor.d (0.4905-1) stable; urgency=medium + + * Release apparmor.d v0.4905 + + -- Alexandre Pujol Tue, 03 Mar 2026 22:02:14 +0100 + +apparmor.d (0.4904-1) stable; urgency=medium + + * Release apparmor.d v0.4904 + + -- Alexandre Pujol Wed, 11 Feb 2026 22:53:39 +0100 + +apparmor.d (0.4903-1) stable; urgency=medium + + * Release apparmor.d v0.4903 + + -- Alexandre Pujol Thu, 05 Feb 2026 00:19:20 +0100 + +apparmor.d (0.4902-1) stable; urgency=medium + + * Release apparmor.d v0.4902 + + -- Alexandre Pujol Sun, 11 Jan 2026 01:01:26 +0100 + +apparmor.d (0.4901-1) stable; urgency=medium + + * Release apparmor.d v0.4901 + + -- Alexandre Pujol Fri, 09 Jan 2026 19:26:50 +0100 + +apparmor.d (0.4900-1) stable; urgency=medium + + * Release apparmor.d v0.4900 + + -- Alexandre Pujol Tue, 23 Dec 2025 01:03:09 +0100 + apparmor.d (0.001-1) stable; urgency=medium * Release 0.001-1 diff --git a/debian/common.hide b/debian/common.hide new file mode 100644 index 0000000000..8fc1d019d1 --- /dev/null +++ b/debian/common.hide @@ -0,0 +1 @@ +# This file is generated by "just", all edit will be lost. diff --git a/debian/apparmor.d.postinst b/debian/common.postinst similarity index 74% rename from debian/apparmor.d.postinst rename to debian/common.postinst index 4e659173cf..dfb2b60845 100644 --- a/debian/apparmor.d.postinst +++ b/debian/common.postinst @@ -7,6 +7,6 @@ set -e #DEBHELPER# -systemctl is-active -q apparmor && systemctl reload apparmor ||: +deb-systemd-invoke reload apparmor.service || true exit 0 diff --git a/debian/apparmor.d.postrm b/debian/common.postrm similarity index 55% rename from debian/apparmor.d.postrm rename to debian/common.postrm index 4e659173cf..2d83cea75c 100644 --- a/debian/apparmor.d.postrm +++ b/debian/common.postrm @@ -7,6 +7,11 @@ set -e #DEBHELPER# -systemctl is-active -q apparmor && systemctl reload apparmor ||: +case "$1" in + remove|purge) + apparmor_parser --purge-cache 2>/dev/null || true + deb-systemd-invoke reload apparmor.service || true + ;; +esac exit 0 diff --git a/debian/control b/debian/control index 7f2028b0ee..2b61e694cf 100644 --- a/debian/control +++ b/debian/control @@ -1,11 +1,11 @@ Source: apparmor.d Section: admin -Priority: optional +Priority: standard Maintainer: Alexandre Pujol -Build-Depends: debhelper (>= 13.4), - debhelper-compat (= 13), - golang-any, +Build-Depends: debhelper-compat (= 13), + golang-go, config-package-dev, + just, Homepage: https://github.com/roddhjav/apparmor.d Vcs-Browser: https://github.com/roddhjav/apparmor.d Vcs-Git: https://github.com/roddhjav/apparmor.d.git @@ -14,9 +14,16 @@ Rules-Requires-Root: no Package: apparmor.d Architecture: any -Depends: apparmor-profiles -Conflicts: apparmor-profiles-extra -Provides: apparmor-profiles-extra -Description: Full set of AppArmor profiles (~ 1500 profiles) - apparmor.d is a set of over 1500 AppArmor profiles whose aim is to confine - most Linux based applications and processes. +Depends: apparmor-profiles, ${misc:Depends}, ${shlibs:Depends} +Conflicts: apparmor-profiles-extra, apparmor.d.enforced, +Description: Full set of AppArmor profiles (complain mode) + apparmor.d is a set of over 2000 AppArmor policies whose aim is to confine + most Linux based applications and processes. + +Package: apparmor.d.enforced +Architecture: any +Depends: apparmor-profiles, ${misc:Depends}, ${shlibs:Depends} +Conflicts: apparmor-profiles-extra, apparmor.d, +Description: Full set of AppArmor profiles (enforced mode) + apparmor.d is a set of over 2000 AppArmor policies whose aim is to confine + most Linux based applications and processes. diff --git a/debian/copyright b/debian/copyright index 771503801a..04900924fa 100644 --- a/debian/copyright +++ b/debian/copyright @@ -4,5 +4,13 @@ Upstream-Contact: Alexandre Pujol Source: https://gitlab.com/roddhjav/apparmor.d Files: * -Copyright: 2021-2023 Alexandre Pujol +Copyright: 2021-2025 Alexandre Pujol License: GPL-2 + +License: GPL-2 + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2. + . + On Debian systems, the complete text of version 2 of the GNU General + Public License can be found in `/usr/share/common-licenses/GPL-2' diff --git a/debian/rules b/debian/rules index a30a693df4..e091888d09 100755 --- a/debian/rules +++ b/debian/rules @@ -3,11 +3,47 @@ # Copyright (C) 2021-2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only +export DEB_BUILD_MAINT_OPTIONS = hardening=+all +export DEB_LDFLAGS_MAINT_APPEND = -Wl,-z,relro,-z,now + +# Include hardening flags +DPKG_EXPORT_BUILDFLAGS = 1 +include /usr/share/dpkg/buildflags.mk + +# Pass hardening flags to Go +export CGO_CPPFLAGS := $(CPPFLAGS) +export CGO_CFLAGS := $(CFLAGS) +export CGO_LDFLAGS := $(LDFLAGS) +export GOFLAGS := -buildmode=pie -trimpath -ldflags=-linkmode=external -mod=readonly -modcacherw + %: dh $@ --with=config-package # golang/1.19 compresses debug symbols itself. override_dh_dwz: -# do not run 'make check' by default as it can be long for dev package +# Disable golang buildsystem auto-detection. +# Debhelper auto-detects Go projects from go.mod and tries to use the golang +# buildsystem, which creates symlink structures incompatible with //go:embed. +# We use 'just' for building with manual hardening flags instead. +override_dh_auto_configure: override_dh_auto_test: + +override_dh_strip: + dh_strip --no-automatic-dbgsym + +override_dh_install: + dh_install + for pkgname in $(shell dh_listpackages); do \ + cp debian/common.hide debian/$${pkgname}.hide; \ + cp debian/common.postinst debian/$${pkgname}.postinst; \ + cp debian/common.postrm debian/$${pkgname}.postrm; \ + done + +override_dh_auto_build: + just build=.build/enforce enforce + just build=.build/complain complain + +override_dh_auto_install: + just build=.build/complain destdir="${CURDIR}/debian/apparmor.d" install + just build=.build/enforce destdir="${CURDIR}/debian/apparmor.d.enforced" install diff --git a/debian/upstream/metadata b/debian/upstream/metadata new file mode 100644 index 0000000000..9e4cbb47f4 --- /dev/null +++ b/debian/upstream/metadata @@ -0,0 +1,7 @@ +--- +Archive: GitHub +Bug-Database: https://github.com/roddhjav/apparmor.d/issues +Bug-Submit: https://github.com/roddhjav/apparmor.d/issues/new +Changelog: https://github.com/roddhjav/apparmor.d/tags +Repository: https://github.com/roddhjav/apparmor.d.git +Repository-Browse: https://github.com/roddhjav/apparmor.d diff --git a/debian/watch b/debian/watch new file mode 100644 index 0000000000..3717d945d3 --- /dev/null +++ b/debian/watch @@ -0,0 +1,5 @@ +Version: 5 + +Template: Github +Owner: roddhjav +Project: apparmor.d diff --git a/dists/apparmor.d.spec b/dists/apparmor.d.spec index 339d880366..8d51e90b72 100644 --- a/dists/apparmor.d.spec +++ b/dists/apparmor.d.spec @@ -7,7 +7,7 @@ # Warning: for development only, use https://build.opensuse.org/package/show/home:cboltz/apparmor.d for production use. Name: apparmor.d -Version: 0.0001 +Version: 0.4907.0 Release: 1%{?dist} Summary: Set of over 1500 AppArmor profiles License: GPL-2.0-only @@ -15,6 +15,7 @@ URL: https://github.com/roddhjav/apparmor.d Source0: %{name}-%{version}.tar.gz Requires: apparmor-profiles BuildRequires: distribution-release +BuildRequires: just BuildRequires: golang-packaging BuildRequires: apparmor-profiles @@ -25,32 +26,32 @@ AppArmor.d is a set of over 1500 AppArmor profiles whose aim is to confine most %autosetup %build -%make_build +just complain %install -%make_install +just destdir="%{buildroot}" install %posttrans -rm -f /var/cache/apparmor/* 2>/dev/null -systemctl is-active -q apparmor && systemctl reload apparmor ||: +apparmor_parser --purge-cache +%restart_on_update apparmor %files %license LICENSE %doc README.md %config /etc/apparmor.d/ /usr/bin/aa-log +/usr/bin/aa-mode %dir /usr/lib/systemd/system/*.service.d /usr/lib/systemd/system/*.service.d/apparmor.conf %dir /usr/lib/systemd/user/*.service.d /usr/lib/systemd/user/*.service.d/apparmor.conf -/usr/share/bash-completion/completions/aa-log - %dir /usr/share/zsh %dir /usr/share/zsh/site-functions -/usr/share/zsh/site-functions/_aa-log.zsh - -%doc %{_mandir}/man8/aa-log.8.gz +/usr/share/zsh/site-functions/_aa-*.zsh +/usr/share/bash-completion/completions/aa-* +%doc %{_mandir}/man1/aa-*.1.gz +%doc %{_mandir}/man8/aa-*.8.gz %changelog diff --git a/dists/build.sh b/dists/build.sh deleted file mode 100644 index 1f2e204c24..0000000000 --- a/dists/build.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env bash -# Build the package for Archlinux/openSUSE/Debian/Ubuntu -# Copyright (C) 2022-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - -# Usage: make [ dpkg | pkg | rpm ] - -set -eu -o pipefail - -readonly COMMAND="$1" -readonly OUTPUT="$PWD/.pkg" -readonly PKGNAME=apparmor.d -VERSION="0.$(git rev-list --count HEAD)" -readonly VERSION - -main() { - case "$COMMAND" in - pkg) - PKGDEST="$OUTPUT" makepkg --syncdeps --force --cleanbuild --noconfirm --noprogressbar - ;; - - dpkg) - dch --newversion="$VERSION-1" --urgency=medium --distribution="$(lsb_release -sc)" --controlmaint "Release $VERSION-1" - dpkg-buildpackage -b -d --no-sign - lintian || true - mv ../"${PKGNAME}_${VERSION}-1"_*.deb "$OUTPUT" - ;; - - rpm) - RPMBUILD_ROOT=$(mktemp -d /tmp/$PKGNAME.XXXXXX) - ARCH=$(uname -m) - readonly RPMBUILD_ROOT ARCH - - mkdir -p "$RPMBUILD_ROOT"/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS/tmp} - cp -p "dists/$PKGNAME.spec" "$RPMBUILD_ROOT/SPECS" - tar -czf "$RPMBUILD_ROOT/SOURCES/$PKGNAME-$VERSION.tar.gz" --transform "s,^,$PKGNAME-$VERSION/," ./* - - cd "$RPMBUILD_ROOT" - sed -i "s/^Version:.*/Version: $VERSION/" "SPECS/$PKGNAME.spec" - rpmbuild -bb --define "_topdir $RPMBUILD_ROOT" "SPECS/$PKGNAME.spec" - - mv "$RPMBUILD_ROOT/RPMS/$ARCH/"*.rpm "$OUTPUT" - rm -rf "$RPMBUILD_ROOT" - ;; - - *) ;; - esac -} - -mkdir -p "$OUTPUT" -main "$@" diff --git a/dists/docker.sh b/dists/docker.sh index 2e581883c0..5ce985bde4 100644 --- a/dists/docker.sh +++ b/dists/docker.sh @@ -4,7 +4,7 @@ # SPDX-License-Identifier: GPL-2.0-only # Usage: -# just package ubuntu24 +# just package ubuntu 24.04 # just package archlinux # just package opensuse @@ -15,17 +15,17 @@ readonly PREFIX="builder-" readonly PKGNAME=apparmor.d readonly VOLUME=/tmp/build readonly BUILDIR=/home/build/tmp -readonly OUTDIR=".pkg" -readonly OUTPUT="$PWD/$OUTDIR" -readonly DISTRIBUTION="${1:-}" -readonly RELEASE="${2:-}" -VERSION="0.$(git rev-list --count HEAD)" +readonly OUTPUT=".pkg" +readonly DISTRIBUTION="$1" +RELEASE="${2:-}" +FLAVOR="${3:-}" PACKAGER="$(git config user.name) <$(git config user.email)>" -readonly VERSION PACKAGER +[[ "$RELEASE" == "-" ]] && RELEASE="" +readonly RELEASE FLAVOR PACKAGER _start() { local img="$1" - docker start "$img" + docker start "$img" || return 1 } _is_running() { @@ -63,21 +63,28 @@ build_in_docker_makepkg() { docker pull "$BASEIMAGE/$dist" docker run -tid --name "$img" --volume "$VOLUME:$BUILDIR" \ --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 - mv "$VOLUME/$PKGNAME/$OUTDIR/$PKGNAME"-*.pkg.* "$OUTPUT" + docker exec --workdir="$BUILDIR/$PKGNAME" "$img" just build-pkg + mv "$VOLUME/$PKGNAME/$OUTPUT/$PKGNAME"*.pkg.* "$OUTPUT" } build_in_docker_dpkg() { local img dist="$1" target="$1" release="$2" - [[ "$dist" == whonix ]] && dist=debian - [[ "$release" == "13" ]] && release=trixie + [[ "$release" == 14 ]] && release="forky" + if [[ "$dist" == whonix ]]; then + dist=debian + fi img="$PREFIX$dist$release" + + # Adjustments for test flavor + if [[ "$FLAVOR" == "test" ]]; then + sed -i -e "s;just build=.build/complain complain;just build=.build/complain complain-test;" "$VOLUME/$PKGNAME/debian/rules" + fi + if _exist "$img"; then if ! _is_running "$img"; then _start "$img" @@ -87,15 +94,11 @@ build_in_docker_dpkg() { docker run -tid --name "$img" --volume "$VOLUME:$BUILDIR" \ --env DISTRIBUTION="$target" "$BASEIMAGE/$dist:$release" docker exec "$img" sudo apt-get update -q - docker exec "$img" sudo apt-get install -y config-package-dev lsb-release libdistro-info-perl - if [[ "$dist" == debian && "$release" == "12" ]]; then - aptopt=(-t bookworm-backports) - fi - docker exec "$img" sudo apt-get install -y "${aptopt[@]}" golang-go + docker exec "$img" sudo apt-get install -y config-package-dev lsb-release libdistro-info-perl golang-go fi - docker exec --workdir="$BUILDIR/$PKGNAME" "$img" bash dists/build.sh dpkg - mv "$VOLUME/$PKGNAME/$OUTDIR/${PKGNAME}_${VERSION}-1"_*.* "$OUTPUT" + docker exec --workdir="$BUILDIR/$PKGNAME" "$img" just build-dpkg + mv "$VOLUME/$PKGNAME/$OUTPUT/$PKGNAME"*.deb "$OUTPUT" } build_in_docker_rpm() { @@ -113,13 +116,14 @@ build_in_docker_rpm() { docker exec "$img" sudo zypper install -y distribution-release golang-packaging apparmor-profiles fi - docker exec --workdir="$BUILDIR/$PKGNAME" "$img" bash dists/build.sh rpm - mv "$VOLUME/$PKGNAME/$OUTDIR/$PKGNAME-$VERSION-"*.rpm "$OUTPUT" + docker exec --workdir="$BUILDIR/$PKGNAME" "$img" just build-rpm + mv "$VOLUME/$PKGNAME/$OUTPUT/$PKGNAME"*.rpm "$OUTPUT" } main() { case "$DISTRIBUTION" in archlinux) + sync build_in_docker_makepkg "$DISTRIBUTION" ;; diff --git a/dists/docstring.sh b/dists/docstring.sh new file mode 100644 index 0000000000..06b52b914d --- /dev/null +++ b/dists/docstring.sh @@ -0,0 +1,325 @@ +#!/usr/bin/env bash +# Generate markdown documentation from abstractions and tunables +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Usage: +# just docstring + +set -eu -o pipefail + +readonly ABSTRACTIONS_DIR="apparmor.d/abstractions" +readonly TUNABLES_DIR="apparmor.d/tunables" +readonly ABSTRACTIONS_DOCS_DIR="docs/abstractions/" +readonly TUNABLES_DOCS_DIR="docs/tunables/" + +# Extract description from abstraction file header +# Skips copyright/license and extracts meaningful comments +_get_docs() { + local file="$1" + while IFS= read -r line; do + [[ -z "$line" ]] && continue + [[ ! "$line" =~ ^# ]] && break + [[ "$line" =~ (Copyright|SPDX-License-Identifier|^#\ apparmor\.d\ ) ]] && continue + [[ "$line" =~ (LOGPROF-SUGGEST|NEEDS-VARIABLE) ]] && continue + [[ "$line" =~ ^#aa: ]] && continue + + local comment="${line#\# }" + if [[ $comment == "#" ]]; then + echo "" + elif [[ -n "$comment" ]]; then + echo "$comment" + fi + done < "$file" +} + +# Extract required variables from abstraction file +_get_variables() { + local file="$1" + grep "^# NEEDS-VARIABLE:" "$file" 2>/dev/null | sed 's/^# NEEDS-VARIABLE: //' | tr '\n' ', ' | sed 's/, $//' || true +} + +# Check if an abstraction is core (has no external includes) +# Returns 0 if core, 1 if not core +_is_core_abstraction() { + local file="$1" + local name="$2" + + # Get base name without path components + local base_name + base_name="$(basename "$name")" + + # Check for include directives, excluding self-includes to .d directories + while IFS= read -r line; do + # Skip comments and empty lines + [[ "$line" =~ ^[[:space:]]*# ]] && continue + [[ -z "$line" ]] && continue + + # Check for include directives + if [[ "$line" =~ ^[[:space:]]*include ]]; then + # Extract the included path + local included_path="${line#*> "$TUNABLES_DOCS_DIR/$category.md" + done < <(find "$TUNABLES_DIR" -type f -print0 | sort -z) +} + +# Generate documentation for abstractions +_generate_abstractions_docs() { + echo "Generating abstraction documentation..." + + while IFS= read -r -d '' file; do + name="${file#apparmor.d/abstractions/}" + # Skip files inside .d directories (e.g., bash.d/complete) + [[ "$name" == *".d/"* ]] && continue + category="$(_get_abstraction_type "$name" "$file")" + # echo "Processing: $file -> |$category|" + + docs="$(_get_docs "$file")" + variables="$(_get_variables "$file")" + + if [[ -z "$docs" && -z "$variables" ]]; then + continue + fi + printf "\n## %s\n\n" "$name" >> "$ABSTRACTIONS_DOCS_DIR/$category.md" + + if [[ -n "$docs" ]]; then + printf "%s\n" "$docs" >> "$ABSTRACTIONS_DOCS_DIR/$category.md" + fi + if [[ -n "$variables" ]]; then + printf "\n**Required variables:** %s\n" "$variables" >> "$ABSTRACTIONS_DOCS_DIR/$category.md" + fi + done < <(find "$ABSTRACTIONS_DIR" -type f -print0 | sort -z) +} + +mkdir -p "$ABSTRACTIONS_DOCS_DIR" "$TUNABLES_DOCS_DIR" +_init_files +_generate_abstractions_docs +_generate_tunables_docs diff --git a/dists/flags/arch.flags b/dists/flags/arch.flags index 8910bb2805..a50c0b3a07 100644 --- a/dists/flags/arch.flags +++ b/dists/flags/arch.flags @@ -1,4 +1,4 @@ aurpublish complain makepkg complain -mkinitcpio attach_disconnected,complain -pacman attach_disconnected,complain +mkinitcpio complain +pacman complain diff --git a/dists/flags/debian.flags b/dists/flags/debian.flags index 5e29c01538..f270d9e4c0 100644 --- a/dists/flags/debian.flags +++ b/dists/flags/debian.flags @@ -1,16 +1,23 @@ apt-helper complain +apt-methods-sqv complain +deb-systemd-helper complain +deb-systemd-invoke complain +debconf-escape complain dhclient complain dhclient-script complain dpkg complain dpkg-architecture complain dpkg-buildflags complain dpkg-checkbuilddeps complain +dpkg-db-backup complain dpkg-deb complain dpkg-divert complain dpkg-genbuildinfo complain dpkg-genchanges complain +dpkg-maintscript-helper complain dpkg-preconfigure complain dpkg-query complain +dpkg-scripts complain dpkg-split complain dpkg-status complain dpkg-trigger complain @@ -18,5 +25,5 @@ dpkg-vendor complain ifup complain macchanger complain run-parts complain -unattended-upgrade attach_disconnected,complain -unattended-upgrade-shutdown attach_disconnected,complain +unattended-upgrade complain +unattended-upgrade-shutdown complain diff --git a/dists/flags/main.flags b/dists/flags/main.flags index 06c3e3e27e..169cc88790 100644 --- a/dists/flags/main.flags +++ b/dists/flags/main.flags @@ -1,15 +1,12 @@ -# Common profile flags definition for all distributions -# File format: one profile by line using the format: ' ' +# Common profile mode for all distributions +# File format: one profile mode by line using the format: ' ' -bwrap attach_disconnected,mediate_deleted,complain -bwrap-app attach_disconnected,mediate_deleted,complain -default attach_disconnected,mediate_deleted,complain -default-sudo attach_disconnected,complain -systemd attach_disconnected,mediate_deleted,complain -systemd-service attach_disconnected,complain -systemd-user attach_disconnected,mediate_deleted,complain +# FSP only +systemd complain +systemd-user complain +sd complain +sdu complain -aa-notify complain akonadi_akonotes_resource complain akonadi_archivemail_agent complain akonadi_birthdays_resource complain @@ -30,9 +27,9 @@ akonadi_unifiedmailbox_agent complain anacron complain at complain atd complain -auditctl attach_disconnected,complain -auditd attach_disconnected,complain -augenrules attach_disconnected,complain +auditctl complain +auditd complain +augenrules complain avahi-autoipd complain avahi-browse complain avahi-publish complain @@ -45,12 +42,12 @@ cc-remote-login-helper complain cctk complain cockpit-askpass complain cockpit-bridge complain -cockpit-certificate-ensure attach_disconnected,complain +cockpit-certificate-ensure complain cockpit-certificate-helper complain cockpit-desktop complain -cockpit-session attach_disconnected,complain +cockpit-session complain cockpit-ssh complain -cockpit-tls attach_disconnected,complain +cockpit-tls complain cockpit-ws complain cockpit-wsinstance-factory complain cups-backend-beh complain @@ -73,66 +70,52 @@ cups-notifier-dbus complain cups-notifier-mailto complain cups-notifier-rss complain cups-pk-helper-mechanism complain -cupsd attach_disconnected,complain ddcutil complain -dino attach_disconnected,complain +decibels complain +dino complain discord complain discord-chrome-sandbox complain DiscoverNotifier complain -dkms attach_disconnected,complain +dkms complain dmsetup complain -dockerd attach_disconnected,complain +docker complain +dockerd complain dolphin complain downloadhelper complain +dracut-install complain drkonqi complain drkonqi-coredump-cleanup complain drkonqi-coredump-processor complain ephy-profile-migrator complain -epiphany attach_disconnected,complain -epiphany-search-provider complain +epiphany complain epiphany-webapp-provider complain evolution-user-prompter complain -fail2ban-client attach_disconnected,complain -fail2ban-server attach_disconnected,complain +fail2ban-client complain +fail2ban-server complain fdisk complain filezilla complain finalrd complain -firewall-applet attach_disconnected,complain +firewall-applet complain firewall-config complain -firewalld attach_disconnected,complain flameshot complain -flatpak attach_disconnected,mediate_deleted,complain -flatpak-app attach_disconnected,mediate_deleted,complain +flatpak complain flatpak-oci-authenticator complain -flatpak-portal attach_disconnected,complain -flatpak-session-helper attach_disconnected,complain +flatpak-session-helper-app complain flatpak-system-helper complain flatpak-validate-icon complain -fstrim complain fuse-overlayfs complain -fusermount complain gdk-pixbuf-thumbnailer complain gdm-generate-config complain gdm-runtime-config complain -gdm-session attach_disconnected,complain gdm-xsession complain -gimp complain gmenudbusmenuproxy complain gnome-browser-connector-host complain -gnome-control-center attach_disconnected,complain +gnome-control-center complain gnome-control-center-goa-helper complain gnome-disk-image-mounter complain -gnome-disks complain -gnome-extension-gsconnect complain gnome-extension-manager complain gnome-initial-setup complain -gnome-music attach_disconnected,complain -gnome-photos-thumbnailer complain gnome-remote-desktop-daemon complain -gnome-software complain -gnome-system-monitor attach_disconnected,complain -gnome-terminal-server complain -gnome-tweaks complain grub-bios-setup complain grub-editenv complain grub-file complain @@ -141,7 +124,7 @@ grub-glue-efi complain grub-kbdcomp complain grub-macbless complain grub-menulst2cfg complain -grub-mkconfig attach_disconnected,complain +grub-mkconfig complain grub-mkdevicemap complain grub-mkfont complain grub-mkimage complain @@ -160,24 +143,20 @@ grub-render-label complain grub-script-check complain grub-set-default complain grub-syslinux2cfg complain -gsd-printer attach_disconnected,complain gsd-wwan complain -gsettings complain gvfsd-dav complain gvfsd-wsdd complain hostnamectl complain hyprctl complain hyprlock complain -hyprpaper attach_disconnected,complain +hyprpaper complain hyprpicker complain hyprpm complain ibus-engine-table complain -ibus-memconf attach_disconnected,complain +ibus-memconf complain im-launch complain -install-info complain iwctl complain iwd complain -jitterentropy-rngd complain kaccess complain kactivitymanagerd complain kalendarac complain @@ -189,93 +168,111 @@ kauth-kded-smart-helper complain kauth-kinfocenter-dmidecode-helper complain kcminit complain kconf_update complain -kde-powerdevil attach_disconnected,mediate_deleted,complain +kde-powerdevil complain kde-systemd-start-condition complain kded complain +kdestroy complain +kdump_mem_estimator complain +kdump-config complain +kdump-tools-init complain,attach_disconnected +kernel complain kernel-install complain -keyboxd complain +kernel-postinst-kdump complain kglobalacceld complain -kgx complain +kinit complain kio_http_cache_cleaner complain kiod complain kioworker complain -konsole attach_disconnected,mediate_deleted,complain +klist complain +konsole complain kscreen_backend_launcher complain kscreen_osd_service complain -ksmserver attach_disconnected,mediate_deleted,complain +ksmserver complain ksplashqml complain -kwin_wayland attach_disconnected,mediate_deleted,complain +kwin_wayland complain kwin_wayland_wrapper complain kwin_x11 complain landscape-sysinfo complain landscape-sysinfo.wrapper complain -language-validate attach_disconnected,complain +language-validate complain +languagetool complain last complain lastlog complain libreoffice complain libvirt-dbus complain -libvirtd attach_disconnected,complain -lightdm attach_disconnected,complain +libvirtd complain +lightdm complain lightdm-session complain +linux-check-removal complain +linux-update-symlinks complain locale-gen complain localectl complain -localsearch complain -localsearch-control complain -localsearch-writeback complain -login attach_disconnected,complain +login complain loginctl complain -low-memory-monitor attach_disconnected,complain -lvm attach_disconnected,complain +low-memory-monitor complain +lsfd complain +lslocks complain +lsns complain +lvm complain lvmconfig complain lvmdump complain lvmpolld complain +machinectl complain man complain mate-notification-daemon complain -mdevctl complain -metadata-cleaner attach_disconnected,complain -mke2fs complain -ModemManager attach_disconnected,complain -mount attach_disconnected,complain -multipath attach_disconnected,complain +mdadm complain +mdadm-mkconf complain +ModemManager complain +mount complain +mullvad-exclude complain +multipath complain multipathd complain -netplan.script attach_disconnected,complain -networkctl attach_disconnected,complain +needrestart-hook complain +needrestart-notify complain +needrestart-restart complain +netplan complain +networkctl complain networkd-dispatcher complain -nm-online complain nm-openvpn-service-openvpn-helper complain nm-priv-helper complain nmcli complain nvidia-detector complain nvidia-persistenced complain -ollama attach_disconnected,complain -os-prober attach_disconnected,complain +ollama complain +oomctl complain +os-prober complain pam_kwallet_init complain -pam-tmpdir-helper complain -passimd attach_disconnected,complain -pkttyagent complain +passimd complain pkla-admin-identities complain +pkla-check-authorization complain +pkttyagent complain plank complain plasma_waitforname complain plasma-browser-integration-host complain plasma-discover complain -plasmashell attach_disconnected,mediate_deleted,complain +plasma-keyboard complain +plasma-login-greeter complain +plasma-login-wallpaper +plasmashell complain plymouth complain -plymouth-set-default-theme attach_disconnected,complain +plymouth-set-default-theme complain plymouthd complain -polkit-kde-authentication-agent attach_disconnected,complain,mediate_deleted +polkit-kde-authentication-agent complain +pollinate complain +pycompile complain qdbus complain remmina complain run-parts complain +runc complain runuser complain +rustdesk complain sdcv complain -sddm attach_disconnected,mediate_deleted,complain +sddm complain sddm-greeter complain -secure-time-sync attach_disconnected,complain +secure-time-sync complain sftp-server complain -signal-desktop attach_disconnected,complain -signal-desktop-chrome-sandbox complain sing-box complain -slirp4netns attach_disconnected,complain +slirp4netns complain snap complain snap-device-helper complain snap-discard-ns complain @@ -286,19 +283,20 @@ snapd complain snapd-apparmor complain snapshot complain speech-dispatcher complain +sshd-auth complain ssservice complain startplasma complain -startx attach_disconnected,complain -steam attach_disconnected,mediate_deleted,complain -steam-fossilize attach_disconnected,complain -steam-game-native attach_disconnected,complain -steam-game-proton attach_disconnected,complain -steam-gameoverlayui attach_disconnected,complain -steam-launch attach_disconnected,complain -steam-launcher attach_disconnected,complain -steam-runtime attach_disconnected,complain -steamerrorreporter attach_disconnected,complain -strawberry attach_disconnected,mediate_deleted,complain +startx complain +steam complain +steam-fossilize complain +steam-game-native complain +steam-game-proton complain +steam-gameoverlayui complain +steam-launch complain +steam-launcher complain +steam-runtime complain +steamerrorreporter complain +strawberry complain sulogin complain swtpm complain swtpm_ioctl complain @@ -306,84 +304,105 @@ swtpm_localca complain swtpm_setup complain sysstat-sa complain sysstat-sadc complain -systemd-analyze complain systemd-ask-password complain -systemd-binfmt attach_disconnected,complain +systemd-binfmt complain +systemd-bless-boot complain systemd-cgls complain systemd-cgtop complain -systemd-cryptsetup attach_disconnected,complain -systemd-dissect attach_disconnected,complain +systemd-cryptsetup complain +systemd-dissect complain systemd-escape complain -systemd-generator-bless-boot attach_disconnected,complain -systemd-generator-cloud-init attach_disconnected,complain -systemd-generator-cryptsetup attach_disconnected,complain -systemd-generator-debug attach_disconnected,complain -systemd-generator-ds-identify attach_disconnected,complain +systemd-generator-bless-boot complain +systemd-generator-cloud-init complain +systemd-generator-cryptsetup complain +systemd-generator-debug complain +systemd-generator-ds-identify complain systemd-generator-environment-arch complain systemd-generator-environment-flatpak complain -systemd-generator-fstab attach_disconnected,complain -systemd-generator-getty attach_disconnected,complain -systemd-generator-gpt-auto attach_disconnected,complain -systemd-generator-hibernate-resume attach_disconnected,complain -systemd-generator-integritysetup attach_disconnected,complain -systemd-generator-ostree attach_disconnected,complain -systemd-generator-run attach_disconnected,complain -systemd-generator-system-update attach_disconnected,complain -systemd-generator-user-autostart attach_disconnected,complain -systemd-generator-user-environment attach_disconnected,complain -systemd-generator-veritysetup attach_disconnected,complain -systemd-homed attach_disconnected,complain +systemd-generator-environment-snapd complain +systemd-generator-friendly-recovery complain +systemd-generator-fstab complain +systemd-generator-getty complain +systemd-generator-gpt-auto complain +systemd-generator-hibernate-resume complain +systemd-generator-import complain +systemd-generator-integritysetup complain +systemd-generator-openvpn complain +systemd-generator-ostree complain +systemd-generator-rc-local complain +systemd-generator-run complain +systemd-generator-snapd complain +systemd-generator-ssh complain +systemd-generator-sshd-socket complain +systemd-generator-system-update complain +systemd-generator-sysv complain +systemd-generator-tpm2 complain +systemd-generator-user-autostart complain +systemd-generator-user-environment complain +systemd-generator-veritysetup complain +systemd-homed complain systemd-homework complain -systemd-inhibit attach_disconnected,complain -systemd-journald attach_disconnected,mediate_deleted +systemd-importd complain +systemd-inhibit complain +systemd-initctl complain systemd-mount complain systemd-network-generator complain systemd-portabled complain -systemd-remount-fs complain -systemd-resolve complain -systemd-shutdown complain systemd-sleep-tlp complain systemd-socket-proxyd complain -systemd-udevd attach_disconnected,complain -systemd-user-sessions attach_disconnected,complain -systemd-userwork attach_disconnected,complain +systemd-sysext complain +systemd-sysupdate complain +systemd-udevd complain +systemd-user-sessions complain +systemd-userwork complain systemsettings complain telegram-desktop complain -totem attach_disconnected,complain +timedatectl complain +totem complain tracker-writeback complain ucf complain +ucfq complain +ucfr complain +udev-ata_id complain +udev-bcache-export-cached complain +udev-cdrom_id complain udev-dmi-memory-id complain +udev-fido_id complain +udev-hdparm complain +udev-probe-bcache complain udisksctl complain -udisksd attach_disconnected,complain +udisksd complain ufw complain +umu-run complain +update-catalog complain update-grub complain +update-info-dir complain update-secureboot-policy complain +update-shells complain +updatectl complain userdbctl complain -utempter attach_disconnected,complain +utempter complain veracrypt complain -virt-manager attach_disconnected,complain -virtinterfaced attach_disconnected,complain +virtinterfaced complain virtiofsd complain,attach_disconnected virtlockd complain virtnetworkd complain,attach_disconnected -virtnodedevd attach_disconnected,complain -virtsecretd attach_disconnected,complain -virtstoraged attach_disconnected,complain -waybar attach_disconnected,complain -wechat attach_disconnected,complain -wechat-appimage attach_disconnected,complain +virtnodedevd complain +virtsecretd complain +virtstoraged complain +waybar complain +wechat complain +wechat-appimage complain wg-quick complain -wsdd complain -xdg-dbus-proxy attach_disconnected,complain +whoopsie complain +whoopsie-preferences complain +xdg-dbus-proxy complain xdg-desktop-icon complain xdg-desktop-portal-kde complain xdg-desktop-portal-rewrite-launchers complain -xdg-desktop-portal-validate-icon attach_disconnected,complain -xdg-user-dirs-gtk-update complain +xdg-desktop-portal-validate-icon complain xdm-xsession complain xembedsniproxy complain -xfce-session attach_disconnected,complain +xfce-session complain xsettingsd complain -xwaylandvideobridge complain zpool complain - diff --git a/dists/flags/ubuntu.flags b/dists/flags/ubuntu.flags index a6d6bcc850..21485a53cb 100644 --- a/dists/flags/ubuntu.flags +++ b/dists/flags/ubuntu.flags @@ -1,25 +1,56 @@ -apport attach_disconnected,complain +apport complain apport-checkreports complain apport-gtk complain apt-esm-hook complain apt-esm-json-hook complain apt-helper complain +apt-methods-sqv complain +apt_news complain check-new-release-gtk complain +debconf-escape complain +deb-systemd-helper complain +deb-systemd-invoke complain +dhclient complain +dhclient-script complain do-release-upgrade complain +dpkg-architecture complain +dpkg-buildflags complain +dpkg-checkbuilddeps complain +dpkg complain +dpkg-db-backup complain +dpkg-deb complain +dpkg-divert complain dpkg-genbuildinfo complain +dpkg-genchanges complain +dpkg-maintscript-helper complain +dpkg-preconfigure complain +dpkg-query complain +dpkg-scripts complain +dpkg-split complain +dpkg-status complain +dpkg-trigger complain +dpkg-vendor complain +esm_cache complain +fanctl complain hwe-support-status complain +ifup complain list-oem-metapackages complain livepatch-notification complain +macchanger complain notify-reboot-required complain package-data-downloader complain -package-system-locked attach_disconnected,complain +package-system-locked complain release-upgrade-motd complain +run-parts complain software-properties-gtk complain ubuntu-advantage complain ubuntu-advantage-notification complain ubuntu-distro-info complain +ubuntu-fan-net complain ubuntu-report complain -update-manager attach_disconnected,complain +unattended-upgrade complain +unattended-upgrade-shutdown complain +update-manager complain update-motd-fsck-at-reboot complain update-motd-updates-available complain update-notifier complain diff --git a/dists/flags/whonix.flags b/dists/flags/whonix.flags index dc984d6906..77ce5492a8 100644 --- a/dists/flags/whonix.flags +++ b/dists/flags/whonix.flags @@ -1,20 +1,45 @@ anondate complain apt-helper complain +apt-methods-sqv complain +debconf-escape complain +deb-systemd-helper complain +deb-systemd-invoke complain +dhclient complain +dhclient-script complain +dpkg-architecture complain +dpkg-buildflags complain +dpkg-checkbuilddeps complain +dpkg complain +dpkg-db-backup complain +dpkg-deb complain +dpkg-divert complain dpkg-genbuildinfo complain -msgcollector complain +dpkg-genchanges complain +dpkg-maintscript-helper complain +dpkg-preconfigure complain +dpkg-query complain +dpkg-scripts complain +dpkg-split complain +dpkg-status complain +dpkg-trigger complain +dpkg-vendor complain +ifup complain +macchanger complain msgcollector-br-add complain +msgcollector complain msgcollector-generic-gui-message complain msgcollector-striphtml complain -msgdispatcher complain msgdispatcher-autostart complain +msgdispatcher complain msgdispatcher-delete complain msgdispatcher-dispatch complain open-link-confirmation complain -pam_faillock_not_if_x complain pam-abort-on-locked-password complain +pam_faillock_not_if_x complain pam-info complain rads complain -sdwdate attach_disconnected,complain +run-parts complain +sdwdate complain sdwdate-clock-jump complain sdwdate-gui complain sdwdate-start complain @@ -23,17 +48,17 @@ sensible-browser complain systemcheck-canary complain timesanitycheck complain tor-bootstrap-check complain -tor-consensus-valid-after complain -torbrowser attach_disconnected,complain +torbrowser complain torbrowser-glxtest complain torbrowser-plugin-container complain torbrowser-start complain torbrowser-updater complain torbrowser-updater-permission-fix complain -torbrowser-updater-permission-fix complain torbrowser-vaapitest complain torbrowser-wrapper complain -torbrowser-wrapper complain +tor-consensus-valid-after complain +unattended-upgrade complain +unattended-upgrade-shutdown complain +whonix-firewalld complain whonix-firewall-edit complain whonix-firewall-restarter complain -whonix-firewalld complain diff --git a/dists/ignore/main.ignore b/dists/ignore/main.ignore index 3cccf4c056..44fda8f0a1 100644 --- a/dists/ignore/main.ignore +++ b/dists/ignore/main.ignore @@ -2,13 +2,19 @@ # File format: one ignore by line, it can be a profile name or a directory to ignore # Contains profiles and configuration for full system confinement, only included -# when built with 'make full' +# when built with 'just fsp' apparmor.d/groups/_full +# Experimental system states +apparmor.d/tunables/multiarch.d/state + # Provided by other packages man # Work in progress profiles +apparmor.d/groups/code +apparmor.d/groups/cosmic apparmor.d/groups/steam +claude dunst plasma-discover diff --git a/dists/overwrite b/dists/overwrite index 1464f03ff2..b9002175b2 100644 --- a/dists/overwrite +++ b/dists/overwrite @@ -1,33 +1,54 @@ -# Apparmor 4.0 ships several profiles that allow userns and are otherwise -# unconfined. This file keeps track of them and allow apparmor.d to replace -# them by our own. +# Apparmor 4.0 and over ships a few profiles that can conflict with apparmor.d +# This file keeps track of them and allow apparmor.d to replace them by our own. # File format: one profile name by line. +# Overwrite unconfined upstream profiles that only allow userns brave chrome chromium +cockpit-desktop element-desktop epiphany firefox flatpak foliate +font-manager loupe -lsblk -lsusb msedge mullvad nautilus -openvpn opera os-prober plasmashell -remmina signal-desktop slirp4netns -steam systemd-coredump thunderbird -transmission -unix-chkpwd virtiofsd + +# Overwrite upstreamed profiles, our local version may be more up to date +unix-chkpwd + +# Overwrite some profiles recently added in apparmor while being already present in apparmor.d for a while +# They can be multiple justification for keeping our profiles here, or or the contrary using upstream ones: +# - Keep ours: If we/they use abstractions, tunable, rules, and integration with apparmor.d that would break if using the upstream profile +# - Drop ours: when upstream profiles is better (see pkg/prebuild/prepare/configure.go) +# +# It is more and more common that these profiles simply present incompatibilies with apparmor.d in general. +fusermount3 +hostname # Has @{bin} defined in header, would conflict with apparmor.d's @{bin} tunables +lsblk +lsusb +openvpn +pollinate +remmina +systemd-detect-virt # Missing integration with @{p_systemd} +transmission +usr.bin.papers +usr.bin.passt wg-quick +who + +# Cannot be used as libreoffice handle this path. Conflict with apparmor.d due to a missing abi version. +usr.lib.libreoffice.program.soffice.bin + diff --git a/dists/ubuntu/abstractions/trash b/dists/ubuntu/abstractions/trash deleted file mode 100644 index d9ad012217..0000000000 --- a/dists/ubuntu/abstractions/trash +++ /dev/null @@ -1,75 +0,0 @@ -abi , - -# requires - - owner @{user_config_dirs}/trashrc rw, - owner @{user_config_dirs}/trashrc.lock rwk, - owner @{user_config_dirs}/#@{int} rwk, - owner @{user_config_dirs}/trashrc.* rwl -> @{user_config_dirs}/#@{int}, - - owner @{run}/user/@{uid}/#@{int} rw, - owner @{run}/user/@{uid}/trash.so*.[0-9].slave-socket rwl -> @{run}/user/@{uid}/#@{int}, - - # Home trash location - owner @{user_share_dirs}/Trash/ rw, - owner @{user_share_dirs}/Trash/#@{int} rw, - owner @{user_share_dirs}/Trash/directorysizes{,.*} rwl -> @{user_share_dirs}/Trash/#@{int}, - owner @{user_share_dirs}/Trash/files/{,**} rw, - owner @{user_share_dirs}/Trash/info/ rw, - owner @{user_share_dirs}/Trash/info/*.trashinfo{,.*} rw, - owner @{user_share_dirs}/Trash/expunged/ rw, - owner @{user_share_dirs}/Trash/expunged/[0-9]* rw, - owner @{user_share_dirs}/Trash/expunged/[0-9]*/ rw, - owner @{user_share_dirs}/Trash/expunged/[0-9]*/** rw, - - # Partitions' trash location when the admin creates the .Trash/ folder in the top lvl dir - owner /media/*/.Trash/ rw, - owner /media/*/.Trash/@{uid}/ rw, - owner /media/*/.Trash/@{uid}/#@{int} rw, - owner /media/*/.Trash/@{uid}/directorysizes{,.*} rwl -> /media/*/.Trash/@{uid}/#@{int}, - owner /media/*/.Trash/@{uid}/files/{,**} rw, - owner /media/*/.Trash/@{uid}/info/ rw, - owner /media/*/.Trash/@{uid}/info/*.trashinfo{,.*} rw, - owner /media/*/.Trash/@{uid}/expunged/ rw, - owner /media/*/.Trash/@{uid}/expunged/[0-9]* rw, - owner /media/*/.Trash/@{uid}/expunged/[0-9]*/ rw, - owner /media/*/.Trash/@{uid}/expunged/[0-9]*/** rw, - - # Partitions' trash location when the admin doesn't create the .Trash/ folder in the top lvl dir - owner /media/*/.Trash-@{uid}/ rw, - owner /media/*/.Trash-@{uid}/#@{int} rw, - owner /media/*/.Trash-@{uid}/directorysizes{,.*} rwl -> /media/*/.Trash-@{uid}/#@{int}, - owner /media/*/.Trash-@{uid}/files/{,**} rw, - owner /media/*/.Trash-@{uid}/info/ rw, - owner /media/*/.Trash-@{uid}/info/*.trashinfo{,.*} rw, - owner /media/*/.Trash-@{uid}/expunged/ rw, - owner /media/*/.Trash-@{uid}/expunged/[0-9]* rw, - owner /media/*/.Trash-@{uid}/expunged/[0-9]*/ rw, - owner /media/*/.Trash-@{uid}/expunged/[0-9]*/** rw, - - # Removable media's trash location when the admin creates the .Trash/ folder in the top lvl dir - owner /media/*/*/.Trash/ rw, - owner /media/*/*/.Trash/@{uid}/ rw, - owner /media/*/*/.Trash/@{uid}/#@{int} rw, - owner /media/*/*/.Trash/@{uid}/directorysizes{,.*} rwl -> /media/*/*/.Trash/@{uid}/#@{int}, - owner /media/*/*/.Trash/@{uid}/files/{,**} rw, - owner /media/*/*/.Trash/@{uid}/info/ rw, - owner /media/*/*/.Trash/@{uid}/info/*.trashinfo{,.*} rw, - owner /media/*/*/.Trash/@{uid}/expunged/ rw, - owner /media/*/*/.Trash/@{uid}/expunged/[0-9]* rw, - owner /media/*/*/.Trash/@{uid}/expunged/[0-9]*/ rw, - owner /media/*/*/.Trash/@{uid}/expunged/[0-9]*/** rw, - - # Removable media's trash location when the admin doesn't create the .Trash/ folder in the top lvl dir - owner /media/*/*/.Trash-@{uid}/ rw, - owner /media/*/*/.Trash-@{uid}/#@{int} rw, - owner /media/*/*/.Trash-@{uid}/directorysizes{,.*} rwl -> /media/*/*/.Trash-@{uid}/#@{int}, - owner /media/*/*/.Trash-@{uid}/files/{,**} rw, - owner /media/*/*/.Trash-@{uid}/info/ rw, - owner /media/*/*/.Trash-@{uid}/info/*.trashinfo{,.*} rw, - owner /media/*/*/.Trash-@{uid}/expunged/ rw, - owner /media/*/*/.Trash-@{uid}/expunged/[0-9]* rw, - owner /media/*/*/.Trash-@{uid}/expunged/[0-9]*/ rw, - owner /media/*/*/.Trash-@{uid}/expunged/[0-9]*/** rw, - - include if exists diff --git a/docs/abstractions/.template/app.md b/docs/abstractions/.template/app.md new file mode 100644 index 0000000000..1bf125b422 --- /dev/null +++ b/docs/abstractions/.template/app.md @@ -0,0 +1,7 @@ +--- +title: App abstractions +tags: + - abstractions + - app + - layer 3 +--- diff --git a/docs/abstractions/.template/attached.md b/docs/abstractions/.template/attached.md new file mode 100644 index 0000000000..3f4adea181 --- /dev/null +++ b/docs/abstractions/.template/attached.md @@ -0,0 +1,14 @@ +--- +title: Attached abstractions +tags: + - abstractions + - attached + - special +--- + +These abstractions are used to manage special rule when re-attached paths are enabled. +When they are needed, they are **automatically** included in the profile as a drop-in replacement of the standard abstraction. See the [Re-attached path section](../development/internal.md#re-attached-path) for more details. + +!!! danger "Must not be used" + + The following abstractions must not be used manually. diff --git a/docs/abstractions/.template/common.md b/docs/abstractions/.template/common.md new file mode 100644 index 0000000000..cec62a18c6 --- /dev/null +++ b/docs/abstractions/.template/common.md @@ -0,0 +1,7 @@ +--- +title: Common abstractions +tags: + - abstractions + - common + - layer 2 +--- diff --git a/docs/abstractions/.template/core.md b/docs/abstractions/.template/core.md new file mode 100644 index 0000000000..d72bdf426b --- /dev/null +++ b/docs/abstractions/.template/core.md @@ -0,0 +1,7 @@ +--- +title: Core abstractions +tags: + - abstractions + - core + - layer 0 +--- diff --git a/docs/abstractions/.template/dbus.md b/docs/abstractions/.template/dbus.md new file mode 100644 index 0000000000..89f1bcaf31 --- /dev/null +++ b/docs/abstractions/.template/dbus.md @@ -0,0 +1,8 @@ +--- +title: Dbus abstractions +tags: + - abstractions + - dbus + - system +--- + diff --git a/docs/abstractions/.template/dev.md b/docs/abstractions/.template/dev.md new file mode 100644 index 0000000000..e83cdb167e --- /dev/null +++ b/docs/abstractions/.template/dev.md @@ -0,0 +1,7 @@ +--- +title: Dev abstractions +tags: + - abstractions + - dev + - system +--- diff --git a/docs/abstractions/.template/flatpak.md b/docs/abstractions/.template/flatpak.md new file mode 100644 index 0000000000..5bca9b91a2 --- /dev/null +++ b/docs/abstractions/.template/flatpak.md @@ -0,0 +1,9 @@ +--- +title: Flatpak abstractions +tags: + - abstractions + - flatpak + - system +--- + +These abstractions should only be used by the flatpak profiles. They provide the necessary rules to run Flatpak applications confined with AppArmor. They are designed to very closely match the [Flatpak Sandbox Permissions](https://docs.flatpak.org/en/latest/sandbox-permissions.html). Therefore, they are different to they host equivalents, as flatpak apps do not have access to the full host filesystem. diff --git a/docs/abstractions/.template/generic.md b/docs/abstractions/.template/generic.md new file mode 100644 index 0000000000..1d12b9ccb2 --- /dev/null +++ b/docs/abstractions/.template/generic.md @@ -0,0 +1,7 @@ +--- +title: Generic abstractions +tags: + - abstractions + - generic + - system +--- diff --git a/docs/abstractions/.template/mapping.md b/docs/abstractions/.template/mapping.md new file mode 100644 index 0000000000..844daf35c8 --- /dev/null +++ b/docs/abstractions/.template/mapping.md @@ -0,0 +1,9 @@ +--- +title: Mapping abstractions +tags: + - abstractions + - flatpak + - mapping +--- + +These abstractions should only be used in Full System Policy mode when a user is confined. See the [User Confinement section](../development/internal.md#user-confinement) for more details. diff --git a/docs/abstractions/.template/sys.md b/docs/abstractions/.template/sys.md new file mode 100644 index 0000000000..a81828ce71 --- /dev/null +++ b/docs/abstractions/.template/sys.md @@ -0,0 +1,7 @@ +--- +title: Sys abstractions +tags: + - abstractions + - sys + - system +--- diff --git a/docs/abstractions/.template/udev.md b/docs/abstractions/.template/udev.md new file mode 100644 index 0000000000..8b4a90ad32 --- /dev/null +++ b/docs/abstractions/.template/udev.md @@ -0,0 +1,7 @@ +--- +title: Udev abstractions +tags: + - abstractions + - udev + - system +--- diff --git a/docs/abstractions/index.md b/docs/abstractions/index.md new file mode 100644 index 0000000000..1c86ffbd4b --- /dev/null +++ b/docs/abstractions/index.md @@ -0,0 +1,120 @@ +--- +title: Abstractions +tags: + - abstractions +--- + +Abstractions enable resources from one profile to be shared with another and with the system. The table below lists currently supported interfaces, with links to further details for each interface. + +This project and the official apparmor-profiles project provide a large selection of abstractions to be included in profiles. They should always be used as they target wide compatibility across hardware and distributions while only allowing the bare minimum access. + +!!! example + + For instance, to allow download directory access instead of read and write permissions: + ```sh + owner @{HOME}/@{XDG_DOWNLOAD_DIR}/{,**} rw, + ``` + + You should write: + ```sh + include + ``` + +## Architecture + +Abstraction are structured in layers as follows: + +
+ +- **[Layer 0](core.md)** + + --- + + For core atomic functionalities. + + --- + + *This resource uses* `mesa`, `openssl`, `bash-strict`, `gtk-strict`... + +- **[Layer 1](generic.md)** + + --- + + For generic access. + + --- + + *This program needs this resource.* `nameservice-strict`, `authentication`, ... + +- **[Layer 2](kind.md)** + + --- + + For common kind of program. + + --- + + *This program kind is* a game, an electron app + +- **[Layer 3](app.md)** + + --- + + For application + + --- + + *This program is* `sudo`, `firefox` + +
+ +## System abstractions + +In addition to the above layers, there are abstractions that provide access to system specific part of the system resources. + +To use the terminology detailed earlier, these abstractions are `layer -1` + +
+ +- **[Dbus](dbus.md)** + + --- + + Specific to a dbus interface + + --- + + *This interfaces needs* `bus/system/org.freedesktop.ModemManager1` ... + +- **[sys](sys.md)** + + --- + + sys filesystem access + + --- + + *This program needs/has this resource.* `sys/input`, `sys/hmon`, ... + +- **[udev](udev.md)** + + --- + + For udev device access + + --- + + *This program kind is* `udev/input` + +- **[dev](dev.md)** + + --- + + For device access + + --- + + *This program kind is* `/dev/input` + +
+ diff --git a/docs/assets/avatar-icon.png b/docs/assets/avatar-icon.png new file mode 100644 index 0000000000..80170da1e9 Binary files /dev/null and b/docs/assets/avatar-icon.png differ diff --git a/docs/assets/stylesheets/extra.css b/docs/assets/stylesheets/extra.css index 8691707dbe..a472882313 100644 --- a/docs/assets/stylesheets/extra.css +++ b/docs/assets/stylesheets/extra.css @@ -1,22 +1,22 @@ -[data-md-color-scheme=default] { - --md-footer-fg-color: var(--md-text-color); - --md-footer-fg-color--light: #808080; - --md-footer-fg-color--lighter: #b6b6b6; - --md-footer-bg-color: transparent; - --md-footer-bg-color--dark: transparent; +[data-md-color-scheme="default"] { + --md-footer-bg-color: #ffffff; --pg-purple: #603aa0; --pg-red: #c0322f; - --pg-orange: #ac2f09; + --pg-orange: #ffa500; --pg-teal: #04756a; --pg-brown: #8d6e62; --pg-blue: #0e66ae; --pg-green: #2e7e31; --pg-blue-gray: #546d78; + + /* Custom accent color - warm amber-brown */ + --md-accent-fg-color: #a67c52; + --md-accent-fg-color--transparent: #a67c521a; + --md-accent-bg-color: #fff; } -[data-md-color-scheme=slate] { - --md-footer-bg-color: transparent; - --md-footer-bg-color--dark: var(--md-default-bg-color--darkest); +[data-md-color-scheme="slate"] { + --md-footer-bg-color: #0b0c0f; --pg-purple: #af94de; --pg-red: #ff6c6a; --pg-orange: #e97b5a; @@ -25,6 +25,16 @@ --pg-blue: #74b9f1; --pg-green: #72cd75; --pg-blue-gray: #9ab2bc; + + /* Custom accent color - lighter amber-brown for dark mode */ + --md-accent-fg-color: #d4a574; + --md-accent-fg-color--transparent: #d4a5741a; + --md-accent-bg-color: #000; +} + +.md-footer-meta { + background-color: var(--md-footer-bg-color); + border-top: .05rem solid var(--md-footer-bg-color); } /* Badge colors */ diff --git a/docs/concepts.md b/docs/concepts.md deleted file mode 100644 index eb4ccbbc42..0000000000 --- a/docs/concepts.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -title: Concepts ---- - -*One profile a day keeps the hacker away* - -There are over 50000 Linux packages and even more applications. It is simply not possible to write an AppArmor profile for all of them. Therefore, a question arises: - -**What to confine and why?** - -We take inspiration from the [Android/ChromeOS Security Model](https://arxiv.org/pdf/1904.05572v2.pdf), and we apply it to the Linux world. Modern [Linux security distributions](https://clip-os.org/en/) usually consider an immutable core base image with a carefully selected set of applications. Everything else should be sandboxed. Therefore, this project tries to confine all the *core* applications you will usually find in a Linux system: all systemd services, xwayland, network, bluetooth, your desktop environment, etc. Non-core user applications are out of scope as they should be sandboxed using a dedicated tool (minijail, bubblewrap, toolbox, etc). - -This is fundamentally different from how AppArmor is usually used on Linux servers as it is common to only confine the applications that face the internet and/or the users. - - -[android_model]: https://arxiv.org/pdf/1904.05572v2.pdf -[clipos]: https://clip-os.org/en/ -[write xor execute]: https://en.wikipedia.org/wiki/W%5EX - diff --git a/docs/configuration.md b/docs/configuration.md index dda450a85f..645f5a1d58 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -32,7 +32,7 @@ The profiles heavily use the **largely extended** [XDG directory variables](#xdg ``` 3. Then restart the AppArmor service to reload the profiles in the kernel: ```sh - sudo systemctl restart apparmor.service + sudo systemctl reload apparmor.service ``` ### Profile Additions @@ -41,7 +41,7 @@ You can extend any profile with your own rules by creating a file in the `/etc/a **Example** -By default, `nautilus` (and any file browser) only allows access to user files. Thus, your cannot browse system files such as `/etc/`, `/srv/`, `/var/`. You can change this behaviour by creating a local profile addition file for `nautilus`: +By default, `nautilus` (and any file browser) only allows access to user files. Thus, your cannot browse system files such as `/etc/`, `/srv/`, `/var/`. You can change this behavior by creating a local profile addition file for `nautilus`: 1. Create the file `/etc/apparmor.d/local/nautilus` and add the following rules in it: ```sh @@ -55,7 +55,7 @@ By default, `nautilus` (and any file browser) only allows access to user files. ``` 2. Then restart the AppArmor service to reload the profiles in the kernel: ```sh - sudo systemctl restart apparmor.service + sudo systemctl reload apparmor.service ``` ### XDG variables @@ -108,7 +108,7 @@ Please ensure that all personal directories you are using are well-defined XDG d | GPG | `@{XDG_GPG_DIR}` | `.gnupg` | | SSH | `@{XDG_SSH_DIR}` | `.ssh` | | Private | `@{XDG_PRIVATE_DIR}` | `.{p,P}rivate {p,P}rivate` | - | Passwords | `@{XDG_PASSWORD_STORE_DIR}` | `.password-store` | + | Passwords | `@{XDG_PASSWORDSTORE_DIR}` | `.password-store` | @@ -143,7 +143,7 @@ Please ensure that all personal directories you are using are well-defined XDG d | Books | `@{user_books_dirs}` | `@{HOME}/@{XDG_BOOKS_DIR} @{MOUNTS}/@{XDG_BOOKS_DIR}` | | Games | `@{user_games_dirs}` | `@{HOME}/@{XDG_GAMES_DIR} @{MOUNTS}/@{XDG_GAMES_DIR}` | | Private | `@{user_private_dirs}` | `@{HOME}/@{XDG_PRIVATE_DIR} @{MOUNTS}/@{XDG_PRIVATE_DIR}` | - | Passwords | `@{user_passwordstore_dirs}` | `@{HOME}/@{XDG_PASSWORD_STORE_DIR} @{MOUNTS}/@{XDG_PASSWORD_STORE_DIR}` | + | Passwords | `@{user_passwordstore_dirs}` | `@{HOME}/@{XDG_PASSWORDSTORE_DIR} @{MOUNTS}/@{XDG_PASSWORDSTORE_DIR}` | | Work | `@{user_work_dirs}` | `@{HOME}/@{XDG_WORK_DIR} @{MOUNTS}/@{XDG_WORK_DIR}` | | Mail | `@{user_mail_dirs}` | `@{HOME}/@{XDG_MAIL_DIR} @{MOUNTS}/@{XDG_MAIL_DIR}` | | Projects | `@{user_projects_dirs}` | `@{HOME}/@{XDG_PROJECTS_DIR} @{MOUNTS}/@{XDG_PROJECTS_DIR}` | @@ -171,9 +171,9 @@ All profiles use the variables defined above. Therefore, you can personalize the @{XDG_PROJECTS_DIR}+="go" ``` -- If you use Keepass, personalize `XDG_PASSWORD_STORE_DIR` with your password directory. Eg: +- If you use Keepass, personalize `XDG_PASSWORDSTORE_DIR` with your password directory. Eg: ```sh - @{XDG_PASSWORD_STORE_DIR}+="@{HOME}/.keepass/" + @{XDG_PASSWORDSTORE_DIR}+="@{HOME}/.keepass/" ``` - Add pacman integration with your AUR helper. Eg for `yay`: diff --git a/docs/development/abstractions.md b/docs/development/abstractions.md index 9390945f8a..3121e742b3 100644 --- a/docs/development/abstractions.md +++ b/docs/development/abstractions.md @@ -19,6 +19,27 @@ This project and the official apparmor-profiles project provide a large selectio All of these abstractions can be extended by a system admin by adding rules in a file under `/etc/apparmor.d/.d` where `` is the name of one of these abstractions. +## Architecture + +Abstraction are structured in layers as follows: + +- **Layer 0:** for core atomic functionalities. They cannot include other abstractions. + + E.g.: *this resource uses* `mesa`, `openssl`, `bash-strict`, `gtk`... + +- **Layer 1:** for generic access. Cannot be architecture or device specific. Needs to be agnostic. + + E.g.: *This program needs/has this resource.* `nameservice`, `authentication`, `base`, `shell`, `graphics`, `audio-client`, `desktop`, `kde`, `gnome`... + +- **Layer 2:** for common kind of program. Only present inside `abstraction/common`. Multiple layer 2 can be used alongside with layer 1 and 0 abstractions. + + E.g.: *This program kind is* is a game, an electron app, a gnome app, sandboxed with bwrap app, a systemd app... + +- **Layer 3:** for application. Only present inside `abstraction/app`. The use of a layer 3 abstraction usually means you should not use any other abstractions (but base). Not a strict rule, but a good practice. Mostly used to provide common rules for subprofiles where the subprofiles only need to add rules for the specific use case. + + E.g.: *This program is* `firefox`, `sudo`, `systemctl`, `pgrep`, `editor`, `chromium`... + + ## Application helper Abstraction that aims at including a complete set of rules for a given program. The calling profile only needs to add rules dependant of its use case/program. @@ -196,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`** @@ -206,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} @@ -213,7 +243,7 @@ A minimal set of rules for all electron based UI applications. It works as a *fu ### **`common/game`** -Core set of resources for any games on Linux. Runtimes such as sandboxing, wine, proton, game launchers should use this abstraction. +Core set of resources for any games on Linux. Runtimes such as sandboxing, wine, proton, game launchers should use this abstraction. This abstraction uses the following tunables: diff --git a/docs/development/autopkgtest.md b/docs/development/autopkgtest.md new file mode 100644 index 0000000000..18fbf6388f --- /dev/null +++ b/docs/development/autopkgtest.md @@ -0,0 +1,87 @@ +--- +title: Autopkgtest +--- + +**autopkgtest** is Debian's automated package testing framework that validates packages work correctly after installation in clean VM. To ensure real-world functionality, it performs integration testing by installing packages and running tests defined in `debian/tests/`. It is thus a good method to validate the apparmor profiles. + +!!! note + + The autopkgtest suite integration in apparmor.d is currently a work in progress + +**Workflow** + +1. Create a testing VM for autopkgtest +2. Run autopkgtest on a wide range of source package +3. Continuously collect AppArmor logs during the tests + + +## VM Setup and Management + +**Create the test VM** + +The test VM is a VM as defined in the [Development VM](vm.md) section, with a specific cloud-init configuration for autopkgtest. We use the same `setup-testbed` script to prepare the VM as `autopkgtest-build-qemu`. In addition, we ensure the VM is built with the lastest `apparmor.d` profiles in test mode. + +You can create the image, then the VM, and shut it down with: + +```sh +just img test +just create test +just halt test +``` + +Example: + +```sh +just img ubuntu 25.10 test +just create ubuntu25.10 test +just halt ubuntu25.10 test +``` + +**Update `apparmor.d` in the VM** + +Others VM defined in this project ships with a `aa-update` command that build and update the package. This does not apply to the `test` flavor because: + +1. We do not want to mount this project to a VM where the tests can be destructive +2. The `setup-testbed` script gets rid of most build dependencies for `apparmor.d` + +To update apparmor.d in the VM without creating a new image, use the `autopkgtest-update` command, it will build the package on the host, and install it in the VM: + +```sh +just autopkgtest-update +``` + +Example: + +```sh +just autopkgtest-update ubuntu 25.10 +``` + +## Test Execution Workflow + +The autopkgtest suite runs the tests for all source packages listed in `tests/autopkgtest/src-packages`. It installs each package in the test VM, runs its autopkgtest suite, and monitors AppArmor logs for any policy violations. It is possible to control the range of packages tested using alphabetical start and end points in the `tests/autopkgtest/autopkgtest.sh` script. + +To run the full suite for a Debian/Ubuntu system: + +```sh +just autopkgtest +``` + +Example: + +```sh +just autopkgtest ubuntu25.10 +``` + +## Log Analysis + +The full raw logs are available in the `.logs/autopkgtest/` directory. One can run the following commands to analyze the logs and generate missing rules: + +Report all collected logs using `aa-log` +```sh +just autopkgtest-log +``` + +Generate missing rules using `aa-log --rules` +```sh +just autopkgtest-rules +``` diff --git a/docs/development/build.md b/docs/development/build.md index 5145a84168..874abaa232 100644 --- a/docs/development/build.md +++ b/docs/development/build.md @@ -2,7 +2,7 @@ title: Building the profiles --- -The profiles in `apparmor.d` must not be used directly. They need to be prebuilt (by running `make`). This page documents all possibles prebuild tasks. It is not intended to be read by end user, and it is only targeted at developers and maintainers. +The profiles in `apparmor.d` must not be used directly. They need to be prebuilt (by running `just complain`). This page documents all possibles prebuild tasks. It is not intended to be read by end user, and it is only targeted at developers and maintainers. The build system is fully configurable, general usage can be seen with: ```sh @@ -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,26 @@ 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 see bus= name= label= #aa:exec [P|U|p|u|PU|pu|] profiles... #aa:only filters... #aa:exclude filters... @@ -66,6 +75,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. @@ -96,12 +111,6 @@ Install systemd unit drop in files from `systemd/default`. They configure the va *Enabled by default. Can be disabled in `cmd/prebuild/main.go`* -### **`systemd-early`** - -Install systemd unit drop in files from `systemd/early` to ensure some services start after AppArmor. THis task will be removed in the future, as it will not be needed any more. - -*Enabled by default. Can be disabled in `pkg/prebuild/cli/cli.go`* - ### **`fsp`** Configure AppArmor for full system policy. @@ -129,6 +138,12 @@ Resolve variables in profile attachments. It fixes issues with the userland AppA *Enabled by default. Can be disabled in `cmd/prebuild/main.go`* +### **`base-strict`** + +This task will use `base-strict` as base abstraction instead of `base`. + +*Enabled by default. Can be disabled in `cmd/prebuild/main.go`* + ### **`attach`** This task reattaches disconnected paths. See the [Re-attached path](internal.md#re-attached-path) page. It will: @@ -139,6 +154,16 @@ This task reattaches disconnected paths. See the [Re-attached path](internal.md# *Enabled when abi >= 4.0* +### **`stacked-dbus`** + +Stacked profile name is under the form `A//&B`. The resulting stacked name can be used in peer label rules. However, in dbus rules, + +Resolve peer label variable in dbus rules. It transforms peer label rules set from `label="@{p_dbus_session}"` to `label="A//&B"`. + +See: https://gitlab.com/apparmor/apparmor/-/issues/537#note_2699570190 + +*Enabled for Ubuntu 25.04+* + ### **`hotfix`** Temporary fix for #74, #80 & #235. Only an issue on Gnome, can be disabled on server. diff --git a/docs/development/dbus.md b/docs/development/dbus.md index e4133e5d14..ecd8674722 100644 --- a/docs/development/dbus.md +++ b/docs/development/dbus.md @@ -20,6 +20,8 @@ Default **system**, **session**, and **accessibility** bus access are provided w - `abstractions/bus-session` - `abstractions/bus-accessibility` +Do not use the dbus abstractions from apparmor in this project, they won't work as expected as the dbus daemon is confined. Furthermore, in `apparmor.d` there is no such thing as a strict dbus abstraction (`abstractions/dbus-strict`) as they are strict by default: bus access needs to be explicitly allowed using an interface abstraction or a directive. + ### Interfaces Access to common dbus interfaces is done using the abstractions under **[`abstractions/bus/`](https://github.com/roddhjav/apparmor.d/tree/main/apparmor.d/abstractions/bus)**. They are kept minimal on purpose. The goal is not to give full talk access an interface but to provide a *read-only* like view of it. It may be required to have a look at the dbus interface documentation to check what method can be safely allowed. @@ -43,10 +45,11 @@ We use a special [directive](directives.md) to generate more advanced dbus acces **``** -: Access type. Can be `own` or `talk`: +: Access type. Can be `own`, `talk`, or `see`: - - `own` means the profile owns the dbus interface. It is allowed to send and receive from anyone on this interface. - - `talk` means the profile can talk on a given interface to the profile that owns it (a label must be given under the `label` option). + - `own` means the profile owns the dbus interface. It is allowed to send and receive from anyone on this interface. It should only be used for profile owning the dbus interface. + - `talk` means the profile can talk on a given interface to the profile that owns it (a label must be given under the `label` option). It should only be used when full access to an interface is required. + - `see` means the profile can see a given interface, but cannot talk to it. It is mostly used for desktop integration, as it allows the profile to be seen by the desktop environment without giving it more access. **``** diff --git a/docs/development/directives.md b/docs/development/directives.md index 841bc66088..53e3bbc7a9 100644 --- a/docs/development/directives.md +++ b/docs/development/directives.md @@ -146,7 +146,6 @@ The `exec` directive is useful to allow executing transitions to a profile witho /etc/systemd/oomd.conf.d/{,**} r, @{run}/systemd/io.system.ManagedOOM rw, @{run}/systemd/io.systemd.ManagedOOM rw, - @{run}/systemd/notify rw, @{sys}/fs/cgroup/cgroup.controllers r, @{sys}/fs/cgroup/memory.pressure r, @{sys}/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/memory.* r, diff --git a/docs/development/guidelines.md b/docs/development/guidelines.md index fad9015818..76e0e0aee9 100644 --- a/docs/development/guidelines.md +++ b/docs/development/guidelines.md @@ -4,27 +4,26 @@ title: Guidelines ## Common structure -AppArmor profiles can be written without any specific guidelines. However, when you work with over 1500 profiles, you need a common structure among all the profiles. +AppArmor profiles can be written without any specific guidelines. However, when you work with over 1500 profiles, you need a common structure among all the profiles. -The logic behind it is that if a rule is present in a profile, it should only be in one place, making it easier to review profiles. +The logic behind it is that if a rule is present in a profile, it should only be in one place, making it easier to review profiles. For example, if a program needs to run executable binaries then the rules allowing it can only be in a specific rule block (just after the `@{exec_path} mr,` rule). It is therefore easy to ensure some profile features such as: * A profile has access to a given resource * A profile enforces a strict [write xor execute](https://en.wikipedia.org/wiki/W%5EX) (W^X) policy. -It also improves compatibilities and makes personalization easier thanks to the use of more variables. +It also improves compatibility and makes personalization easier thanks to the use of more variables. -## Guidelines +!!! danger "Why does it matter?" -!!! note + The structure presented below is more important than it looks. Without this it would be easy to miss some rules when reviewing profiles, making the whole system more opaque and less secure. - This profile guideline is still evolving, feel free to propose improvements - as long as they do not vary too much from the existing rules. +## Guidelines In order to ensure a common structure across the profiles, all new profile **must** follow the guidelines presented here. -The rules in the profile should be sorted in the rule ***block*** as follows: +The rules in the profile should be written in *blocks* of same rule type. Each *block* should be sorted in the profile as follows: | Order | Name | Example | |:-----:|:----:|:-------:| @@ -53,29 +52,30 @@ This rule order is taken from AppArmor with minor changes as we tend to: - Divide the file block into multiple subcategories - Put the block with the longer rules (`files`, `dbus`) after the other blocks -### The file block +### File sub-blocks -The file block should be sorted as follows: +The file block is usually the longest block in a profile. It should be written in sub-blocks of identical file types. +The file sub blocks **must** be sorted as follows. | Order | Description | Example | Link | |:-----:|:-----------:|:-------:|:------:| | **1** | The entry point of the profile | `@{exec_path} mr,` | [:octicons-link-external-24:](https://github.com/roddhjav/apparmor.d/blob/2e4788c51ef73798c0ac94993af3cd769723e8e4/apparmor.d/groups/gnome/gdm#L67) | -| **2** | The binaries and library required | `@{bin}/`, `@{lib}/`, `/opt/`. It is the only place where you can have `mr`, `rix`, `rPx`, `rUx`, `rPUX` rules. | [:octicons-link-external-24:](https://github.com/roddhjav/apparmor.d/blob/2e4788c51ef73798c0ac94993af3cd769723e8e4/apparmor.d/groups/gnome/gdm#L69-L76) | -| **3** | The shared resources | `/usr/share` | [:octicons-link-external-24:](https://github.com/roddhjav/apparmor.d/blob/2e4788c51ef73798c0ac94993af3cd769723e8e4/apparmor.d/groups/network/NetworkManager#L111-L120) | -| **4** | The system configuration | `/etc` | [:octicons-link-external-24:](https://github.com/roddhjav/apparmor.d/blob/2e4788c51ef73798c0ac94993af3cd769723e8e4/apparmor.d/groups/network/NetworkManager#L111-L120) | -| **5** | The system data | `/`, `/var`, `/boot` | [:octicons-link-external-24:](https://github.com/roddhjav/apparmor.d/blob/2e4788c51ef73798c0ac94993af3cd769723e8e4/apparmor.d/groups/gnome/tracker-extract#L83-L93) | -| **6** | The user data | `owner @{HOME}/` | [:octicons-link-external-24:](https://github.com/roddhjav/apparmor.d/blob/2e4788c51ef73798c0ac94993af3cd769723e8e4/apparmor.d/groups/gnome/tracker-extract#L96-L98) | -| **7** | The user configuration, cache and dotfiles | `@{user_cache_dirs}`, `@{user_config_dirs}`, `@{user_share_dirs}` | [:octicons-link-external-24:](https://github.com/roddhjav/apparmor.d/blob/2e4788c51ef73798c0ac94993af3cd769723e8e4/apparmor.d/groups/browsers/firefox#L179-L202) | -| **8** | Temporary and runtime data | `/tmp/`, `@{run}/`, `/dev/shm/` | [:octicons-link-external-24:]() | -| **9** | Sys files | `@{sys}/` | [:octicons-link-external-24:]() | -| **10** | Proc files | `@{PROC}/` | [:octicons-link-external-24:]() | -| **11** | Dev files | `/dev/` | [:octicons-link-external-24:]() | -| **12** | Deny rules | `deny` | [:octicons-link-external-24:]() | +| **2** | The binaries and library required | `@{bin}/`, `@{lib}/`, `/opt/`. It is the only place where you can have `mr`, `rix`, `rPx`, `rUx`, `rPUX` rules. | [:octicons-link-external-24:](https://github.com/roddhjav/apparmor.d/blob/2e4788c51ef73798c0ac94993af3cd769723e8e4/apparmor.d/groups/gnome/gdm#L69-L76) | +| **3** | The shared resources | `/usr/share` | [:octicons-link-external-24:](https://github.com/roddhjav/apparmor.d/blob/2e4788c51ef73798c0ac94993af3cd769723e8e4/apparmor.d/groups/network/NetworkManager#L111-L120) | +| **4** | The system configuration | `/etc` | [:octicons-link-external-24:](https://github.com/roddhjav/apparmor.d/blob/2e4788c51ef73798c0ac94993af3cd769723e8e4/apparmor.d/groups/network/NetworkManager#L111-L120) | +| **5** | The system data | `/`, `/var`, `/boot` | [:octicons-link-external-24:](https://github.com/roddhjav/apparmor.d/blob/2e4788c51ef73798c0ac94993af3cd769723e8e4/apparmor.d/groups/gnome/tracker-extract#L83-L93) | +| **6** | The user data | `owner @{HOME}/` | [:octicons-link-external-24:](https://github.com/roddhjav/apparmor.d/blob/2e4788c51ef73798c0ac94993af3cd769723e8e4/apparmor.d/groups/gnome/tracker-extract#L96-L98) | +| **7** | The user configuration, cache and dotfiles | `@{user_cache_dirs}`, `@{user_config_dirs}`, `@{user_share_dirs}` | [:octicons-link-external-24:](https://github.com/roddhjav/apparmor.d/blob/2e4788c51ef73798c0ac94993af3cd769723e8e4/apparmor.d/groups/browsers/firefox#L179-L202) | +| **8** | Temporary and runtime data | `/tmp/`, `@{run}/`, `/dev/shm/` | [:octicons-link-external-24:]() | +| **9** | Sys files | `@{sys}/` | [:octicons-link-external-24:]() | +| **10** | Proc files | `@{PROC}/` | [:octicons-link-external-24:]() | +| **11** | Dev files | `/dev/` | [:octicons-link-external-24:]() | +| **12** | Deny rules | `deny` | [:octicons-link-external-24:]() | -### The dbus block +### Dbus block -The dbus block should be sorted as follows: +Dbus rules must be written in a dedicated block just before the file block. The dbus block **must** be sorted as follows: - The system bus should be sorted *before* the session bus - The bind rules should be sorted *after* send & receive rules @@ -87,6 +87,7 @@ dbus send bus=session path=/org/freedesktop/DBus member={RequestName,ReleaseName} peer=(name=org.freedesktop.DBus, label="@{p_dbus_session}"), ``` + If there is no predictable label it can be omitted. ### Profile rules @@ -132,3 +133,6 @@ If there is no predictable label it can be omitted. ``` Does not help, and if generalized it would add a lot of complexity to any profiles. +#### :material-numeric-7-circle: Clarity over cleverness + +: Always prefer clarity to cleverness. E.g., if a rule is more explicit but longer, prefer it over a shorter but less explicit one. diff --git a/docs/development/integration.md b/docs/development/integration.md index de60c8c475..f80404ce7c 100644 --- a/docs/development/integration.md +++ b/docs/development/integration.md @@ -14,15 +14,43 @@ Although the integration test suite is intended to be run in a [Development VM]( ## Getting started -Prepare the test environment: +**Prepare the test environment:** ```sh -just img -just vm +just img +just create ``` -Run the integration tests on the test VM: +Example: ```sh -just integration +just img ubuntu 25.10 desktop +just create ubuntu25.10 desktop +``` + +**Install dependencies for the integration tests** +```sh +just tests-init +``` + +Example: +```sh +just tests-init ubuntu25.10 desktop +``` + +**Run the integration tests** + +It: synchronizes the tests, unmount the shared directory, then run the tests. +```sh +just tests-run +``` + +Example: +```sh +just tests-run ubuntu25.10 desktop +``` + +Partial tests can also be run. For example the following command will only run the tests in the `tests/integration/apt` directory on the `ubuntu25` `desktop` machine: +```sh +just tests-run ubuntu25.10 desktop apt ``` ## Create integration tests diff --git a/docs/development/internal.md b/docs/development/internal.md index c90391b048..9c3b13478a 100644 --- a/docs/development/internal.md +++ b/docs/development/internal.md @@ -209,8 +209,8 @@ The possible solutions are: ``` ## Udev rules - -See the **[kernel docs](https://raw.githubusercontent.com/torvalds/linux/master/Documentation/admin-guide/devices.txt)** to check the major block and char numbers used in `/run/udev/data/`. +c +See the **[kernel docs](https://www.kernel.org/doc/html/latest/admin-guide/devices.html)** to check the major block and char numbers used in `/run/udev/data/`. Special care must be given as sometimes udev numbers are allocated dynamically by the kernel. Therefore, the full range must be allowed: diff --git a/docs/development/roadmap.md b/docs/development/roadmap.md index e8a047a037..5efd8129a4 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 -- [ ] **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)) @@ -21,8 +28,27 @@ This is the current list of features that must be implemented to get to a stable - [ ] General documentation improvements - [ ] **General improvements** - - [ ] Provide a proper fix for #74, #80 & #235 - - [ ] The apt/dpkg profiles needs to be reworked + - [ ] 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) + +- [ ] **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 @@ -34,12 +60,22 @@ This is the current list of features that must be implemented to get to a stable - [ ] Fully rewrite the way user data is allowed / denied. The current implementation requires too much configuration to be usable by everyone. - [ ] Add a prompt listener to handle the user data access. -- [ ] **[Full System Policy](https://github.com/roddhjav/apparmor.d/issues/252)** +- [x] **[Full System Policy](https://github.com/roddhjav/apparmor.d/issues/252)** - [ ] Debug tool to show the profiles transition tree, and ensure no profile is missing - - [ ] Remove the `default` profile + - [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/development/tests.md b/docs/development/tests.md index df614b4fe0..c02427ae50 100644 --- a/docs/development/tests.md +++ b/docs/development/tests.md @@ -6,25 +6,48 @@ Misconfigured AppArmor profiles is one of the most effective ways to break someo **Current** -- [x] **[Build:](https://gitlab.com/roddhjav/apparmor.d/-/pipelines)** `make` - - Build the profiles for all supported distributions. - - All CI jobs validate the profiles syntax and ensure they can be safely loaded into a kernel. - - Ensure the profile entry point (`@{exec_path}`) is defined. - -- [x] **[Checks:](https://github.com/roddhjav/apparmor.d/blob/main/tests/check.sh)** `make check` checks basic style of profiles: - - Ensure apparmor.d header & licence - - Ensure 2 spaces indentation - - Ensure local include for profile and subprofiles - - Ensure abi 4 is used - - Ensure modern profile naming - - Ensure `vim:syntax=apparmor` - -- [x] **[Integration Tests:](integration.md)** `just integration ` - - Run simple CLI commands to ensure no logs are raised. - - Uses the [bats](https://github.com/bats-core/bats-core) test system. - - Run in the Github Action as well as in all local [test VM](vm.md). - -**Plan** +
+ +- :material-github:   **[Build](build.md)** `just complain` + + --- + + Build the profiles for all supported distributions. + + - [x] All CI jobs validate the profiles syntax and, + - [x] ensure they can be safely loaded into a kernel. + +- :octicons-check-24:   **[Checks](check.md)** `just check` + + --- + + Checks for common style and security issues: + + - [x] Security checks + - [x] Style and maintainability checks + +- :material-package:   **[Integration Tests](integration.md)** `just test-run` + + Run commands to ensure no logs are raised. + + --- + + - [x] Uses the [bats](https://github.com/bats-core/bats-core) test system. + - [x] Run in the Github Action as well as in all local [test VM](vm.md). + +- :material-test-tube:   **[Distribution Tests](autopkgtest.md)** `just autopkgtest` + + Run the autopkgtest suite for Ubuntu and Debian. + + --- + + - [x] Setup autopkgtest for Ubuntu. + - [x] Validate profiles on Ubuntu. + +
+ + +**Future** For more complex software suite, more integration tests need to be done. The plan is to run existing integration suite from these very software in an environment with `apparmor.d` profiles. diff --git a/docs/development/vm.md b/docs/development/vm.md index ead82ed0fa..1ca3851567 100644 --- a/docs/development/vm.md +++ b/docs/development/vm.md @@ -5,32 +5,54 @@ title: Development VM To ensure compatibility across distribution, this project ships a wide range of development and tests VM images. The test VMs can be built locally using [cloud-init](https://cloud-init.io/), [packer](https://www.packer.io/) on Qemu/KVM using Libvirt. No other hypervisor will be targeted for these tests. The files that generate these images can be found in the **[tests/packer](https://github.com/roddhjav/apparmor.d/tree/main/tests/packer)** directory. -The VMs are fully managed using a [justfile](https://github.com/casey/just) that provide an integration environment helper for `apparmor.d`. + +The VMs are fully managed using a [Justfile](https://github.com/casey/just) that provides an integration environment helper for `apparmor.d`. ```sh $ just ``` ``` -Integration environment helper for apparmor.d - Available recipes: - default # Show this help message - package dist # Build the apparmor.d package - img dist flavor # Build the image - vm dist flavor # Create the machine - up dist flavor # Start a machine - halt dist flavor # Stops the machine - destroy dist flavor # Destroy the machine - ssh dist flavor # Connect to the machine - list # List the machines - images # List the machine images - available # List the machine that can be created - integration dist flavor # Run the integration tests on the machine - lint # Run the linters - clean # Remove the machine images - get_ip dist flavor - get_osinfo dist + help # Show this help message + clean # Remove all build artifacts + + ... + + [vm] + img dist release flavor # Build the VM image + create osinfo flavor # Create the machine + up osinfo flavor # Start a machine + halt osinfo flavor # Stops the machine + reboot osinfo flavor # Reboot the machine + destroy osinfo flavor # Destroy the machine + snapshots osinfo flavor # List all snapshots for a machine + snapshot osinfo flavor snapname # Snapshot a machine + restore osinfo flavor snapname # Restore a machine to a specified snapshot + delete osinfo flavor snapname # Delete a specified snapshot from a machine + ssh osinfo flavor # Connect to the machine + mount osinfo flavor # Mount the shared directory on the machine + umount osinfo flavor # Unmout the shared directory on the machine + list # List the machines + images # List the VM images + available # List the VM images that can be created + + ... + +Build variables available: + build # Build directory (default: .build) + destdir # Installation destination (default: /) + pkgdest # Package output directory (default: /home/alex/06_Projects/Security/apparmor.d/.pkg) + opt # Prebuild option, only used for the dev install target (default: complain) + +Development variables available: + username # VM username (default: user) + password # VM password (default: user) + disk_size # VM disk size (default: 40G) + vcpus # VM CPU (default: 6) + ram # VM RAM (default: 4096) + +See https://apparmor.pujol.io/development/ for more information. ``` ## Requirements @@ -56,22 +78,26 @@ $ just available ``` ``` -Distribution Flavor -archlinux gnome -archlinux kde -archlinux server -archlinux xfce -debian12 gnome -debian12 kde -debian12 server -ubuntu24 server +Distribution Release Flavor +archlinux - gnome +archlinux - kde +debian 13 gnome +debian 13 server +debian 13 test +opensuse - gnome +opensuse - kde +ubuntu 24.04 server +ubuntu 25.05 desktop +ubuntu 25.05 kubuntu +ubuntu 25.10 test + ... ``` A VM image can be build with: ```sh -$ just img archlinux gnome +$ just img archlinux - gnome ``` The image will then be showed in the list of images: @@ -81,14 +107,14 @@ $ just images ``` ``` -Distribution Flavor Size Date -archlinux gnome 3.3G Mar 1 14:49 +OsInfo Flavor Size Date +archlinux gnome 3.5GB Sep 25 23:25 ``` The VM can then be created with: ```sh -$ just vm archlinux gnome +$ just create archlinux gnome ``` And connected to with: diff --git a/docs/development/workflow.md b/docs/development/workflow.md index 7737e3775e..f5bb7b0bc7 100644 --- a/docs/development/workflow.md +++ b/docs/development/workflow.md @@ -6,7 +6,7 @@ title: Workflow
-- :material-file-document:   **[Write a blanck profile](#add-a-blank-profile)** +- :material-file-document:   **[Write a blank profile](#add-a-blank-profile)**
@@ -36,7 +36,7 @@ title: Workflow Here is the bare minimum for the program `foo`: ``` sh # apparmor.d - Full set of apparmor profiles -# Copyright (C) 2024 You +# Copyright (C) 2025 You # SPDX-License-Identifier: GPL-2.0-only abi , @@ -57,7 +57,7 @@ profile foo @{exec_path} { ## Development Install -It is not recommended installing the full project *"manually"* (with `make`, `sudo make install`). The distribution specific packages are intended to be used in development as they include additional rule to ensure compatibility with upstream (see `debian/`, `PKGBUILD` and `dists/apparmor.d.spec`). +It is not recommended installing the full project *"manually"* (with `just complain`, `sudo just install`). The distribution specific packages are intended to be used in development as they include additional rule to ensure compatibility with upstream (see `debian/`, `PKGBUILD` and `dists/apparmor.d.spec`). Instead, install an individual profile or the development package, the following way. @@ -66,25 +66,25 @@ Instead, install an individual profile or the development package, the following === ":material-arch: Archlinux" ```sh - make pkg + just pkg ``` === ":material-ubuntu: Ubuntu" ```sh - make dpkg + just dpkg ``` === ":material-debian: Debian" ```sh - make dpkg + just dpkg ``` === ":simple-suse: openSUSE" ```sh - make rpm + just rpm ``` === ":material-docker: Docker" @@ -102,7 +102,7 @@ Instead, install an individual profile or the development package, the following **Format** ```sh -make dev name= +just dev ``` **Exampe** @@ -110,7 +110,7 @@ make dev name= : Testing the profile `pass` ``` - make dev name=pass + just dev pass ``` This: @@ -119,9 +119,6 @@ make dev name= - Install the profile to `/etc/apparmor.d/` - Load the profile by restarting the AppArmor service. - -More advanced development, like editing the abstractions or working over multiple profiles at the same time requires installing the full development package. - For this individual profile installation to work, the full package needs to be installed, regardless of the installation method ([dev](#development-package) or [stable](../install.md)). ## Program Profiling @@ -130,7 +127,7 @@ For this individual profile installation to work, the full package needs to be i To discover the access needed by a program, you can use the following tools: -1. Star the program in *complain* mode, let it initialize itself, then close it. +1. Start the program in *complain* mode, let it initialize itself, then close it. 1. Run **[`aa-log -r`](../usage.md#apparmor-log)**. It will: - Convert the logs to AppArmor rules. @@ -175,21 +172,15 @@ After 2 or 3 iterations, you should have a working profile. ## Development Settings -### Profile flags +### Profile mode -Flags for all profiles in this project are tracked under the [`dists/flags`](https://github.com/roddhjav/apparmor.d/tree/main/dists/flags) directory. It is used for profile that are not considered stable. Files in this directory should respect the following format: ` `, flags should be comma separated. +Mode for all profiles (`complain`, `enforce`...) in this project are tracked under the [`dists/flags`](https://github.com/roddhjav/apparmor.d/tree/main/dists/flags) directory. It is used for profile that are not considered stable. Files in this directory should respect the following format: ` `. For instance, to move `adb` in *complain* mode, edit **[`dists/flags/main.flags`](https://github.com/roddhjav/apparmor.d/blob/main/dists/flags/main.flags)** and add the following line: ```sh adb complain ``` -Beware, flags defined in this file overwrite flags in the profile. So you may need to add other flags. Example for `gnome-shell`: -```sh -gnome-shell attach_disconnected,mediate_deleted,complain -``` - - ### Ignore profiles It can be handy to not install a profile for a given distribution. Profiles and directories to ignore are tracked under the [`dists/ignore`](https://github.com/roddhjav/apparmor.d/tree/main/dists/ignore) directory. Files in this directory should respect the following format: ``. One ignore by line. It can be a profile name or a directory to ignore (relative to the project root). diff --git a/docs/enforce.md b/docs/enforce.md index 692cbd1e36..cd72646457 100644 --- a/docs/enforce.md +++ b/docs/enforce.md @@ -11,52 +11,71 @@ The default package configuration installs all profiles in *complain* mode. This - When reporting an issue, you **must** ensure the affected profiles are in complain mode. +**Prerequisite** + +As the `enforced` version of the package conficts with the default `apparmor.d` package, you need to uninstall it first: + === ":material-arch: Archlinux" - In the `PKGBUILD`, replace `make` by `make enforce`: + ```sh + sudo pacman -R apparmor.d + ``` + +=== ":material-ubuntu: Ubuntu" - ```diff - - make DISTRIBUTION=arch - + make enforce DISTRIBUTION=arch + ```sh + sudo apt purge apparmor.d ``` - Then, build the package with: `make pkg` +=== ":material-debian: Debian" -=== ":material-ubuntu: Ubuntu" + ```sh + sudo apt purge apparmor.d + ``` - In `debian/rules`, add the following lines: +=== ":simple-suse: openSUSE" - ```make - override_dh_auto_build: - make enforce + ```sh + sudo zypper remove apparmor.d ``` - Then, build the package with: `make dpkg` -=== ":material-debian: Debian" - - In `debian/rules`, add the following lines: +**Installation** + +=== ":material-arch: Archlinux" + + `apparmor.d.enforced` is available in the [Arch User Repository][aur]: - ```make - override_dh_auto_build: - make enforce + ```sh + yay -S apparmor.d.enforced # or your preferred AUR install method ``` - Then, build the package with: `make dpkg` +=== ":material-ubuntu: Ubuntu" -=== ":simple-suse: openSUSE" + Using the [pkg.pujol.io][repo] debian repository, install the package: + ```sh + sudo apt install apparmor.d.enforced + ``` - In `dists/apparmor.d.spec`, replace `%make_build` by `%make_build enforce` - ```diff - - %make_build - + %make_build enforce +=== ":material-debian: Debian" + + Using the [pkg.pujol.io][repo] debian repository, install the package: + ```sh + sudo apt install apparmor.d.enforced ``` - Then, build the package with: `make rpm` +=== ":simple-suse: openSUSE" + + openSUSE users need to add [cboltz](https://en.opensuse.org/User:Cboltz) repo on OBS: + + ```sh + zypper install apparmor.d.enforced + ``` === ":material-home: Partial Install" - Use the `make enforce` command to build instead of `make` + Use the `just enforce` command to build instead of `just complain` [aur]: https://aur.archlinux.org/packages/apparmor.d-git +[repo]: https://pkg.pujol.io diff --git a/docs/full-system-policy.md b/docs/full-system-policy.md index 80da55c2a6..7a87649091 100644 --- a/docs/full-system-policy.md +++ b/docs/full-system-policy.md @@ -4,9 +4,9 @@ title: Full system policy (FSP) !!! danger - Full system policy is still under early development: - - - Do not run this outside of a development VM! + Full system policy is still under development: + + - It is experimental, and it has only been tested on server. - This is an **advanced** feature, you should understand what you are doing before use. **You have been warned!!!** @@ -27,14 +27,14 @@ Particularly: - Every system application will be **blocked** if they do not have a profile. - Any non-standard system app need to be explicitly profiled and allowed to run. For instance, if you want to use your own proxy or VPN software, you need to ensure it is correctly profiled and allowed to run in the `systemd` profile. - Desktop environment must be explicitly supported, your UI will not start otherwise. Again, it is a **feature**. -- FSP mode will run unknown user application into the `default` profile. It might be enough for your application. If not you have to make a profile for it. - In FSP mode, all sandbox managers **must** have a profile. Then user sandboxed applications (flatpak, snap, etc) will work as expected. - +- PID 1 is the last program that should be confined. It does not make sense to confine only PID. All other programs must be confined first. +- User interactive shell must be confined. This is done through PAM and Role Based Access Control (RBAC). ## Installation -This feature is only enabled when the project is built with `make full`. [Early policy](https://gitlab.com/apparmor/apparmor/-/wikis/AppArmorInSystemd#early-policy-loads) load **must** also be enabled. Once `apparmor.d` has been installed in FSP mode, it is required to reboot to apply the changes. +This feature is only enabled when the project is built with `just fsp`. [Early policy](https://gitlab.com/apparmor/apparmor/-/wikis/AppArmorInSystemd#early-policy-loads) load **must** also be enabled. Once `apparmor.d` has been installed in FSP mode, it is required to reboot to apply the changes. In `/etc/apparmor/parser.conf` ensure you have: ``` @@ -45,109 +45,170 @@ Optimize=compress-fast === ":material-arch: Archlinux" - In `PKGBUILD`, replace `make` by `make full`: + In `PKGBUILD`, replace `just complain` by `just fsp-complain`: ```diff - - make - + make full + - just complain + + just fsp-complain ``` - Then, build the package with: `make pkg` + Then, build the package with: `just pkg` === ":material-ubuntu: Ubuntu" - In `debian/rules`, add the following lines: + In `debian/rules`, replace `just complain` by `just fsp-complain`: ```make - override_dh_auto_build: - make full + override_dh_auto_build: + - just complain + override_dh_auto_build: + + just fsp-complain ``` - Then, build the package with: `make dpkg` + Then, build the package with: `just dpkg` === ":material-debian: Debian" - In `debian/rules`, add the following lines: + In `debian/rules`, replace `just complain` by `just fsp-complain`: ```make - override_dh_auto_build: - make full + override_dh_auto_build: + - just complain + override_dh_auto_build: + + just fsp-complain ``` - Then, build the package with: `make dpkg` + Then, build the package with: `just dpkg` === ":simple-suse: openSUSE" - In `dists/apparmor.d.spec`, replace `%make_build` by `%make_build full` + In `dists/apparmor.d.spec`, replace `just complain` by `just fsp-complain`: ```diff - - %make_build - + %make_build full + %build + - just complain + %build + + just fsp-complain ``` - Then, build the package with: `make rpm` + Then, build the package with: `just rpm` === ":material-home: Partial Install" - Use the `make full` command to build instead of `make` + Use the `just fsp-complain` command to build instead of `just complain` +## Systemd -## Structure +The profiles dedicated for full system policies are maintained in the **[`_full`][full]** group. Systemd (as PID 1) is the entrypoint of the system, thus in FSP mode, it is also the entry point of the confinement. -The profiles dedicated for full system policies are maintained in the **[`_full`][full]** group. +```sh +systemd # PID 1, entrypoint, requires "Early policy" +├── systemd # To restart itself +├── systemd-generators-* # Systemd system and environment generators +└── sd # Internal service starter and config handler, handles all services + ├── Px or px, # Any service with profile + ├── Px -> # Any service without profile defined in the unit file (see systemd/full/systemd) + ├── &* # Stacked service as defined in the unit file (see systemd/full/systemd) + ├── sd-mount # Handles mount operations from services + ├── sd-umount # Handles unmount operations from services + ├── sd//systemctl # Internal system systemctl + └── systemd-user # Profile for 'systemd --user' + ├── systemd-user # To restart itself + ├── systemd-user-generators-* # Systemd user and environment generators + └── sdu # Handles all user services + ├── Px or px, # Any user service with profile + ├── Px -> # Any user service without profile defined in the unit file (see systemd/full/systemd) + ├── &* # Stacked user service as defined in the unit file (see systemd/full/systemd) + └── sdu//systemctl # Internal user systemctl +``` +
+
Overall architecture of the systemd profiles stack
+
-### Systemd +### Design rationale -**`systemd`** +The systemd profiles design aims at providing a flexible and secure confinement for systemd and its services while addressing several challenges: -This profile aims to confine PID 1. Systemd is (kind of obviously) a highly privileged program. The purpose of this profile is to transition to other less privileged program as soon as possible. On high security environments, it can also be used to strictly limit the list of allowed privileged program. +- Differentiate systemd (PID 1) and `system --user` +- Keep `systemd` and `systemd-user` as mininal as possible, and transition to less privileged profiles. +- Allow the executor profiles to handled stacked profiles. +- Most additions need to be done in the `sd`/`sdu` profile, not in `systemd`/`systemd-user`. +- Dedicated `sd-mount` / `sd-umount` profiles for most mount from the unit services. -- It allows internal systemd access, -- It allows starting all common root services. +### Profile `systemd` -To work as intended, all privileged services started by systemd **must** have a profile. For a given distribution, the list of these services can be found under: -```sh -/usr/lib/systemd/system-generators/* -/usr/lib/systemd/system-environment-generators/* -/usr/lib/systemd/system/*.service -``` +The profile for `systemd` (PID 1) does not specify an attachment path because it is directly loaded by systemd thanks to the [early policy](https://gitlab.com/apparmor/apparmor/-/wikis/AppArmorInSystemd#early-policy-loads) feature. -The main [fallback](#fallback) profile (`default`) is not intended to be used by privileged program or service. Such programs must have a dedicated profile and will fail otherwise. This is a **feature**, not a bug. +Systemd is (kind of obviously) a highly privileged program. The purpose of this profile is to transition to other less privileged program as soon as possible. It only allows transition to two kinds of profiles: -**`systemd-user`** +- The systemd executor (profile named `sd`) it is the systemd internal service starter and config handler. +- The system generators (profiles named `systemd-generators-*`), they are used at boot time to generate systemd unit files based on the current system configuration. -This profile is for `systemd --user`, it aims to confine userland systemd. It does not require a lot of access and is only intended to handle user services. +!!! note "Profile requirement" -- It allows internal systemd user access, -- It allows starting all common user services. + To work as intended, all system generators **must** have a profile. For a given distribution, the list of these generators can be found under `/usr/lib/systemd/system-generators/*` -To work as intended, userland services started by `systemd --user` **should** have a profile. For a given distribution, the list of these services can be found under: +### Profile `sd` -```sh -/usr/lib/systemd/user-environment-generators/* -/usr/lib/systemd/user-generators/* -/usr/lib/systemd/user/*.service -``` +`sd` is a profile for SystemD-executor run as root, it is used to run all services files and to encapsulate stacked services profiles (hence the short name to keep security attribute easy to read). It aims at reducing the size of the main systemd profile. + +In an even more secure environment, it can also be used to strictly limit the list of allowed services that can be started by systemd(1). +{ .annotate } + +1. **:construction: Work in Progress :construction:** + +!!! note "Profile requirement" + + To work as intended, all privileged services **must** have a profile. For a given distribution, the list of these services can be found under: + ``` + /usr/lib/systemd/system/*.service + /usr/lib/systemd/system-environment-generators/* + ``` + +### Profile `systemd-user` + +`sd` allow transition to `systemd-user`, the profile for `systemd --user`. It is only intended to handle user based sessions. -!!! info +Similarly to `systemd`, it only allows transition to two kinds of profiles: - To be allowed to run, additional root or user services may need to add extra rules inside the `usr/systemd.d` or `usr/systemd-user.d` directory. For example, when installing a new privileged service `foo` with [stacking](development/internal.md#no-new-privileges) you may need to add the following to `/etc/apparmor.d/usr/systemd.d/foo`: +- The systemd executor (profile named `sdu`) it is the systemd internal **user** service starter and config handler. +- The user generators, they are used at user session start to generate systemd unit files based on the current user configuration. + +!!! note "Profile requirement" + + To work as intended, all userland generators **must** have a profile For a given distribution, the list of these services can be found under: ``` - @{lib}/foo rPx -> systemd//&foo, + /usr/lib/systemd/user-environment-generators/* + /usr/lib/systemd/user-generators/* ``` -### Fallback +!!! info "Future Improvements" + + To differentiate user session started with `systemd --user` and a root session also started with `systemd --user`, future improvements will use apparmor namespace and will allow further restrictions of this profile. + +### Profile `sdu` + +`sdu` is a profile for SystemD-executor run as User, it is used to run all services files and to encapsulate stacked services profiles (hence the short name). It aims at reducing the size of the systemd-user profile. + +!!! note "Profile requirement" + + To work as intended, all userland services **must** have a profile For a given distribution. If it is to complex to ensure all services are profiled, you can add rules in a local addition file under `/etc/apparmor.d/usr/sdu.d`. + +## Role Based Access Control (RBAC) + +In FSP, interactive shell from the user must be confined. This is done through [pam_apparmor](https://gitlab.com/apparmor/apparmor/-/wikis/pam_apparmor). It provides [Role-based access controls (RBAC)](https://en.wikipedia.org/wiki/Role-based_access_control) that can restrict interactive shell to well-defined role. The role needs to be defined. This project ship with a default set of roles, but you can create your own. The default roles are: -In addition to the `systemd` profiles, a full system policy needs to ensure that no programs run in an unconfined state at any time. The fallback profiles consist of a set generic specialized profiles: +- **`user`**: This is the default role. It is used for any user that does not have a specific role defined. It has access to the user home directory and other sensitive files. -- **`default`** is used for any *classic* user application with a GUI. It has full access to user home directories. -- **`bwrap`, `bwrap-app`** are used for *classic* user application that are sandboxed with **bwrap**. +- **`admin`**: This role is used for any user that has administrative access. It has access to the system files and directories, but not to the user home directory. -!!! warning +The profiles dedicated for the roles definition are maintained in the **[`_roles`][role]** group. - The main fallback profile (`default`) is not intended to be used by privileged program or service. Such programs **must** have they dedicated profile and would break otherwise. +!!! note -Additionally, special user access can be setup using PAM rules set such as a random shell interactively opened (as user or as root). + The roles provided are only examples. It is recommended to create your own roles based on your needs. + For example, the play machine provides three roles: `root`, `play`, and `deploy`. See the [play machine](play.md) page for more details. [apparmor-wiki]: https://gitlab.com/apparmor/apparmor/-/wikis/FullSystemPolicy [full]: https://github.com/roddhjav/apparmor.d/blob/main/apparmor.d/groups/_full +[role]: https://github.com/roddhjav/apparmor.d/blob/main/apparmor.d/groups/_roles diff --git a/docs/index.md b/docs/index.md index 6f09983cba..88aa903699 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,48 +1,98 @@ --- title: AppArmor.d +hide: + - toc --- - + + -Building the largest set of AppArmor profiles: - -- [Linux Security Summit North America (LSS-NA 2023)](https://events.linuxfoundation.org/linux-security-summit-north-america/) *([Slide](https://lssna2023.sched.com/event/1K7bI/building-the-largest-working-set-of-apparmor-profiles-alexandre-pujol-the-collaboratory-tudublin), [Video](https://www.youtube.com/watch?v=OzyalrOzxE8))* -- [Ubuntu Summit 2023](https://events.canonical.com/event/31/) *([Slide](https://events.canonical.com/event/31/contributions/209/), [Video](https://www.youtube.com/watch?v=GK1J0TlxnFI))* - -### Chat - -A development chat is available on https://matrix.to/#/#apparmor.d:matrix.org +
+
+
+
+ +

apparmor.d

+

Full set of AppArmor policies

+

apparmor.d is a collection of AppArmor profiles designed to restrict the behavior of Linux applications and processes.

+

Its goal is to confine everything, targeting both desktops and servers across all distributions that support AppArmor.

+ + Get started + + + + Demo Server + + +
+
+
+
diff --git a/docs/install.md b/docs/install.md index ff4a1b6bb6..7529f6a834 100644 --- a/docs/install.md +++ b/docs/install.md @@ -37,14 +37,24 @@ The following desktop environments are supported: **Build dependency** * Go >= 1.23 +* [just](https://github.com/casey/just) >= 1.40.0 ## Configure AppArmor -As there are a lot of rules (~80k lines), it is recommended to enable fast caching compression of AppArmor profiles. In `/etc/apparmor/parser.conf`, add `write-cache` and `Optimize=compress-fast`: +As there are a lot of rules (~100k lines), it is recommended to enable fast caching compression of AppArmor profiles. [Early policy](https://gitlab.com/apparmor/apparmor/-/wikis/AppArmorInSystemd#early-policy-loads) load **must** also be enabled. +In `/etc/apparmor/parser.conf` ensure you have: +``` +write-cache +cache-loc /etc/apparmor/earlypolicy/ +Optimize=compress-fast +``` + +Or run: ```sh echo 'write-cache' | sudo tee -a /etc/apparmor/parser.conf +echo 'cache-loc /etc/apparmor/earlypolicy/' | sudo tee -a /etc/apparmor/parser.conf echo 'Optimize=compress-fast' | sudo tee -a /etc/apparmor/parser.conf ``` @@ -53,81 +63,69 @@ echo 'Optimize=compress-fast' | sudo tee -a /etc/apparmor/parser.conf === ":material-arch: Archlinux" - `apparmor.d-git` is available in the [Arch User Repository][aur]: - - ```sh - yay -S apparmor.d-git # or your preferred AUR install method - ``` - - Or without an AUR helper: + `apparmor.d` is available in the [Arch User Repository][aur]: ```sh - git clone https://aur.archlinux.org/apparmor.d-git.git - cd apparmor.d-git - makepkg -si + yay -S apparmor.d # or your preferred AUR install method ``` === ":material-ubuntu: Ubuntu" - Build the package from sources: + `apparmor.d` is available under the [pkg.pujol.io][repo] debian repository. + The repository is signed with my [GPG key][keys]. Configure it as follows: ```sh - sudo apt install apparmor-profiles build-essential config-package-dev debhelper golang-go rsync git - git clone https://github.com/roddhjav/apparmor.d.git - cd apparmor.d - dpkg-buildpackage -b -d --no-sign - sudo dpkg -i ../apparmor.d_*.deb + sudo apt-get install wget gnupg + wget -qO - https://pkg.pujol.io/debian/gpgkey \ + | gpg --dearmor \ + | sudo tee /usr/share/keyrings/roddhjav.gpg >/dev/null + cat <<-EOF | sudo tee /etc/apt/sources.list.d/roddhjav.sources + Types: deb + URIs: https://pkg.pujol.io/debian/repo + Suites: $(lsb_release -cs) + Components: main + Signed-By: /usr/share/keyrings/roddhjav.gpg + EOF + sudo apt-get update ``` - !!! tip - - If you have `devscripts` installed, you can use the one liner: - - ```sh - make dpkg - ``` + Install the package: + ```sh + sudo apt install apparmor.d + ``` !!! warning - **Beware**: do not install a `.deb` made for Debian on Ubuntu, the packages are different. - - If your distribution is based on Ubuntu, you may want to manually set the target distribution by exporting `DISTRIBUTION=ubuntu`. + Only Ubuntu `24.04`, `25.10`, and `26.04` are currently supported. === ":material-debian: Debian" - Build the package from sources: + `apparmor.d` is available under the [pkg.pujol.io][repo] debian repository. + The repository is signed with my [GPG key][keys]. Configure it as follows: ```sh - sudo apt install apparmor-profiles build-essential config-package-dev debhelper golang-go rsync git - git clone https://github.com/roddhjav/apparmor.d.git - cd apparmor.d - dpkg-buildpackage -b -d --no-sign - sudo dpkg -i ../apparmor.d_*.deb + sudo apt-get install wget gnupg + wget -qO - https://pkg.pujol.io/debian/gpgkey \ + | gpg --dearmor \ + | sudo tee /usr/share/keyrings/roddhjav.gpg >/dev/null + cat <<-EOF | sudo tee /etc/apt/sources.list.d/roddhjav.sources + Types: deb + URIs: https://pkg.pujol.io/debian/repo + Suites: $(lsb_release -cs) + Components: main + Signed-By: /usr/share/keyrings/roddhjav.gpg + EOF + sudo apt-get update ``` - !!! tip - - If you have `devscripts` installed, you can use the one liner: - - ```sh - make dpkg - ``` - - !!! note - - You may need golang from the backports repository to build: - - ```sh - echo 'deb http://deb.debian.org/debian bookworm-backports main contrib non-free' | sudo tee -a /etc/apt/sources.list - sudo apt update - sudo apt install -t bookworm-backports golang-go - ``` + Install the package: + ```sh + sudo apt install apparmor.d + ``` !!! warning - **Beware**: do not install a `.deb` made for Ubuntu on Debian, the packages are different. - - If your distribution is based on Debian, you may want to manually set the target distribution by exporting `DISTRIBUTION=debian`. + Only `trixie` is currently supported. === ":simple-suse: openSUSE" @@ -144,15 +142,15 @@ echo 'Optimize=compress-fast' | sudo tee -a /etc/apparmor/parser.conf For test purposes, you can install specific profiles with the following commands. Abstractions, tunable, and most of the OS dependent post-processing is managed. ```sh - make - sudo make profile-names... + just complain + sudo just local profile-names... ``` !!! warning Partial installation is discouraged because profile dependencies are not fetched. To prevent some AppArmor issues, the dependencies are automatically switched to unconfined (`rPx` -> `rPUx`). The installation process warns on the missing profiles so that you can easily install them if desired. (PR is welcome see [#77](https://github.com/roddhjav/apparmor.d/issues/77)) - For instance, `sudo make pass` gives: + For instance, `sudo just local pass` gives: ```sh Warning: profile dependencies fallback to unconfined. @{bin}/wl-{copy,paste} rPx, @@ -194,3 +192,5 @@ echo 'Optimize=compress-fast' | sudo tee -a /etc/apparmor/parser.conf ``` [aur]: https://aur.archlinux.org/packages/apparmor.d-git +[keys]: https://pujol.io/keys +[repo]: https://pkg.pujol.io diff --git a/docs/issues.md b/docs/issues.md index 1db3b195ae..2f38f4c5a1 100644 --- a/docs/issues.md +++ b/docs/issues.md @@ -6,28 +6,24 @@ title: Known issues Known bugs are tracked on the meta issue **[#75](https://github.com/roddhjav/apparmor.d/issues/74)**. -## Complain mode +## Ubuntu -A profile in *complain* mode cannot break the program it confines. However, there are some **major exceptions**: +### Dbus -1. `deny` rules are enforced even in *complain* mode, -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`. +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. -## Pacman "could not get current working directory" +### Snap -```sh -$ sudo pacman -Syu -... -error: could not get current working directory -:: Processing package changes... -... -``` +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. -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. +## Complain mode + +A profile in *complain* mode cannot break the program it confines. However, there are some **major exceptions**: -This provides a basic protection against some packages (on the AUR) that may have rogue install script. +1. `deny` rules are enforced even in *complain* mode, +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]: https://github.com/roddhjav/apparmor.d/blob/main/apparmor.d/groups/pacman/pacman diff --git a/docs/linter/checks/abi.md b/docs/linter/checks/abi.md new file mode 100644 index 0000000000..0d8ab5a4b2 --- /dev/null +++ b/docs/linter/checks/abi.md @@ -0,0 +1,33 @@ +--- +title: Abi +--- + +# `abi` + +Use of incorrect or missing ABI version. + +## Problematic rule + +```sh +# WRONG +abi , +``` + +```sh +# WRONG +# missing 'abi ,' +``` + +## Correct rule + +```sh +abi , +``` + +## Rationale + +All profiles in the project must use the same ABI version to ensure compatibility with the AppArmor kernel module and features. The current default ABI targeted by this project is `4.0`. + +## Exceptions + +None diff --git a/docs/linter/checks/abstractions.md b/docs/linter/checks/abstractions.md new file mode 100644 index 0000000000..0b93154519 --- /dev/null +++ b/docs/linter/checks/abstractions.md @@ -0,0 +1,51 @@ +--- +title: Abstractions +--- + +# `abstractions` + +Use of dangerous or deprecated abstractions + +## Problematic rule + +```sh +# WRONG +include +``` + +## Correct rule + +```sh +include +``` + +## Rationale + +Some abstractions provide more access than required, do not integrate with profiles defined in apparmor.d or with non-Ubuntu systems. + +The following abstractions are considered dangerous: + +- `dbus`: Full dbus access +- `dbus-accessibility`: Full dbus accessibility access +- `dbus-session`: Full dbus session access +- `dbus-system`: Full dbus system access +- `user-tmp`: Full access to user temporary files (See [too-wide](too-wide.md) check) + +Deprecated abstractions: + +- `bash` -> `shell`: `bash` does not cover all shells. +- `nameservice` -> `nameservice-strict`: `nameservice` gives network access which is not required in most cases. + +Deprecated abstractions, would conflict with apparmor.d integration + +- `dbus-accessibility-strict` -> `bus-accessibility` +- `dbus-network-manager-strict` -> `network-manager-observe` +- `dbus-session-strict` -> `bus-session` +- `dbus-system-strict` -> `bus-system` +- `gnome` -> `gnome-strict` +- `kde` -> `kde-strict` +- `X` -> `X-strict` + +## Exceptions + +None diff --git a/docs/linter/checks/bin.md b/docs/linter/checks/bin.md new file mode 100644 index 0000000000..893028356f --- /dev/null +++ b/docs/linter/checks/bin.md @@ -0,0 +1,39 @@ +--- +title: Bin +--- + +# `bin` / `sbin` + +Use of incorrect binary path in rules. + +## Problematic rule + +```sh +# WRONG +@{bin}/cron Px, +``` + +```sh +# WRONG +@{sbin}/pass Px, +``` + +## Correct rule + +```sh +@{sbin}/cron Px, +``` + +```sh +@{bin}/pass Px, +``` + +## Rationale + +To differentiate between system binaries and administrator binaries, `apparmor.d` uses two separate variables: `@{bin}` for regular binaries and `@{sbin}` for system binaries. + +The list of known path in `/usr/sbin` is maintained under the `sbin.list` file. + +## Exceptions + +Some binaries may be installed in both @{bin} and @{sbin} depending on the package it is installed from. For instance, upstream docker package installs `dockerd` in `/usr/bin/` while the distribution package installs it in `/usr/sbin/`. In such cases, both paths is required. diff --git a/docs/linter/checks/directory-mark.md b/docs/linter/checks/directory-mark.md new file mode 100644 index 0000000000..c8bafaf275 --- /dev/null +++ b/docs/linter/checks/directory-mark.md @@ -0,0 +1,28 @@ +--- +title: Directory Mark +--- + +# `directory-mark` + +Missing directory mark (trailing slash) in well-known directory paths. + +## Problematic rule + +```sh +# WRONG +owner @{HOME} r, +``` + +## Correct rule + +```sh +owner @{HOME}/ r, +``` + +## Rationale + +In AppArmor profiles, a directory path **must** be explicitly marked with a trailing slash (`/`) to indicate that it refers to a directory rather than to a file. + +## Exceptions + +None diff --git a/docs/linter/checks/equivalent.md b/docs/linter/checks/equivalent.md new file mode 100644 index 0000000000..1bdb3036d4 --- /dev/null +++ b/docs/linter/checks/equivalent.md @@ -0,0 +1,39 @@ +--- +title: Equivalent +--- + +# `equivalent` + +Missing rules to equivalent paths. + +## Problematic rule + +```sh +# WRONG +@{bin}/grep ix, +``` + +## Correct rule + +```sh +@{bin}/{,e}grep ix, +``` + +## Rationale + +In AppArmor profiles, certain binaries may have equivalent paths that need to be explicitly allowed to ensure proper functionality. + +For example, the `grep` binary can be accessed as both `grep` and `egrep` (`exec grep -E "$@"`). Failing to include rules for all equivalent paths **will** lead to unexpected denials in some distributions. + +The following equivalent paths exist: + +- `@{bin}/awk` -> `@{bin}/{m,g,}awk` +- `@{bin}/grep` -> `@{bin}/{,e}grep` +- `@{bin}/gs` -> `@{bin}/gs{,.bin}` +- `@{bin}/which` -> `@{bin}/which{,.debianutils}` +- `@{sbin}/xtables-legacy-multi` -> `@{sbin}/xtables-{nft,legacy}-multi` +- `@{bin}/xtables-nft-multi` -> `@{sbin}/xtables-{nft,legacy}-multi` + +## Exceptions + +None diff --git a/docs/linter/checks/header.md b/docs/linter/checks/header.md new file mode 100644 index 0000000000..be5e544c35 --- /dev/null +++ b/docs/linter/checks/header.md @@ -0,0 +1,19 @@ +--- +title: Header +--- + +# `header` + +Missing or incorrect profile header. + +All profile files **must** begin with a standardized header that includes the project name, copyright information, and SPDX licence identifier. + +```sh +# apparmor.d - Full set of apparmor profiles +# Copyright (C) +# SPDX-License-Identifier: GPL-2.0-only +``` + +## Exceptions + +None diff --git a/docs/linter/checks/include.md b/docs/linter/checks/include.md new file mode 100644 index 0000000000..d20a8b1acb --- /dev/null +++ b/docs/linter/checks/include.md @@ -0,0 +1,33 @@ +--- +title: Local include +--- + +# `include` + +Missing inclusion of local rule additions. + +## Problematic rule + +```sh +# WRONG +profile pass { + ... +} + +``` + +## Correct rule + +```sh +profile pass { + include if exists +} +``` + +## Rationale + +To allow for easier customization and extension of AppArmor profiles and subprofiles, all profiles and abstractions **must** include local rule additions. + +## Exceptions + +None diff --git a/docs/linter/checks/profile.md b/docs/linter/checks/profile.md new file mode 100644 index 0000000000..8da5aa54e8 --- /dev/null +++ b/docs/linter/checks/profile.md @@ -0,0 +1,50 @@ +--- +title: Profile / Subprofile +--- + +# `profile` / `subprofile` + +Missing or incorrect profile name. + +## Problematic rule + +```sh +cat /etc/apparmor.d/foo +# WRONG +profile myfoo { + ... +} +``` + +```sh +cat /etc/apparmor.d/foo +# WRONG +profile @{bin}/foo { + ... +} +``` + +## Correct rule + +```sh +cat /etc/apparmor.d/foo +profile foo { + ... +} +``` + +```sh +cat /etc/apparmor.d/foo +# WRONG +profile foo @{bin}/foo { + ... +} +``` + +## Rationale + +AppArmor profiles and subprofiles **must** have a name that matches the filename of the profile. Old syntax that includes profile attachment instead of a profile name **must** be avoided. + +## Exceptions + +None diff --git a/docs/linter/checks/tabs.md b/docs/linter/checks/tabs.md new file mode 100644 index 0000000000..5e492f5712 --- /dev/null +++ b/docs/linter/checks/tabs.md @@ -0,0 +1,11 @@ +--- +title: Tabs +--- + +# `tabs` + +Tabs are not allowed. 2 spaces **must** be used for indentation. + +## Exceptions + +None diff --git a/docs/linter/checks/too-wide.md b/docs/linter/checks/too-wide.md new file mode 100644 index 0000000000..cac09a5b0d --- /dev/null +++ b/docs/linter/checks/too-wide.md @@ -0,0 +1,44 @@ +--- +title: Rule too wide +--- + +# `too-wide` + +Rule too wide may lead to confinement escape or data leaks. + +## Problematic rule + +```sh +# WRONG +/tmp/** rw, +``` + +```sh +# WRONG +/etc/** rw, +``` + +## Correct rule + +Limit access to only required files as much as you can. For example: + +```sh +/tmp/@{rand6}/{,**} rw, +``` + +```sh +/etc//** rw, +``` + +## Rationale + +Full access to entire config and temporary directories is dangerous as it may allow confinement escape or data leaks. It is better to restrict access to only the required files or subdirectories. + +## Exceptions + +When a profile needs access to the full system, because it is a package manager for example. + +## Related Resources + +* [Access to `/tmp` breaks program isolation](https://github.com/roddhjav/apparmor.d/discussions/294) +* [Abusing Ubuntu 24.04 features for root privilege escalation](https://labs.snyk.io/resources/abusing-ubuntu-root-privilege-escalation/) diff --git a/docs/linter/checks/trailing.md b/docs/linter/checks/trailing.md new file mode 100644 index 0000000000..02739a5bd3 --- /dev/null +++ b/docs/linter/checks/trailing.md @@ -0,0 +1,11 @@ +--- +title: Trailing space +--- + +# `trailing` + +Trailing whitespace are not allowed. + +## Exceptions + +None diff --git a/docs/linter/checks/transition.md b/docs/linter/checks/transition.md new file mode 100644 index 0000000000..c47e3043b6 --- /dev/null +++ b/docs/linter/checks/transition.md @@ -0,0 +1,40 @@ +--- +title: Transition +--- + +# `transition` + +`Pix` transition leads to unmaintainable profile. + +## Problematic rule + +```sh +# WRONG +@{bin}/foo Pix, +``` + +## Correct rule + +```sh +@{bin}/foo ix, +``` + +Or, if the transition is needed: + +```sh +@{bin}/foo Px, +``` + +## Rationale + +The actual enforced transition will depend on the presence of other profiles and is therefore unpredictable. If a profile exists, it will transition and may allow more access than the original profile. If no profile exists, the program will be run inherited in the same profile, which may lead to breakage and maintenance issues. + +It is **also** a security risk when used alongside a wildcard (`@{bin}/* Pix`) as, when a lot of profiles are present (like in apparmor.d) it pretty much allow to transition to any program in the system. + +## Exceptions + +It can be used in profile for an interactive shell environments. In this case, as long as profiles like `apt` or `apparmor_parser` it may be equivalent to giving full admin access to the user. + +## Related Resources + +* The [`role_play` profile of the AppArmor Play machine](https://github.com/roddhjav/play/blob/e81baf3b42513983112f3e82250710003c0dd95a/apparmor.d/groups/roles/role_play#L50-L55) use it to provide a fully confined admin role. diff --git a/docs/linter/checks/tunables.md b/docs/linter/checks/tunables.md new file mode 100644 index 0000000000..588f53cea7 --- /dev/null +++ b/docs/linter/checks/tunables.md @@ -0,0 +1,30 @@ +--- +title: Tunables +--- + +# `tunables` + +Variables must be used + +## Problematic rule + +```sh +# WRONG +owner @{HOME}/.config/foo/{,**} rw, +``` + +## Correct rule + +```sh +owner @{user_config_dirs}/foo/{,**} rw, +``` + +## Rationale + +Using variables instead of hardcoding paths allows for better maintainability and compatibility across different systems and user configurations. It also makes the profile more adaptable to changes in directory structures or user environments. + +See [Variables](../../variables.md) for more information on available variables. + +## Exceptions + +None diff --git a/docs/linter/checks/useless.md b/docs/linter/checks/useless.md new file mode 100644 index 0000000000..aba3e7b3f0 --- /dev/null +++ b/docs/linter/checks/useless.md @@ -0,0 +1,29 @@ +--- +title: Useless rule +--- + +# `useless` + +Rule already included in the base abstraction, remove it. + +## Problematic rule + +```sh +# WRONG +@{sys}/devices/system/cpu/online r, +``` + +## Correct rule + +```sh +# CORRECT +# Rule already included in the base abstraction, no need to include it again +``` + +## Exceptions + +None + +## Related Resources + +* The [`base-strict` abstraction](https://github.com/roddhjav/apparmor.d/blob/main/apparmor.d/abstractions/base-strict) diff --git a/docs/linter/checks/vim.md b/docs/linter/checks/vim.md new file mode 100644 index 0000000000..8f17c39c5a --- /dev/null +++ b/docs/linter/checks/vim.md @@ -0,0 +1,30 @@ +--- +title: Vim syntax +--- + +# `vim` + +Missing vim syntax: `# vim:syntax=apparmor` + +## Problematic rule + +A profile without the vim syntax highlighting comment at the end. + +## Correct rule + +```sh +profile foo { + ... +} + +# vim:syntax=apparmor + +``` + +## Rationale + +The vim syntax highlighting comment enables proper syntax highlighting when editing the profile in vim. This improves readability and helps prevent syntax errors. + +## Exceptions + +None diff --git a/docs/linter/index.md b/docs/linter/index.md new file mode 100644 index 0000000000..d7afdaa60e --- /dev/null +++ b/docs/linter/index.md @@ -0,0 +1,111 @@ +--- +title: Linter +--- + +The profiles are checked for common style and security issues with `just check`. This page documents all the checks performed. + +!!! note "Check system" + + Future implementation will expand this basic check system to a full linter and security analyzer system. + + +## Overview + +| Output | Check ID | Description | +|---|---|---| +| **:fontawesome-solid-ban:** | `abi` | Missing ABI | +| **:fontawesome-solid-ban:** | `abstractions` | Use of dangerous abstraction | +| **:fontawesome-solid-ban:** | `abstractions` | Use of deprecated abstraction | +| **:fontawesome-solid-ban:** | `abstractions` | Use of deprecated, ubuntu only abstraction | +| **:fontawesome-solid-ban:** | `bin` | Use of `@{sbin}` instead of `@{bin}` | +| **:fontawesome-solid-ban:** | `directory-mark` | Missing directory mark | +| **:fontawesome-solid-ban:** | `equivalent` | Missing equivalent program | +| **:fontawesome-solid-ban:** | `header` | Missing header | +| **:fontawesome-solid-ban:** | `include` | Missing include | +| **:fontawesome-solid-ban:** | `indentation` | Invalid indentation | +| **:fontawesome-solid-ban:** | `profile` | Missing profile name | +| **:fontawesome-solid-ban:** | `sbin` | Use of `@{bin}` instead of `@{sbin}` | +| **:fontawesome-solid-ban:** | `subprofiles` | Missing subprofiles | +| **:fontawesome-solid-ban:** | `tabs` | Tabs are not allowed | +| **:fontawesome-solid-ban:** | `trailing` | Line has trailing whitespace | +| **:fontawesome-solid-ban:** | `transition` | `Pix` transition leads to unmaintainable profile | +| **:fontawesome-solid-ban:** | `transition` | Executable should be should be used inherited: `ix` or `Cx` | +| **:fontawesome-solid-ban:** | `transition` | Executable should transition to another (sub)profile with `Px` or `Cx` | +| **:fontawesome-solid-ban:** | `tunables` | Variables must be used | +| **:fontawesome-solid-ban:** | `udev` | Udev data path without a description comment | +| **:fontawesome-solid-ban:** | `useless` | Rule already included in the base abstraction | +| **:fontawesome-solid-ban:** | `vim` | Missing vim syntax | +| **:fontawesome-solid-warning:** | `transition` | Path `@{bin}/XXX` should transition to a subprofile with 'Cx' | +|**:fontawesome-solid-warning:** | `too-wide` | Rule too wide may lead to confinement escape or data leaks | + +## Directive + +We use a special [directive](directives.md) to ignore specific checks: + +- Inline directive is supported +- Directive before a paragraph applies to all rules in the paragraph +- Directive within the first 5 lines of a file applies to the whole file + +**Format** + +```sh +#aa:lint ignore= +``` + +**``** + +: Check id to ignore. + + +**Example** + +Ignore the `too-wide` check in the `dpkg` profile: + +!!! quote "" + + **[apparmor.d/groups/apt/dpkg](https://github.com/roddhjav/apparmor.d/blob/094795cc6d628923b7454fd3a9289c44891edc62/apparmor.d/groups/apt/dpkg#L52-L61)** + ``` sh linenums="52" + #aa:lint ignore=too-wide + # Install/update packages + / r, + /*{,/} rw, + @{efi}/** rwl -> @{efi}/**, + /etc/** rwl -> /etc/**, + /opt/** rwl -> /opt/**, + /srv/** rwl -> /srv/**, + /usr/** rwlk -> /usr/**, + /var/** rwlk -> /var/**, + ``` + +## Description Template + + --- + title: id + --- + + # `id` + + + + ## Problematic rule + + ```sh + # WRONG + + ``` + + ## Correct rule + + ```sh + + ``` + + ## Rationale + + + + ## Exceptions + + None + + ## Related Resources diff --git a/docs/overview.md b/docs/overview.md new file mode 100644 index 0000000000..50f8d17cb1 --- /dev/null +++ b/docs/overview.md @@ -0,0 +1,52 @@ +--- +title: Overview +--- + +!!! danger "Help Wanted" + + This project is still in its early development. Help is very welcome; see [Development](development/index.md) + +**AppArmor.d** is a set of over 1500 AppArmor profiles whose aim is to confine most Linux based applications and processes. + +### Purpose + +- Confine all root processes such as all `systemd` tools, `bluetooth`, `dbus`, `polkit`, `NetworkManager`, `OpenVPN`, `GDM`, `rtkit`, `colord` +- Confine all Desktop environments +- Confine all user services such as `Pipewire`, `Gvfsd`, `dbus`, `xdg`, `xwayland` +- Confine some *"special"* user applications: web browsers, file managers, etc +- Should not break a normal usage of the confined software + +See the **[Security Model](security/index.md)** pages for more detail on the architecture. + +### Goals + +- Target both desktops and servers +- Support for all distributions that support AppArmor: + * [:material-arch: Arch Linux](install.md#archlinux) + * [:material-ubuntu: Ubuntu 24.04/25.10](install.md#ubuntu) + * [:material-debian: Debian 12/13](install.md#debian) + * [:simple-suse: openSUSE Tumbleweed](install.md#opensuse) +- Support for all major desktop environments: + - [x] :material-gnome: Gnome (GDM) + - [x] :simple-kde: KDE (SDDM) + - [ ] :simple-xfce: XFCE (Lightdm) *(work in progress)* +- [Fully tested](development/tests.md) + +### Demo + +You want to try this project, or you are curious about the advanced usage and security it can provide without installing it on your machine. You can try it online on my AppArmor play machine at https://play.pujol.io/ + +### Presentations + +Building the largest set of AppArmor profiles: + +- [Linux Security Summit North America (LSS-NA 2023)](https://events.linuxfoundation.org/linux-security-summit-north-america/) *([Slide](https://lssna2023.sched.com/event/1K7bI/building-the-largest-working-set-of-apparmor-profiles-alexandre-pujol-the-collaboratory-tudublin), [Video](https://www.youtube.com/watch?v=OzyalrOzxE8))* +- [Ubuntu Summit 2023](https://events.canonical.com/event/31/) *([Slide](https://events.canonical.com/event/31/contributions/209/), [Video](https://www.youtube.com/watch?v=GK1J0TlxnFI))* + +Lessons learned while making an AppArmor Play machine: + +- [Linux Security Summit North America (LSS-NA 2025)](https://events.linuxfoundation.org/linux-security-summit-north-america/) *([Slide](https://lssna2025.sched.com/event/1zalf/lessons-learned-while-making-an-apparmor-play-machine-alexandre-pujol-linagora), [Video](https://www.youtube.com/watch?v=zCSl8honRI0))* + +### Chat + +A development chat is available on https://matrix.to/#/#apparmor.d:matrix.org diff --git a/docs/report.md b/docs/report.md index e82d4e9e75..199951f633 100644 --- a/docs/report.md +++ b/docs/report.md @@ -11,7 +11,7 @@ When creating [an issue on Github][newissue], please post a link to the [paste] aa-log -R ``` -??? question "No logs with `aa-log`?" +!!! question "No logs with `aa-log`?" If the log file is empty, check that Auditd is running: @@ -30,7 +30,7 @@ If this command produces nothing, use `-s` to provide all logs since boot time ( aa-log -s -R ``` -??? question "No logs with `aa-log -s`?" +!!! question "No logs with `aa-log -s`?" On certain distributions/configurations, AppArmor logs in journal could be taken over by *auditd* when it is installed. To overcome this, `systemd-journald-audit.socket` could be enabled: @@ -43,6 +43,7 @@ You can get older logs with: ```sh aa-log -R -f ``` + Where `` is `1`, `2`, `3` and `4` (the rotated audit log file). [newissue]: https://github.com/roddhjav/apparmor.d/issues/new diff --git a/docs/security/arch1.png b/docs/security/arch1.png new file mode 100644 index 0000000000..fc5ae8b531 Binary files /dev/null and b/docs/security/arch1.png differ diff --git a/docs/security/arch2.png b/docs/security/arch2.png new file mode 100644 index 0000000000..fdfe40a13a Binary files /dev/null and b/docs/security/arch2.png differ diff --git a/docs/security/architecture.md b/docs/security/architecture.md new file mode 100644 index 0000000000..828fcc0360 --- /dev/null +++ b/docs/security/architecture.md @@ -0,0 +1,81 @@ +--- +title: Security Architecture +icon: material/wallpaper +--- + +!!! warning + + This security architecture is still a work in progress. Comments and feedbacks are welcome. [Discuss it on Github](https://github.com/roddhjav/apparmor.d/discussions/1013) + +## Preliminaries + +
+ +**The best is the enemy of the good.** + +
+ +The architecture presented here can be seen as a general overview of what any modern Linux security construction may want to achieve. + +Example of current Linux distribution implementing something similar with various use case in mind are: + +
+ +- :material-package:   **[ClipOS](https://clip-os.org/en/)** +- :material-ubuntu:   **[Ubuntu Core](https://ubuntu.com/core)** +- :material-fedora:   **[Fedora Atomic Desktops](https://fedoraproject.org/atomic-desktops/)** +- :material-fedora:   **[Fedora Core OS](https://fedoraproject.org/coreos/)** +- :material-atom:   **[Particle OS](https://github.com/systemd/particleos)** +- :material-train-car-flatbed-car:   **[Flatcar OS](https://www.flatcar.org/)** +- :simple-opensuse:   **[openSUSE MicroOS](https://get.opensuse.org/microos/)** +- :simple-opensuse:   **[](https://)** + +
+ +A careful reader would have noticed that the common ground among these distributions is to be constituted of a fully immutable core system. If such a construction is probably the future of Linux, as of today it can raise some usability concerns (cf [rule :material-numeric-6-circle:](#user-freedom "User freedom.")). Therefore, the current project propose a pragmatic long term solution: + +1. We acknowledge the end goal need to be fully compatible with system that respect 100% of the security model presented here. +2. We stay compatible with a *"classic"* Linux construction (i.e. without immutable core), and try to implement as mush as we can on classic distribution. It is considered as a transitional state. + +## Security Architecture + +As attacker usually comes from the top (a high level application) and goes down to the core system, we present the security architecture similarly. + +1. **In application sandboxing:** separation of privilege, least privilege principle, within different process of the application itself. It can be implemented using tools such as: Landlock, bwrap, and Apparmor. +The purpose is to separate highly privileged code from the rest of the application. + +1. **Application sandboxing:** Isolate the application from the rest of the system with tools such as. In this context, "sandboxing" does not refer to a special technology, but to the general concept. It can be implemented in various ways: trough VM (Qemu/KVM, Firecracker, Cloudhypervisor, Kata Containers), or container (Docker, gVisor, Flatpak, Snap) with different level of isolation and integration with the rest of the system. + +1. **Confined user:** The user is confined in its own environment. Limiting what they can do **[:material-police-badge-outline:{ .pg-red }](../full-system-policy.md "Only for Full System Policy (FSP)")**. + +1. **System confinement:** separation of privilege, the least privilege principle, within all part of the core system. For example, Gnome is constituted by about 50 small services running in the background. Each of them are confined independently with granular access to other part of the DE. + +
+ ![_security-implementation-architecture](arch1.png#only-light) + ![_security-implementation-architecture](arch2.png#only-dark) +
Overview of the security architecture
+
+ +## Security Levels + +As `apparmor.d` can be used in multiple security model, it provides different mode to fit into the following **proposed** security target. + +**`default`** + +This confinement level can be summarized as *the most we can do without requiring user configuration*. It provides a good level of security for most use cases while requiring minimal configuration from the user. It is suitable for general purpose use. The goal with this level is that the end user should not be aware of AppArmor and its configuration. + +- Principle of least privilege applied +- Strict Principle Of Least Astonishment (POLA) + +**`strict`** + +Stronger confinement for applications. Suitable for more sensitive use cases. This level includes a few sublevel depending on how the user want to configure it. + +**`fsp`** + +Full System Policy confinement for applications. Suitable for very high security use cases. + +**`extreme`** + +Maximum confinement for applications. Suitable for the most extreme security use cases. This level may break some applications and require significant user and application configuration as well as patching some applications to work properly. +The goal is to provide a kind of Multi Category Security (MCS) using apparmor on top of the FSP model. diff --git a/docs/security/ecosystem.md b/docs/security/ecosystem.md new file mode 100644 index 0000000000..1323c68215 --- /dev/null +++ b/docs/security/ecosystem.md @@ -0,0 +1,79 @@ +--- +title: Ecosystem +icon: simple/linux +--- + +## Use cases & users + +Linux's user can be anyone from novices that does not know they are running Linux and that have no idea that AppArmor exist to the most advanced power user that want full control over their devices. + +In opposition of other operating system such as Windows or macOS, Linux can be used in a wide variety of application and use case such as: an OS for embedded device, a mobile OS, a workstation, a gaming console, a server, a global fleet of servers. + +The ecosystem is so open that there is no compatibility requirements that define Linux in any way. Particularity in terms of: + +1. **Diversity:** They are a wide range of package managers, sandboxing & virtualization tools, init system, display server, Desktop environment. +3. **Users:** *everyone* +2. **Use case:** *everything* +4. **Location:** *everywhere* + +This diversity is a strength of Linux but also a challenge when trying to define a security model that can fit all these use cases while being easy to use and understand by everyone. + +## Ecosystem + +**Architecture** + +Despite its diversity, only two major system architecture exists in the Linux ecosystem: + +1. **Purposed built systems** such as embedded systems or servers that are designed to run a limited set of tasks and thus that can *easily* support strict and limited security policies. +2. **General purpose systems** such as desktops Linux that are designed to run anything, anyhow. + +We note there is trend in the Linux world toward purposed built systems even for desktop usage. + +**Security consideration** + +Due to the diversity of use case and users in the Linux ecosystem, no particular security requirements/ minimum standard can be assumed for applications or users. However, some general hypothesis can be made: + +- Open ecosystem, immense, enforced by package maintainer and distributions +- Any language present, secure or not, past and future +- No rules in software quality +- No rules in security requirements +- The packages are mostly installed from *"trusted source"* +- Distribution repository are well known trusted source +- Software usually do not want to spy on you. Still some do it. +- Continuously find new security vulnerabilities + +## Stakeholders + +In the Linux ecosystem, there are many stakeholders having some kind of power over the system. These stakeholders can be: + +- **The end user:** the person using the device. +- **The device owner:** the company/university/organization owning the device. In case of a personal device, the end user is also the device owner. +- **The Linux vendor:** The Linux distribution +- **The device manufacturer:** The hardware manufacturers providing firmware and drivers +- **Third party app developer/companies:** Other proprietary software company that may run on the device + +These stakeholders may have different requirements and objectives regarding the security of the system. For example, the end user may want to protect their privacy, while the device owner may want to ensure that the device is used for work purposes only. + +## Requirements + +From the above, we can derive the following requirements to apply on our security model. + +#### Rqr :material-numeric-1-circle: - User Freedom. + +: Explicitly supports extreme personalization[^1] + +[^1]: It does not mean the personalization has to be easy to do, just that it must be possible. + +#### Rqr :material-numeric-2-circle: - User Privacy + +: The system should be at the service of the end user in its goal to protect its privacy. The system should not be at the service of the developer, the distributor or a third party application. + +#### Rqr :material-numeric-3-circle: - Principle Of Least Astonishment (POLA) + +: A component of a system should behave in a way that most users will expect it to behave, and therefore not astonish or surprise users. + +#### Rqr :material-numeric-4-circle: - No strict compatibility + +: Whatever application you have, the system should find a way to run it. Native, containerized, virtualized, emulated, etc.[^2] + +[^2]: Some way may be explicitly blocked, but other way should be available. diff --git a/docs/security/hardening.md b/docs/security/hardening.md new file mode 100644 index 0000000000..a5c2129243 --- /dev/null +++ b/docs/security/hardening.md @@ -0,0 +1,30 @@ +--- +title: Security Hardening +icon: material/bandage +--- + +A careful reader would have noticed that these sections do not mention anything about security hardening, whilst it is a common thing in modern secure system. + +
+ +**What is the problem with security hardening?** + +
+ +In one sentence, *It is the opposite of security by design.* Security hardening means retrofitting security controls onto an existing system, while *secure by design* means building security into the architecture from the beginning. + +Hardening a system usually means installing a set of security tools and configurations on top of an existing system because they look cool, secure or trendy. The problem is that when doing so, you usually do not have a clear idea of what you are trying to achieve, what are the threats you are trying to mitigate, and what are the trade-offs you are making. + +!!! tip "To sum up" + + Hardening is like adding additional reinforcement to a bridge because after finishing it, you realized it could be dangerous. It would have been way better to design the bridge with more structural support in mind from the start. + +**Example** + +- Instead of disabling some kernel modules, it is better to build the kernel without the module at all and to lock it down. In such a way, even if an attacker get root access to the system, it would not be possible for them to load anything in the kernel. + +- Instead of disabling USB storage devices because they could be used to exfiltrate data, it would be way better to design the system in such a way that even if a USB storage device is connected, it cannot be used to exfiltrate data. + +In other words, it is way more secure, and stable to design a system with security in mind from the start, rather than trying to patch it afterwards. + +This is why these sections focus on the complex question of *what do you want to achieve?* rather than the simpler question of *how to harden your system?*. diff --git a/docs/security/index.md b/docs/security/index.md new file mode 100644 index 0000000000..0babd4ea3c --- /dev/null +++ b/docs/security/index.md @@ -0,0 +1,64 @@ +--- +title: Security +--- + +There are over 50000 Linux packages and even more applications. It is simply not possible to write an AppArmor profile for all of them. Therefore, a question arises: + +
+ +**What to confine, how, and why?** + +
+ +The security model presented here help us to scope the security policies within the broader context of system security and privacy. + +This section presents the security model considered for the profiles in `apparmor.d`. Despite that this security model looks at Linux security in general, we are only focusing on the threats, model, and implementation within the scope of AppArmor. + +!!! warning + + This security model is still a work in progress. Comments and feedbacks are welcome. [Discuss it on Github](https://github.com/roddhjav/apparmor.d/discussions/1013) + +
+ +- :simple-linux:   **[:material-numeric-1-circle-outline: Ecosystem Review](ecosystem.md)** + + --- + + What are Linux based systems used for? By whom and how? + +- :material-bomb:   **[:material-numeric-2-circle-outline: Threat model](threat.md)** + + --- + + The list of threats the :material-numeric-1-circle-outline: Ecosystem is continuously facing. + +- :material-security:   **[:material-numeric-3-circle-outline: Security Model](model.md)** + + --- + + Given the :material-numeric-1-circle-outline: Ecosystem and the :material-numeric-2-circle-outline: Threat model, what are the rules that should be enforced? + +- :material-source-commit-local:   **[:material-numeric-4-circle-outline: Security Implementation](architectureimplementation.md)** + + --- + + How AppArmor is used to enforce part of the :material-numeric-3-circle-outline: Security Model? + +
+ + +!!! quote "Security Model" + + A computer security model is a scheme for specifying and enforcing security policies. A security model may be founded upon a formal model of access rights, a model of computation, a model of distributed computing, or no particular theoretical grounding at all. + + *Source: [Wikipedia](https://en.wikipedia.org/wiki/Computer_security_model)* + +!!! example "References" + + 1. [The Android Platform Security Model (2023)](https://arxiv.org/pdf/1904.05572v3.pdf) + 1. [ClipOS](https://docs.clip-os.org/) - A security OS made by the ANSSI (the French NIST) and used for sensitive French government related activities. + 1. [Spectrum](https://spectrum-os.org) - A step towards usable secure computing + 1. [QubesOS](https://www.qubes-os.org/) - A reasonably secure operating system + 1. [Whonix](https://www.whonix.org/) – An anonymous operating system + 1. [Kairos](https://kairos.io) + diff --git a/docs/security/model.md b/docs/security/model.md new file mode 100644 index 0000000000..88c5511dd9 --- /dev/null +++ b/docs/security/model.md @@ -0,0 +1,12 @@ +--- +title: Security Model +icon: material/security +--- + +Given the **[:material-numeric-1-circle-outline: Ecosystem](ecosystem.md)** context and the **[:material-numeric-2-circle-outline: Threat model](threat.md)** explained in the previous sections, this section presents the security model that should ideally be enforced. + +It covers the basic principles, rules and objectives to consider when building a secure system. It may be changed to fit into use case and threat model modification or specific needs. + +!!! warning "Work in progress" + + This security model is not yet properlly defined. Comments and feedbacks are welcome. [Discuss it on Github](https://github.com/roddhjav/apparmor.d/discussions/1013) diff --git a/docs/security/threat.md b/docs/security/threat.md new file mode 100644 index 0000000000..f3c8e30e3e --- /dev/null +++ b/docs/security/threat.md @@ -0,0 +1,37 @@ +--- +title: Threat model +icon: material/bomb +--- + +The importance of the threat depends on the use case & application. For example the fact that *adversaries can get physical access to device* is a bigger concern on mobile & embedded device than on a server or even on a VM. +However, these remain valid anyway. + +## Modularity + +Across the linux ecosystem, treats can varies. As such not all threats are relevant to all users and some threats only matter for some security models. As such the underlying implementation should be modular enough to allow selection of the relevant threats and to enforce a given security model even if it lead to a trade off in terms of usability. + +## Threats + +!!! warning "Work in progress" + + This threats are not yet properlly defined. Comments and feedbacks are welcome. [Discuss it on Github](https://github.com/roddhjav/apparmor.d/discussions/1013) + +### `PA` Physical access + +Adversaries can get physical access to the devices. + +### `C` Communication + +Network communication is untrusted + +### `P` Platform + +The Linux system can be targeted. + +### `UI` User interaction + +Many stakeholders in the ecosystem can act as supply chain attack vectors. + +## Out of scope + +Some threats are considered out of scope for various reasons. diff --git a/docs/usage.md b/docs/usage.md index 372762998a..eacf33ffb1 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -66,12 +66,14 @@ gnome-shell (complain) user /usr/bin/gnome-shell ps (complain) user ps auxZ ``` -??? info "Hide the kernel thread in `ps`" - - To hide the kernel thread in `ps` use `ps auxZ | grep -v '\[.*\]'`. You can +??? info "Display the process hierarchy and hide the kernel thread in `ps`" + + In order to list above processes with displaying the process hierarchy you can, alternatively, use `ps auxfZ`. + + To hide the kernel thread in `ps` use `LIBPROC_HIDE_KERNEL=1 ps auxfZ`. You can add an alias in your shell: ```sh - alias p="ps auxZ | grep -v '\[.*\]'" + alias p="LIBPROC_HIDE_KERNEL=1 ps auxfZ" ``` @@ -116,7 +118,7 @@ profile dnsmasq { ### Help ``` -aa-log [-h] [--systemd] [--file file] [--rules | --raw] [--since] [profile] +aa-log [-h] [--systemd] [--file file] [--load] [--rules | --raw] [--since] [--namespace] [profile] Review AppArmor generated messages in a colorful way. It supports logs from auditd, systemd, syslog as well as dbus session events. @@ -125,12 +127,18 @@ aa-log [-h] [--systemd] [--file file] [--rules | --raw] [--since] [profile] Default logs are read from '/var/log/audit/audit.log'. Other files in '/var/log/audit/' can easily be checked: 'aa-log -f 1' parses 'audit.log.1' + Use 'aa-log -f -' to read from standard input. + + Logs written with 'aa-log' can be read again with 'aa-log -l'. Options: -h, --help Show this help message and exit. -f, --file FILE Set a logfile or a suffix to the default log file. -s, --systemd Parse systemd logs from journalctl. + -n, --namespace NS Filter the logs to the specified namespace. -r, --rules Convert the log into AppArmor rules. -R, --raw Print the raw log without any formatting. + -b, --boot NUM Show entries from the specified boot. -S, --since DATE Show entries not older than the specified date. + -l, --load Load logs from the default aa-log output. ``` diff --git a/docs/variables.md b/docs/variables.md index 7dc8e5ff6e..9dda5c756d 100644 --- a/docs/variables.md +++ b/docs/variables.md @@ -50,7 +50,7 @@ title: Variables References | GPG | `@{XDG_GPG_DIR}` | `.gnupg` | | SSH | `@{XDG_SSH_DIR}` | `.ssh` | | Private | `@{XDG_PRIVATE_DIR}` | `.{p,P}rivate {p,P}rivate` | -| Passwords | `@{XDG_PASSWORD_STORE_DIR}` | `.password-store` | +| Passwords | `@{XDG_PASSWORDSTORE_DIR}` | `.password-store` | @@ -85,7 +85,7 @@ title: Variables References | Books | `@{user_books_dirs}` | `@{HOME}/@{XDG_BOOKS_DIR} @{MOUNTS}/@{XDG_BOOKS_DIR}` | | Games | `@{user_games_dirs}` | `@{HOME}/@{XDG_GAMES_DIR} @{MOUNTS}/@{XDG_GAMES_DIR}` | | Private | `@{user_private_dirs}` | `@{HOME}/@{XDG_PRIVATE_DIR} @{MOUNTS}/@{XDG_PRIVATE_DIR}` | -| Passwords | `@{user_passwordstore_dirs}` | `@{HOME}/@{XDG_PASSWORD_STORE_DIR} @{MOUNTS}/@{XDG_PASSWORD_STORE_DIR}` | +| Passwords | `@{user_passwordstore_dirs}` | `@{HOME}/@{XDG_PASSWORDSTORE_DIR} @{MOUNTS}/@{XDG_PASSWORDSTORE_DIR}` | | Work | `@{user_work_dirs}` | `@{HOME}/@{XDG_WORK_DIR} @{MOUNTS}/@{XDG_WORK_DIR}` | | Mail | `@{user_mail_dirs}` | `@{HOME}/@{XDG_MAIL_DIR} @{MOUNTS}/@{XDG_MAIL_DIR}` | | Projects | `@{user_projects_dirs}` | `@{HOME}/@{XDG_PROJECTS_DIR} @{MOUNTS}/@{XDG_PROJECTS_DIR}` | @@ -168,7 +168,8 @@ title: Variables References | Home directories | `@{HOME}` | `@{HOMEDIRS}/*/ /root/` | | Root Mountpoints | `@{MOUNTDIRS}` | `/media/ @{run}/media/@{user}/ /mnt/` | | Mountpoints directories | `@{MOUNTS}` | `@{MOUNTDIRS}/*/ @{run}/user/@{uid}/gvfs/` | -| Bin | `@{bin}` | `/{usr/,}{s,}bin` | +| Bin | `@{bin}` | `/{usr/,}bin` | +| Sbin | `@{sbin}` | `/{usr/,}sbin` | | Lib | `@{lib}` | `/{usr/,}lib{,exec,32,64}` | | multi-arch library | `@{multiarch}` | `*-linux-gnu*` | | Proc | `@{PROC}` | `/proc/` | diff --git a/go.mod b/go.mod index 3bea9f5484..aea7e86612 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ module github.com/roddhjav/apparmor.d -go 1.23.0 +go 1.24.0 diff --git a/mkdocs.yml b/mkdocs.yml deleted file mode 100644 index 153af0d4e5..0000000000 --- a/mkdocs.yml +++ /dev/null @@ -1,169 +0,0 @@ -# apparmor.d - Full set of apparmor profiles -# Copyright (C) 2021-2024 Alexandre Pujol -# SPDX-License-Identifier: GPL-2.0-only - -# Project information -site_name: AppArmor.d -site_url: https://apparmor.pujol.io -site_author: Alexandre Pujol -site_description: >- - Full set of AppArmor profiles - -# Repository -repo_name: roddhjav/apparmor.d -repo_url: https://github.com/roddhjav/apparmor.d -edit_uri: edit/main/docs/ - -# Copyright -copyright: Copyright © 2021-2024 Alexandre Pujol - -# Configuration -theme: - name: material - logo: assets/favicon.png - favicon: assets/favicon.png - palette: - - scheme: default - primary: white - toggle: - icon: material/brightness-7 - name: Switch to dark mode - - - scheme: slate - primary: brown - accent: deep orange - toggle: - icon: material/brightness-4 - name: Switch to light mode - icon: - repo: fontawesome/brands/github - edit: material/file-edit-outline - view: material/file-eye-outline - features: - - content.action.edit - - content.code.annotate - - content.code.copy - - content.tabs.link - - content.tooltips - - navigation.indexes - - navigation.instant - - navigation.sections - - navigation.tabs - - navigation.top - - search.highlight - - search.share - - search.suggest - -extra_css: - - assets/stylesheets/extra.css - -# Plugins -plugins: - - privacy - - search - - offline: - enabled: !ENV [MKDOCS_OFFLINE, true] - - git-revision-date-localized: - enabled: !ENV [ENABLED_GIT_REVISION_DATE, true] - enable_creation_date: true - fallback_to_build_date: true - - minify: - minify_html: true - - git-committers: - enabled: !ENV [ENABLED_GIT_REVISION_DATE, true] - token: !ENV [MKDOCS_GIT_COMMITTERS_APIKEY] - repository: roddhjav/apparmor.d - branch: main - -# Customization -extra: - social: - - icon: fontawesome/brands/twitter - link: https://twitter.com/roddhjav - - icon: fontawesome/brands/github - link: https://github.com/roddhjav/apparmor.d - - icon: fontawesome/brands/gitlab - link: https://gitlab.com/roddhjav/apparmor.d - - icon: fontawesome/solid/up-right-from-square - link: https://pujol.io - -# Extensions -markdown_extensions: - - abbr - - admonition - - attr_list - - def_list - - footnotes - - tables - - md_in_html - - toc: - permalink: true - toc_depth: 3 - - pymdownx.betterem: - smart_enable: all - - pymdownx.caret - - pymdownx.mark - - pymdownx.tilde - - pymdownx.details - - pymdownx.emoji: - emoji_index: !!python/name:material.extensions.emoji.twemoji - emoji_generator: !!python/name:material.extensions.emoji.to_svg - - pymdownx.highlight: - anchor_linenums: true - - pymdownx.inlinehilite - - pymdownx.keys - - pymdownx.magiclink: - repo_url_shorthand: true - user: squidfunk - repo: mkdocs-material - - pymdownx.smartsymbols - - pymdownx.snippets: - auto_append: - - docs/abbreviations.md - - pymdownx.superfences: - custom_fences: - - name: mermaid - class: mermaid - format: !!python/name:pymdownx.superfences.fence_code_format - - pymdownx.tabbed: - alternate_style: true - slugify: !!python/object/apply:pymdownx.slugs.slugify - kwds: - case: lower - - pymdownx.tasklist: - custom_checkbox: true - -# Page tree -nav: - - Home: - - index.md - - Getting Started: - - concepts.md - - install.md - - configuration.md - - usage.md - - report.md - - Advanced: - - variables.md - - enforce.md - - full-system-policy.md - - Troubleshooting: - - issues.md - - recovery.md - - Development: - - development/index.md - - development/roadmap.md - - Profiles: - - development/workflow.md - - development/guidelines.md - - development/abstractions.md - - development/internal.md - - development/directives.md - - development/dbus.md - - development/recommendations.md - - Packages: - - development/build.md - - Tests: - - development/tests.md - - development/vm.md - - development/integration.md diff --git a/pkg/aa/all.go b/pkg/aa/all.go index 21368d3201..557899e8d7 100644 --- a/pkg/aa/all.go +++ b/pkg/aa/all.go @@ -4,6 +4,8 @@ package aa +import "fmt" + const ( ALL Kind = "all" ) @@ -13,7 +15,10 @@ type All struct { } func newAll(q Qualifier, rule rule) (Rule, error) { - return &All{Base: newBase(rule)}, nil + if len(rule.GetSlice()) > 0 { + return nil, fmt.Errorf("'all' rule cannot have additional arguments") + } + return &All{Base: newBase(rule)}, rule.ValidateMapKeys([]string{}) } func (r *All) Kind() Kind { diff --git a/pkg/aa/apparmor.go b/pkg/aa/apparmor.go index f0deaffc91..29b39f4644 100644 --- a/pkg/aa/apparmor.go +++ b/pkg/aa/apparmor.go @@ -2,15 +2,65 @@ // Copyright (C) 2021-2023 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only +// Package aa parses, formats, and manipulates AppArmor policy: profiles, +// rules, includes, variables, and abstractions. It is the core data model +// shared by the prebuild pipeline and the command-line tools. +// +// Each rule and profile element implements [fmt.Stringer]; serialisation +// is delegated to per-kind Go templates under templates/ that are loaded +// at build time via go:embed and rendered by [renderTemplate]. package aa import ( + "slices" + "strings" + "github.com/roddhjav/apparmor.d/pkg/paths" ) // MagicRoot is the default Apparmor magic directory: /etc/apparmor.d/. var MagicRoot = paths.New("/etc/apparmor.d") +// FileKind represents an AppArmor file kind. +type FileKind uint8 + +const ( + ProfileKind FileKind = iota + AbstractionKind + TunableKind +) + +var ( + fileKinds = map[FileKind]string{ + ProfileKind: PROFILE.String(), + AbstractionKind: "abstraction", + TunableKind: "tunable", + } +) + +func KindFromPath(file *paths.Path) FileKind { + dirname := file.Parent().String() + switch { + case strings.Contains(dirname, "abstractions"): + return AbstractionKind + case strings.Contains(dirname, "tunables"): + return TunableKind + case strings.Contains(dirname, "local"): + return AbstractionKind + case strings.Contains(dirname, "mappings"): + return AbstractionKind + default: + return ProfileKind + } +} + +func (k FileKind) String() string { + if res, ok := fileKinds[k]; ok { + return res + } + return "" +} + // AppArmorProfileFiles represents a full set of apparmor profiles type AppArmorProfileFiles map[string]*AppArmorProfileFile @@ -19,8 +69,11 @@ type AppArmorProfileFiles map[string]*AppArmorProfileFile // - Some rules are not supported yet (subprofile, hat...) // - The structure is simplified as it only aims at writing profile, not parsing it. type AppArmorProfileFile struct { - Preamble Rules - Profiles []*Profile + Preamble Rules + Profiles []*Profile + Hats []*Hat + Conditions []*Condition + Kind FileKind } func NewAppArmorProfile() *AppArmorProfileFile { @@ -33,7 +86,7 @@ func DefaultTunables() *AppArmorProfileFile { return &AppArmorProfileFile{ Preamble: Rules{ &Variable{Name: "arch", Values: []string{"x86_64", "amd64", "i386"}, Define: true}, - &Variable{Name: "bin", Values: []string{"/{,usr/}{,s}bin"}, Define: true}, + &Variable{Name: "bin", Values: []string{"/{,usr/}bin"}, Define: true}, &Variable{Name: "c", Values: []string{"[0-9a-zA-Z]"}, Define: true}, &Variable{Name: "dpkg_script_ext", Values: []string{"config", "templates", "preinst", "postinst", "prerm", "postrm"}, Define: true}, &Variable{Name: "etc_ro", Values: []string{"/{,usr/}etc/"}, Define: true}, @@ -45,14 +98,16 @@ func DefaultTunables() *AppArmorProfileFile { &Variable{Name: "multiarch", Values: []string{"*-linux-gnu*"}, Define: true}, &Variable{Name: "rand", Values: []string{"@{c}{@{c},}{@{c},}{@{c},}{@{c},}{@{c},}{@{c},}{@{c},}{@{c},}{@{c},}"}, Define: true}, // Up to 10 characters &Variable{Name: "run", Values: []string{"/run/", "/var/run/"}, Define: true}, - &Variable{Name: "sbin", Values: []string{"/{,usr/}sbin"}, Define: true}, &Variable{Name: "uid", Values: []string{"{[0-9],[1-9][0-9],[1-9][0-9][0-9],[1-9][0-9][0-9][0-9],[1-9][0-9][0-9][0-9][0-9],[1-9][0-9][0-9][0-9][0-9][0-9],[1-9][0-9][0-9][0-9][0-9][0-9][0-9],[1-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9],[1-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9],[1-4][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]}"}, Define: true}, &Variable{Name: "user_cache_dirs", Values: []string{"/home/*/.cache"}, Define: true}, &Variable{Name: "user_config_dirs", Values: []string{"/home/*/.config"}, Define: true}, &Variable{Name: "user_share_dirs", Values: []string{"/home/*/.local/share"}, Define: true}, + &Variable{Name: "user_bin_dirs", Values: []string{"/home/*/.local/bin"}, Define: true}, + &Variable{Name: "user_lib_dirs", Values: []string{"/home/*/.local/lib"}, Define: true}, &Variable{Name: "user", Values: []string{"[a-zA-Z_]{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}"}, Define: true}, &Variable{Name: "version", Values: []string{"@{int}{.@{int},}{.@{int},}{-@{rand},}"}, Define: true}, &Variable{Name: "w", Values: []string{"[a-zA-Z0-9_]"}, Define: true}, + &Variable{Name: "word", Values: []string{"@{w}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}{@{w},}"}, Define: true}, }, } } @@ -111,3 +166,24 @@ func (f *AppArmorProfileFile) Format() { p.Format() } } + +// Merge merges two profiles together. +func (f *AppArmorProfileFile) Merge(other *AppArmorProfileFile) error { + f.Preamble = append(f.Preamble, other.Preamble...) + f.Profiles = append(f.Profiles, other.Profiles...) + return nil +} + +// Clean the profile file from comments +func (f *AppArmorProfileFile) Clean() { + delete := []int{} + for i, r := range f.Preamble { + switch r.(type) { + case *Comment: + delete = append(delete, i) + } + } + for i := len(delete) - 1; i >= 0; i-- { + f.Preamble = slices.Delete(f.Preamble, delete[i], delete[i]+1) + } +} diff --git a/pkg/aa/apparmor_test.go b/pkg/aa/apparmor_test.go index 9d68596d39..bc049d6789 100644 --- a/pkg/aa/apparmor_test.go +++ b/pkg/aa/apparmor_test.go @@ -13,15 +13,15 @@ import ( ) var ( - testData = paths.New("../../tests/testdata/") - intData = paths.New("../../apparmor.d") + testData = paths.New("../../tests/testdata/") + apparmorDDir = paths.New("../../apparmor.d") ) // mustReadProfileFile read a file and return its content as a slice of string. // It panics if an error occurs. It removes the last comment line. func mustReadProfileFile(path *paths.Path) string { res := strings.Split(path.MustReadFileAsString(), "\n") - return strings.Join(res[:len(res)-2], "\n") + return strings.Join(res[:len(res)-2], "\n") + "\n" } func TestAppArmorProfileFile_String(t *testing.T) { @@ -36,7 +36,7 @@ func TestAppArmorProfileFile_String(t *testing.T) { want: ``, }, { - name: "foo", + name: "string.aa", f: &AppArmorProfileFile{ Preamble: Rules{ &Comment{Base: Base{Comment: " Simple test profile for the AppArmorProfileFile.String() method", IsLineRule: true}}, @@ -88,7 +88,6 @@ func TestAppArmorProfileFile_String(t *testing.T) { Type: "stream", Address: "@/tmp/.ICE-unix/1995", PeerLabel: "gnome-shell", - PeerAddr: "none", }, &Dbus{Access: []string{"bind"}, Bus: "session", Name: "org.gnome.*"}, &Dbus{ @@ -144,8 +143,8 @@ func TestAppArmorProfileFile_Sort(t *testing.T) { include1, all1, rlimit3, userns1, capability1, capability2, network2, network1, mount2, mount1, remount2, umount2, pivotroot1, changeprofile2, mqueue2, iouring2, signal1, - signal2, ptrace1, unix2, dbus2, dbus1, file1, file2, - link2, includeLocal1, + signal2, ptrace1, unix2, dbus2, dbus1, file1, + link2, file2, includeLocal1, }, }}, }, @@ -211,33 +210,34 @@ func TestAppArmorProfileFile_Integration(t *testing.T) { &Include{IsMagic: true, Path: "tunables/global"}, &Variable{ Name: "exec_path", Define: true, - Values: []string{"@{bin}/aa-status", "@{bin}/apparmor_status"}, + Values: []string{"@{sbin}/aa-status", "@{sbin}/apparmor_status"}, }, }, Profiles: []*Profile{{ Header: Header{ Name: "aa-status", Attachments: []string{"@{exec_path}"}, + Flags: []string{"attach_disconnected"}, }, Rules: Rules{ &Include{IfExists: true, IsMagic: true, Path: "local/aa-status"}, &Capability{Names: []string{"dac_read_search"}}, &File{Path: "@{exec_path}", Access: []string{"m", "r"}}, - &File{Path: "@{PROC}/@{pids}/attr/apparmor/current", Access: []string{"r"}}, + &File{Path: "@{PROC}/@{pid}/attr/apparmor/current", Access: []string{"r"}}, &File{Path: "@{PROC}/", Access: []string{"r"}}, &File{Path: "@{sys}/module/apparmor/parameters/enabled", Access: []string{"r"}}, &File{Path: "@{sys}/kernel/security/apparmor/profiles", Access: []string{"r"}}, - &File{Path: "@{PROC}/@{pids}/attr/current", Access: []string{"r"}}, + &File{Path: "@{PROC}/@{pid}/attr/current", Access: []string{"r"}}, &Include{IsMagic: true, Path: "abstractions/consoles"}, &File{Owner: true, Path: "@{PROC}/@{pid}/mounts", Access: []string{"r"}}, &Include{IsMagic: true, Path: "abstractions/base"}, - &File{Path: "/dev/tty@{int}", Access: []string{"r", "w"}}, + &File{Path: "/dev/tty@{u8}", Access: []string{"r", "w"}}, &Capability{Names: []string{"sys_ptrace"}}, &Ptrace{Access: []string{"read"}}, }, }}, }, - want: mustReadProfileFile(intData.Join("groups/apparmor/aa-status")), + want: mustReadProfileFile(apparmorDDir.Join("groups/apparmor/aa-status")), }, } for _, tt := range tests { diff --git a/pkg/aa/base.go b/pkg/aa/base.go index eaf69f71cd..ae83019fc8 100644 --- a/pkg/aa/base.go +++ b/pkg/aa/base.go @@ -5,6 +5,7 @@ package aa import ( + "fmt" "strings" ) @@ -17,6 +18,15 @@ type Base struct { Paddings []string } +func extractFlag(comment, flag string) (string, bool) { + if !strings.Contains(comment, flag) { + return comment, false + } + comment = strings.ReplaceAll(comment, flag+" ", "") + comment = strings.ReplaceAll(comment, flag, "") + return comment, true +} + func newBase(rule rule) Base { comment := "" fileInherit, noNewPrivs, optional := false, false, false @@ -31,19 +41,11 @@ func newBase(rule rule) Base { comment = rule[len(rule)-1].comment } } - switch { - case strings.Contains(comment, "file_inherit"): - fileInherit = true - comment = strings.Replace(comment, "file_inherit ", "", 1) - case strings.HasPrefix(comment, "no new privs"): - noNewPrivs = true - comment = strings.Replace(comment, "no new privs ", "", 1) - case strings.Contains(comment, "optional:"): - optional = true - comment = strings.Replace(comment, "optional: ", "", 1) - } + comment, fileInherit = extractFlag(comment, "file_inherit") + comment, noNewPrivs = extractFlag(comment, "no new privs") + comment, optional = extractFlag(comment, "optional:") return Base{ - Comment: comment, + Comment: strings.TrimRight(comment, " "), NoNewPrivs: noNewPrivs, FileInherit: fileInherit, Optional: optional, @@ -61,11 +63,16 @@ func newBaseFromLog(log map[string]string) Base { if strings.Contains(log["info"], "optional:") { optional = true comment = strings.Replace(log["info"], "optional: ", "", 1) + } else if strings.Contains(log["info"], "no new privs") { + noNewPrivs = true + comment = strings.TrimSpace(strings.Replace(log["info"], "no new privs", "", 1)) } else { noNewPrivs = true + if log["info"] != "" { + comment += " " + log["info"] + } } - } - if log["info"] != "" { + } else if log["info"] != "" { comment += " " + log["info"] } return Base{ @@ -88,7 +95,7 @@ func (r *Base) merge(other Base) bool { r.NoNewPrivs = r.NoNewPrivs || other.NoNewPrivs r.FileInherit = r.FileInherit || other.FileInherit r.Optional = r.Optional || other.Optional - if other.Comment != "" { + if other.Comment != "" && other.Comment != r.Comment { r.Comment += " " + other.Comment } return true @@ -99,6 +106,7 @@ func (r Base) addLine(other Rule) bool { } type Qualifier struct { + Priority int Audit bool AccessType string } @@ -108,7 +116,17 @@ func newQualifierFromLog(log map[string]string) Qualifier { return Qualifier{Audit: audit} } +func (r *Qualifier) Validate() error { + if r.Priority < -100 || r.Priority > 100 { + return fmt.Errorf("invalid priority: %d", r.Priority) + } + return nil +} + func (r Qualifier) Compare(o Qualifier) int { + if r := compare(r.Priority, o.Priority); r != 0 { + return r + } if r := compare(r.Audit, o.Audit); r != 0 { return r } @@ -116,7 +134,7 @@ func (r Qualifier) Compare(o Qualifier) int { } func (r Qualifier) Equal(o Qualifier) bool { - return r.Audit == o.Audit && r.AccessType == o.AccessType + return r.Priority == o.Priority && r.Audit == o.Audit && r.AccessType == o.AccessType } func (r Qualifier) getLenAudit() int { diff --git a/pkg/aa/blocks.go b/pkg/aa/blocks.go index d0826dfa28..79803cfc8b 100644 --- a/pkg/aa/blocks.go +++ b/pkg/aa/blocks.go @@ -4,17 +4,35 @@ package aa +import ( + "strings" +) + const ( - HAT Kind = "hat" + HAT Kind = "hat" + IF Kind = "if" + ELSE Kind = "else" ) // Hat represents a single AppArmor hat. type Hat struct { Base Name string + Flags []string Rules Rules } +func newHat(rule rule) (*Hat, error) { + name := "" + if len(rule) > 0 { + name = strings.TrimPrefix(rule.Get(0), HAT.Tok()) + } + return &Hat{ + Name: name, + Flags: rule.GetValuesAsSlice(tokFLAGS), + }, rule.ValidateMapKeys([]string{"flags"}) +} + func (p *Hat) Kind() Kind { return HAT } @@ -45,3 +63,47 @@ func (p *Hat) Lengths() []int { } func (p *Hat) setPaddings(max []int) {} // No paddings for hat + +// Condition represents a single AppArmor condition. +type Condition struct { + Base + Expression string + IfRules Rules + ElseRules Rules +} + +func newCondition(rule rule) (*Condition, error) { + expression := strings.TrimPrefix(rule.GetString(), IF.Tok()+" ") + return &Condition{Expression: expression}, nil +} + +func (p *Condition) Kind() Kind { + return IF +} + +func (p *Condition) Constraint() Constraint { + return BlockRule +} + +func (p *Condition) String() string { + return renderTemplate(p.Kind(), p) +} + +func (p *Condition) Validate() error { + return nil +} + +func (p *Condition) Compare(other Rule) int { + o, _ := other.(*Condition) + return compare(p.Expression, o.Expression) +} + +func (p *Condition) Merge(other Rule) bool { + return false // Never merge hat blocks +} + +func (p *Condition) Lengths() []int { + return []int{} // No len for hat +} + +func (p *Condition) setPaddings(max []int) {} // No paddings for hat diff --git a/pkg/aa/capability.go b/pkg/aa/capability.go index a55f8bc9ba..c11484611c 100644 --- a/pkg/aa/capability.go +++ b/pkg/aa/capability.go @@ -40,7 +40,7 @@ func newCapability(q Qualifier, rule rule) (Rule, error) { Base: newBase(rule), Qualifier: q, Names: names, - }, nil + }, rule.ValidateMapKeys([]string{}) } func newCapabilityFromLog(log map[string]string) Rule { diff --git a/pkg/aa/change_profile.go b/pkg/aa/change_profile.go index 5334b343c8..1feb0d3f5a 100644 --- a/pkg/aa/change_profile.go +++ b/pkg/aa/change_profile.go @@ -54,7 +54,7 @@ func newChangeProfile(q Qualifier, rule rule) (Rule, error) { ExecMode: mode, Exec: exec, ProfileName: target, - }, nil + }, rule.ValidateMapKeys([]string{}) } func newChangeProfileFromLog(log map[string]string) Rule { @@ -83,6 +83,9 @@ func (r *ChangeProfile) Validate() error { if err := validateValues(r.Kind(), "mode", []string{r.ExecMode}); err != nil { return fmt.Errorf("%s: %w", r, err) } + if r.ExecMode != "" && r.Exec == "" { + return fmt.Errorf("change_profile: '%s' requires an exec condition", r.ExecMode) + } return nil } diff --git a/pkg/aa/data_test.go b/pkg/aa/data_test.go index b96fd865fa..b96330fadd 100644 --- a/pkg/aa/data_test.go +++ b/pkg/aa/data_test.go @@ -65,8 +65,40 @@ var ( "denied_mask": "create", "comm": "sddm-greeter", } - network1 = &Network{Domain: "netlink", Type: "raw", Protocol: "15"} + network3Log = map[string]string{ + "apparmor": "ALLOWED", + "class": "net", + "operation": "sendmsg", + "info": "failed af match", + "error": "-13", + "profile": "unattended-upgrade", + "comm": "unattended-upgr", + "laddr": "127.0.0.1", + "lport": "57007", + "faddr": "127.0.0.53", + "saddr": "127.0.0.1", + "src": "57007", + "fport": "53", + "sock_type": "dgram", + "protocol": "17", + "requested": "send", + "denied": "send", + } + network1 = &Network{ + Access: []string{}, + Domain: "netlink", + Type: "raw", + Protocol: "15", + } network2 = &Network{Domain: "inet", Type: "dgram"} + network3 = &Network{ + Base: Base{Comment: " failed af match"}, + LocalAddress: LocalAddress{IP: "127.0.0.1", Port: "57007"}, + PeerAddress: PeerAddress{IP: "127.0.0.53", Port: "53", Src: "127.0.0.1"}, + Access: []string{"send"}, + Type: "dgram", + Protocol: "17", + } // Mount mount1Log = map[string]string{ diff --git a/pkg/aa/dbus.go b/pkg/aa/dbus.go index fa4ec7ec44..243bc96cf3 100644 --- a/pkg/aa/dbus.go +++ b/pkg/aa/dbus.go @@ -16,7 +16,7 @@ func init() { "send", "receive", "bind", "eavesdrop", "r", "read", "w", "write", "rw", }, - "bus": []string{"system", "session", "accessibility"}, + "bus": []string{"system", "session", "accessibility", "fcitx"}, } } @@ -38,6 +38,12 @@ func newDbus(q Qualifier, rule rule) (Rule, error) { if err != nil { return nil, err } + if err := rule.ValidateMapKeys([]string{"bus", "name", "path", "interface", "member", "peer"}); err != nil { + return nil, err + } + if err := rule.GetValues("peer").ValidateMapKeys([]string{"name", "label"}); err != nil { + return nil, err + } return &Dbus{ Base: newBase(rule), Qualifier: q, @@ -60,6 +66,10 @@ func newDbusFromLog(log map[string]string) Rule { } else { peerName = log["name"] } + member, present := log["member"] + if !present { + member = log["method"] + } return &Dbus{ Base: newBaseFromLog(log), Qualifier: newQualifierFromLog(log), @@ -68,7 +78,7 @@ func newDbusFromLog(log map[string]string) Rule { Name: name, Path: log["path"], Interface: log["interface"], - Member: log["member"], + Member: member, PeerName: peerName, PeerLabel: log["peer_label"], } @@ -90,7 +100,28 @@ func (r *Dbus) Validate() error { if err := validateValues(r.Kind(), "access", r.Access); err != nil { return fmt.Errorf("%s: %w", r, err) } - return validateValues(r.Kind(), "bus", []string{r.Bus}) + if err := validateValues(r.Kind(), "bus", []string{r.Bus}); err != nil { + return fmt.Errorf("%s: %w", r, err) + } + + // Bind access cannot have member, interface, or path modifiers + if len(r.Access) == 1 && r.Access[0] == "bind" { + if r.Member != "" { + return fmt.Errorf("dbus bind cannot have member modifier") + } + if r.Interface != "" { + return fmt.Errorf("dbus bind cannot have interface modifier") + } + } + + // Eavesdrop access cannot have non-bus modifiers + if len(r.Access) == 1 && r.Access[0] == "eavesdrop" { + if r.Name != "" || r.Path != "" || r.Interface != "" || r.Member != "" || + r.PeerName != "" || r.PeerLabel != "" { + return fmt.Errorf("dbus eavesdrop cannot have non-bus modifiers") + } + } + return nil } func (r *Dbus) Compare(other Rule) int { diff --git a/pkg/aa/file.go b/pkg/aa/file.go index 091f9436f9..87c47b8908 100644 --- a/pkg/aa/file.go +++ b/pkg/aa/file.go @@ -21,10 +21,11 @@ const ( func init() { requirements[FILE] = requirement{ - "access": {"m", "r", "w", "l", "k"}, + "access": {"m", "r", "w", "a", "l", "k"}, "transition": { "ix", "ux", "Ux", "px", "Px", "cx", "Cx", "pix", "Pix", "cix", "Cix", "pux", "PUx", "cux", "CUx", "x", + "Pux", "pUx", }, } } @@ -58,6 +59,10 @@ func newFile(q Qualifier, rule rule) (Rule, error) { if rule.Get(0) == FILE.Tok() { rule = rule[1:] } + // Skip safe/unsafe modifiers (handled at exec time) + if rule.Get(0) == "unsafe" || rule.Get(0) == "safe" { + rule = rule[1:] + } r := rule.GetSlice() size := len(r) @@ -65,7 +70,13 @@ func newFile(q Qualifier, rule rule) (Rule, error) { return nil, fmt.Errorf("missing file or access in rule: %s", rule) } - path, access = r[0], r[1] + // Determine format: "path access" vs "access path" + // Try parsing first token as access - if valid, use "access path" format + if testAccess, _ := toAccess(FILE, r[0]); len(testAccess) > 0 { + access, path = r[0], r[1] + } else { + path, access = r[0], r[1] + } if size > 2 { if r[2] != tokARROW { return nil, fmt.Errorf("missing '%s' in rule: %s", tokARROW, rule) @@ -84,10 +95,13 @@ func newFile(q Qualifier, rule rule) (Rule, error) { Path: path, Access: accesses, Target: target, - }, nil + }, rule.ValidateMapKeys([]string{}) } func newFileFromLog(log map[string]string) Rule { + if log["operation"] == "link" { + log["requested_mask"] += "l" + } accesses, err := toAccess("file-log", log["requested_mask"]) if err != nil { panic(fmt.Errorf("newFileFromLog(%v): %w", log, err)) @@ -136,19 +150,41 @@ func (r *File) Validate() error { return fmt.Errorf("invalid mode '%s'", v) } } - if r.Target != "" && !isAARE(r.Target) { - return fmt.Errorf("'%s' is not a valid AARE", r.Target) + if err := validateAAREPattern(r.Path); err != nil { + return err + } + // Conflicting access: write (w) and append (a) cannot coexist + hasW := slices.Contains(r.Access, "w") + hasA := slices.Contains(r.Access, "a") + if hasW && hasA { + return fmt.Errorf("conflicting file access: 'w' and 'a' cannot coexist") } return nil } func (r *File) Compare(other Rule) int { o, _ := other.(*File) + if o.AccessType == "deny" { + return -1 // Deny file rules always come last + } - letterR := getLetterIn(fileAlphabet, r.Path) - letterO := getLetterIn(fileAlphabet, o.Path) - if fileWeights[letterR] != fileWeights[letterO] && letterR != "" && letterO != "" { - return fileWeights[letterR] - fileWeights[letterO] + // Compare by file group - use pattern matching + groupR := getGroup(fileWeights, r.Path) + groupO := getGroup(fileWeights, o.Path) + if groupR != "" && groupO != "" { + weightR := fileWeights[groupR] + weightO := fileWeights[groupO] + if weightR != weightO { + return weightR - weightO + } + } else if groupR != "" { + return -1 + } else if groupO != "" { + return 1 + } + + if res := r.Qualifier.Compare(o.Qualifier); res != 0 { + return res } if res := compare(r.Owner, o.Owner); res != 0 { return res @@ -159,10 +195,7 @@ func (r *File) Compare(other Rule) int { if res := compare(r.Access, o.Access); res != 0 { return res } - if res := compare(r.Target, o.Target); res != 0 { - return res - } - return r.Qualifier.Compare(o.Qualifier) + return compare(r.Target, o.Target) } func (r *File) Merge(other Rule) bool { @@ -180,6 +213,11 @@ func (r *File) Merge(other Rule) bool { } func (r *File) Lengths() []int { + // Deny rules don't participate in padding alignment + if r.AccessType == "deny" { + return []int{0, 0, 0, 0} + } + // Add padding to align with other transition rule lenPath := 0 isTransition := util.Intersect( @@ -207,12 +245,23 @@ func (r *File) addLine(other Rule) bool { if other.Kind() != r.Kind() { return false } + o := other.(*File) + + // Deny rules are all grouped together without blank lines + if r.AccessType == "deny" && o.AccessType == "deny" { + return false + } - letterI := getLetterIn(fileAlphabet, r.Path) - letterJ := getLetterIn(fileAlphabet, other.(*File).Path) - groupI, ok1 := fileAlphabetGroups[letterI] - groupJ, ok2 := fileAlphabetGroups[letterJ] - return letterI != letterJ && (!ok1 || !ok2 || groupI != groupJ) + patternI := getGroup(fileWeights, r.Path) + patternJ := getGroup(fileWeights, o.Path) + if patternI == "" || patternJ == "" { + return patternI != patternJ + } + groupI, ok1 := fileAlphabetGroups[patternI] + groupJ, ok2 := fileAlphabetGroups[patternJ] + + // Add newline if patterns differ and they're in different groups (or unrecognized) + return patternI != patternJ && (!ok1 || !ok2 || groupI != groupJ) } type Link struct { @@ -255,7 +304,7 @@ func newLink(q Qualifier, rule rule) (Rule, error) { Subset: subset, Path: path, Target: target, - }, nil + }, rule.ValidateMapKeys([]string{}) } func newLinkFromLog(log map[string]string) Rule { @@ -284,14 +333,29 @@ func (r *Link) Validate() error { if !isAARE(r.Path) { return fmt.Errorf("'%s' is not a valid AARE", r.Path) } - if !isAARE(r.Target) { - return fmt.Errorf("'%s' is not a valid AARE", r.Target) - } return nil } func (r *Link) Compare(other Rule) int { o, _ := other.(*Link) + if o.AccessType == "deny" { + return -1 // Deny file rules always come last + } + + // Compare by file group - use pattern matching + groupR := getGroup(fileWeights, r.Path) + groupO := getGroup(fileWeights, o.Path) + if groupR != "" && groupO != "" { + weightR := fileWeights[groupR] + weightO := fileWeights[groupO] + if weightR != weightO { + return weightR - weightO + } + } else if groupR != "" { + return -1 + } else if groupO != "" { + return 1 + } if res := compare(r.Owner, o.Owner); res != 0 { return res @@ -329,3 +393,35 @@ func (r *Link) setPaddings(max []int) { []any{r.Owner, r.Subset, r.Path, r.Target})..., ) } + +// compareFileLink compares File and Link rules by their file group weight. +func compareFileLink(a, b Rule) int { + pathA := "" + switch r := a.(type) { + case *File: + pathA = r.Path + case *Link: + pathA = r.Path + } + + pathB := "" + switch r := b.(type) { + case *File: + pathB = r.Path + case *Link: + pathB = r.Path + } + + groupA := getGroup(fileWeights, pathA) + groupB := getGroup(fileWeights, pathB) + if groupA != "" && groupB != "" { + if res := fileWeights[groupA] - fileWeights[groupB]; res != 0 { + return res + } + } else if groupA != "" { + return -1 + } else if groupB != "" { + return 1 + } + return compare(pathA, pathB) +} diff --git a/pkg/aa/io_uring.go b/pkg/aa/io_uring.go index 76e9e172d2..ffb71df07f 100644 --- a/pkg/aa/io_uring.go +++ b/pkg/aa/io_uring.go @@ -28,12 +28,15 @@ func newIOUring(q Qualifier, rule rule) (Rule, error) { if err != nil { return nil, err } + if err := rule.ValidateNonEmptyValues([]string{"label"}); err != nil { + return nil, err + } return &IOUring{ Base: newBase(rule), Qualifier: q, Access: accesses, Label: rule.GetValuesAsString("label"), - }, nil + }, rule.ValidateMapKeys([]string{"label"}) } func newIOUringFromLog(log map[string]string) Rule { diff --git a/pkg/aa/mount.go b/pkg/aa/mount.go index bbf66b577f..aa0c4064b7 100644 --- a/pkg/aa/mount.go +++ b/pkg/aa/mount.go @@ -6,6 +6,7 @@ package aa import ( "fmt" + "slices" ) const ( @@ -15,25 +16,50 @@ const ( ) func init() { + conflicts[MOUNT] = map[string][][]string{ + "flags": { + {"rw", "ro"}, + {"strictatime", "nostrictatime"}, + {"lazytime", "nolazytime"}, + {"symfollow", "nosymfollow"}, + }, + } requirements[MOUNT] = requirement{ - "flags_bind": { - "B", "bind", "R", "rbind", + "fstype": { + "auto", "btrfs", "cgroup", "cgroup2", "configfs", "debugfs", + "devpts", "devtmpfs", "efivarfs", "ext2", "ext3", "ext4", "fuse.*", + "fuseblk", "fusectl", "hugetlbfs", "iso9660", "mqueue", "nfs", + "nfs4", "proc", "pstore", "ramfs", "rootfs", "securityfs", + "selinuxfs", "squashfs", "sysfs", "tmpfs", "tracefs", }, - "flags_change": { - "remount", "unbindable", "shared", "private", "slave", "runbindable", + "flags": { + // flags bind + "B", "bind", "M", "R", "rbind", + + // flags change + "shared", "slave", "nostrictatime", "lazytime", "nolazytime", "rshared", "rprivate", "rslave", "make-unbindable", "make-shared", "make-private", "make-slave", "make-runbindable", "make-rshared", - "make-rprivate", "make-rslave", - }, - "flags": { - "ro", "rw", "acl", "async", "atime", "bind", "dev", "diratime", + "make-rprivate", "make-rslave", "symfollow", + + // flags mount + "r", "read-only", "ro", "rw", "w", + "acl", "async", "atime", "bind", "dev", "diratime", "dirsync", "exec", "iversion", "loud", "mand", "move", "noacl", "noatime", "nodev", "nodiratime", "noexec", "noiversion", "nomand", - "norelatime", "nosuid", "nouser", "private", "rbind", "relatime", + "norelatime", "nosuid", "nosymfollow", "nouser", "private", "rbind", "relatime", "remount", "rprivate", "rshared", "rslave", "runbindable", "shared", "silent", "slave", "strictatime", "suid", "sync", "unbindable", "user", "verbose", }, + "change": { + // Change flags are mount flags that indicate a change operation + // and cannot have a source path. + "private", "rprivate", "slave", "rslave", "shared", "rshared", + "unbindable", "runbindable", "remount", + "make-unbindable", "make-private", "make-slave", "make-shared", + "make-runbindable", "make-rprivate", "make-rslave", "make-rshared", + }, } } @@ -64,7 +90,10 @@ func newMountConditionsFromLog(log map[string]string) MountConditions { } func (m MountConditions) Validate() error { - return validateValues(MOUNT, "flags", m.Options) + if err := validateValues(MOUNT, "flags", m.Options); err != nil { + return err + } + return validateConflicts(MOUNT, "flags", m.Options) } func (m MountConditions) Compare(other MountConditions) int { @@ -131,7 +160,7 @@ func newMount(q Qualifier, rule rule) (Rule, error) { MountConditions: conditions, Source: src, MountPoint: mount, - }, nil + }, rule.ValidateMapKeys([]string{"fstype", "options", "flags"}) } func newMountFromLog(log map[string]string) Rule { @@ -160,18 +189,35 @@ func (r *Mount) Validate() error { if err := r.MountConditions.Validate(); err != nil { return fmt.Errorf("%s: %w", r, err) } + if r.Source != "" && r.MountPoint != "" { + for _, opt := range r.Options { + if slices.Contains(requirements[MOUNT]["change"], opt) { + return fmt.Errorf("mount option '%s' cannot be used with a source path", opt) + } + } + } return nil } func (r *Mount) Compare(other Rule) int { o, _ := other.(*Mount) - if res := compare(r.Source, o.Source); res != 0 { + // Order: no fstype before fstype, then by options, then by source presence, then by mountpoint + if res := compare(r.FsType, o.FsType); res != 0 { + return res + } + if res := compare(len(r.Options) > 0, len(o.Options) > 0); res != 0 { + return res + } + if res := compare(r.Options, o.Options); res != 0 { + return res + } + if res := compare(r.Source != "", o.Source != ""); res != 0 { return res } if res := compare(r.MountPoint, o.MountPoint); res != 0 { return res } - if res := r.MountConditions.Compare(o.MountConditions); res != 0 { + if res := compare(r.Source, o.Source); res != 0 { return res } return r.Qualifier.Compare(o.Qualifier) @@ -232,7 +278,7 @@ func newUmount(q Qualifier, rule rule) (Rule, error) { Qualifier: q, MountConditions: conditions, MountPoint: mount, - }, nil + }, rule.ValidateMapKeys([]string{"fstype", "options", "flags"}) } func newUmountFromLog(log map[string]string) Rule { @@ -328,7 +374,7 @@ func newRemount(q Qualifier, rule rule) (Rule, error) { Qualifier: q, MountConditions: conditions, MountPoint: mount, - }, nil + }, rule.ValidateMapKeys([]string{"fstype", "options", "flags"}) } func newRemountFromLog(log map[string]string) Rule { diff --git a/pkg/aa/mqueue.go b/pkg/aa/mqueue.go index 12ae4bd599..0ed1889dcb 100644 --- a/pkg/aa/mqueue.go +++ b/pkg/aa/mqueue.go @@ -53,7 +53,7 @@ func newMqueue(q Qualifier, rule rule) (Rule, error) { Type: rule.GetValuesAsString("type"), Label: rule.GetValuesAsString("label"), Name: name, - }, nil + }, rule.ValidateMapKeys([]string{"type", "label"}) } func newMqueueFromLog(log map[string]string) Rule { @@ -92,6 +92,18 @@ func (r *Mqueue) Validate() error { if err := validateValues(r.Kind(), "type", []string{r.Type}); err != nil { return fmt.Errorf("%s: %w", r, err) } + // Only validate name if it's not an access keyword (parser may put access in Name) + nameIsAccess := slices.Contains(requirements[MQUEUE]["access"], r.Name) + if !nameIsAccess && r.Name != "" { + // POSIX mqueue names must start with / + if r.Type == "posix" && !strings.HasPrefix(r.Name, "/") && !strings.Contains(r.Name, "@{") { + return fmt.Errorf("mqueue: posix queue name '%s' must start with /", r.Name) + } + // SYSV mqueue names must not start with / + if r.Type == "sysv" && strings.HasPrefix(r.Name, "/") { + return fmt.Errorf("mqueue: sysv queue name '%s' must not start with /", r.Name) + } + } return nil } diff --git a/pkg/aa/network.go b/pkg/aa/network.go index d5a2af70b0..c229b64e74 100644 --- a/pkg/aa/network.go +++ b/pkg/aa/network.go @@ -6,7 +6,10 @@ package aa import ( "fmt" + "net" "slices" + "strconv" + "strings" ) const NETWORK Kind = "network" @@ -24,78 +27,183 @@ func init() { "netlink", "packet", "ash", "econet", "atmsvc", "rds", "sna", "irda", "pppox", "wanpipe", "llc", "ib", "mpls", "can", "tipc", "bluetooth", "iucv", "rxrpc", "isdn", "phonet", "ieee802154", "caif", "alg", - "nfc", "vsock", "kcm", "qipcrtr", "smc", "xdp", "mctp", + "nfc", "vsock", "kcm", "qipcrtr", "smc", "xdp", "mctp", "unspec", }, "type": []string{ "stream", "dgram", "seqpacket", "rdm", "raw", "packet", }, "protocol": []string{"tcp", "udp", "icmp"}, + "local-only": []string{ + "create", "bind", "listen", "getattr", "setattr", "getopt", "setopt", "shutdown", + }, } } -type AddressExpr struct { - Source string - Destination string - Port string +type LocalAddress struct { + IP string + Port string +} + +func newLocalAddress(rule rule) (LocalAddress, error) { + return LocalAddress{ + IP: rule.GetValuesAsString("ip"), + Port: rule.GetValuesAsString("port"), + }, nil } -func newAddressExprFromLog(log map[string]string) AddressExpr { - return AddressExpr{ - Source: log["laddr"], - Destination: log["faddr"], - Port: log["lport"], +func newLocalAddressFromLog(log map[string]string) LocalAddress { + return LocalAddress{ + IP: log["laddr"], + Port: log["lport"], } } -func (r AddressExpr) Compare(other AddressExpr) int { - if res := compare(r.Source, other.Source); res != 0 { - return res +// validatePortRange validates a port or port range string. +func validatePortRange(port string) error { + if port == "" { + return nil + } + if strings.Contains(port, "-") { + parts := strings.SplitN(port, "-", 2) + if len(parts) != 2 { + return fmt.Errorf("invalid port range: %s", port) + } + start, err1 := strconv.Atoi(parts[0]) + end, err2 := strconv.Atoi(parts[1]) + if err1 != nil || err2 != nil { + return fmt.Errorf("invalid port range: %s", port) + } + if start < 0 || start > 65535 || end < 0 || end > 65535 { + return fmt.Errorf("invalid port range: %s", port) + } + if start > end { + return fmt.Errorf("invalid port range: %s", port) + } + return nil + } + p, err := strconv.Atoi(port) + if err != nil || p < 0 || p > 65535 { + return fmt.Errorf("invalid port: %s", port) + } + return nil +} + +func (r LocalAddress) Validate() error { + if r.IP != "" && r.IP != "none" && net.ParseIP(r.IP) == nil { + return fmt.Errorf("invalid IP address: %s", r.IP) } - if res := compare(r.Destination, other.Destination); res != 0 { + return validatePortRange(r.Port) +} + +func (r LocalAddress) Compare(other LocalAddress) int { + if res := compare(r.IP, other.IP); res != 0 { return res } return compare(r.Port, other.Port) } +type PeerAddress struct { + IP string + Port string + Src string +} + +func newPeerAddress(rule rule) (PeerAddress, error) { + return PeerAddress{ + IP: rule.GetValues("peer").GetValuesAsString("ip"), + Port: rule.GetValues("peer").GetValuesAsString("port"), + }, nil +} + +func newPeerAddressFromLog(log map[string]string) PeerAddress { + return PeerAddress{ + IP: log["faddr"], + Port: log["fport"], + Src: log["saddr"], + } +} + +func (r PeerAddress) Validate() error { + if r.IP != "" && r.IP != "none" && net.ParseIP(r.IP) == nil { + return fmt.Errorf("invalid IP address: %s", r.IP) + } + return validatePortRange(r.Port) +} + +func (r PeerAddress) Compare(other PeerAddress) int { + if res := compare(r.IP, other.IP); res != 0 { + return res + } + if res := compare(r.Port, other.Port); res != 0 { + return res + } + return compare(r.Src, other.Src) +} + type Network struct { Base Qualifier - AddressExpr + LocalAddress + PeerAddress + Access []string Domain string Type string Protocol string } func newNetwork(q Qualifier, rule rule) (Rule, error) { + var accesses []string nType, protocol, domain := "", "", "" - r := rule.GetSlice() - if len(r) > 0 { - domain = r[0] - } - if len(r) >= 2 { - if slices.Contains(requirements[NETWORK]["type"], r[1]) { - nType = r[1] - } else if slices.Contains(requirements[NETWORK]["protocol"], r[1]) { - protocol = r[1] + + // Classify each token as access, domain, type, or protocol + allowedMapKeys := map[string]bool{"ip": true, "port": true, "peer": true, "type": true} + for _, token := range rule.GetSlice() { + switch { + case slices.Contains(requirements[NETWORK]["access"], token): + accesses = append(accesses, token) + case slices.Contains(requirements[NETWORK]["domains"], token): + domain = token + case slices.Contains(requirements[NETWORK]["type"], token): + nType = token + case slices.Contains(requirements[NETWORK]["protocol"], token): + protocol = token + case allowedMapKeys[token]: + // Map key tokens (ip, port, peer, type) are handled separately + default: + return nil, fmt.Errorf("unrecognized network token: %s", token) } } + + localAdress, err := newLocalAddress(rule) + if err != nil { + return nil, err + } + peerAddress, err := newPeerAddress(rule) + if err != nil { + return nil, err + } return &Network{ - Base: newBase(rule), - Qualifier: q, - Domain: domain, - Type: nType, - Protocol: protocol, - }, nil + Base: newBase(rule), + Qualifier: q, + LocalAddress: localAdress, + PeerAddress: peerAddress, + Access: accesses, + Domain: domain, + Type: nType, + Protocol: protocol, + }, rule.ValidateMapKeys([]string{"ip", "port", "peer", "type"}) } func newNetworkFromLog(log map[string]string) Rule { return &Network{ - Base: newBaseFromLog(log), - Qualifier: newQualifierFromLog(log), - AddressExpr: newAddressExprFromLog(log), - Domain: log["family"], - Type: log["sock_type"], - Protocol: log["protocol"], + Base: newBaseFromLog(log), + Qualifier: newQualifierFromLog(log), + LocalAddress: newLocalAddressFromLog(log), + PeerAddress: newPeerAddressFromLog(log), + Access: Must(toAccess(NETWORK, log["requested"])), + Domain: log["family"], + Type: log["sock_type"], + Protocol: log["protocol"], } } @@ -112,6 +220,9 @@ func (r *Network) String() string { } func (r *Network) Validate() error { + if err := validateValues(r.Kind(), "access", r.Access); err != nil { + return fmt.Errorf("%s: %w", r, err) + } if err := validateValues(r.Kind(), "domains", []string{r.Domain}); err != nil { return fmt.Errorf("%s: %w", r, err) } @@ -121,6 +232,17 @@ func (r *Network) Validate() error { if err := validateValues(r.Kind(), "protocol", []string{r.Protocol}); err != nil { return fmt.Errorf("%s: %w", r, err) } + if err := r.LocalAddress.Validate(); err != nil { + return fmt.Errorf("%s: %w", r, err) + } + if err := r.PeerAddress.Validate(); err != nil { + return fmt.Errorf("%s: %w", r, err) + } + if r.PeerAddress.IP != "" || r.PeerAddress.Port != "" || r.Src != "" { + if len(r.Access) > 0 && allLocalOnly(r.Access, requirements[NETWORK]["local-only"]) { + return fmt.Errorf("peer modifier not allowed with local-only access types in network rule") + } + } return nil } @@ -129,13 +251,19 @@ func (r *Network) Compare(other Rule) int { if res := compare(r.Domain, o.Domain); res != 0 { return res } + if res := compare(r.Access, o.Access); res != 0 { + return res + } if res := compare(r.Type, o.Type); res != 0 { return res } if res := compare(r.Protocol, o.Protocol); res != 0 { return res } - if res := r.AddressExpr.Compare(o.AddressExpr); res != 0 { + if res := r.LocalAddress.Compare(o.LocalAddress); res != 0 { + return res + } + if res := r.PeerAddress.Compare(o.PeerAddress); res != 0 { return res } return r.Qualifier.Compare(o.Qualifier) diff --git a/pkg/aa/parse.go b/pkg/aa/parse.go index e01696d747..dc9dc3950a 100644 --- a/pkg/aa/parse.go +++ b/pkg/aa/parse.go @@ -8,13 +8,20 @@ import ( "fmt" "regexp" "slices" + "strconv" "strings" + "unicode" ) const ( tokALLOW = "allow" tokAUDIT = "audit" tokDENY = "deny" + tokOTHER = "other" + tokPROMPT = "prompt" + tokPRIORITY = "priority" + tokSAFE = "safe" + tokUNSAFE = "unsafe" tokARROW = "->" tokEQUAL = "=" tokLESS = "<" @@ -55,23 +62,291 @@ var ( tok = map[Kind]string{ COMMENT: "#", VARIABLE: "@{", + BOOLEAN: "$", HAT: "^", } - openBlocks = []rune{tokOPENPAREN, tokOPENBRACE, tokOPENBRACKET} - closeBlocks = []rune{tokCLOSEPAREN, tokCLOSEBRACE, tokCLOSEBRACKET} + inHeader = false + regParagraph = regexp.MustCompile(`(?s).*?\n\n|$`) + regVariableDefinition = regexp.MustCompile(`@{(.*)}\s*[+=]+\s*(.*)`) +) - inHeader = false - regParagraph = regexp.MustCompile(`(?s).*?\n\n|$`) +const ( + CONTENT Kind = "content" + RAW Kind = "raw" + QUALIFIER Kind = "qualifier" ) +// Intermediate token for the representation of apparmor blocks such as +// profile, subprofile, hat, qualifier and condition. +type block struct { + kind Kind + raw string + next *block +} + +// Split a raw input block string into tokens by '{', '}', but ignore +// variables and second level blocks. +func tokenizeBlock(input string) ([]*block, error) { + if len(input) > 0 && input[0] == tokOPENBRACE { + return nil, fmt.Errorf("wrong block format: %s", input) + } + + blocks := []*block{} + blockStack := []rune{} + blockRecorded := false + blockStart := 0 + blockEnd := 0 + blockContentStart := 0 + blockContentStartBkp := 0 + blockContentEnd := 0 + inComment := false + + for idx, r := range input { + switch r { + case '#': + inComment = true + + case '\n': + inComment = false + + case tokOPENBRACE: + if inComment { + continue + } + blockStack = append(blockStack, r) + + // Block rules starts with ' {', ignore nested blocks and variables + if len(blockStack) == 1 { + ignore := false + + // Ignore the block if it is inside a variable definition + if input[idx-1] == '@' { + ignore = true + } else { + i := idx + for i > 0 && input[i] != '\n' { + i-- + } + j := idx + for j < len(input) && input[j] != '\n' { + j++ + } + line := input[i:j] + match := regVariableDefinition.FindStringSubmatch(line) + if len(match) > 0 { + ignore = true + } else if !unicode.IsSpace(rune(input[idx-1])) { + ignore = true + } else { + // Check if this is a brace expansion (e.g., {a,b,c}) vs block delimiter. + // A brace expansion has a matching } on the same line. + rest := input[idx+1 : j] + if strings.Contains(rest, "}") { + ignore = true + } + } + } + + if !ignore { + blockStart = idx + blockRecorded = true + } + } + + case tokCLOSEBRACE: + if inComment { + continue + } + if len(blockStack) <= 0 { + return nil, fmt.Errorf("unbalanced block, missing '{' for '} at: }%s", + input[blockContentStart:idx]) + } + + if len(blockStack) == 1 && blockRecorded { + blockRecorded = false + blockEnd = idx + blockContentStartBkp = blockContentStart + blockContentEnd = blockStart + blockContentRaw := input[blockContentStart:blockContentEnd] + blockContentStart = blockEnd + 1 + + // Collect the block header + i := len(blockContentRaw) - 1 + for i > 0 && blockContentRaw[i] != '\n' { + i-- + } + blockHeader := strings.Trim(blockContentRaw[i:], "\n\t ") + + // Ignore commented block, restore previous id values + if len(blockHeader) > 0 && blockHeader[0] == '#' { + blockContentStart = blockContentStartBkp + blockStack = blockStack[:len(blockStack)-1] + continue + } + + // Collect out of block content (preamble, profile content outside of sub blocks) + blockContentRaw = blockContentRaw[:i] + if blockContentRaw != "" { + blocks = append(blocks, &block{ + kind: CONTENT, + raw: blockContentRaw, + }) + } + + // Collect the block content + blockRaw := input[blockStart+1 : blockEnd] + blockRaw = strings.Trim(blockRaw, "\n\t ") + var kind Kind + switch { + case strings.HasPrefix(blockHeader, PROFILE.Tok()), isAARE(blockHeader): + kind = PROFILE + case strings.HasPrefix(blockHeader, HAT.Tok()), + strings.HasPrefix(blockHeader, HAT.String()): + kind = HAT + case strings.HasPrefix(blockHeader, IF.Tok()): + kind = IF + case strings.HasPrefix(blockHeader, ELSE.Tok()), + blockHeader == "": + kind = ELSE + case isProfileBlockHeader(blockHeader): + kind = PROFILE + case isRuleBlockHeader(blockHeader): + // Rule block modifiers: "owner { ... }", "audit { ... }" + // Wrap the block content with the modifier prefix on each rule + blockRaw = prependToRules(blockHeader, blockRaw) + kind = CONTENT + default: + return nil, fmt.Errorf("unrecognized block type: %s", blockHeader) + } + blocks = append(blocks, &block{ + kind: kind, + raw: blockHeader, + next: &block{ + kind: RAW, + raw: blockRaw, + }, + }) + } + blockStack = blockStack[:len(blockStack)-1] + } + } + + if len(blockStack) != 0 { + return nil, fmt.Errorf("unbalanced block, missing '}': %s", + input[blockContentEnd:]) + } + if len(blocks) == 0 { + // No block found, it can be a tunable/abstraction file. + blocks = append(blocks, &block{ + kind: CONTENT, + raw: input, + }) + } else if blockContentStart < len(input) { + // Capture any remaining content after the last block + remaining := input[blockContentStart:] + remaining = strings.Trim(remaining, "\n\t ") + if remaining != "" { + blocks = append(blocks, &block{ + kind: CONTENT, + raw: remaining, + }) + } + } + return blocks, nil +} + +func parseBlock(b *block) (Rules, error) { + var res Rules + + switch b.kind { + case CONTENT: + var err error + res, err = parseContentRules(b.raw) + if err != nil { + return nil, err + } + for _, r := range res { + if r.Constraint() == PreambleRule { + return nil, fmt.Errorf("Rule not allowed in block: %s", r) + } + } + + case RAW: + blocks, err := tokenizeBlock(b.raw) + if err != nil { + return nil, err + } + for _, block := range blocks { + rules, err := parseBlock(block) + if err != nil { + return nil, err + } + res = append(res, rules...) + } + return res, nil + + case PROFILE: + inHeader = true + header, err := newHeader(parseRule(b.raw)) + inHeader = false + if err != nil { + return nil, err + } + rules, err := parseBlock(b.next) + if err != nil { + return nil, err + } + profile := &Profile{ + Header: header, + Rules: rules, + } + res = append(res, profile) + + case HAT: + inHeader = true + hat, err := newHat(parseRule(b.raw)) + inHeader = false + if err != nil { + return nil, err + } + rules, err := parseBlock(b.next) + if err != nil { + return nil, err + } + hat.Rules = rules + res = append(res, hat) + + case IF, ELSE: + condition, err := newCondition(parseRule(b.raw)) + if err != nil { + return nil, err + } + rules, err := parseBlock(b.next) + if err != nil { + return nil, err + } + if b.kind == IF { + condition.IfRules = rules + } else { + condition.ElseRules = rules + } + res = append(res, condition) + + } + return res, nil +} + // Parse the line rule from a raw string. func parseLineRules(isPreamble bool, input string) (string, Rules, error) { var res Rules var r Rule var err error + var remaining []string for _, line := range strings.Split(input, "\n") { tmp := strings.TrimLeft(line, "\t ") + processed := false + switch { case strings.HasPrefix(tmp, COMMENT.Tok()): r, err = newComment(rule{kv{comment: tmp[1:]}}) @@ -79,7 +354,7 @@ func parseLineRules(isPreamble bool, input string) (string, Rules, error) { return "", nil, err } res = append(res, r) - input = strings.Replace(input, line, "", 1) + processed = true case strings.HasPrefix(tmp, INCLUDE.Tok()): r, err = newInclude(parseRule(line)[1:]) @@ -87,7 +362,7 @@ func parseLineRules(isPreamble bool, input string) (string, Rules, error) { return "", nil, err } res = append(res, r) - input = strings.Replace(input, line, "", 1) + processed = true case strings.HasPrefix(tmp, VARIABLE.Tok()) && isPreamble: r, err = newVariable(parseRule(line)) @@ -95,10 +370,24 @@ func parseLineRules(isPreamble bool, input string) (string, Rules, error) { return "", nil, err } res = append(res, r) - input = strings.Replace(input, line, "", 1) + processed = true + + case strings.HasPrefix(tmp, BOOLEAN.Tok()) && isPreamble: + r, err = newBoolean(parseRule(line)) + if err != nil { + return "", nil, err + } + res = append(res, r) + processed = true + } + + if processed { + remaining = append(remaining, "") + } else { + remaining = append(remaining, line) } } - return input, res, nil + return strings.Join(remaining, "\n"), res, nil } // Parse the comma rules from a raw string. It splits rules string into tokens @@ -149,7 +438,7 @@ func parseCommaRules(input string) ([]rule, error) { case tokCOLON: if blockCounter == 0 && !comment { - if idx+1 < size && !strings.ContainsRune(" \n", rune(input[idx+1])) { + if idx+1 < size && !strings.ContainsRune(" \t\n", rune(input[idx+1])) { // Colon in AARE, it is valid, not a separator aare = true } @@ -168,15 +457,13 @@ func parseCommaRules(input string) ([]rule, error) { return rules, nil } -func parseParagraph(input string) (Rules, error) { - // Line rules - var raw string +// parseContentRules parses line and comma rules from a raw string. +func parseContentRules(input string) (Rules, error) { raw, res, err := parseLineRules(false, input) if err != nil { return nil, err } - // Comma rules rules, err := parseCommaRules(raw) if err != nil { return nil, err @@ -186,13 +473,7 @@ func parseParagraph(input string) (Rules, error) { return nil, err } - res = append(res, rrr...) - // for _, r := range res { - // if r.Constraint() == PreambleRule { - // return nil, fmt.Errorf("Rule not allowed in block: %s", r) - // } - // } - return res, nil + return append(res, rrr...), nil } // Split a raw input rule string into tokens by space or =, but ignore spaces @@ -207,44 +488,69 @@ func parseParagraph(input string) (Rules, error) { // []string{"owner", "@{user_config_dirs}/powerdevilrc{,.@{rand6}}", "rwl", "->", "@{user_config_dirs}/#@{int}"} func tokenizeRule(str string) []string { var currentToken strings.Builder - isVariable, wasTokPLUS, quoted := false, false, false + isVariable, wasTokPLUS, wasTokQM, wasTokCOLON, quoted := false, false, false, false, false + sawAssignment := false blockStack := []rune{} tokens := make([]string, 0, len(str)/2) - if inHeader && len(str) > 2 && str[0:2] == VARIABLE.Tok() { - isVariable = true + trimmed := strings.TrimLeft(str, " \t") + if inHeader && len(trimmed) > 1 && strings.Contains(trimmed, "=") { + if trimmed[0:2] == VARIABLE.Tok() || trimmed[0] == '$' { + isVariable = true + } } + + escaped := false for _, r := range str { + if escaped { + currentToken.WriteRune(r) + escaped = false + continue + } + if r == '\\' { + currentToken.WriteRune(r) + escaped = true + continue + } switch { - case (r == ' ' || r == '\t') && len(blockStack) == 0 && !quoted: - // Split on space/tab if not in a block or quoted + case unicode.IsSpace(r) && len(blockStack) == 0 && !quoted: + // Split on space/tab/newline if not in a block or quoted if currentToken.Len() != 0 { tokens = append(tokens, currentToken.String()) currentToken.Reset() } - case (r == '+' || r == '=') && len(blockStack) == 0 && !quoted && isVariable: - // Handle variable assignment + case (r == '+' || r == '?' || r == ':' || r == '=') && len(blockStack) == 0 && !quoted && isVariable && !sawAssignment: + // Handle variable assignment operators: =, +=, ?=, := if currentToken.Len() != 0 { tokens = append(tokens, currentToken.String()) currentToken.Reset() } if wasTokPLUS { tokens[len(tokens)-1] = tokPLUS + tokEQUAL + } else if wasTokQM { + tokens[len(tokens)-1] = "?=" + } else if wasTokCOLON { + tokens[len(tokens)-1] = ":=" } else { tokens = append(tokens, string(r)) } wasTokPLUS = (r == '+') + wasTokQM = (r == '?') + wasTokCOLON = (r == ':') + if r == '=' { + sawAssignment = true + } case r == '"' && len(blockStack) == 0: quoted = !quoted currentToken.WriteRune(r) - case slices.Contains(openBlocks, r): + case r == tokOPENPAREN || r == tokOPENBRACE || r == tokOPENBRACKET: blockStack = append(blockStack, r) currentToken.WriteRune(r) - case slices.Contains(closeBlocks, r): + case r == tokCLOSEPAREN || r == tokCLOSEBRACE || r == tokCLOSEBRACKET: if len(blockStack) > 0 { blockStack = blockStack[:len(blockStack)-1] } else { @@ -256,6 +562,7 @@ func tokenizeRule(str string) []string { currentToken.WriteRune(r) } } + if currentToken.Len() != 0 { tokens = append(tokens, currentToken.String()) } @@ -286,13 +593,14 @@ func parseRule(str string) rule { res := make(rule, 0, len(str)/2) tokens := tokenizeRule(str) - inAare := len(tokens) > 0 && (isAARE(tokens[0]) || tokens[0] == tokOWNER) + inAare := len(tokens) > 0 && (tokens[0] == tokOWNER || (isAARE(tokens[0]) && !inHeader)) for idx, token := range tokens { switch { - case token == tokEQUAL, token == tokPLUS+tokEQUAL, token == tokLESS+tokEQUAL: // Variable & Rlimit + case token == tokEQUAL, token == tokPLUS+tokEQUAL, token == tokLESS+tokEQUAL, + token == "?=", token == ":=": // Variable, Boolean & Rlimit res = append(res, kv{key: token}) - case strings.Contains(token, "=") && !inAare: // Map + case strings.Contains(token, "=") && !inAare && !isAARE(token): // Map items := strings.SplitN(token, "=", 2) key := items[0] if len(items) > 1 { @@ -411,7 +719,10 @@ func (r rule) GetAsMap() map[string][]string { res := map[string][]string{} for _, kv := range r { if kv.values != nil { - res[kv.key] = kv.values.GetSlice() + if res[kv.key] == nil { + res[kv.key] = []string{} + } + res[kv.key] = append(res[kv.key], kv.values.GetSlice()...) } } return res @@ -431,12 +742,13 @@ func (r rule) GetAsMap() map[string][]string { // {key: "label", values: rule{{Key: "power-profiles-daemon"}}}, // }}, func (r rule) GetValues(key string) rule { + var res rule for _, kv := range r { - if kv.key == key { - return kv.values + if kv.key == key && kv.values != nil { + res = append(res, kv.values...) } } - return nil + return res } // GetValuesAsSlice return the values from a key as a slice. @@ -466,6 +778,30 @@ func (r rule) GetValuesAsString(key string) string { return r.GetValues(key).GetString() } +// ValidateMapKeys validate that all map keys in a rule are in the validKeys slice. +func (r rule) ValidateMapKeys(validKeys []string) error { + for _, kv := range r { + if kv.values != nil { + if !slices.Contains(validKeys, kv.key) { + return fmt.Errorf("invalid modifier '%s' in rule: %s", kv.key, r) + } + } + } + return nil +} + +// ValidateNonEmptyValues validates that keys which are present have non-empty values. +func (r rule) ValidateNonEmptyValues(keys []string) error { + for _, kv := range r { + if kv.values != nil && slices.Contains(keys, kv.key) { + if len(kv.values) == 0 { + return fmt.Errorf("empty value for '%s' in rule: %s", kv.key, r) + } + } + } + return nil +} + // String return a generic representation of a rule. func (r rule) String() string { var res strings.Builder @@ -503,6 +839,57 @@ func isAARE(str string) bool { } } +// isProfileBlockHeader checks if a block header represents a profile +// that starts with a qualifier prefix or namespace. +func isProfileBlockHeader(header string) bool { + // Handle qualifier prefixes: "audit /path", "allow /path" + prefixes := []string{"audit ", "allow ", "deny "} + for _, p := range prefixes { + if strings.HasPrefix(header, p) { + rest := strings.TrimPrefix(header, p) + if isAARE(rest) || strings.HasPrefix(rest, PROFILE.Tok()) || isProfileBlockHeader(rest) { + return true + } + } + } + + // Handle namespace prefix: ":ns:path" or ":ns:name" + if len(header) > 2 && header[0] == ':' { + // Must have a second colon after the namespace name + if idx := strings.Index(header[1:], ":"); idx > 0 { + return true + } + } + return false +} + +// isRuleBlockHeader checks if a block header is a rule modifier block +// like "owner { ... }" or "audit { ... }" that applies to all rules inside. +func isRuleBlockHeader(header string) bool { + modifiers := []string{"owner", "audit", "deny", "allow"} + for _, m := range modifiers { + if header == m { + return true + } + } + return false +} + +// prependToRules prepends a modifier to each rule line in a block. +func prependToRules(modifier, blockContent string) string { + lines := strings.Split(blockContent, "\n") + var result []string + for _, line := range lines { + trimmed := strings.TrimSpace(line) + if trimmed == "" || strings.HasPrefix(trimmed, "#") { + result = append(result, line) + } else { + result = append(result, modifier+" "+trimmed) + } + } + return strings.Join(result, "\n") +} + // Convert a slice of internal rules to a slice of ApparmorRule. func newRules(rules []rule) (Rules, error) { var err error @@ -516,6 +903,7 @@ func newRules(rules []rule) (Rules, error) { owner := false q := Qualifier{} + hasAccessType := false // track if allow/deny/prompt was seen qualifier: switch rule.Get(0) { // File & Link prefix @@ -523,12 +911,38 @@ func newRules(rules []rule) (Rules, error) { owner = true rule = rule[1:] goto qualifier + + // File exec modifiers and "other" prefix - these are only valid + // before file rules, not before other rule types like change_profile. + // We peek at the next token to decide. + case tokUNSAFE, tokSAFE, tokOTHER: + rule = rule[1:] + goto qualifier + // Qualifier - case tokALLOW, tokDENY: + case tokPRIORITY: + priority, err := strconv.Atoi(rule.GetValues(tokPRIORITY).GetString()) + if err != nil { + return nil, fmt.Errorf("invalid priority value in rule: %s", rule) + } + if priority < -1000 || priority > 1000 { + return nil, fmt.Errorf("priority value %d out of range [-1000, 1000]", priority) + } + q.Priority = priority + rule = rule[1:] + goto qualifier + case tokALLOW, tokDENY, tokPROMPT: + if hasAccessType { + return nil, fmt.Errorf("conflicting access types '%s' and '%s' in rule: %s", q.AccessType, rule.Get(0), rule) + } + hasAccessType = true q.AccessType = rule.Get(0) rule = rule[1:] goto qualifier case tokAUDIT: + if hasAccessType { + return nil, fmt.Errorf("'audit' must appear before '%s' in rule: %s", q.AccessType, rule) + } q.Audit = true rule = rule[1:] goto qualifier @@ -540,28 +954,34 @@ func newRules(rules []rule) (Rules, error) { if err != nil { return nil, err } - if owner && r.Kind() == LINK { - r.(*Link).Owner = owner + if owner { + switch r := r.(type) { + case *File: + r.Owner = owner + case *Link: + r.Owner = owner + default: + return nil, fmt.Errorf("owner not allowed in %s rule : %s", r.Kind(), rule) + } } res = append(res, r) + } else { raw := rule.Get(0) - if raw != "" { - // File - if isAARE(raw) || owner { - r, err = newFile(q, rule) - if err != nil { - return nil, err - } - r.(*File).Owner = owner - res = append(res, r) - } else { - fmt.Printf("Unknown rule: %s", rule) - // return nil, fmt.Errorf("Unknown rule: %s", rule) - } - } else { + if raw == "" { return nil, fmt.Errorf("unrecognized rule: %s", rule) } + testAccess, _ := toAccess(FILE, raw) + if !isAARE(raw) && !owner && len(testAccess) == 0 { + return nil, fmt.Errorf("unknown rule: %s", rule) + } + r, err = newFile(q, rule) + if err != nil { + return nil, err + } + r.(*File).Owner = owner + res = append(res, r) + } } } @@ -571,9 +991,10 @@ func newRules(rules []rule) (Rules, error) { func (f *AppArmorProfileFile) parsePreamble(preamble string) error { var err error inHeader = true + isPreamble := f.Kind == ProfileKind // Line rules - preamble, lineRules, err := parseLineRules(true, preamble) + preamble, lineRules, err := parseLineRules(isPreamble, preamble) if err != nil { return err } @@ -591,9 +1012,17 @@ func (f *AppArmorProfileFile) parsePreamble(preamble string) error { f.Preamble = append(f.Preamble, commaRules...) for _, r := range f.Preamble { - if r.Constraint() == BlockRule { - f.Preamble = nil - return fmt.Errorf("Rule not allowed in preamble: %s", r) + switch f.Kind { + case ProfileKind: + if r.Constraint() == BlockRule { + f.Preamble = nil + return fmt.Errorf("rule not allowed in profile preamble: %s", r) + } + + case AbstractionKind, TunableKind: + + default: + return fmt.Errorf("unknown profile file kind") } } inHeader = false @@ -602,56 +1031,32 @@ func (f *AppArmorProfileFile) parsePreamble(preamble string) error { // Parse an apparmor profile file. // -// Warning: It is purposely an uncomplete basic parser for apparmor profile, +// Warning: It is purposely an uncomplete parser for apparmor profile, // it is only aimed for internal tooling purpose. For "simplicity", it is not // using antlr / participle. It is only used for experimental feature in the -// apparmor.d project. -// -// Very basic: -// - Only supports parsing of preamble and profile headers. -// - Stop at the first profile header. -// - Does not support multiline coma rules. -// - Does not support multiple profiles by file. +// apparmor.d project. Technically, it is more a scanner than a parser. // // Current use case: // - Parse include and tunables // - Parse variable in profile preamble and in tunable files // - Parse (sub) profiles header to edit flags func (f *AppArmorProfileFile) Parse(input string) (int, error) { - var raw strings.Builder - rawHeader := "" - nb := 0 + if err := f.Scan(input); err != nil { + return 0, err + } -done: + // nb is the line index of the first profile or hat header. Callers + // rely on it to split the input into preamble (lines[:nb]) and + // body (lines[nb:]). for i, line := range strings.Split(input, "\n") { tmp := strings.TrimLeft(line, "\t ") - switch { - case tmp == "": - continue - case strings.HasPrefix(tmp, PROFILE.Tok()): - rawHeader = strings.TrimRight(tmp, "{") - nb = i - break done - case strings.HasPrefix(tmp, HAT.String()), strings.HasPrefix(tmp, HAT.Tok()): - nb = i - break done - default: - raw.WriteString(tmp + "\n") + if strings.HasPrefix(tmp, PROFILE.Tok()) || + strings.HasPrefix(tmp, HAT.String()) || + strings.HasPrefix(tmp, HAT.Tok()) { + return i, nil } } - - if err := f.parsePreamble(raw.String()); err != nil { - return nb, err - } - if rawHeader != "" { - header, err := newHeader(parseRule(rawHeader)) - if err != nil { - return nb, err - } - profile := &Profile{Header: header} - f.Profiles = append(f.Profiles, profile) - } - return nb, nil + return 0, nil } // ParseRules parses apparmor profile rules by paragraphs @@ -680,7 +1085,7 @@ func ParseRules(input string) (ParaRules, []string, error) { } paragraphs = append(paragraphs, paragraph) - rules, err := parseParagraph(paragraph) + rules, err := parseContentRules(paragraph) if err != nil { return nil, nil, err } @@ -689,3 +1094,88 @@ func ParseRules(input string) (ParaRules, []string, error) { return paragraphRules, paragraphs, nil } + +// Scan an apparmor profile file with multiple profiles, hats, and nested. +// Like Parse, but process all profiles and blocks in the file. +func (f *AppArmorProfileFile) Scan(input string) (retErr error) { + defer func() { + if r := recover(); r != nil { + retErr = fmt.Errorf("%v", r) + } + }() + + blocks, err := tokenizeBlock(input) + if err != nil { + return err + } + + // Check if the file has any profile/hat blocks + hasProfileBlocks := false + for _, block := range blocks { + if block.kind == PROFILE || block.kind == HAT { + hasProfileBlocks = true + break + } + } + _ = hasProfileBlocks + + for _, block := range blocks { + switch block.kind { + case CONTENT: + if err := f.parsePreamble(block.raw); err != nil { + return err + } + + case PROFILE: + inHeader = true + header, err := newHeader(parseRule(block.raw)) + inHeader = false + if err != nil { + return err + } + rules, err := parseBlock(block.next) + if err != nil { + return err + } + profile := &Profile{ + Header: header, + Rules: rules, + } + f.Profiles = append(f.Profiles, profile) + + case HAT: + inHeader = true + hat, err := newHat(parseRule(block.raw)) + inHeader = false + if err != nil { + return err + } + rules, err := parseBlock(block.next) + if err != nil { + return err + } + hat.Rules = rules + f.Hats = append(f.Hats, hat) + + case IF, ELSE: + condition, err := newCondition(parseRule(block.raw)) + if err != nil { + return err + } + rules, err := parseBlock(block.next) + if err != nil { + return err + } + if block.kind == IF { + condition.IfRules = rules + } else { + condition.ElseRules = rules + } + f.Conditions = append(f.Conditions, condition) + + default: + return fmt.Errorf("illegal %s block in profile file", block.kind) + } + } + return nil +} diff --git a/pkg/aa/parse_test.go b/pkg/aa/parse_test.go index 71607fd325..1a43a8e5b4 100644 --- a/pkg/aa/parse_test.go +++ b/pkg/aa/parse_test.go @@ -5,9 +5,14 @@ package aa import ( + "os" "reflect" + "regexp" + "slices" "strings" "testing" + + "github.com/roddhjav/apparmor.d/pkg/paths" ) func Test_tokenizeRule(t *testing.T) { @@ -110,6 +115,47 @@ func Test_parseCommaRules(t *testing.T) { } } +func Test_tokenizeBlock(t *testing.T) { + for _, tt := range testBlocks { + t.Run(tt.name, func(t *testing.T) { + got, err := tokenizeBlock(tt.raw) + if (err != nil) != tt.wTokenizeErr { + t.Errorf("tokenizeBlock() error = %v, wantErr %v", err, tt.wTokenizeErr) + return + } + if !reflect.DeepEqual(got, tt.blocks) { + t.Errorf("tokenizeBlock() = %v, want %v", got, tt.blocks) + } + }) + } +} + +func Test_parseBlock(t *testing.T) { + for _, tt := range testBlocks { + t.Run(tt.name, func(t *testing.T) { + for idx, b := range tt.blocks { + var err error + var got Rules + want := tt.rules[idx] + if idx == 0 && b.kind == CONTENT && (strings.HasPrefix(b.raw, "# Simple test") || strings.Contains(b.raw, "$")) { + f := &AppArmorProfileFile{} + err = f.parsePreamble(b.raw) + got = f.Preamble + } else { + got, err = parseBlock(b) + } + if (err != nil) != tt.wParseBlockErr { + t.Errorf("parseBlock() error = %v, wantErr %v", err, tt.wParseBlockErr) + return + } + if !reflect.DeepEqual(got, want) { + t.Errorf("parseBlock() = %v, want %v", got, want) + } + } + }) + } +} + func Test_newRules(t *testing.T) { for _, tt := range testParseRules { if tt.wRule == nil { @@ -134,13 +180,17 @@ func Test_newRules(t *testing.T) { func Test_AppArmorProfileFile_Parse(t *testing.T) { for _, tt := range testBlocks { t.Run(tt.name, func(t *testing.T) { + expected := tt.apparmorAll + if expected == nil { + expected = tt.apparmor + } got := &AppArmorProfileFile{} nb, err := got.Parse(tt.raw) if (err != nil) != tt.wParseErr { t.Errorf("AppArmorProfileFile.Parse() error = %v, wantErr %v", err, tt.wParseErr) } - if !reflect.DeepEqual(got, tt.apparmor) { - t.Errorf("AppArmorProfileFile.Parse() = |%v|, want |%v|", got, tt.apparmor) + if !reflect.DeepEqual(got, expected) { + t.Errorf("AppArmorProfileFile.Parse() = |%v|, want |%v|", got, expected) } raw := strings.Join(strings.Split(tt.raw, "\n")[nb:], "\n") gotRules, _, err := ParseRules(raw) @@ -155,6 +205,262 @@ func Test_AppArmorProfileFile_Parse(t *testing.T) { } } +func Test_AppArmorProfileFile_Scan(t *testing.T) { + for _, tt := range testBlocks { + t.Run(tt.name, func(t *testing.T) { + if tt.apparmorAll == nil { + tt.apparmorAll = tt.apparmor + } + got := &AppArmorProfileFile{} + if err := got.Scan(tt.raw); (err != nil) != tt.wParseErr { + t.Errorf("AppArmorProfileFile.Scan() error = %v, wantErr %v", err, tt.wParseErr) + } + if !reflect.DeepEqual(got, tt.apparmorAll) { + t.Errorf("AppArmorProfileFile.Scan() = %v, want %v", got, tt.apparmorAll) + } + }) + } + for _, tt := range testParser { + t.Run(tt.name, func(t *testing.T) { + got := &AppArmorProfileFile{} + if err := got.Scan(tt.raw); (err != nil) != tt.wantErr { + t.Errorf("AppArmorProfileFile.Scan() error = %v, wantErr %v", err, tt.wantErr) + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("AppArmorProfileFile.Scan() = %v, want %v", got, tt.want) + } + }) + } +} + +type testReport struct { + Success bool `csv:"success"` + Name string `csv:"name"` + Desc string `csv:"desc"` + Error string `csv:"error"` +} + +type testReports []*testReport + +func (r testReports) SumUp(t *testing.T) { + success := 0 + for _, r := range r { + if r.Success { + success++ + } + } + t.Logf("[TOTAL]: %d tests, success: %d, fail %d, success rate: %v%%\n", + len(r), success, len(r)-success, (success*100.0)/len(r)) +} + +func testAppArmorProfileFiles(t *testing.T, rootdir *paths.Path, files []*paths.Path, parses []bool) { + templateFailure := "\033[0;31m[FAILED]\033[0m(\033[0;37m%s\033[0m): %v" + templateSuccess := "\033[0;32m[SUCCESS]\033[0m(\033[0;37m%s\033[0m)" + ignorePath := []string{"abstractions/transmission-common"} + + reports := testReports{} + for _, parse := range parses { + base := "Parse/" + if !parse { + base = "Scan/" + } + + for _, file := range files { + if !file.Exist() { + panic(file.String() + " %s not found") + } + name, err := file.RelFrom(rootdir) + if err != nil { + panic(err) + } + if strings.HasPrefix(name.String(), "abi/") { + t.Logf("Skipping abi file: %s", name) + continue + } + if slices.Contains(ignorePath, name.String()) { + t.Logf("Skipping ignored file: %s", name) + continue + } + + t.Run(base+name.String(), func(t *testing.T) { + var err error + r := &testReport{Name: name.String()} + raw := file.MustReadFileAsString() + + p := &AppArmorProfileFile{} + p.Kind = KindFromPath(file) + if parse { + _, err = p.Parse(raw) + } else { + err = p.Scan(raw) + } + if err != nil { + r.Error = err.Error() + reports = append(reports, r) + t.Errorf(templateFailure, name, err) + return + } + + if err = p.Validate(); err != nil { + r.Error = err.Error() + reports = append(reports, r) + t.Errorf(templateFailure, name, err) + return + } + + r.Success = true + reports = append(reports, r) + t.Logf(templateSuccess, name) + }) + } + + reports.SumUp(t) + } +} + +// Test the parser on our own profiles +func Test_Parser_ApparmorD(t *testing.T) { + files, err := apparmorDDir.ReadDirRecursiveFiltered(nil, paths.FilterOutDirectories(), paths.FilterOutNames("README.md")) + if err != nil { + panic(err) + } + + // [14/12/25]: 4750 tests, success: 4750, fail 0, success rate: 100% + testAppArmorProfileFiles(t, apparmorDDir, files, []bool{true, false}) +} + +// Test the parser on apparmor default and extra profiles +func Test_Parser_UpstreamProfiles(t *testing.T) { + // os.Setenv("WITH_UPSTREAM", "true") + if os.Getenv("WITH_UPSTREAM") == "" { + t.Skip("Skipping test in CI environment") + } + apparmorDir := os.Getenv("APPARMOR_DIR") + if apparmorDir == "" { + apparmorDir = "../../../apparmor" + } + + dirnames := []string{ + // [14/12/25]: 357 tests, success: 357, fail 0, success rate: 100% + "profiles/apparmor.d", // apparmor-profiles + + // [14/12/25]: 110 tests, success: 110, fail 0, success rate: 100% + "profiles/apparmor/profiles/extras", // apparmor-profiles-extras + } + for _, dir := range dirnames { + datadir := paths.New(apparmorDir).Join(dir) + files, err := datadir.ReadDirRecursiveFiltered(nil, paths.FilterOutDirectories(), paths.FilterOutNames("README")) + if err != nil { + panic(err) + } + testAppArmorProfileFiles(t, datadir, files, []bool{false}) + } +} + +// Test the parser on apparmor own's test suite +func Test_Parser_UpstreamTestSuite(t *testing.T) { + // os.Setenv("WITH_UPSTREAM", "true") + if os.Getenv("WITH_UPSTREAM") == "" { + t.Skip("Skipping test in CI environment") + } + apparmorDir := os.Getenv("APPARMOR_DIR") + if apparmorDir == "" { + apparmorDir = "../../../apparmor" + } + + regTestDescription := regexp.MustCompile(`(?m)^#=(DESCRIPTION|Description) (.+)$`) + regTestResult := regexp.MustCompile(`(?m)^#=EXRESULT (.+)$`) + regTestDisabled := regexp.MustCompile(`(?m)^#=DISABLED$`) + getSettings := func(profile string) (string, bool, bool) { + desc := regTestDescription.FindStringSubmatch(profile) + result := regTestResult.FindStringSubmatch(profile) + disabled := regTestDisabled.FindStringSubmatch(profile) + if len(disabled) == 1 && disabled[0] == "#=DISABLED" { + return "", false, true + } + if len(desc) == 3 && len(result) == 2 { + return desc[2], result[1] == "FAIL", false + } + return "", false, false + } + + datadir := paths.New(apparmorDir).Join("parser/tst/simple_tests") + files, err := datadir.ReadDirRecursiveFiltered(nil, paths.FilterOutDirectories(), + paths.FilterOutNames("readme")) + if err != nil { + panic(err) + } + + reports := testReports{} + templateFailure := "\033[0;31m[FAILED]\033[0m(\033[0;37m%s\033[0m): %v" + templateSuccess := "\033[0;32m[SUCCESS]\033[0m(\033[0;37m%s\033[0m)" + for _, file := range files { + if !file.Exist() { + panic(file.String() + " %s not found") + } + name, err := file.RelFrom(datadir) + if err != nil { + panic(err) + } + + raw := file.MustReadFileAsString() + desc, wantErr, isDisabled := getSettings(raw) + if isDisabled { + t.Logf("Skipping disabled test: %s", name) + continue + } + t.Run(name.String(), func(t *testing.T) { + r := &testReport{Name: name.String()} + r.Desc = desc + + p := &AppArmorProfileFile{} + err := p.Scan(raw) + if err != nil { + if wantErr { + r.Success = true + reports = append(reports, r) + t.Logf(templateSuccess, name) + } else { + r.Error = err.Error() + reports = append(reports, r) + t.Errorf(templateFailure, name, err) + } + return + } + + err = p.Validate() + if err != nil { + if wantErr { + r.Success = true + reports = append(reports, r) + t.Logf(templateSuccess, name) + } else { + r.Error = err.Error() + reports = append(reports, r) + t.Errorf(templateFailure, name, err) + } + return + } + + // No errors occurred + if wantErr { + r.Error = "expected error but got none" + reports = append(reports, r) + t.Errorf(templateFailure, name, "expected error but got none") + } else { + r.Success = true + reports = append(reports, r) + t.Logf(templateSuccess, name) + } + }) + } + + // [01/06/24]: 1986 tests, success: 1242, fail 744, success rate: 62% + // [14/12/25]: 2148 tests, success: 1722, fail 422, success rate: 80% + // [23/03/26]: 2222 tests, success: 2035, fail 187, success rate: 91% + reports.SumUp(t) +} + var ( // Test cases for tokenizeRule, parseRule,rule getters, and newRules testParseRules = []struct { @@ -264,6 +570,19 @@ var ( wGetSlice: []string{"@{XDG_PROJECTS_DIR}", "+=", `"Git"`}, wString: `@{XDG_PROJECTS_DIR} += "Git"`, }, + { + name: "variable-5", + raw: `@{name} = super{p,P}roductivity Super?Productivity`, + tokens: []string{"@{name}", "=", "super{p,P}roductivity", "Super?Productivity"}, + rule: rule{ + {key: "@{name}"}, {key: "="}, {key: "super{p,P}roductivity"}, {key: "Super?Productivity"}, + }, + getIdx: 3, + wGet: "Super?Productivity", + wGetString: `@{name} = super{p,P}roductivity Super?Productivity`, + wGetSlice: []string{"@{name}", "=", "super{p,P}roductivity", "Super?Productivity"}, + wString: `@{name} = super{p,P}roductivity Super?Productivity`, + }, { name: "header", raw: `profile foo @{exec_path} xattrs=(security.tagged=allowed) flags=(complain attach_disconnected)`, @@ -307,6 +626,7 @@ var ( wGetSlice: []string{"include", ""}, wString: `include `, wRule: &Include{IfExists: false, IsMagic: true, Path: "tunables/global"}, + wError: true, // newRules only convert comma rules }, { name: "include-if-exists", @@ -321,6 +641,7 @@ var ( wGetSlice: []string{"include", "if", "exists", `"/etc/apparmor.d/dummy"`}, wString: `include if exists "/etc/apparmor.d/dummy"`, wRule: &Include{IfExists: true, IsMagic: false, Path: "/etc/apparmor.d/dummy"}, + wError: true, // newRules only convert comma rules }, { name: "rlimit", @@ -499,6 +820,33 @@ var ( Peer: "at-spi-bus-launcher", }, }, + { + name: "ptrace", + raw: "ptrace peer=/bin/true peer=/sbin/init peer=MY_PROFILE", + tokens: []string{"ptrace", "peer=/bin/true", "peer=/sbin/init", "peer=MY_PROFILE"}, + rule: rule{ + {key: "ptrace"}, + {key: "peer", values: rule{{key: "/bin/true"}}}, + {key: "peer", values: rule{{key: "/sbin/init"}}}, + {key: "peer", values: rule{{key: "MY_PROFILE"}}}, + }, + getIdx: 3, + getKey: "peer", + wGet: "peer", + wGetString: "ptrace", + wGetSlice: []string{"ptrace"}, + wGetAsMap: map[string][]string{ + "peer": {"/bin/true", "/sbin/init", "MY_PROFILE"}, + }, + wGetValues: rule{{key: "/bin/true"}, {key: "/sbin/init"}, {key: "MY_PROFILE"}}, + wGetValuesAsSlice: []string{"/bin/true", "/sbin/init", "MY_PROFILE"}, + wGetValuesAsString: "/bin/true /sbin/init MY_PROFILE", + wString: "ptrace peer=/bin/true peer=/sbin/init peer=MY_PROFILE", + wRule: &Ptrace{ + Peer: "/bin/true", + }, + wError: true, + }, { name: "unix-1", raw: `unix (send receive) type=stream addr="@/tmp/.ICE[0-9]*-unix/19 5" peer=(label="@{p_systemd}", addr=none)`, @@ -544,7 +892,7 @@ var ( raw: ` unix (connect, receive, send) type=stream peer=(addr="@/tmp/ibus/dbus-????????")`, - tokens: []string{"unix", "(connect, receive, send)\n", "type=stream\n", `peer=(addr="@/tmp/ibus/dbus-????????")`}, + tokens: []string{"unix", "(connect, receive, send)", "type=stream", `peer=(addr="@/tmp/ibus/dbus-????????")`}, rule: rule{ {key: "unix"}, {key: "connect"}, {key: "receive"}, {key: "send"}, {key: "type", values: rule{{key: "stream"}}}, @@ -835,11 +1183,16 @@ var ( }, } - // Test cases for Parse + // Test cases for tokenizeBlock, parseBlock, and Parse testBlocks = []struct { name string raw string + blocks []*block + wTokenizeErr bool + rules []Rules + wParseBlockErr bool apparmor *AppArmorProfileFile + apparmorAll *AppArmorProfileFile wParseErr bool wRules ParaRules wParseRulesErr bool @@ -847,6 +1200,10 @@ var ( { name: "empty", raw: "", + blocks: []*block{{kind: CONTENT, raw: ""}}, + wTokenizeErr: false, + rules: []Rules{nil}, + wParseBlockErr: false, apparmor: &AppArmorProfileFile{}, wParseErr: false, wRules: ParaRules{}, @@ -858,6 +1215,23 @@ var ( # IsLineRule comment include # comment included @{lib_dirs} = @{lib}/@{name} /opt/@{name} # comment in variable`, + blocks: []*block{ + { + kind: "content", + raw: "\n\t\t\t# IsLineRule comment\n\t\t\tinclude # comment included\n\t\t\t@{lib_dirs} = @{lib}/@{name} /opt/@{name} # comment in variable", + }, + }, + wTokenizeErr: false, + rules: []Rules{ + { + &Comment{Base: Base{IsLineRule: true, Comment: " IsLineRule comment"}}, + &Include{ + Base: Base{Comment: " comment included"}, + Path: "tunables/global", IsMagic: true, + }, + }, + }, + wParseBlockErr: false, apparmor: &AppArmorProfileFile{ Preamble: Rules{ &Comment{Base: Base{IsLineRule: true, Comment: " IsLineRule comment"}}, @@ -888,7 +1262,46 @@ var ( alias /mnt/{,usr.sbin.}mount.cifs -> /sbin/mount.cifs, @{coreutils} += gawk {,e,f}grep head profile @{exec_path} { + } `, + blocks: []*block{ + { + kind: "content", + raw: "# Simple test\n\t\t\tinclude \n\n\t\t\t# { commented block }\n\t\t\t@{name} = {D,d}ummy\n\t\t\t@{exec_path} = @{bin}/@{name}\n\t\t\t@{exec_path} += @{lib}/@{name}\n\t\t\talias /mnt/{,usr.sbin.}mount.cifs -> /sbin/mount.cifs,\n\t\t\t@{coreutils} += gawk {,e,f}grep head", + }, + { + kind: "profile", + raw: "profile @{exec_path}", + next: &block{ + kind: "raw", + raw: "", + }, + }, + }, + wTokenizeErr: false, + rules: []Rules{ + { + &Comment{Base: Base{IsLineRule: true, Comment: " Simple test"}}, + &Include{IsMagic: true, Path: "tunables/global"}, + &Comment{Base: Base{IsLineRule: true, Comment: " { commented block }"}}, + &Variable{Name: "name", Values: []string{"{D,d}ummy"}, Define: true}, + &Variable{Name: "exec_path", Values: []string{"@{bin}/@{name}"}, Define: true}, + &Variable{Name: "exec_path", Values: []string{"@{lib}/@{name}"}, Define: false}, + &Variable{Name: "coreutils", Values: []string{"gawk", "{,e,f}grep", "head"}, Define: false}, + &Alias{Path: "/mnt/{,usr.sbin.}mount.cifs", RewrittenPath: "/sbin/mount.cifs"}, + }, + { + &Profile{ + Header: Header{ + Name: "@{exec_path}", + Attachments: []string{}, + Attributes: map[string]string{}, + Flags: []string{}, + }, + }, + }, + }, + wParseBlockErr: false, apparmor: &AppArmorProfileFile{ Preamble: Rules{ &Comment{Base: Base{IsLineRule: true, Comment: " Simple test"}}, @@ -915,9 +1328,157 @@ var ( wRules: ParaRules{}, wParseRulesErr: false, }, + { + name: "condition-1", + raw: ` + $FOO=true + $BAR = false + + /bin/true { + /bin/false rix, + if ${FOO} { + /bin/true rix, + } + /bin/true rix, + if ${BAR} { + /etc/shadow rw, + } + /bin/sh rix, + }`, + blocks: []*block{ + { + kind: CONTENT, + raw: "\n\t\t\t$FOO=true\n\t\t\t$BAR = false\n", + }, + { + kind: PROFILE, + raw: "/bin/true", + next: &block{ + kind: RAW, + raw: "/bin/false rix,\n\t\t\t if ${FOO} {\n\t\t\t /bin/true rix,\n\t\t\t }\n\t\t\t /bin/true rix,\n\t\t\t if ${BAR} {\n\t\t\t /etc/shadow rw,\n\t\t\t }\n\t\t\t /bin/sh rix,", + }, + }, + }, + wTokenizeErr: false, + rules: []Rules{ + { + &Boolean{Name: "FOO", Value: true}, + &Boolean{Name: "BAR", Value: false}, + }, + { + &Profile{ + Header: Header{ + Name: "/bin/true", + Attachments: []string{}, + Attributes: map[string]string{}, + Flags: []string{}, + }, + Rules: Rules{ + &File{Path: "/bin/false", Access: []string{"r", "ix"}}, + &Condition{ + Expression: "${FOO}", + IfRules: Rules{ + &File{Path: "/bin/true", Access: []string{"r", "ix"}}, + }, + }, + &File{Path: "/bin/true", Access: []string{"r", "ix"}}, + &Condition{ + Expression: "${BAR}", + IfRules: Rules{ + &File{Path: "/etc/shadow", Access: []string{"r", "w"}}, + }, + }, + &File{Path: "/bin/sh", Access: []string{"r", "ix"}}, + }, + }, + }, + }, + wParseBlockErr: false, + apparmor: &AppArmorProfileFile{ + Preamble: Rules{ + &Boolean{Name: "FOO", Value: true}, + &Boolean{Name: "BAR", Value: false}, + }, + }, + apparmorAll: &AppArmorProfileFile{ + Preamble: Rules{ + &Boolean{Name: "FOO", Value: true}, + &Boolean{Name: "BAR", Value: false}, + }, + Profiles: []*Profile{ + { + Header: Header{ + Name: "/bin/true", + Attachments: []string{}, + Attributes: map[string]string{}, + Flags: []string{}, + }, + Rules: Rules{ + &File{Path: "/bin/false", Access: []string{"r", "ix"}}, + &Condition{ + Expression: "${FOO}", + IfRules: Rules{ + &File{Path: "/bin/true", Access: []string{"r", "ix"}}, + }, + }, + &File{Path: "/bin/true", Access: []string{"r", "ix"}}, + &Condition{ + Expression: "${BAR}", + IfRules: Rules{ + &File{Path: "/etc/shadow", Access: []string{"r", "w"}}, + }, + }, + &File{Path: "/bin/sh", Access: []string{"r", "ix"}}, + }, + }, + }, + }, + wParseErr: false, + wRules: ParaRules{nil}, + wParseRulesErr: false, + }, { name: "string.aa", raw: testData.Join("string.aa").MustReadFileAsString(), + blocks: []*block{ + { + kind: CONTENT, + raw: "# Simple test profile for the AppArmorProfileFile.String() method\n\nabi ,\n\nalias /mnt/usr -> /usr,\n\ninclude \n\n@{exec_path} = @{bin}/foo @{lib}/foo", + }, + { + kind: PROFILE, + raw: "profile foo @{exec_path} xattrs=(security.tagged=allowed) flags=(complain attach_disconnected)", + next: &block{ + kind: RAW, + raw: pStringAAContentStr, + }, + }, + }, + wTokenizeErr: false, + rules: []Rules{ + { + &Comment{Base: Base{IsLineRule: true, Comment: " Simple test profile for the AppArmorProfileFile.String() method"}}, + &Include{Path: "tunables/global", IsMagic: true}, + &Variable{ + Name: "exec_path", Define: true, + Values: []string{"@{bin}/foo", "@{lib}/foo"}, + }, + &Abi{IsMagic: true, Path: "abi/4.0"}, + &Alias{Path: "/mnt/usr", RewrittenPath: "/usr"}, + }, + { + &Profile{ + Header: Header{ + Name: "foo", + Attachments: []string{"@{exec_path}"}, + Attributes: map[string]string{"security.tagged": "allowed"}, + Flags: []string{"complain", "attach_disconnected"}, + }, + Rules: rulesStringAA, + }, + }, + }, + wParseBlockErr: false, apparmor: &AppArmorProfileFile{ Preamble: Rules{ &Comment{Base: Base{Comment: " Simple test profile for the AppArmorProfileFile.String() method", IsLineRule: true}}, @@ -940,6 +1501,29 @@ var ( }, }, }, + apparmorAll: &AppArmorProfileFile{ + Preamble: Rules{ + &Comment{Base: Base{Comment: " Simple test profile for the AppArmorProfileFile.String() method", IsLineRule: true}}, + &Include{IsMagic: true, Path: "tunables/global"}, + &Variable{ + Name: "exec_path", Define: true, + Values: []string{"@{bin}/foo", "@{lib}/foo"}, + }, + &Abi{IsMagic: true, Path: "abi/4.0"}, + &Alias{Path: "/mnt/usr", RewrittenPath: "/usr"}, + }, + Profiles: []*Profile{ + { + Header: Header{ + Name: "foo", + Attachments: []string{"@{exec_path}"}, + Attributes: map[string]string{"security.tagged": "allowed"}, + Flags: []string{"complain", "attach_disconnected"}, + }, + Rules: rulesStringAA, + }, + }, + }, wParseErr: false, wRules: ParaRules{ { @@ -990,7 +1574,6 @@ var ( Type: "stream", Address: "@/tmp/.ICE-unix/1995", PeerLabel: "gnome-shell", - PeerAddr: "none", }, }, { @@ -1010,21 +1593,353 @@ var ( &File{Path: "@{PROC}/@{pid}/task/@{tid}/comm", Access: []string{"r", "w"}}, &File{Path: "@{sys}/devices/@{pci}/class", Access: []string{"r"}}, }, + { + &Include{IfExists: true, IsMagic: true, Path: "local/foo"}, + }, }, wParseRulesErr: false, }, { - name: "full.aa", - raw: testData.Join("full.aa").MustReadFileAsString(), - apparmor: &AppArmorProfileFile{ - Preamble: Rules{ - &Comment{Base: Base{IsLineRule: true, Comment: " Simple test profile with all rules used"}}, - &Include{ - Base: Base{Comment: " a comment", Optional: true}, - IsMagic: true, Path: "tunables/global", - }, - &Include{IfExists: true, Path: "/etc/apparmor.d/global/dummy space"}, - &Variable{Name: "name", Values: []string{"torbrowser", "\"tor browser\""}, Define: true}, + name: "string.aa/content", + raw: pStringAAContentStr, + blocks: []*block{{ + kind: CONTENT, + raw: pStringAAContentStr, + }}, + wTokenizeErr: false, + rules: []Rules{rulesStringAA}, + wParseBlockErr: false, + apparmor: &AppArmorProfileFile{}, + wParseErr: true, + wRules: ParaRules{ + { + &Include{IsMagic: true, Path: "abstractions/base"}, + &Include{IsMagic: true, Path: "abstractions/nameservice-strict"}, + }, + { + &Rlimit{Key: "nproc", Op: "<=", Value: "200"}, + }, + { + &Capability{Names: []string{"dac_read_search"}}, + &Capability{Names: []string{"dac_override"}}, + }, + { + &Network{Domain: "inet", Type: "stream"}, + &Network{Domain: "inet6", Type: "stream"}, + }, + { + &Mount{ + Base: Base{IsLineRule: false, Comment: " failed perms check"}, + MountConditions: MountConditions{ + FsType: "fuse.portal", + Options: []string{"rw", "rbind"}, + }, + Source: "@{run}/user/@{uid}/", + MountPoint: "/", + }, + }, + { + &Umount{ + MountConditions: MountConditions{Options: []string{}}, + MountPoint: "@{run}/user/@{uid}/", + }, + }, + { + &Signal{ + Access: []string{"receive"}, + Set: []string{"term"}, + Peer: "at-spi-bus-launcher", + }, + }, + { + &Ptrace{Access: []string{"read"}, Peer: "nautilus"}, + }, + { + &Unix{ + Access: []string{"send", "receive"}, + Type: "stream", + Address: "@/tmp/.ICE-unix/1995", + PeerLabel: "gnome-shell", + }, + }, + { + &Dbus{Access: []string{"bind"}, Bus: "session", Name: "org.gnome.*"}, + &Dbus{ + Access: []string{"receive"}, + Bus: "system", + Path: "/org/freedesktop/DBus", + Interface: "org.freedesktop.DBus", + Member: "AddMatch", + PeerName: ":1.3", + PeerLabel: "power-profiles-daemon", + }, + }, + { + &File{Path: "/opt/intel/oneapi/compiler/*/linux/lib/*.so./*", Access: []string{"m", "r"}}, + &File{Path: "@{PROC}/@{pid}/task/@{tid}/comm", Access: []string{"r", "w"}}, + &File{Path: "@{sys}/devices/@{pci}/class", Access: []string{"r"}}, + }, + }, + wParseRulesErr: false, + }, + { + name: "profile0.aa", + raw: testData.Join("profile0.aa").MustReadFileAsString(), + blocks: []*block{ + { + kind: PROFILE, + raw: "profile A flags=(attach_disconnected)", + next: &block{ + kind: RAW, + raw: "/path/to/A mr,\n\n profile B {\n /path/to/B mr,\n }\n profile C {\n /path/to/C mr,\n }\n profile D {\n /path/to/D mr,\n }", + }, + }, + }, + wTokenizeErr: false, + rules: []Rules{ + {&Profile{ + Header: Header{ + Name: "A", Attachments: []string{}, Attributes: map[string]string{}, + Flags: []string{"attach_disconnected"}, + }, + Rules: Rules{ + &File{Path: "/path/to/A", Access: []string{"m", "r"}}, + profileB, + profileC, + profileD, + }, + }}, + }, + wParseBlockErr: false, + apparmor: &AppArmorProfileFile{ + Profiles: []*Profile{ + { + Header: Header{ + Name: "A", Attachments: []string{}, Attributes: map[string]string{}, + Flags: []string{"attach_disconnected"}, + }, + }, + }, + }, + apparmorAll: &AppArmorProfileFile{ + Profiles: []*Profile{ + { + Header: Header{ + Name: "A", Attachments: []string{}, Attributes: map[string]string{}, + Flags: []string{"attach_disconnected"}, + }, + Rules: Rules{ + &File{Path: "/path/to/A", Access: []string{"m", "r"}}, + profileB, + profileC, + profileD, + }, + }, + }, + }, + wParseErr: false, + wRules: ParaRules{ + { + &File{Path: "/path/to/A", Access: []string{"m", "r"}}, + }, + }, + wParseRulesErr: false, + }, + { + name: "profile1.aa", + raw: testData.Join("profile1.aa").MustReadFileAsString(), + blocks: []*block{ + { + kind: PROFILE, + raw: "profile A flags=(attach_disconnected)", + next: &block{ + kind: RAW, + raw: "/path/to/A mr,\n\n profile B {\n /path/to/B mr,\n\n profile C {\n /path/to/C mr,\n\n profile D {\n /path/to/D mr,\n }\n }\n }", + }, + }, + }, + wTokenizeErr: false, + rules: []Rules{ + {&Profile{ + Header: Header{ + Name: "A", Attachments: []string{}, Attributes: map[string]string{}, + Flags: []string{"attach_disconnected"}, + }, + Rules: Rules{ + &File{Path: "/path/to/A", Access: []string{"m", "r"}}, + &Profile{ + Header: Header{ + Name: "B", Attachments: []string{}, Attributes: map[string]string{}, Flags: []string{}, + }, + Rules: Rules{ + &File{Path: "/path/to/B", Access: []string{"m", "r"}}, + &Profile{ + Header: Header{ + Name: "C", Attachments: []string{}, Attributes: map[string]string{}, Flags: []string{}, + }, + Rules: Rules{ + &File{Path: "/path/to/C", Access: []string{"m", "r"}}, + &Profile{ + Header: Header{ + Name: "D", Attachments: []string{}, Attributes: map[string]string{}, Flags: []string{}, + }, + Rules: Rules{ + &File{Path: "/path/to/D", Access: []string{"m", "r"}}, + }, + }, + }, + }, + }, + }, + }, + }}, + }, + wParseBlockErr: false, + apparmor: &AppArmorProfileFile{ + Profiles: []*Profile{ + { + Header: Header{ + Name: "A", Attachments: []string{}, Attributes: map[string]string{}, + Flags: []string{"attach_disconnected"}, + }, + }, + }, + }, + apparmorAll: &AppArmorProfileFile{ + Profiles: []*Profile{ + { + Header: Header{ + Name: "A", Attachments: []string{}, Attributes: map[string]string{}, + Flags: []string{"attach_disconnected"}, + }, + Rules: Rules{ + &File{Path: "/path/to/A", Access: []string{"m", "r"}}, + &Profile{ + Header: Header{ + Name: "B", Attachments: []string{}, Attributes: map[string]string{}, Flags: []string{}, + }, + Rules: Rules{ + &File{Path: "/path/to/B", Access: []string{"m", "r"}}, + &Profile{ + Header: Header{ + Name: "C", Attachments: []string{}, Attributes: map[string]string{}, Flags: []string{}, + }, + Rules: Rules{ + &File{Path: "/path/to/C", Access: []string{"m", "r"}}, + &Profile{ + Header: Header{ + Name: "D", Attachments: []string{}, Attributes: map[string]string{}, Flags: []string{}, + }, + Rules: Rules{ + &File{Path: "/path/to/D", Access: []string{"m", "r"}}, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + wParseErr: false, + wRules: ParaRules{ + { + &File{Path: "/path/to/A", Access: []string{"m", "r"}}, + }, + { + &File{Path: "/path/to/B", Access: []string{"m", "r"}}, + }, + { + &File{Path: "/path/to/C", Access: []string{"m", "r"}}, + }, + }, + wParseRulesErr: false, + }, + { + name: "full.aa", + raw: testData.Join("full.aa").MustReadFileAsString(), + blocks: []*block{ + { + kind: CONTENT, + raw: "# Simple test profile with all rules used\n\nabi ,\n\nalias /mnt/usr -> /usr,\n\ninclude # optional: a comment\ninclude if exists \"/etc/apparmor.d/global/dummy space\"\n\n@{name}=torbrowser \"tor browser\" \n@{lib_dirs} = @{lib}/@{name} /opt/@{name} # another comment\n@{config_dirs} = @{HOME}/.mozilla/\n@{cache_dirs}=@{user_cache_dirs}/mozilla/\n\nalias /mnt/{,usr.sbin.}mount.cifs -> /sbin/mount.cifs,\n\n@{exec_path} = @{bin}/@{name} @{lib_dirs}/@{name}", + }, + { + kind: PROFILE, + raw: "profile foo @{exec_path} xattrs=(security.tagged=allowed) flags=(complain attach_disconnected)", + next: &block{ + kind: RAW, + raw: "include \n include \n include \"/etc/apparmor.d/abstractions/dummy space\"\n\n all,\n\n set rlimit nproc <= 200,\n\n userns,\n\n capability dac_read_search,\n capability dac_override,\n\n network inet stream,\n network netlink raw,\n\n mount /{,**},\n mount options=(rw rbind) /tmp/newroot/ -> /tmp/newroot/,\n mount options=(rw silent rprivate) -> /oldroot/,\n mount fstype=devpts options=(rw nosuid noexec) devpts -> /newroot/dev/pts/,\n\n remount /newroot/{,**},\n\n umount @{run}/user/@{uid}/,\n\n pivot_root oldroot=/tmp/oldroot/ /tmp/,\n\n change_profile -> libvirt-@{uuid},\n\n mqueue r type=posix /,\n\n io_uring sqpoll label=foo,\n\n signal (receive) set=(cont,term,winch) peer=at-spi-bus-launcher,\n\n ptrace (read) peer=nautilus,\n\n unix (send receive) type=stream addr=\"@/tmp/.ICE[0-9]-unix/19 5\" peer=(label=gnome-shell, addr=none),\n\n dbus bind bus=session name=org.gnome.*,\n dbus receive bus=system path=/org/freedesktop/DBus\n interface=org.freedesktop.DBus\n member=AddMatch\n peer=(name=:1.3, label=power-profiles-daemon),\n\n # A comment! before a paragraph of rules\n \"/opt/Mullvad VPN/resources/*.so*\" mr,\n \"/opt/Mullvad VPN/resources/*\" r,\n \"/opt/Mullvad VPN/resources/openvpn\" rix,\n /usr/share/gnome-shell/extensions/ding@rastersoft.com/{,*/}ding.js rPx,\n /opt/intel/oneapi/compiler/*/linux/lib/*.so./* rm,\n\n owner @{user_config_dirs}/powerdevilrc{,.@{rand6}} rwl -> @{user_config_dirs}/#@{int},\n link @{user_config_dirs}/kiorc -> @{user_config_dirs}/#@{int},\n\n @{run}/udev/data/+pci:* r,\n\n @{sys}/devices/@{pci}/class r,\n\n owner @{PROC}/@{pid}/task/@{tid}/comm rw,\n\n ^action {\n include \n include if exists \n }\n\n profile systemctl {\n include \n include \n\n capability net_admin,\n \n include if exists \n }\n\n profile sudo {\n include \n include \n\n @{sh_path} rix,\n\n include if exists \n }\n\n include if exists ", + }, + }, + { + kind: CONTENT, + raw: "\n", + }, + { + kind: PROFILE, + raw: "profile foo2", + next: &block{ + kind: RAW, + raw: "include \n\n include if exists ", + }, + }, + }, + wTokenizeErr: false, + rules: []Rules{ + // block 0: preamble content (parsed via parsePreamble) + { + &Comment{Base: Base{IsLineRule: true, Comment: " Simple test profile with all rules used"}}, + &Include{Base: Base{Comment: " a comment", Optional: true}, IsMagic: true, Path: "tunables/global"}, + &Include{IfExists: true, Path: "/etc/apparmor.d/global/dummy space"}, + &Variable{Name: "name", Values: []string{"torbrowser", "\"tor browser\""}, Define: true}, + &Variable{Base: Base{Comment: " another comment"}, Name: "lib_dirs", Values: []string{"@{lib}/@{name}", "/opt/@{name}"}, Define: true}, + &Variable{Name: "config_dirs", Values: []string{"@{HOME}/.mozilla/"}, Define: true}, + &Variable{Name: "cache_dirs", Values: []string{"@{user_cache_dirs}/mozilla/"}, Define: true}, + &Variable{Name: "exec_path", Values: []string{"@{bin}/@{name}", "@{lib_dirs}/@{name}"}, Define: true}, + &Abi{IsMagic: true, Path: "abi/4.0"}, + &Alias{Path: "/mnt/usr", RewrittenPath: "/usr"}, + &Alias{Path: "/mnt/{,usr.sbin.}mount.cifs", RewrittenPath: "/sbin/mount.cifs"}, + }, + // block 1: profile foo (parseBlock returns Rules{&Profile{...}}) + { + &Profile{ + Header: Header{ + Name: "foo", + Attachments: []string{"@{exec_path}"}, + Attributes: map[string]string{"security.tagged": "allowed"}, + Flags: []string{"complain", "attach_disconnected"}, + }, + Rules: rulesFullAA, + }, + }, + // block 2: empty content (newline) + nil, + // block 3: profile foo2 + { + &Profile{ + Header: Header{ + Name: "foo2", + Attachments: []string{}, + Attributes: map[string]string{}, + Flags: []string{}, + }, + Rules: Rules{ + &Include{IsMagic: true, Path: "abstractions/base"}, + &Include{IfExists: true, IsMagic: true, Path: "local/foo2"}, + }, + }, + }, + }, + apparmor: &AppArmorProfileFile{ + Preamble: Rules{ + &Comment{Base: Base{IsLineRule: true, Comment: " Simple test profile with all rules used"}}, + &Include{ + Base: Base{Comment: " a comment", Optional: true}, + IsMagic: true, Path: "tunables/global", + }, + &Include{IfExists: true, Path: "/etc/apparmor.d/global/dummy space"}, + &Variable{Name: "name", Values: []string{"torbrowser", "\"tor browser\""}, Define: true}, &Variable{ Base: Base{Comment: " another comment"}, Define: true, Name: "lib_dirs", Values: []string{"@{lib}/@{name}", "/opt/@{name}"}, @@ -1047,6 +1962,50 @@ var ( }, }, }, + apparmorAll: &AppArmorProfileFile{ + Preamble: Rules{ + &Comment{Base: Base{IsLineRule: true, Comment: " Simple test profile with all rules used"}}, + &Include{ + Base: Base{Comment: " a comment", Optional: true}, + IsMagic: true, Path: "tunables/global", + }, + &Include{IfExists: true, Path: "/etc/apparmor.d/global/dummy space"}, + &Variable{Name: "name", Values: []string{"torbrowser", "\"tor browser\""}, Define: true}, + &Variable{ + Base: Base{Comment: " another comment"}, Define: true, + Name: "lib_dirs", Values: []string{"@{lib}/@{name}", "/opt/@{name}"}, + }, + &Variable{Name: "config_dirs", Values: []string{"@{HOME}/.mozilla/"}, Define: true}, + &Variable{Name: "cache_dirs", Values: []string{"@{user_cache_dirs}/mozilla/"}, Define: true}, + &Variable{Name: "exec_path", Values: []string{"@{bin}/@{name}", "@{lib_dirs}/@{name}"}, Define: true}, + &Abi{IsMagic: true, Path: "abi/4.0"}, + &Alias{Path: "/mnt/usr", RewrittenPath: "/usr"}, + &Alias{Path: "/mnt/{,usr.sbin.}mount.cifs", RewrittenPath: "/sbin/mount.cifs"}, + }, + Profiles: []*Profile{ + { + Header: Header{ + Name: "foo", + Attachments: []string{"@{exec_path}"}, + Attributes: map[string]string{"security.tagged": "allowed"}, + Flags: []string{"complain", "attach_disconnected"}, + }, + Rules: rulesFullAA, + }, + { + Header: Header{ + Name: "foo2", + Attachments: []string{}, + Attributes: map[string]string{}, + Flags: []string{}, + }, + Rules: Rules{ + &Include{IsMagic: true, Path: "abstractions/base"}, + &Include{IfExists: true, IsMagic: true, Path: "local/foo2"}, + }, + }, + }, + }, wParseErr: false, wRules: ParaRules{ { @@ -1217,4 +2176,263 @@ var ( wParseRulesErr: false, }, } + + // Additional test cases for Scan()) + testParser = []struct { + name string + raw string + want *AppArmorProfileFile + wantErr bool + }{ + { + name: "parse.aa", + raw: testData.Join("parse.aa").MustReadFileAsString(), + want: &AppArmorProfileFile{ + Preamble: Rules{ + &Comment{Base: Base{IsLineRule: true, Comment: " apparmor.d - Full set of apparmor profiles"}}, + &Comment{Base: Base{IsLineRule: true, Comment: " Copyright (C) 2024 Alexandre Pujol "}}, + &Comment{Base: Base{IsLineRule: true, Comment: " SPDX-License-Identifier: GPL-2.0-only"}}, + &Comment{Base: Base{IsLineRule: true, Comment: " TODO: Test rule with only ','"}}, + &Include{ + Base: Base{Optional: true, Comment: " A nice message"}, + IsMagic: true, Path: "tunables/global", + }, + &Include{IfExists: true, Path: "/etc/apparmor.d/global/dummy space"}, + &Variable{ + Name: "name", Define: true, + Values: []string{"torbrowser", "\"tor browser\""}, + }, + &Variable{ + Base: Base{Comment: " This is a comment"}, + Name: "lib_dirs", Define: true, + Values: []string{"@{lib}/@{name}", "/opt/@{name}"}, + }, + &Variable{ + Name: "exec_path", Define: true, + Values: []string{"@{bin}/@{name}", "@{lib_dirs}/@{name}"}, + }, + &Abi{IsMagic: true, Path: "abi/4.0"}, + &Alias{Path: "/mnt/usr", RewrittenPath: "/usr"}, + &Alias{Path: "/mnt/{,usr.sbin.}mount.cifs", RewrittenPath: "/sbin/mount.cifs"}, + }, + Profiles: []*Profile{ + { + Header: Header{ + Name: "foo", + Attachments: []string{"@{exec_path}"}, + Attributes: map[string]string{"security.tagged": "allowed"}, + Flags: []string{"complain", "attach_disconnected"}, + }, + Rules: Rules{ + &Include{IsMagic: true, Path: "abstractions/base"}, + &Comment{Base: Base{IsLineRule: true, Comment: " Oh my god, it's a comment! before a paragraph of rules"}}, + &Include{IfExists: true, IsMagic: true, Path: "local/foo"}, + &Remount{MountConditions: MountConditions{Options: []string{}}, MountPoint: "/newroot/{,**}"}, + &Unix{ + Access: []string{"send", "receive"}, + Type: "stream", + Address: "\"@/tmp/.ICE[0-9]-unix/19 5\"", + PeerLabel: "gnome-shell", + PeerAddr: "none", + }, + &Dbus{ + Base: Base{Comment: " wfdwde"}, + Access: []string{"bind"}, Bus: "session", Name: "org.gnome.*", + }, + &Dbus{ + Access: []string{"receive"}, + Bus: "system", + Path: "/org/freedesktop/DBus", + Interface: "org.freedesktop.DBus", + Member: "AddMatch", + PeerName: ":1.3", + PeerLabel: "power-profiles-daemon", + }, + &File{ + Base: Base{Comment: " To be able to read the /proc/ files"}, + Path: "\"/opt/Mullvad VPN/resources/*.so*\"", Access: []string{"m", "r"}, + }, + &File{Path: "/usr/share/gnome-shell/extensions/ding@rastersoft.com/{,*/}ding.js", Access: []string{"r", "Px"}}, + &File{Path: "@{bin}/zsh", Access: []string{"r", "ix"}}, + &File{Owner: true, Path: "/{var/,}tmp/#@{int}", Access: []string{"r", "w"}}, + &File{Owner: true, Path: "@{user_config_dirs}/powerdevilrc{,.@{rand6}}", Access: []string{"r", "w", "l"}, Target: "@{user_config_dirs}/#@{int}"}, + }, + }, + }, + }, + wantErr: false, + }, + } + + // Indirect test resources + pStringAAContentStr = `include + include + + set rlimit nproc <= 200, + + capability dac_read_search, + capability dac_override, + + network inet stream, + network inet6 stream, + + mount fstype=fuse.portal options=(rw rbind) @{run}/user/@{uid}/ -> /, # failed perms check + + umount @{run}/user/@{uid}/, + + signal receive set=term peer=at-spi-bus-launcher, + + ptrace read peer=nautilus, + + unix (send receive) type=stream addr=@/tmp/.ICE-unix/1995 peer=(label=gnome-shell), + + dbus bind bus=session name=org.gnome.*, + dbus receive bus=system path=/org/freedesktop/DBus + interface=org.freedesktop.DBus + member=AddMatch + peer=(name=:1.3, label=power-profiles-daemon), + + /opt/intel/oneapi/compiler/*/linux/lib/*.so./* rm, + @{PROC}/@{pid}/task/@{tid}/comm rw, + @{sys}/devices/@{pci}/class r, + + include if exists ` + rulesStringAA = Rules{ + &Include{IsMagic: true, Path: "abstractions/base"}, + &Include{IsMagic: true, Path: "abstractions/nameservice-strict"}, + &Include{IfExists: true, IsMagic: true, Path: "local/foo"}, + &Rlimit{Key: "nproc", Op: "<=", Value: "200"}, + &Capability{Names: []string{"dac_read_search"}}, + &Capability{Names: []string{"dac_override"}}, + &Network{Domain: "inet", Type: "stream"}, + &Network{Domain: "inet6", Type: "stream"}, + &Mount{ + Base: Base{Comment: " failed perms check"}, + MountConditions: MountConditions{ + FsType: "fuse.portal", + Options: []string{"rw", "rbind"}, + }, + Source: "@{run}/user/@{uid}/", + MountPoint: "/", + }, + &Umount{ + MountConditions: MountConditions{Options: []string{}}, + MountPoint: "@{run}/user/@{uid}/", + }, + &Signal{ + Access: []string{"receive"}, + Set: []string{"term"}, + Peer: "at-spi-bus-launcher", + }, + &Ptrace{Access: []string{"read"}, Peer: "nautilus"}, + &Unix{ + Access: []string{"send", "receive"}, + Type: "stream", + Address: "@/tmp/.ICE-unix/1995", + PeerLabel: "gnome-shell", + }, + &Dbus{Access: []string{"bind"}, Bus: "session", Name: "org.gnome.*"}, + &Dbus{ + Access: []string{"receive"}, + Bus: "system", + Name: "", + Path: "/org/freedesktop/DBus", + Interface: "org.freedesktop.DBus", + Member: "AddMatch", + PeerName: ":1.3", + PeerLabel: "power-profiles-daemon", + }, + &File{Path: "/opt/intel/oneapi/compiler/*/linux/lib/*.so./*", Access: []string{"m", "r"}}, + &File{Path: "@{PROC}/@{pid}/task/@{tid}/comm", Access: []string{"r", "w"}}, + &File{Path: "@{sys}/devices/@{pci}/class", Access: []string{"r"}}, + } + rulesFullAA = Rules{ + &Include{IsMagic: true, Path: "abstractions/base"}, + &Include{IsMagic: true, Path: "abstractions/nameservice-strict"}, + &Include{Path: "/etc/apparmor.d/abstractions/dummy space"}, + &Comment{Base: Base{IsLineRule: true, Comment: " A comment! before a paragraph of rules"}}, + &All{}, + &Rlimit{Key: "nproc", Op: "<=", Value: "200"}, + &Userns{Create: true}, + &Capability{Names: []string{"dac_read_search"}}, + &Capability{Names: []string{"dac_override"}}, + &Network{Domain: "inet", Type: "stream"}, + &Network{Domain: "netlink", Type: "raw"}, + &Mount{MountConditions: MountConditions{Options: []string{}}, Source: "/{,**}"}, + &Mount{MountConditions: MountConditions{Options: []string{"rw", "rbind"}}, Source: "/tmp/newroot/", MountPoint: "/tmp/newroot/"}, + &Mount{MountConditions: MountConditions{Options: []string{"rw", "rprivate", "silent"}}, MountPoint: "/oldroot/"}, + &Mount{MountConditions: MountConditions{FsType: "devpts", Options: []string{"rw", "noexec", "nosuid"}}, Source: "devpts", MountPoint: "/newroot/dev/pts/"}, + &Remount{MountConditions: MountConditions{Options: []string{}}, MountPoint: "/newroot/{,**}"}, + &Umount{MountConditions: MountConditions{Options: []string{}}, MountPoint: "@{run}/user/@{uid}/"}, + &PivotRoot{OldRoot: "/tmp/oldroot/", NewRoot: "/tmp/"}, + &ChangeProfile{ProfileName: "libvirt-@{uuid}"}, + &Mqueue{Access: []string{"r"}, Type: "posix", Name: "/"}, + &IOUring{Access: []string{"sqpoll"}, Label: "foo"}, + &Signal{Access: []string{"receive"}, Set: []string{"cont", "term", "winch"}, Peer: "at-spi-bus-launcher"}, + &Ptrace{Access: []string{"read"}, Peer: "nautilus"}, + &Unix{Access: []string{"send", "receive"}, Type: "stream", Address: "\"@/tmp/.ICE[0-9]-unix/19 5\"", PeerLabel: "gnome-shell", PeerAddr: "none"}, + &Dbus{Access: []string{"bind"}, Bus: "session", Name: "org.gnome.*"}, + &Dbus{Access: []string{"receive"}, Bus: "system", Path: "/org/freedesktop/DBus", Interface: "org.freedesktop.DBus", Member: "AddMatch", PeerName: ":1.3", PeerLabel: "power-profiles-daemon"}, + &File{Path: "\"/opt/Mullvad VPN/resources/*.so*\"", Access: []string{"m", "r"}}, + &File{Path: "\"/opt/Mullvad VPN/resources/*\"", Access: []string{"r"}}, + &File{Path: "\"/opt/Mullvad VPN/resources/openvpn\"", Access: []string{"r", "ix"}}, + &File{Path: "/usr/share/gnome-shell/extensions/ding@rastersoft.com/{,*/}ding.js", Access: []string{"r", "Px"}}, + &File{Path: "/opt/intel/oneapi/compiler/*/linux/lib/*.so./*", Access: []string{"m", "r"}}, + &File{Owner: true, Path: "@{user_config_dirs}/powerdevilrc{,.@{rand6}}", Access: []string{"r", "w", "l"}, Target: "@{user_config_dirs}/#@{int}"}, + &Link{Path: "@{user_config_dirs}/kiorc", Target: "@{user_config_dirs}/#@{int}"}, + &File{Path: "@{run}/udev/data/+pci:*", Access: []string{"r"}}, + &File{Path: "@{sys}/devices/@{pci}/class", Access: []string{"r"}}, + &File{Owner: true, Path: "@{PROC}/@{pid}/task/@{tid}/comm", Access: []string{"r", "w"}}, + &Hat{ + Name: "action", + Flags: []string{}, + Rules: Rules{ + &Include{IsMagic: true, Path: "abstractions/base"}, + &Include{IfExists: true, IsMagic: true, Path: "local/foo_action"}, + }, + }, + &Profile{ + Header: Header{Name: "systemctl", Attachments: []string{}, Attributes: map[string]string{}, Flags: []string{}}, + Rules: Rules{ + &Include{IsMagic: true, Path: "abstractions/base"}, + &Include{IsMagic: true, Path: "abstractions/systemctl"}, + &Include{IfExists: true, IsMagic: true, Path: "local/foo_systemctl"}, + &Capability{Names: []string{"net_admin"}}, + }, + }, + &Profile{ + Header: Header{Name: "sudo", Attachments: []string{}, Attributes: map[string]string{}, Flags: []string{}}, + Rules: Rules{ + &Include{IsMagic: true, Path: "abstractions/base"}, + &Include{IsMagic: true, Path: "abstractions/app/sudo"}, + &Include{IfExists: true, IsMagic: true, Path: "local/foo_sudo"}, + &File{Path: "@{sh_path}", Access: []string{"r", "ix"}}, + }, + }, + &Include{IfExists: true, IsMagic: true, Path: "local/foo"}, + } + profileB = &Profile{ + Header: Header{ + Name: "B", Attachments: []string{}, Attributes: map[string]string{}, Flags: []string{}, + }, + Rules: Rules{ + &File{Path: "/path/to/B", Access: []string{"m", "r"}}, + }, + } + profileC = &Profile{ + Header: Header{ + Name: "C", Attachments: []string{}, Attributes: map[string]string{}, Flags: []string{}, + }, + Rules: Rules{ + &File{Path: "/path/to/C", Access: []string{"m", "r"}}, + }, + } + profileD = &Profile{ + Header: Header{ + Name: "D", Attachments: []string{}, Attributes: map[string]string{}, Flags: []string{}, + }, + Rules: Rules{ + &File{Path: "/path/to/D", Access: []string{"m", "r"}}, + }, + } ) diff --git a/pkg/aa/pivot_root.go b/pkg/aa/pivot_root.go index 8632b4490b..c682ddb27f 100644 --- a/pkg/aa/pivot_root.go +++ b/pkg/aa/pivot_root.go @@ -37,7 +37,7 @@ func newPivotRoot(q Qualifier, rule rule) (Rule, error) { OldRoot: rule.GetValuesAsString("oldroot"), NewRoot: newroot, TargetProfile: target, - }, nil + }, rule.ValidateMapKeys([]string{"oldroot"}) } func newPivotRootFromLog(log map[string]string) Rule { diff --git a/pkg/aa/preamble.go b/pkg/aa/preamble.go index 50e7dbef7a..7b39372124 100644 --- a/pkg/aa/preamble.go +++ b/pkg/aa/preamble.go @@ -6,6 +6,8 @@ package aa import ( "fmt" + "regexp" + "slices" "strings" ) @@ -14,11 +16,18 @@ const ( ALIAS Kind = "alias" INCLUDE Kind = "include" VARIABLE Kind = "variable" + BOOLEAN Kind = "boolean" COMMENT Kind = "comment" tokIFEXISTS = "if exists" ) +var ( + // reValidVarName matches valid variable names: must start with a letter, + // followed by letters, digits, or underscores. + reValidVarName = regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9_]*$`) +) + type Comment struct { Base } @@ -67,24 +76,34 @@ type Abi struct { func newAbi(q Qualifier, rule rule) (Rule, error) { var magic bool - if len(rule) != 1 { + + // Rejoin tokens that were split by spaces (e.g., "< includes/path >") + path := strings.Join(rule.GetSlice(), " ") + if path == "" { return nil, fmt.Errorf("invalid abi format: %s", rule) } - - path := rule.Get(0) switch path[0] { case '"': magic = false + if !strings.HasSuffix(path, "\"") || len(path) < 3 { + return nil, fmt.Errorf("invalid path %s in rule: %s", path, rule) + } case '<': magic = true + if !strings.HasSuffix(path, ">") || len(path) < 3 { + return nil, fmt.Errorf("invalid path %s in rule: %s", path, rule) + } default: return nil, fmt.Errorf("invalid path %s in rule: %s", path, rule) } + path = strings.Trim(path, "\"<>") + path = strings.Trim(path, " \t") + path = strings.Trim(path, "\"") return &Abi{ Base: newBase(rule), - Path: strings.Trim(path, "\"<>"), + Path: path, IsMagic: magic, - }, nil + }, rule.ValidateMapKeys([]string{}) } func (r *Abi) Kind() Kind { @@ -138,7 +157,7 @@ func newAlias(q Qualifier, rule rule) (Rule, error) { Base: newBase(rule), Path: rule.Get(0), RewrittenPath: rule.Get(2), - }, nil + }, rule.ValidateMapKeys([]string{}) } func (r *Alias) Kind() Kind { @@ -197,21 +216,31 @@ func newInclude(rule rule) (Rule, error) { r = r[2:] } - path := r[0] + path := strings.Join(r, " ") // Rejoin in case of spaces in path switch path[0] { case '"': magic = false + if !strings.HasSuffix(path, "\"") || len(path) < 3 { + return nil, fmt.Errorf("invalid path %s in rule: %s", path, rule) + } + path = strings.Trim(path, "\"") case '<': magic = true + if !strings.HasSuffix(path, ">") || len(path) < 3 { + return nil, fmt.Errorf("invalid path %s in rule: %s", path, rule) + } + path = strings.Trim(path, "<>") + path = strings.Trim(path, " \t") default: - return nil, fmt.Errorf("invalid path format: %v", path) + // Allow bare/relative paths (e.g., simple_tests/includes/...) + magic = false } return &Include{ Base: newBase(rule), IfExists: ifexists, - Path: strings.Trim(path, "\"<>"), + Path: path, IsMagic: magic, - }, nil + }, rule.ValidateMapKeys([]string{}) } func (r *Include) Kind() Kind { @@ -274,8 +303,12 @@ func newVariable(rule rule) (Rule, error) { r := rule.GetSlice() name := strings.Trim(rule.Get(0), VARIABLE.Tok()+"}") + if !reValidVarName.MatchString(name) { + return nil, fmt.Errorf("invalid variable name '%s': must start with a letter", name) + } + switch rule.Get(1) { - case tokEQUAL: + case tokEQUAL, "?=", ":=": define = true values = r[2:] case tokPLUS + tokEQUAL: @@ -284,6 +317,21 @@ func newVariable(rule rule) (Rule, error) { default: return nil, fmt.Errorf("invalid operator in variable: %v", rule) } + + // Validate variable values + for _, v := range values { + if strings.HasSuffix(v, ",") { + return nil, fmt.Errorf("trailing comma in variable value: %s", v) + } + quoteCount := strings.Count(v, "\"") + if quoteCount%2 != 0 { + return nil, fmt.Errorf("unbalanced quotes in variable value: %s", v) + } + if strings.Contains(v, "!") { + return nil, fmt.Errorf("invalid character '!' in variable value: %s", v) + } + } + return &Variable{ Base: newBase(rule), Name: name, @@ -335,3 +383,90 @@ func (r *Variable) Lengths() []int { } func (r *Variable) setPaddings(max []int) {} // No paddings for variable + +type Boolean struct { + Base + Name string + Value bool +} + +func newBoolean(rule rule) (Rule, error) { + name, value := "", "" + + switch len(rule) { + case 1: + name = strings.Trim(rule.Get(0), BOOLEAN.Tok()+"{}") + value = rule.GetValuesAsString(rule.Get(0)) + + case 3: + name = strings.Trim(rule.Get(0), BOOLEAN.Tok()+"{}") + op := rule.Get(1) + if op != tokEQUAL && op != "?=" && op != ":=" { + return nil, fmt.Errorf("invalid boolean format, missing %s in: %s", tokEQUAL, rule) + } + value = rule.Get(2) + + case 4: + // Handle ?= and := operators: "$VAR ? = value" or "$VAR : = value" + name = strings.Trim(rule.Get(0), BOOLEAN.Tok()+"{}") + op := rule.Get(1) + if (op == "?" || op == ":") && rule.Get(2) == tokEQUAL { + value = rule.Get(3) + } else { + return nil, fmt.Errorf("invalid boolean format: %v", rule) + } + + default: + return nil, fmt.Errorf("invalid boolean format: %v", rule) + } + + valueLower := strings.ToLower(value) + if !slices.Contains([]string{"true", "false"}, valueLower) { + return nil, fmt.Errorf("invalid boolean value %s in rule: %s", value, rule) + } + return &Boolean{ + Base: newBase(rule), + Name: name, + Value: valueLower == "true", + }, nil +} + +func (r *Boolean) Kind() Kind { + return BOOLEAN +} + +func (r *Boolean) Constraint() Constraint { + return PreambleRule +} + +func (r *Boolean) String() string { + return renderTemplate(r.Kind(), r) +} + +func (r *Boolean) Validate() error { + return nil +} + +func (r *Boolean) Compare(other Rule) int { + o, _ := other.(*Boolean) + if res := compare(r.Name, o.Name); res != 0 { + return res + } + return compare(r.Value, o.Value) +} + +func (r *Boolean) Merge(other Rule) bool { + o, _ := other.(*Boolean) + + if r.Name == o.Name && r.Value == o.Value { + b := &r.Base + return b.merge(o.Base) + } + return false +} + +func (r *Boolean) Lengths() []int { + return []int{} // No len for boolean +} + +func (r *Boolean) setPaddings(max []int) {} // No paddings for boolean diff --git a/pkg/aa/profile.go b/pkg/aa/profile.go index 5d097cad93..8f08c380ed 100644 --- a/pkg/aa/profile.go +++ b/pkg/aa/profile.go @@ -6,7 +6,9 @@ package aa import ( "fmt" + "regexp" "slices" + "strconv" "strings" ) @@ -20,12 +22,54 @@ const ( func init() { requirements[PROFILE] = requirement{ tokFLAGS: { - "attach_disconneced.path=", "attach_disconnected", "audit", - "chroot_relative", "complain", "debug", "default_allow", "enforce", - "interruptible", "kill.signal=", "kill", "kill", "mediate_deleted", + "attach_disconnected", "attach_disconnected.ipc", "attach_disconnected.ipc=", + "attach_disconnected.path=", + "audit", + "chroot_attach", "chroot_no_attach", "chroot_relative", + "complain", "debug", + "default_allow", "delegate_deleted", + "enforce", "error=", + "interruptible", "kill", "kill.signal=", + "mediate_deleted", + "namespace_relative", "no_attach_disconnected", "prompt", "unconfined", }, } + conflicts[PROFILE] = map[string][][]string{ + tokFLAGS: { + // Mode conflicts: enforce, complain, kill, unconfined, prompt are mutually exclusive + {"enforce", "complain"}, + {"enforce", "kill"}, + {"enforce", "unconfined"}, + {"enforce", "prompt"}, + {"complain", "kill"}, + {"complain", "unconfined"}, + {"complain", "prompt"}, + {"kill", "unconfined"}, + {"kill", "prompt"}, + // Note: kill + interruptible is valid (flags_ok33, flags_ok36) + {"unconfined", "prompt"}, + + // default_allow conflicts with all modes except enforce + {"default_allow", "complain"}, + {"default_allow", "kill"}, + {"default_allow", "unconfined"}, + {"default_allow", "prompt"}, + {"default_allow", "enforce"}, + + // Namespace conflicts + {"namespace_relative", "chroot_relative"}, + + // Deletion conflicts + {"mediate_deleted", "delegate_deleted"}, + + // Disconnected conflicts + {"attach_disconnected", "no_attach_disconnected"}, + {"attach_disconnected.ipc", "no_attach_disconnected"}, + {"attach_disconnected.ipc=", "no_attach_disconnected"}, + {"chroot_attach", "chroot_no_attach"}, + }, + } } // Profile represents a single AppArmor profile. @@ -38,6 +82,7 @@ type Profile struct { // Header represents the header of a profile. type Header struct { Name string + NameSpace string Attachments []string Attributes map[string]string Flags []string @@ -61,12 +106,17 @@ func newHeader(rule rule) (Header, error) { for k, v := range rule.GetValues(tokATTRIBUTES).GetAsMap() { attributes[k] = strings.Join(v, "") } + + flags := rule.GetValuesAsSlice(tokFLAGS) + for i, f := range flags { + flags[i] = strings.TrimRight(f, ",") + } return Header{ Name: name, Attachments: attachments, Attributes: attributes, - Flags: rule.GetValuesAsSlice(tokFLAGS), - }, nil + Flags: flags, + }, rule.ValidateMapKeys([]string{tokATTRIBUTES, tokFLAGS, "identities"}) } func (p *Profile) Kind() Kind { @@ -85,9 +135,70 @@ func (p *Profile) Validate() error { if err := validateValues(p.Kind(), tokFLAGS, p.Flags); err != nil { return fmt.Errorf("profile %s: %w", p.Name, err) } + if err := validateConflicts(p.Kind(), tokFLAGS, p.Flags); err != nil { + return fmt.Errorf("profile %s: %w", p.Name, err) + } + if err := validateProfileFlags(p.Flags); err != nil { + return fmt.Errorf("profile %s: %w", p.Name, err) + } return p.Rules.Validate() } +// validateProfileFlags performs additional validation on profile flags +// beyond simple value/conflict checks. +func validateProfileFlags(flags []string) error { + for _, f := range flags { + switch { + case strings.HasPrefix(f, "kill.signal="): + sig := strings.TrimPrefix(f, "kill.signal=") + if sig == "" || strings.ContainsAny(sig, ".=/") { + return fmt.Errorf("invalid kill.signal value '%s'", sig) + } + // Signal name must be a valid identifier (letters, digits, +) + // e.g., hup, kill, usr1, rtmin+0 + if !regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9+]*$`).MatchString(sig) { + // Also allow pure numeric signals + if _, err := strconv.Atoi(sig); err != nil { + return fmt.Errorf("invalid kill.signal value '%s'", sig) + } + } + case strings.HasPrefix(f, "error="): + val := strings.TrimPrefix(f, "error=") + if val == "" { + return fmt.Errorf("invalid error value: empty") + } + // error= can be a number or an errno name (e.g., ENOENT, EISCONN) + if _, err := strconv.Atoi(val); err != nil { + // Must be a valid errno name: uppercase letters only + if !regexp.MustCompile(`^E[A-Z]+$`).MatchString(val) { + return fmt.Errorf("invalid error value '%s'", val) + } + } + case strings.HasPrefix(f, "attach_disconnected.path="): + path := strings.TrimPrefix(f, "attach_disconnected.path=") + if path == "" || !strings.HasPrefix(path, "/") { + return fmt.Errorf("invalid attach_disconnected.path value '%s': must be absolute", path) + } + case strings.HasPrefix(f, "attach_disconnected.ipc="): + path := strings.TrimPrefix(f, "attach_disconnected.ipc=") + if path == "" || !strings.HasPrefix(path, "/") { + return fmt.Errorf("invalid attach_disconnected.ipc value '%s': must be absolute", path) + } + } + } + // Check for duplicate attach_disconnected.ipc= values + ipcCount := 0 + for _, f := range flags { + if strings.HasPrefix(f, "attach_disconnected.ipc=") { + ipcCount++ + } + } + if ipcCount > 1 { + return fmt.Errorf("duplicate attach_disconnected.ipc flags") + } + return nil +} + func (p *Profile) Compare(other Rule) int { o, _ := other.(*Profile) if res := compare(p.Name, o.Name); res != 0 { @@ -161,11 +272,13 @@ var ( if strings.Contains(log["flags"], "remount") { return newRemountFromLog(log) } - newRule := newLogMountMap[log["operation"]] - return newRule(log) + if newRule, ok := newLogMountMap[log["operation"]]; ok { + return newRule(log) + } + return newMountFromLog(log) }, "file": func(log map[string]string) Rule { - if log["operation"] == "change_onexec" { + if log["operation"] == "change_onexec" || log["operation"] == "change_profile" { return newChangeProfileFromLog(log) } else { return newFileFromLog(log) @@ -174,6 +287,7 @@ var ( // operation "capable": newCapabilityFromLog, "chmod": newFileFromLog, + "chown": newFileFromLog, "exec": newFileFromLog, "getattr": newFileFromLog, "link": newFileFromLog, @@ -195,6 +309,10 @@ var ( ) func (p *Profile) AddRule(log map[string]string) { + if len(log) == 0 { + return + } + // Generate profile flags and extra rules switch log["error"] { case "-2": diff --git a/pkg/aa/ptrace.go b/pkg/aa/ptrace.go index 7e0990fe8c..1875d0b530 100644 --- a/pkg/aa/ptrace.go +++ b/pkg/aa/ptrace.go @@ -4,16 +4,14 @@ package aa -import ( - "fmt" -) +import "fmt" const PTRACE Kind = "ptrace" func init() { requirements[PTRACE] = requirement{ "access": []string{ - "r", "w", "rw", "read", "readby", "trace", "tracedby", + "r", "w", "rw", "read", "write", "readby", "trace", "tracedby", }, } } @@ -30,12 +28,20 @@ func newPtrace(q Qualifier, rule rule) (Rule, error) { if err != nil { return nil, err } + peers := rule.GetValuesAsSlice("peer") + if len(peers) > 1 { + return nil, fmt.Errorf("multiple 'peer' not allowed in rule: %s", rule) + } + peer := "" + if len(peers) == 1 { + peer = peers[0] + } return &Ptrace{ Base: newBase(rule), Qualifier: q, Access: accesses, - Peer: rule.GetValuesAsString("peer"), - }, nil + Peer: peer, + }, rule.ValidateMapKeys([]string{"peer"}) } func newPtraceFromLog(log map[string]string) Rule { diff --git a/pkg/aa/resolve_test.go b/pkg/aa/resolve_test.go index 5c9c9026fc..1e4a54fe5a 100644 --- a/pkg/aa/resolve_test.go +++ b/pkg/aa/resolve_test.go @@ -85,7 +85,7 @@ func TestAppArmorProfileFile_resolveValues(t *testing.T) { { name: "simple", input: "@{bin}/foo", - want: []string{"/{,usr/}{,s}bin/foo"}, + want: []string{"/{,usr/}bin/foo"}, }, { name: "double", diff --git a/pkg/aa/rlimit.go b/pkg/aa/rlimit.go index 29c617ff13..8db47f55e4 100644 --- a/pkg/aa/rlimit.go +++ b/pkg/aa/rlimit.go @@ -39,7 +39,7 @@ func newRlimit(q Qualifier, rule rule) (Rule, error) { Key: rule.Get(1), Op: rule.Get(2), Value: rule.Get(3), - }, nil + }, rule.ValidateMapKeys([]string{}) } func newRlimitFromLog(log map[string]string) Rule { diff --git a/pkg/aa/rule_test.go b/pkg/aa/rule_test.go index ee50532a93..d7a9fe47d9 100644 --- a/pkg/aa/rule_test.go +++ b/pkg/aa/rule_test.go @@ -193,7 +193,7 @@ var ( name: "capability-multi", rule: &Capability{Names: []string{"dac_override", "dac_read_search"}}, other: capability2, - wCompare: -15, + wCompare: -52, wMerge: false, wString: "capability dac_override dac_read_search,", }, @@ -201,7 +201,7 @@ var ( name: "capability-all", rule: &Capability{}, other: capability2, - wCompare: -1, + wCompare: -10, wMerge: false, wString: "capability,", }, @@ -216,13 +216,24 @@ var ( wMerge: false, wString: "network netlink raw,", }, + { + name: "network3", + fromLog: newNetworkFromLog, + log: network3Log, + rule: network3, + wValidErr: true, + other: network1, + wCompare: -7, + wMerge: false, + wString: "network send dgram ip=127.0.0.1 port=57007 peer=(ip=127.0.0.53, port=53), # failed af match", + }, { name: "mount", fromLog: newMountFromLog, log: mount1Log, rule: mount1, other: mount2, - wCompare: 37, + wCompare: 7, wMerge: false, wString: "mount fstype=overlay overlay -> /var/lib/docker/overlay2/opaque-bug-check1209538631/merged/, # failed perms check", }, @@ -334,7 +345,7 @@ var ( other: unix1, wCompare: 0, wMerge: true, - wString: "unix (send receive) type=stream protocol=0 addr=none peer=(label=dbus-daemon, addr=@/tmp/dbus-AaKMpxzC4k),", + wString: "unix (send receive) type=stream peer=(label=dbus-daemon, addr=@/tmp/dbus-AaKMpxzC4k),", }, { name: "dbus", @@ -366,7 +377,7 @@ var ( name: "dbus/full", rule: &Dbus{Bus: "accessibility"}, other: dbus1, - wCompare: -1, + wCompare: -7, wMerge: false, wString: `dbus bus=accessibility,`, }, @@ -376,7 +387,7 @@ var ( log: file1Log, rule: file1, other: file2, - wCompare: -14, + wCompare: -19, wMerge: false, wString: "/usr/share/poppler/cMap/Identity-H r,", }, @@ -386,7 +397,7 @@ var ( other: &File{}, wCompare: 0, wMerge: true, - wString: " ,", // FIXME: + wString: "file,", }, { name: "file-equal", @@ -429,7 +440,7 @@ var ( log: link1Log, rule: link1, other: link2, - wCompare: -1, + wCompare: 1, wMerge: false, wString: "link /tmp/mkinitcpio.QDWtza/early@{lib}/firmware/i915/dg1_dmc_ver2_02.bin.zst -> /tmp/mkinitcpio.QDWtza/root@{lib}/firmware/i915/dg1_dmc_ver2_02.bin.zst,", }, @@ -439,7 +450,7 @@ var ( log: link3Log, rule: link3, other: link1, - wCompare: 1, + wCompare: -1, wMerge: false, wString: "owner link @{user_config_dirs}/kiorc -> @{user_config_dirs}/#3954,", }, @@ -449,7 +460,7 @@ var ( other: profile2, wCompare: -4, wMerge: false, - wString: "profile sudo {\n}", + wString: "profile sudo {\n}\n", }, { name: "hat", diff --git a/pkg/aa/rules.go b/pkg/aa/rules.go index 8e8ed5d95e..c862018899 100644 --- a/pkg/aa/rules.go +++ b/pkg/aa/rules.go @@ -60,6 +60,7 @@ func (r Rules) Validate() error { return nil } +// String renders all rules as a string func (r Rules) String() string { return renderTemplate("rules", r) } @@ -77,6 +78,25 @@ func (r Rules) Index(item Rule) int { return -1 } +// IndexOf returns the index of the first occurrence of item in r, or -1 if not present. +func (r Rules) IndexOf(item Rule) int { + return r.Index(item) +} + +// Contains checks if the rule is in the slice +func (r Rules) Contains(rule Rule) bool { + return r.IndexOf(rule) != -1 +} + +// Remove removes the first occurrence of rule from the slice and returns the new slice. +func (r Rules) Remove(rule Rule) Rules { + idx := r.IndexOf(rule) + if idx == -1 { + return r + } + return append(r[:idx], r[idx+1:]...) +} + // Replace replaces the elements r[i] by the given rules, and returns the // modified slice. func (r Rules) Replace(i int, rules ...Rule) Rules { @@ -93,6 +113,7 @@ func (r Rules) Delete(i int) Rules { return append(r[:i], r[i+1:]...) } +// DeleteKind removes all rules of the given kind from the slice and returns the new slice. func (r Rules) DeleteKind(kind Kind) Rules { res := make(Rules, 0, len(r)) for _, rule := range r { @@ -106,19 +127,7 @@ func (r Rules) DeleteKind(kind Kind) Rules { return res } -func (r Rules) FilterOut(filter Kind) Rules { - res := make(Rules, 0, len(r)) - for _, rule := range r { - if rule == nil { - continue - } - if rule.Kind() != filter { - res = append(res, rule) - } - } - return res -} - +// Filter returns all rules of the given kind from the slice. func (r Rules) Filter(filter Kind) Rules { res := make(Rules, 0, len(r)) for _, rule := range r { @@ -132,6 +141,7 @@ func (r Rules) Filter(filter Kind) Rules { return res } +// GetVariables returns all Variable rules from the slice. func (r Rules) GetVariables() []*Variable { res := make([]*Variable, 0, len(r)) for _, rule := range r { @@ -143,6 +153,7 @@ func (r Rules) GetVariables() []*Variable { return res } +// GetIncludes returns all Include rules from the slice. func (r Rules) GetIncludes() []*Include { res := make([]*Include, 0, len(r)) for _, rule := range r { @@ -174,8 +185,15 @@ func (r Rules) Merge() Rules { continue } - // If rules are identical, merge them. Ignore comments + // If rules are identical, try to merge them to combine Base fields (NoNewPrivs, FileInherit, etc.) if r[i].Kind() != COMMENT && r[i].Compare(r[j]) == 0 { + // Attempt merge to combine metadata like NoNewPrivs, FileInherit + if r[i].Merge(r[j]) { + r = r.Delete(j) + j-- + continue + } + // If merge returns false but they're identical, delete duplicate r = r.Delete(j) j-- continue @@ -193,6 +211,7 @@ func (r Rules) Merge() Rules { // Sort the rules according to the guidelines: // https://apparmor.pujol.io/development/guidelines/#guidelines func (r Rules) Sort() Rules { + // r = slices.DeleteFunc(r, func(a Rule) bool { return a == nil }) slices.SortFunc(r, func(a, b Rule) int { kindOfA := a.Kind() kindOfB := b.Kind() @@ -203,7 +222,16 @@ func (r Rules) Sort() Rules { if kindOfB == INCLUDE && b.(*Include).IfExists { kindOfB = "include_if_exists" } - return ruleWeights[kindOfA] - ruleWeights[kindOfB] + if kindOfA == LINK { + kindOfA = FILE + } + if kindOfB == LINK { + kindOfB = FILE + } + if res := ruleWeights[kindOfA] - ruleWeights[kindOfB]; res != 0 { + return res + } + return compareFileLink(a, b) } return a.Compare(b) }) @@ -264,6 +292,7 @@ func (r Rules) Format() Rules { // ParaRules is a slice of Rules grouped by paragraph type ParaRules []Rules +// Flatten flattens the ParaRules into a single Rules slice func (r ParaRules) Flatten() Rules { totalLen := 0 for i := range r { diff --git a/pkg/aa/signal.go b/pkg/aa/signal.go index 319e165841..7aea59c288 100644 --- a/pkg/aa/signal.go +++ b/pkg/aa/signal.go @@ -6,6 +6,8 @@ package aa import ( "fmt" + "strconv" + "strings" ) const SIGNAL Kind = "signal" @@ -54,7 +56,7 @@ func newSignal(q Qualifier, rule rule) (Rule, error) { Access: accesses, Set: set, Peer: rule.GetValuesAsString("peer"), - }, nil + }, rule.ValidateMapKeys([]string{"set", "peer"}) } func newSignalFromLog(log map[string]string) Rule { @@ -83,6 +85,15 @@ func (r *Signal) Validate() error { if err := validateValues(r.Kind(), "access", r.Access); err != nil { return fmt.Errorf("%s: %w", r, err) } + // Normalize signal set names (strip leading zeros from rtmin+NNN) + for i, s := range r.Set { + if after, ok := strings.CutPrefix(s, "rtmin+"); ok { + numStr := after + if n, err := strconv.Atoi(numStr); err == nil { + r.Set[i] = fmt.Sprintf("rtmin+%d", n) + } + } + } if err := validateValues(r.Kind(), "set", r.Set); err != nil { return fmt.Errorf("%s: %w", r, err) } diff --git a/pkg/aa/template.go b/pkg/aa/template.go index cb00d2f36e..d5dfff33cf 100644 --- a/pkg/aa/template.go +++ b/pkg/aa/template.go @@ -7,8 +7,11 @@ package aa import ( "embed" "fmt" + "regexp" "strings" "text/template" + + "github.com/roddhjav/apparmor.d/pkg/util" ) var ( @@ -18,8 +21,8 @@ var ( // The current indentation level IndentationLevel = 0 - //go:embed templates/*.j2 - //go:embed templates/rule/*.j2 + //go:embed templates/*.gotmpl + //go:embed templates/rule/*.gotmpl tmplFiles embed.FS // The functions available in the template @@ -83,52 +86,99 @@ var ( } ruleWeights = generateWeights(ruleAlphabet) - // The order the apparmor file rules should be sorted - fileAlphabet = []string{ - "@{exec_path}", // 1. entry point - "@{sh_path}", // 2.1 shells - "@{coreutils_path}", // 2.2 coreutils - "@{open_path}", // 2.3 binaries paths - "@{bin}", // 2.3 binaries - "@{lib}", // 2.4 libraries - "/opt", // 2.5 opt binaries & libraries - "/usr/share", // 3. shared data - "/etc", // 4. system configuration - "/var", // 5.1 system read/write data - "/boot", // 5.2 boot files - "/home", // 6.1 user data - "@{HOME}", // 6.2 home files - "@{user_cache_dirs}", // 7.1 user caches - "@{user_config_dirs}", // 7.2 user config - "@{user_share_dirs}", // 7.3 user shared - "/tmp", // 8.1 Temporary data - "@{tmp}", // 8.1. User temporary data - "/dev/shm", // 8.2 Shared memory - "@{run}", // 8.3 Runtime data - "@{sys}", // 9. Sys files - "@{PROC}", // 10. Proc files - "/dev", // 11. Dev files - "deny", // 12. Deny rules - "profile", // 13. Subprofiles + // The order the apparmor file rules should be sorted. Some rules are sorted + // in the same group and their order is determined by fileWeights. + fileGroups = map[string][]string{ + // 1. entry point + "attachment": { + `@{exec_path}`, + }, + // 2 Binaries + "bin": { + `@{sh_path}`, // Shells + `@{coreutils_path}`, // Coreutils + `@{open_path}`, // Binaries paths + `@{bin}`, // Binaries + }, + // 3 Libraries + "lib": { + `@{lib}`, // Libraries + `@{lib_dirs}`, // Profile libraries + `/opt`, // opt binaries & libraries + }, + // 4. System shared data + "share": { + `@{system_share_dirs}`, + `/usr/share`, + }, + // 5. System configuration + "etc": { + `/etc`, `@{etc_ro}`, `@{etc_rw}`, + `/etc/machine-id$`, + `/var/lib/dbus/machine-id`, + }, + // 6. Boot files + "boot": { + `/boot`, + }, + // 7. System read/write data + "system-data": { + `/$`, + `/usr/`, + `/usr/local/`, + `/home`, + `/var`, + }, + // 8. System user data + "system-user": { + `@{(DESKTOP|GDM|SSDM|LIGHTDM)_HOME}`, + `@{(desktop|gdm|ssdm|lightdm)_[a-z]*_dirs}`, + }, + // 9. User data + "user-data": { + `@{MOUNTDIRS}`, + `@{MOUNTS}`, + `@{HOME}`, + `@{[a-z]*_dirs}`, + `@{user_[a-z]*_dirs}`, + }, + // 10 Temporary data + "tmp": { + `/tmp`, `@{tmp}`, // Temporary data + `/dev/shm`, // Shared memory + }, + // 11 Runtime data + "runtime": { + `@{run}/user/@{uid}`, + `@{run}/gdm`, + `@{run}`, + }, + // 12 Udev data + "udev": {"@{run}/udev"}, + // 13. Sys files + "sys": {"@{sys}"}, + // 14. Proc files + "proc": {"@{PROC}"}, + // 15. Dev files + "dev": {"/dev"}, } - fileWeights = generateWeights(fileAlphabet) - - // Some file rule should be sorted in the same group - fileAlphabetGroups = map[string]string{ - "@{exec_path}": "exec", - "@{sh_path}": "exec", - "@{coreutils_path}": "exec", - "@{open_path}": "exec", - "@{bin}": "exec", - "@{lib}": "exec", - "/opt": "exec", - "/home": "home", - "@{HOME}": "home", - "/tmp": "tmp", - "@{tmp}": "tmp", - "/dev/shm": "tmp", + fileAlphabetGroups = util.InvertFlatten(fileGroups) + + // The order the apparmor file group rules should be sorted + fileAlphabetGroup = []string{ + "attachment", "bin", "lib", "share", "etc", "boot", + "system-data", "system-user", "user-data", + "tmp", "runtime", "udev", "sys", "proc", "dev", } + fileWeights = generateFileWeights(fileAlphabetGroup, fileGroups) + + // Compiled regexps for matching file paths to their sort group + fileReg = generateRegexp(fileWeights) + + // Memoization cache for file path to group label lookups + groupCache = map[string]string{} + // The order AARE should be sorted stringAlphabet = []byte( "!\"#$%&'*(){}[]@+,-./:;<=>?\\^_`|~0123456789abcdefghijklmnopqrstuvwxyz", @@ -138,17 +188,21 @@ var ( // The order the rule values (access, type, domains, etc) should be sorted requirements = map[Kind]requirement{} requirementsWeights map[Kind]map[string]map[string]int + + // Pairs of mutually exclusive values that cannot coexist + conflicts = map[Kind]map[string][][]string{} ) func init() { requirementsWeights = generateRequirementsWeights(requirements) } +// generateTemplates parses and clones the embedded gotmpl files for each rule kind. func generateTemplates(names []Kind) map[Kind]*template.Template { res := make(map[Kind]*template.Template, len(names)) base := template.New("").Funcs(tmplFunctionMap) base = template.Must(base.ParseFS(tmplFiles, - "templates/*.j2", "templates/rule/*.j2", + "templates/*.gotmpl", "templates/rule/*.gotmpl", )) for _, name := range names { t := template.Must(base.Clone()) @@ -160,6 +214,7 @@ func generateTemplates(names []Kind) map[Kind]*template.Template { return res } +// renderTemplate render the template for the given kind and data func renderTemplate(name Kind, data any) string { var res strings.Builder template, ok := tmpl[name] @@ -170,9 +225,19 @@ func renderTemplate(name Kind, data any) string { if err != nil { panic(err) } - return res.String() + return trimTrailingWhitespace(res.String()) +} + +// trimTrailingWhitespace removes trailing spaces and tabs from each line. +func trimTrailingWhitespace(s string) string { + lines := strings.Split(s, "\n") + for i, line := range lines { + lines[i] = strings.TrimRight(line, " \t") + } + return strings.Join(lines, "\n") } +// generateWeights assigns a sort weight to each element based on its position in the alphabet. func generateWeights[T comparable](alphabet []T) map[T]int { res := make(map[T]int, len(alphabet)) for i, r := range alphabet { @@ -181,6 +246,25 @@ func generateWeights[T comparable](alphabet []T) map[T]int { return res } +// generateFileWeights assigns sort weights to file patterns based on their group order. +func generateFileWeights[T comparable](groupOrder []T, groups map[T][]T) map[T]int { + totalLen := 0 + for i := range groups { + totalLen += len(groups[i]) + } + + idx := 0 + res := make(map[T]int, totalLen) + for _, group := range groupOrder { + for _, r := range groups[group] { + res[r] = idx + idx++ + } + } + return res +} + +// generateRequirementsWeights builds per-kind, per-key weight maps for sorting rule values. func generateRequirementsWeights(requirements map[Kind]requirement) map[Kind]map[string]map[string]int { res := make(map[Kind]map[string]map[string]int, len(requirements)) for rule, req := range requirements { @@ -192,6 +276,48 @@ func generateRequirementsWeights(requirements map[Kind]requirement) map[Kind]map return res } +// generateRegexp compiles AARE file patterns into anchored regular expressions. +func generateRegexp(weights map[string]int) map[string]*regexp.Regexp { + res := make(map[string]*regexp.Regexp, len(weights)) + for w := range weights { + // Escape special regex chars that appear in AARE patterns + // Note: $ at end of pattern is kept as regex end anchor for exact matching + pattern := w + pattern = strings.ReplaceAll(pattern, "{", `\{`) + pattern = strings.ReplaceAll(pattern, "}", `\}`) + // Only escape $ if not at end of pattern (end anchor) + if !strings.HasSuffix(pattern, "$") { + pattern = strings.ReplaceAll(pattern, "$", `\$`) + } + res[w] = regexp.MustCompile(`(?m)^` + pattern) + } + return res +} + +// getGroup returns the file sort group label for the given path, using cached results. +func getGroup(weights map[string]int, in string) string { + if result, ok := groupCache[in]; ok { + return result + } + + // Find the best (most specific) matching pattern + // More specific patterns have higher weights within their group + bestLabel := "" + bestWeight := -1 + for w := range weights { + if fileReg[w].MatchString(in) { + // Choose the pattern with the highest weight (most specific) + if weights[w] > bestWeight { + bestWeight = weights[w] + bestLabel = w + } + } + } + groupCache[in] = bestLabel + return bestLabel +} + +// join is a template function that joins slices with spaces or maps as key=value pairs. func join(i any) string { switch i := i.(type) { case []string: @@ -207,6 +333,7 @@ func join(i any) string { } } +// cjoin is a template function that joins values with parentheses when there are multiple items. func cjoin(i any) string { switch i := i.(type) { case []string: @@ -225,6 +352,7 @@ func cjoin(i any) string { } } +// kindOf is a template function that returns the kind string of a rule. func kindOf(i Rule) string { if i == nil { return "" @@ -232,6 +360,7 @@ func kindOf(i Rule) string { return i.Kind().String() } +// setindent is a template function that increments or decrements the indentation level. func setindent(i string) string { switch i { case "++": @@ -242,19 +371,12 @@ func setindent(i string) string { return "" } +// indent is a template function that prepends the current indentation to a string. func indent(s string) string { return strings.Repeat(Indentation, IndentationLevel) + s } +// indentDbus is a template function that indents dbus rule continuation lines with extra padding. func indentDbus(s string) string { return strings.Join([]string{Indentation, s}, " ") } - -func getLetterIn(alphabet []string, in string) string { - for _, letter := range alphabet { - if strings.HasPrefix(in, letter) { - return letter - } - } - return "" -} diff --git a/pkg/aa/templates/apparmor.j2 b/pkg/aa/templates/apparmor.gotmpl similarity index 65% rename from pkg/aa/templates/apparmor.j2 rename to pkg/aa/templates/apparmor.gotmpl index 75a0026fc5..3a414e8aaf 100644 --- a/pkg/aa/templates/apparmor.j2 +++ b/pkg/aa/templates/apparmor.gotmpl @@ -11,4 +11,14 @@ {{- "\n" -}} {{- end -}} + {{- range .Hats -}} + {{- template "hat" . -}} + {{- "\n" -}} + {{- end -}} + + {{- range .Conditions -}} + {{- template "if" . -}} + {{- "\n" -}} + {{- end -}} + {{- end -}} diff --git a/pkg/aa/templates/condition.gotmpl b/pkg/aa/templates/condition.gotmpl new file mode 100644 index 0000000000..81d462cc04 --- /dev/null +++ b/pkg/aa/templates/condition.gotmpl @@ -0,0 +1,26 @@ +{{- /* apparmor.d - Full set of apparmor profiles */ -}} +{{- /* Copyright (C) 2021-2024 Alexandre Pujol */ -}} +{{- /* SPDX-License-Identifier: GPL-2.0-only */ -}} + +{{- define "if" -}} + + {{- "if" -}} + {{- with .Expression -}} + {{ " " }}{{ . }} + {{- end -}} + + {{- " {\n" -}} + {{- setindent "++" -}} + {{- template "rules" .IfRules -}} + {{- setindent "--" -}} + {{- indent "}" -}} + + {{- with .ElseRules -}} + {{- " {\n" -}} + {{- setindent "++" -}} + {{- template "rules" . -}} + {{- setindent "--" -}} + {{- indent "}" -}} + {{- end -}} + +{{- end -}} diff --git a/pkg/aa/templates/hat.j2 b/pkg/aa/templates/hat.gotmpl similarity index 83% rename from pkg/aa/templates/hat.j2 rename to pkg/aa/templates/hat.gotmpl index 694c3accc7..c2dae888a3 100644 --- a/pkg/aa/templates/hat.j2 +++ b/pkg/aa/templates/hat.gotmpl @@ -8,6 +8,9 @@ {{- with .Name -}} {{ " " }}{{ . }} {{- end -}} + {{- with .Flags -}} + {{ " flags=(" }}{{ join . }}{{ ")" }} + {{- end -}} {{- " {\n" -}} {{- setindent "++" -}} diff --git a/pkg/aa/templates/profile.j2 b/pkg/aa/templates/profile.gotmpl similarity index 75% rename from pkg/aa/templates/profile.j2 rename to pkg/aa/templates/profile.gotmpl index f2df9069ce..245e25b512 100644 --- a/pkg/aa/templates/profile.j2 +++ b/pkg/aa/templates/profile.gotmpl @@ -5,8 +5,12 @@ {{- define "profile" -}} {{- "profile" -}} - {{- with .Name -}} - {{ " " }}{{ . }} + {{- if and .Name .NameSpace -}} + {{ " " }}:{{ .NameSpace }}:{{ .Name }} + {{- else -}} + {{- with .Name -}} + {{ " " }}{{ . }} + {{- end -}} {{- end -}} {{- with .Attachments -}} {{ " " }}{{ join . }} @@ -22,6 +26,6 @@ {{- setindent "++" -}} {{- template "rules" .Rules -}} {{- setindent "--" -}} - {{- indent "}" -}} + {{- indent "}\n" -}} {{- end -}} diff --git a/pkg/aa/templates/rule/abi.j2 b/pkg/aa/templates/rule/abi.gotmpl similarity index 100% rename from pkg/aa/templates/rule/abi.j2 rename to pkg/aa/templates/rule/abi.gotmpl diff --git a/pkg/aa/templates/rule/alias.j2 b/pkg/aa/templates/rule/alias.gotmpl similarity index 100% rename from pkg/aa/templates/rule/alias.j2 rename to pkg/aa/templates/rule/alias.gotmpl diff --git a/pkg/aa/templates/rule/all.j2 b/pkg/aa/templates/rule/all.gotmpl similarity index 100% rename from pkg/aa/templates/rule/all.j2 rename to pkg/aa/templates/rule/all.gotmpl diff --git a/pkg/aa/templates/rule/boolean.gotmpl b/pkg/aa/templates/rule/boolean.gotmpl new file mode 100644 index 0000000000..2e756e5932 --- /dev/null +++ b/pkg/aa/templates/rule/boolean.gotmpl @@ -0,0 +1,9 @@ +{{- /* apparmor.d - Full set of apparmor profiles */ -}} +{{- /* Copyright (C) 2021-2024 Alexandre Pujol */ -}} +{{- /* SPDX-License-Identifier: GPL-2.0-only */ -}} + +{{- define "boolean" -}} + {{- "$" -}}{{- .Name -}}{{- " = " -}} + {{- .Value -}} + {{- template "comment" . -}} +{{- end -}} diff --git a/pkg/aa/templates/rule/capability.j2 b/pkg/aa/templates/rule/capability.gotmpl similarity index 100% rename from pkg/aa/templates/rule/capability.j2 rename to pkg/aa/templates/rule/capability.gotmpl diff --git a/pkg/aa/templates/rule/change_profile.j2 b/pkg/aa/templates/rule/change_profile.gotmpl similarity index 100% rename from pkg/aa/templates/rule/change_profile.j2 rename to pkg/aa/templates/rule/change_profile.gotmpl diff --git a/pkg/aa/templates/rule/comment.j2 b/pkg/aa/templates/rule/comment.gotmpl similarity index 80% rename from pkg/aa/templates/rule/comment.j2 rename to pkg/aa/templates/rule/comment.gotmpl index c013f89337..4663bf8d6d 100644 --- a/pkg/aa/templates/rule/comment.j2 +++ b/pkg/aa/templates/rule/comment.gotmpl @@ -4,7 +4,7 @@ {{- define "comment" -}} {{- if or .FileInherit .NoNewPrivs .Optional .Comment -}} - {{- if .IsLineRule }} + {{- if .IsLineRule -}} {{- "#" -}} {{- else -}} {{- " #" -}} @@ -19,7 +19,10 @@ {{- " optional:" -}} {{- end -}} {{- with .Comment -}} - {{ . }} + {{- if or $.FileInherit $.NoNewPrivs $.Optional -}} + {{- " " -}} + {{- end -}} + {{- . -}} {{- end -}} {{- end -}} {{- end -}} diff --git a/pkg/aa/templates/rule/dbus.j2 b/pkg/aa/templates/rule/dbus.gotmpl similarity index 100% rename from pkg/aa/templates/rule/dbus.j2 rename to pkg/aa/templates/rule/dbus.gotmpl diff --git a/pkg/aa/templates/rule/file.j2 b/pkg/aa/templates/rule/file.gotmpl similarity index 85% rename from pkg/aa/templates/rule/file.j2 rename to pkg/aa/templates/rule/file.gotmpl index 52a41a318b..4d2e148ea3 100644 --- a/pkg/aa/templates/rule/file.j2 +++ b/pkg/aa/templates/rule/file.gotmpl @@ -8,8 +8,12 @@ {{- "owner " -}} {{- end -}} {{- .Padding 2 -}} - {{- .Path -}} - {{- " " -}} + {{- if and (not .Path) (not .Target) (not .Access) -}} + {{- "file" -}} + {{- end -}} + {{- with .Path -}} + {{- . -}}{{- " " -}} + {{- end -}} {{- .Padding 3 -}} {{- range .Access -}} {{- . -}} diff --git a/pkg/aa/templates/rule/include.j2 b/pkg/aa/templates/rule/include.gotmpl similarity index 100% rename from pkg/aa/templates/rule/include.j2 rename to pkg/aa/templates/rule/include.gotmpl diff --git a/pkg/aa/templates/rule/io_uring.j2 b/pkg/aa/templates/rule/io_uring.gotmpl similarity index 100% rename from pkg/aa/templates/rule/io_uring.j2 rename to pkg/aa/templates/rule/io_uring.gotmpl diff --git a/pkg/aa/templates/rule/mount.j2 b/pkg/aa/templates/rule/mount.gotmpl similarity index 97% rename from pkg/aa/templates/rule/mount.j2 rename to pkg/aa/templates/rule/mount.gotmpl index 31e83567f6..8dbe995649 100644 --- a/pkg/aa/templates/rule/mount.j2 +++ b/pkg/aa/templates/rule/mount.gotmpl @@ -15,8 +15,9 @@ {{- .Padding 3 -}} {{- with .Source -}} {{ " " }}{{ . }} + {{- else -}} + {{- .Padding 4 -}} {{- end -}} - {{- .Padding 4 -}} {{- with .MountPoint -}} {{ " -> " }}{{ . }} {{- end -}} diff --git a/pkg/aa/templates/rule/mqueue.j2 b/pkg/aa/templates/rule/mqueue.gotmpl similarity index 100% rename from pkg/aa/templates/rule/mqueue.j2 rename to pkg/aa/templates/rule/mqueue.gotmpl diff --git a/pkg/aa/templates/rule/network.gotmpl b/pkg/aa/templates/rule/network.gotmpl new file mode 100644 index 0000000000..4d029cc91d --- /dev/null +++ b/pkg/aa/templates/rule/network.gotmpl @@ -0,0 +1,39 @@ +{{- /* apparmor.d - Full set of apparmor profiles */ -}} +{{- /* Copyright (C) 2021-2024 Alexandre Pujol */ -}} +{{- /* SPDX-License-Identifier: GPL-2.0-only */ -}} + +{{- define "network" -}} + {{- template "qualifier" . -}} + {{ "network" }} + {{- with .Access -}} + {{ " " }}{{ cjoin . }} + {{- end -}} + {{- with .Domain -}} + {{ " " }}{{ . }} + {{- end -}} + {{- with .Type -}} + {{ " " }}{{ . }} + {{- else -}} + {{- with .Protocol -}} + {{ " " }}{{ . }} + {{- end -}} + {{- end -}} + {{- with .LocalAddress.IP -}} + {{ " ip=" }}{{ . }} + {{- end -}} + {{- with .LocalAddress.Port -}} + {{ " port=" }}{{ . }} + {{- end -}} + {{- if and .PeerAddress.IP .PeerAddress.Port -}} + {{ " peer=(ip=" }}{{ .PeerAddress.IP }}{{ ", port="}}{{ .PeerAddress.Port }}{{ ")" }} + {{- else -}} + {{- with .PeerAddress.IP -}} + {{ " peer=(ip=" }}{{ . }}{{ ")" }} + {{- end -}} + {{- with .PeerAddress.Port -}} + {{ " peer=(port=" }}{{ . }}{{ ")" }} + {{- end -}} + {{- end -}} + {{- "," -}} + {{- template "comment" . -}} +{{- end -}} \ No newline at end of file diff --git a/pkg/aa/templates/rule/network.j2 b/pkg/aa/templates/rule/network.j2 deleted file mode 100644 index 6f2503a8b8..0000000000 --- a/pkg/aa/templates/rule/network.j2 +++ /dev/null @@ -1,20 +0,0 @@ -{{- /* apparmor.d - Full set of apparmor profiles */ -}} -{{- /* Copyright (C) 2021-2024 Alexandre Pujol */ -}} -{{- /* SPDX-License-Identifier: GPL-2.0-only */ -}} - -{{- define "network" -}} - {{- template "qualifier" . -}} - {{ "network" }} - {{- with .Domain -}} - {{ " " }}{{ . }} - {{- end -}} - {{- with .Type -}} - {{ " " }}{{ . }} - {{- else -}} - {{- with .Protocol -}} - {{ " " }}{{ . }} - {{- end -}} - {{- end -}} - {{- "," -}} - {{- template "comment" . -}} -{{- end -}} \ No newline at end of file diff --git a/pkg/aa/templates/rule/pivot_root.j2 b/pkg/aa/templates/rule/pivot_root.gotmpl similarity index 84% rename from pkg/aa/templates/rule/pivot_root.j2 rename to pkg/aa/templates/rule/pivot_root.gotmpl index 678617ca0a..b03026a219 100644 --- a/pkg/aa/templates/rule/pivot_root.j2 +++ b/pkg/aa/templates/rule/pivot_root.gotmpl @@ -12,9 +12,9 @@ {{- with .NewRoot -}} {{ " " }}{{ . }} {{- end -}} - {{- .Padding 3 -}} - {{- with .TargetProfile -}} - {{ " -> " }}{{ . }} + {{- if .TargetProfile -}} + {{- .Padding 3 -}} + {{ " -> " }}{{ .TargetProfile }} {{- end -}} {{- "," -}} {{- .Padding 4 -}} diff --git a/pkg/aa/templates/rule/ptrace.j2 b/pkg/aa/templates/rule/ptrace.gotmpl similarity index 100% rename from pkg/aa/templates/rule/ptrace.j2 rename to pkg/aa/templates/rule/ptrace.gotmpl diff --git a/pkg/aa/templates/rule/qualifier.j2 b/pkg/aa/templates/rule/qualifier.gotmpl similarity index 82% rename from pkg/aa/templates/rule/qualifier.j2 rename to pkg/aa/templates/rule/qualifier.gotmpl index a0ff554ecc..69181051a0 100644 --- a/pkg/aa/templates/rule/qualifier.j2 +++ b/pkg/aa/templates/rule/qualifier.gotmpl @@ -3,6 +3,9 @@ {{- /* SPDX-License-Identifier: GPL-2.0-only */ -}} {{- define "qualifier" -}} + {{- with .Priority -}} + {{- "priority=" -}}{{ . }}{{ " " }} + {{- end -}} {{- if .Audit -}} {{- "audit " -}} {{- end -}} diff --git a/pkg/aa/templates/rule/rlimit.j2 b/pkg/aa/templates/rule/rlimit.gotmpl similarity index 100% rename from pkg/aa/templates/rule/rlimit.j2 rename to pkg/aa/templates/rule/rlimit.gotmpl diff --git a/pkg/aa/templates/rule/signal.j2 b/pkg/aa/templates/rule/signal.gotmpl similarity index 100% rename from pkg/aa/templates/rule/signal.j2 rename to pkg/aa/templates/rule/signal.gotmpl diff --git a/pkg/aa/templates/rule/unix.j2 b/pkg/aa/templates/rule/unix.gotmpl similarity index 55% rename from pkg/aa/templates/rule/unix.j2 rename to pkg/aa/templates/rule/unix.gotmpl index fae6a5429f..4aadc51dc1 100644 --- a/pkg/aa/templates/rule/unix.j2 +++ b/pkg/aa/templates/rule/unix.gotmpl @@ -8,31 +8,23 @@ {{- with .Access -}} {{ " " }}{{ cjoin . }} {{- end -}} - {{- .Padding 2 -}} {{- with .Type -}} {{ " type=" }}{{ . }} {{- end -}} - {{- .Padding 3 -}} - {{- with .Protocol -}} - {{ " protocol=" }}{{ . }} + {{- if and .Address (ne .Address "none") -}} + {{ " addr=" }}{{ .Address }} {{- end -}} - {{- .Padding 4 -}} - {{- with .Address -}} - {{ " addr=" }}{{ . }} - {{- end -}} - {{- .Padding 5 -}} {{- with .Label -}} {{ " label=" }}{{ . }} {{- end -}} - {{- .Padding 6 -}} - {{- if and .PeerLabel .PeerAddr -}} - {{ " peer=(label=" }}{{ .PeerLabel }}{{ ", addr="}}{{ .PeerAddr }}{{ ")" }} + {{- if and .PeerLabel .PeerAddr (ne .PeerAddr "none") -}} + {{ " peer=(label=" }}{{ .PeerLabel }}{{ ", addr=" }}{{ .PeerAddr }}{{ ")" }} {{- else -}} {{- with .PeerLabel -}} - {{ overindent "peer=(label=" }}{{ . }}{{ ")" }} + {{ " peer=(label=" }}{{ . }}{{ ")" }} {{- end -}} - {{- with .PeerAddr -}} - {{ overindent "peer=(addr=" }}{{ . }}{{ ")" }} + {{- if and .PeerAddr (ne .PeerAddr "none") -}} + {{ " peer=(addr=" }}{{ .PeerAddr }}{{ ")" }} {{- end -}} {{- end -}} {{- "," -}} diff --git a/pkg/aa/templates/rule/userns.j2 b/pkg/aa/templates/rule/userns.gotmpl similarity index 100% rename from pkg/aa/templates/rule/userns.j2 rename to pkg/aa/templates/rule/userns.gotmpl diff --git a/pkg/aa/templates/rule/variable.j2 b/pkg/aa/templates/rule/variable.gotmpl similarity index 100% rename from pkg/aa/templates/rule/variable.j2 rename to pkg/aa/templates/rule/variable.gotmpl diff --git a/pkg/aa/templates/rules.j2 b/pkg/aa/templates/rules.gotmpl similarity index 94% rename from pkg/aa/templates/rules.j2 rename to pkg/aa/templates/rules.gotmpl index 9c08abfeb9..c7ae93c569 100644 --- a/pkg/aa/templates/rules.j2 +++ b/pkg/aa/templates/rules.gotmpl @@ -39,6 +39,10 @@ {{- template "variable" . -}} {{- end -}} + {{- if eq $kind "boolean" -}} + {{- template "boolean" . -}} + {{- end -}} + {{- if eq $kind "all" -}} {{- template "all" . -}} {{- end -}} @@ -119,6 +123,10 @@ {{- template "hat" . -}} {{- end -}} + {{- if eq $kind "if" -}} + {{- template "if" . -}} + {{- end -}} + {{- "\n" -}} {{- $oldkind = $kind -}} {{- end -}} diff --git a/pkg/aa/unix.go b/pkg/aa/unix.go index 1e8a992989..f397dc6126 100644 --- a/pkg/aa/unix.go +++ b/pkg/aa/unix.go @@ -12,11 +12,16 @@ const UNIX Kind = "unix" func init() { requirements[UNIX] = requirement{ + "type": []string{"stream", "dgram", "seqpacket", "rdm", "raw", "packet"}, + "protocol": []string{"tcp", "udp", "icmp"}, "access": []string{ "create", "bind", "listen", "accept", "connect", "shutdown", "getattr", "setattr", "getopt", "setopt", "send", "receive", "r", "w", "rw", }, + "local-only": []string{ + "create", "bind", "listen", "getattr", "setattr", "getopt", "setopt", "shutdown", + }, } } @@ -39,6 +44,12 @@ func newUnix(q Qualifier, rule rule) (Rule, error) { if err != nil { return nil, err } + if err := rule.ValidateMapKeys([]string{"type", "protocol", "addr", "label", "attr", "opt", "peer"}); err != nil { + return nil, err + } + if err := rule.GetValues("peer").ValidateMapKeys([]string{"label", "addr"}); err != nil { + return nil, err + } return &Unix{ Base: newBase(rule), Qualifier: q, @@ -86,6 +97,14 @@ func (r *Unix) Validate() error { if err := validateValues(r.Kind(), "access", r.Access); err != nil { return fmt.Errorf("%s: %w", r, err) } + if err := validateValues(r.Kind(), "type", []string{r.Type}); err != nil { + return fmt.Errorf("%s: %w", r, err) + } + if r.PeerLabel != "" || r.PeerAddr != "" { + if len(r.Access) > 0 && allLocalOnly(r.Access, requirements[UNIX]["local-only"]) { + return fmt.Errorf("peer modifier not allowed with local-only access types in unix rule") + } + } return nil } @@ -100,6 +119,9 @@ func (r *Unix) Compare(other Rule) int { if res := compare(r.Protocol, o.Protocol); res != 0 { return res } + if res := compare(r.Address == "", o.Address == ""); res != 0 { + return res + } if res := compare(r.Address, o.Address); res != 0 { return res } @@ -143,7 +165,6 @@ func (r *Unix) Lengths() []int { r.getLenAccess(), length("", r.Access), length("type=", r.Type), - length("protocol=", r.Protocol), length("addr=", r.Address), length("label=", r.Label), } @@ -151,7 +172,7 @@ func (r *Unix) Lengths() []int { func (r *Unix) setPaddings(max []int) { r.Paddings = append(r.Qualifier.setPaddings(max[:2]), setPaddings( - max[2:], []string{"", "type=", "protocol=", "addr=", "label="}, - []any{r.Access, r.Type, r.Protocol, r.Address, r.Label})..., + max[2:], []string{"", "type=", "addr=", "label="}, + []any{r.Access, r.Type, r.Address, r.Label})..., ) } diff --git a/pkg/aa/userns.go b/pkg/aa/userns.go index f4a9815c6e..65c4aac575 100644 --- a/pkg/aa/userns.go +++ b/pkg/aa/userns.go @@ -31,7 +31,7 @@ func newUserns(q Qualifier, rule rule) (Rule, error) { Base: newBase(rule), Qualifier: q, Create: create, - }, nil + }, rule.ValidateMapKeys([]string{}) } func newUsernsFromLog(log map[string]string) Rule { diff --git a/pkg/aa/util.go b/pkg/aa/util.go index 485478fef2..2791ab25c0 100644 --- a/pkg/aa/util.go +++ b/pkg/aa/util.go @@ -19,6 +19,7 @@ func Must[T any](v T, err error) T { return v } +// boolToInt converts a boolean to an integer (true = 1, false = 0). func boolToInt(b bool) int { if b { return 1 @@ -26,6 +27,7 @@ func boolToInt(b bool) int { return 0 } +// merge merges two slices of strings according to their kind (file, variable, other) and requirements matrix. func merge(kind Kind, key string, a, b []string) []string { a = append(a, b...) switch kind { @@ -43,6 +45,7 @@ func merge(kind Kind, key string, a, b []string) []string { return slices.Compact(a) } +// length returns the length of a value with its prefix for padding calculation. func length(prefix string, value any) int { var res int switch value := value.(type) { @@ -66,12 +69,16 @@ func length(prefix string, value any) int { if len(value) > 1 { res += 2 // Brackets on slices } + if res > 0 && prefix != "" { + res += len(prefix) // Add prefix length when slice is non-empty + } return res default: panic("length: unsupported type") } } +// setPaddings returns a slice of paddings for each value to align them according to the max lengths provided. func setPaddings(max []int, prefixes []string, values []any) []string { if len(max) != len(values) || len(max) != len(prefixes) { panic("setPaddings: max, prefix, and values must have the same length") @@ -90,6 +97,8 @@ func setPaddings(max []int, prefixes []string, values []any) []string { return res } +// compare compares two values of the same type and returns -1, 0, or 1 +// if a is less than, equal to, or greater than b, respectively. func compare(a, b any) int { switch a := a.(type) { case int: @@ -107,9 +116,19 @@ func compare(a, b any) int { } return len(a) - len(b) case []string: - return slices.CompareFunc(a, b.([]string), func(s1, s2 string) int { - return compare(s1, s2) - }) + b := b.([]string) + // Compare using the formatted representation so that parenthesized + // multi-element values (e.g., "(kill term)") sort before single + // element values (e.g., "hup") based on the '(' character weight. + sa := strings.Join(a, " ") + if len(a) > 1 { + sa = "(" + sa + ")" + } + sb := strings.Join(b, " ") + if len(b) > 1 { + sb = "(" + sb + ")" + } + return compare(sa, sb) case bool: return boolToInt(a) - boolToInt(b.(bool)) default: @@ -120,37 +139,145 @@ func compare(a, b any) int { // compareFileAccess compares two access strings for file rules. // It is aimed to be used in slices.SortFunc. func compareFileAccess(i, j string) int { - if slices.Contains(requirements[FILE]["access"], i) && - slices.Contains(requirements[FILE]["access"], j) { - return requirementsWeights[FILE]["access"][i] - requirementsWeights[FILE]["access"][j] + accessWeights := requirementsWeights[FILE]["access"] + transitionWeights := requirementsWeights[FILE]["transition"] + wi, iIsAccess := accessWeights[i] + wj, jIsAccess := accessWeights[j] + if iIsAccess && jIsAccess { + return wi - wj } - if slices.Contains(requirements[FILE]["transition"], i) && - slices.Contains(requirements[FILE]["transition"], j) { - return requirementsWeights[FILE]["transition"][i] - requirementsWeights[FILE]["transition"][j] + wi, iIsTransition := transitionWeights[i] + wj, jIsTransition := transitionWeights[j] + if iIsTransition && jIsTransition { + return wi - wj } - if slices.Contains(requirements[FILE]["access"], i) { + if iIsAccess { return -1 } return 1 } +// validateValues checks if all values in the slice are valid according to the requirements matrix. func validateValues(kind Kind, key string, values []string) error { for _, v := range values { if v == "" { continue } + + // Skip variable references — they will be expanded at runtime + if strings.Contains(v, "@{") { + continue + } + + v = strings.Trim(v, "`\"") // Strip surrounding quotes for validation if !slices.Contains(requirements[kind][key], v) { - return fmt.Errorf("invalid mode '%s'", v) + // Check for prefix-based values (e.g., "kill.signal=hup" matches "kill.signal=") + found := false + for _, req := range requirements[kind][key] { + if strings.HasSuffix(req, "=") && strings.HasPrefix(v, req) { + found = true + break + } + } + if !found { + return fmt.Errorf("invalid mode '%s'", v) + } } } return nil } +// flagMatch checks if a value matches a conflict pattern. +// Supports exact match and prefix match for patterns ending with "=". +func flagMatch(value, pattern string) bool { + if value == pattern { + return true + } + // Prefix match: "attach_disconnected.ipc=/foo" matches "attach_disconnected.ipc=" + if strings.HasSuffix(pattern, "=") && strings.HasPrefix(value, pattern) { + return true + } + // Also match the other way: value "attach_disconnected.ipc=" prefix matches actual value + if strings.HasSuffix(value, "=") && strings.HasPrefix(pattern, value) { + return true + } + return false +} + +// validateConflicts checks if any values in the slice conflict with each other. +// Conflicts are defined in the conflicts map as pairs of mutually exclusive values. +func validateConflicts(kind Kind, key string, values []string) error { + conflictPairs, ok := conflicts[kind][key] + if !ok { + return nil + } + for _, pair := range conflictPairs { + if len(pair) != 2 { + continue + } + hasFirst := false + hasSecond := false + for _, v := range values { + if flagMatch(v, pair[0]) { + hasFirst = true + } + if flagMatch(v, pair[1]) { + hasSecond = true + } + } + if hasFirst && hasSecond { + return fmt.Errorf("conflicting %s '%s' and '%s'", key, pair[0], pair[1]) + } + } + return nil +} + +// validateAAREPattern checks for invalid AARE (AppArmor Regular Expression) patterns. +func validateAAREPattern(path string) error { + // Check for empty character class: [] + if strings.Contains(path, "[]") { + return fmt.Errorf("empty character class '[]' in path '%s'", path) + } + // Check for empty alternation: {} + if strings.Contains(path, "{}") { + return fmt.Errorf("empty alternation '{}' in path '%s'", path) + } + // Check for single-entry alternation: {word} (no comma inside) + // Skip variable references @{...} and handle nesting + for i := 0; i < len(path); i++ { + if path[i] == '{' && (i == 0 || (path[i-1] != '@' && path[i-1] != '\\')) { + // Find matching closing brace, accounting for nesting + depth := 1 + end := -1 + for j := i + 1; j < len(path); j++ { + if path[j] == '{' { + depth++ + } else if path[j] == '}' { + depth-- + if depth == 0 { + end = j + break + } + } + } + if end > 0 { + inner := path[i+1 : end] + if !strings.Contains(inner, ",") { + return fmt.Errorf("single-entry alternation '{%s}' in path '%s'", inner, path) + } + } + } + } + return nil +} + +// tokenToSlice splits a token string into a slice of strings based on commas or spaces. func tokenToSlice(token string) []string { res := []string{} - token = strings.Trim(token, "()\n") + token = strings.Trim(token, "()\n ") if strings.ContainsAny(token, ", ") { var sep string + token = strings.ReplaceAll(token, " ", " ") switch { case strings.Contains(token, ","): sep = "," @@ -174,16 +301,17 @@ func toValues(kind Kind, key string, input string) ([]string, error) { return nil, fmt.Errorf("unrecognized requirement '%s' for rule %s", key, kind) } - res := tokenToSlice(input) - for idx := range res { - res[idx] = strings.Trim(res[idx], `" `) - if res[idx] == "" { - res = slices.Delete(res, idx, idx+1) + tokens := tokenToSlice(input) + res := make([]string, 0, len(tokens)) + for _, token := range tokens { + token = strings.Trim(token, `" `) + if token == "" { continue } - if !slices.Contains(req, res[idx]) { - return nil, fmt.Errorf("unrecognized %s: %s", key, res[idx]) + if !slices.Contains(req, token) { + return nil, fmt.Errorf("unrecognized %s for rule %s: %s", key, kind, token) } + res = append(res, token) } slices.SortFunc(res, func(i, j string) int { return requirementsWeights[kind][key][i] - requirementsWeights[kind][key][j] @@ -192,35 +320,52 @@ func toValues(kind Kind, key string, input string) ([]string, error) { } // Helper function to convert an access string to a slice of access according to -// the rule requirements as defined in the requirements map. +// the rule requirements as defined in the requirements matrix. func toAccess(kind Kind, input string) ([]string, error) { var res []string switch kind { case FILE: + accessWeights := requirementsWeights[FILE]["access"] + transitionWeights := requirementsWeights[FILE]["transition"] raw := strings.Split(input, "") trans := []string{} - for _, access := range raw { - if slices.Contains(requirements[FILE]["access"], access) { + // Track positions of access vs transition chars to detect interleaving + lastTransPos := -1 + firstAccessAfterTrans := false + for i, access := range raw { + if _, ok := accessWeights[access]; ok { res = append(res, access) + if lastTransPos >= 0 { + firstAccessAfterTrans = true + } } else { + _ = i + if firstAccessAfterTrans { + // Transition char after access char that was after a transition char + // e.g., "prx" → p(trans) r(access) x(trans) — invalid interleaving + return nil, fmt.Errorf("invalid access mode: access and transition chars interleaved in '%s'", input) + } trans = append(trans, access) + lastTransPos = i } } transition := strings.Join(trans, "") if len(transition) > 0 { - if slices.Contains(requirements[FILE]["transition"], transition) { - res = append(res, transition) + resolved := resolveTransition(transition, transitionWeights) + if resolved != "" { + res = append(res, resolved) } else { return nil, fmt.Errorf("unrecognized transition: %s", transition) } } case FILE + "-log": + accessWeights := requirementsWeights[FILE]["access"] raw := strings.Split(input, "") for _, access := range raw { - if slices.Contains(requirements[FILE]["access"], access) { + if _, ok := accessWeights[access]; ok { res = append(res, access) } else if maskToAccess[access] != "" { res = append(res, maskToAccess[access]) @@ -232,7 +377,41 @@ func toAccess(kind Kind, input string) ([]string, error) { default: return toValues(kind, "access", input) } - slices.SortFunc(res, compareFileAccess) return slices.Compact(res), nil } + +// resolveTransition tries to match a transition string against known transitions. +// It handles exact match, case-insensitive match, and repeated transitions (e.g., "pxpxpx" → "px"). +func resolveTransition(transition string, weights map[string]int) string { + // Exact match + if _, ok := weights[transition]; ok { + return transition + } + // Case-insensitive match + for t := range weights { + if strings.EqualFold(transition, t) { + return t + } + } + // Check if it's a repeated valid transition (e.g., "pxpxpx" → "px") + for t := range weights { + if len(t) > 0 && len(transition) > len(t) && len(transition)%len(t) == 0 { + repeated := strings.Repeat(t, len(transition)/len(t)) + if repeated == transition || strings.EqualFold(repeated, transition) { + return t + } + } + } + return "" +} + +// allLocalOnly returns true if all access types are in the local-only list. +func allLocalOnly(access, localOnly []string) bool { + for _, a := range access { + if !slices.Contains(localOnly, a) { + return false + } + } + return true +} diff --git a/pkg/builder/abi.go b/pkg/builder/abi.go new file mode 100644 index 0000000000..2067978b30 --- /dev/null +++ b/pkg/builder/abi.go @@ -0,0 +1,80 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package builder + +import ( + "github.com/roddhjav/apparmor.d/pkg/tasks" + "github.com/roddhjav/apparmor.d/pkg/util" +) + +var ( + regAbi4To5 = util.ToRegexRepl([]string{ + `abi/4.0`, `abi/5.0`, + }) + regAbi4To3 = util.ToRegexRepl([]string{ + `abi/4.0`, `abi/3.0`, + ` userns,`, ` # userns,`, + ` mqueue`, ` # mqueue`, + ` all`, ` # all`, + ` deny mqueue`, ` # deny mqueue`, + }) + regApparmor41To40 = util.ToRegexRepl([]string{ + `priority=[0-9\-]*`, ``, + }) +) + +type ABI5 struct { + tasks.BaseTask +} + +type ABI3 struct { + tasks.BaseTask +} + +type APPARMOR40 struct { + tasks.BaseTask +} + +// NewABI3 creates a new ABI3 builder. +func NewABI3() *ABI3 { + return &ABI3{ + BaseTask: tasks.BaseTask{ + Keyword: "abi3", + Msg: "Build: convert all profiles from abi 4.0 to abi 3.0", + }, + } +} + +// NewABI5 creates a new ABI5 builder. +func NewABI5() *ABI5 { + return &ABI5{ + BaseTask: tasks.BaseTask{ + Keyword: "abi5", + Msg: "Build: convert all profiles from abi 4.0 to abi 5.0", + }, + } +} + +// NewAPPARMOR40 creates a new APPARMOR40 builder. +func NewAPPARMOR40() *APPARMOR40 { + return &APPARMOR40{ + BaseTask: tasks.BaseTask{ + Keyword: "apparmor4.0", + Msg: "Build: convert all profiles from apparmor 4.1 to 4.0 or less", + }, + } +} + +func (b ABI5) Apply(opt *Option, profile string) (string, error) { + return regAbi4To5.Replace(profile), nil +} + +func (b ABI3) Apply(opt *Option, profile string) (string, error) { + return regAbi4To3.Replace(profile), nil +} + +func (b APPARMOR40) Apply(opt *Option, profile string) (string, error) { + return regApparmor41To40.Replace(profile), nil +} diff --git a/pkg/builder/attach.go b/pkg/builder/attach.go new file mode 100644 index 0000000000..9f1b998349 --- /dev/null +++ b/pkg/builder/attach.go @@ -0,0 +1,75 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package builder + +import ( + "fmt" + "strings" + + "github.com/roddhjav/apparmor.d/pkg/aa" + "github.com/roddhjav/apparmor.d/pkg/tasks" +) + +type ReAttach struct { + tasks.BaseTask +} + +// NewAttach creates a new ReAttach builder. +func NewAttach() *ReAttach { + return &ReAttach{ + BaseTask: tasks.BaseTask{ + Keyword: "attach", + Msg: "Feat: re-attach disconnected path", + }, + } +} + +// Apply will re-attach the disconnected path +// - Add the attach_disconnected.path flag on all profile with the attach_disconnected flag +// - Replace the base abstraction by attached/base +// - Replace the consoles abstraction by attached/consoles +// - For compatibility, non disconnected profile will have the @{att} variable set to / +func (b ReAttach) Apply(opt *Option, profile string) (string, error) { + var insert string + var origin = "profile " + opt.Name + + isInside, err := opt.File.IsInsideDir(b.RootApparmor.Join("abstractions/attached")) + if err != nil { + return profile, fmt.Errorf("attach: %v", err) + } + if isInside { + return profile, nil // Do not re-attach twice + } + + if strings.Contains(profile, "attach_disconnected") { + if opt.Kind == aa.ProfileKind { + if strings.Contains(opt.Name, ":") { + parts := strings.Split(opt.Name, ":") + if len(parts) != 3 { + return profile, fmt.Errorf("attach: invalid namespaced profile name: %s", opt.Name) + } + insert = "@{att} = /att/" + parts[1] + "/\n" + } else { + insert = "@{att} = /att/" + opt.Name + "/\n" + } + } + replacer := strings.NewReplacer( + "attach_disconnected", "attach_disconnected,attach_disconnected.path=@{att}", + "include ", "include ", + "include ", "include ", + "include ", "include ", + "include ", "include ", + ) + profile = replacer.Replace(profile) + + } else { + if opt.Kind == aa.ProfileKind { + insert = "@{att} = \"\"\n" + } + + } + + return strings.Replace(profile, origin, insert+origin, 1), nil +} diff --git a/pkg/builder/base-strict.go b/pkg/builder/base-strict.go new file mode 100644 index 0000000000..0e87edf42d --- /dev/null +++ b/pkg/builder/base-strict.go @@ -0,0 +1,33 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package builder + +import ( + "strings" + + "github.com/roddhjav/apparmor.d/pkg/tasks" +) + +type BaseStrict struct { + tasks.BaseTask +} + +// NewBaseStrict creates a new BaseStrict builder. +func NewBaseStrict() *BaseStrict { + return &BaseStrict{ + BaseTask: tasks.BaseTask{ + Keyword: "base-strict", + Msg: "Feat: use 'base-strict' as base abstraction", + }, + } +} + +func (b BaseStrict) Apply(opt *Option, profile string) (string, error) { + profile = strings.ReplaceAll(profile, + "include ", + "include ", + ) + return profile, nil +} diff --git a/pkg/builder/complain.go b/pkg/builder/complain.go new file mode 100644 index 0000000000..358c33f76d --- /dev/null +++ b/pkg/builder/complain.go @@ -0,0 +1,35 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package builder + +import ( + "slices" + + "github.com/roddhjav/apparmor.d/pkg/tasks" + "github.com/roddhjav/apparmor.d/pkg/util" +) + +type Complain struct { + tasks.BaseTask +} + +// NewComplain creates a new Complain builder. +func NewComplain() *Complain { + return &Complain{ + BaseTask: tasks.BaseTask{ + Keyword: "complain", + Msg: "Build: set complain flag on all profiles", + }, + } +} + +func (b Complain) Apply(opt *Option, profile string) (string, error) { + flags := util.GetFlags(profile) + if slices.Contains(flags, "complain") || slices.Contains(flags, "unconfined") { + return profile, nil + } + flags = append(flags, "complain") + return util.SetFlags(profile, flags), nil +} diff --git a/pkg/builder/core.go b/pkg/builder/core.go new file mode 100644 index 0000000000..88d9709b93 --- /dev/null +++ b/pkg/builder/core.go @@ -0,0 +1,67 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package builder + +import ( + "fmt" + "strings" + + "github.com/roddhjav/apparmor.d/pkg/aa" + "github.com/roddhjav/apparmor.d/pkg/paths" + "github.com/roddhjav/apparmor.d/pkg/tasks" +) + +// Builder main directive interface +type Builder interface { + tasks.BaseTaskInterface + Apply(opt *Option, profile string) (string, error) +} + +// Option for a builder +type Option struct { + Name string + File *paths.Path + Kind aa.FileKind +} + +func NewOption(file *paths.Path) *Option { + return &Option{ + Name: strings.TrimSuffix(file.Base(), ".apparmor.d"), + File: file, + Kind: aa.KindFromPath(file), + } +} + +// Builders executes builders on profile strings in a pipeline. +type Builders struct { + *tasks.BaseRunner[Builder] +} + +// NewRunner creates a new Builders instance. +func NewRunner(t *tasks.TaskConfig) *Builders { + return &Builders{ + BaseRunner: tasks.NewBaseRunner[Builder](t), + } +} + +// Run executes all builders on a profile string. +func (r *Builders) Run(file *paths.Path, profile string) (string, error) { + opt := NewOption(file) + var err error + + for _, b := range r.Tasks { + profile, err = b.Apply(opt, profile) + if err != nil { + return "", fmt.Errorf("%s %s: %w", b.Name(), opt.File, err) + } + } + return profile, nil +} + +// Add appends a builder to the pipeline with fluent interface. +func (r *Builders) Add(builder Builder) *Builders { + r.BaseRunner.Add(builder) + return r +} diff --git a/pkg/prebuild/builder/core_test.go b/pkg/builder/core_test.go similarity index 55% rename from pkg/prebuild/builder/core_test.go rename to pkg/builder/core_test.go index 5a1a39da0a..86fa08bc6b 100644 --- a/pkg/prebuild/builder/core_test.go +++ b/pkg/builder/core_test.go @@ -1,14 +1,18 @@ // apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol +// Copyright (C) 2021-2026 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only package builder import ( - "slices" "testing" - "github.com/roddhjav/apparmor.d/pkg/prebuild" + "github.com/roddhjav/apparmor.d/pkg/paths" + "github.com/roddhjav/apparmor.d/pkg/tasks" +) + +var ( + cfg = tasks.NewTaskConfig(paths.New(".build")) ) func TestBuilder_Apply(t *testing.T) { @@ -21,7 +25,7 @@ func TestBuilder_Apply(t *testing.T) { }{ { name: "abi3", - b: Builders["abi3"], + b: NewABI3(), profile: ` abi , profile test { @@ -37,7 +41,7 @@ func TestBuilder_Apply(t *testing.T) { }, { name: "complain-1", - b: Builders["complain"], + b: NewComplain(), profile: ` @{exec_path} = @{bin}/foo profile foo @{exec_path} { @@ -59,7 +63,7 @@ func TestBuilder_Apply(t *testing.T) { }, { name: "complain-2", - b: Builders["complain"], + b: NewComplain(), profile: ` @{exec_path} = @{bin}/foo profile foo @{exec_path} flags=(complain) { @@ -81,7 +85,7 @@ func TestBuilder_Apply(t *testing.T) { }, { name: "complain-3", - b: Builders["complain"], + b: NewComplain(), profile: ` @{exec_path} = @{bin}/foo profile foo @{exec_path} flags=(attach_disconnected) { @@ -93,7 +97,7 @@ func TestBuilder_Apply(t *testing.T) { }`, want: ` @{exec_path} = @{bin}/foo - profile foo @{exec_path} flags=(attach_disconnected,complain) { + profile foo @{exec_path} flags=(attach_disconnected,complain) { include @{exec_path} mr, @@ -103,7 +107,7 @@ func TestBuilder_Apply(t *testing.T) { }, { name: "enforce-1", - b: Builders["enforce"], + b: NewEnforce(), profile: ` @{exec_path} = @{bin}/foo profile foo @{exec_path} { @@ -125,7 +129,7 @@ func TestBuilder_Apply(t *testing.T) { }, { name: "enforce-2", - b: Builders["enforce"], + b: NewEnforce(), profile: ` @{exec_path} = @{bin}/foo profile foo @{exec_path} flags=(complain) { @@ -146,8 +150,8 @@ func TestBuilder_Apply(t *testing.T) { }`, }, { - name: "complain-3", - b: Builders["enforce"], + name: "enforce-3", + b: NewEnforce(), profile: ` @{exec_path} = @{bin}/foo profile foo @{exec_path} flags=(attach_disconnected,complain) { @@ -159,7 +163,7 @@ func TestBuilder_Apply(t *testing.T) { }`, want: ` @{exec_path} = @{bin}/foo - profile foo @{exec_path} flags=(attach_disconnected) { + profile foo @{exec_path} flags=(attach_disconnected) { include @{exec_path} mr, @@ -169,7 +173,7 @@ func TestBuilder_Apply(t *testing.T) { }, { name: "fsp", - b: Builders["fsp"], + b: NewFSP(), profile: ` @{exec_path} = @{bin}/foo profile foo @{exec_path} { @@ -195,7 +199,7 @@ func TestBuilder_Apply(t *testing.T) { }, { name: "userspace-1", - b: Builders["userspace"], + b: NewUserspace(), profile: ` @{exec_path} = @{bin}/baloo_file @{lib}/{,kf6/}baloo_file @{exec_path} += @{lib}/@{multiarch}/{,libexec/}baloo_file @@ -209,7 +213,7 @@ func TestBuilder_Apply(t *testing.T) { want: ` @{exec_path} = @{bin}/baloo_file @{lib}/{,kf6/}baloo_file @{exec_path} += @{lib}/@{multiarch}/{,libexec/}baloo_file - profile baloo /{{,usr/}{,s}bin/baloo_file,{,usr/}lib{,exec,32,64}/{,kf6/}baloo_file,{,usr/}lib{,exec,32,64}/*-linux-gnu*/{,libexec/}baloo_file} { + profile baloo /{{,usr/}bin/baloo_file,{,usr/}lib{,exec,32,64}/{,kf6/}baloo_file,{,usr/}lib{,exec,32,64}/*-linux-gnu*/{,libexec/}baloo_file} { include @{exec_path} mr, @@ -219,7 +223,7 @@ func TestBuilder_Apply(t *testing.T) { }, { name: "userspace-2", - b: Builders["userspace"], + b: NewUserspace(), profile: ` profile foo /usr/bin/foo { include @@ -231,10 +235,103 @@ func TestBuilder_Apply(t *testing.T) { want: "", wantErr: true, }, + { + name: "stacked-dbus-1", + b: NewStackedDbus(), + 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: NewBaseStrict(), + profile: ` +profile foo { + include +}`, + want: ` +profile foo { + include +}`, + }, + { + name: "attach-1", + b: NewAttach(), + 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: NewAttach(), + profile: ` +profile attach-2 flags=(complain) { + include + include + include +}`, + want: ` +@{att} = "" +profile attach-2 flags=(complain) { + include + include + include +}`, + }, + { + name: "debug-1", + b: NewDebug(), + profile: ` +profile debug-1 { + include + # @{exec_path} mr, + audit @{bin}/ls Px, + @{exec_path} mr, + @{bin}/foo Px, + @{bin}/bar ix, +}`, + want: ` +profile debug-1 { + include + # @{exec_path} mr, + audit @{bin}/ls Px, + @{exec_path} mr, + audit @{bin}/foo Px, + @{bin}/bar ix, +}`, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - opt := &Option{File: prebuild.RootApparmord.Join(tt.name)} + opt := &Option{File: cfg.RootApparmor.Join(tt.name), Name: tt.name} + tt.b.SetConfig(cfg) got, err := tt.b.Apply(opt, tt.profile) if (err != nil) != tt.wantErr { t.Errorf("Builder.Apply() error = %v, wantErr %v", err, tt.wantErr) @@ -247,26 +344,31 @@ func TestBuilder_Apply(t *testing.T) { } } -func TestRegister(t *testing.T) { +func TestBuilders_Add(t *testing.T) { tests := []struct { - name string - names []string - wantSuccess bool + name string + builders []Builder + want []string }{ { - name: "test", - names: []string{"complain", "enforce"}, - wantSuccess: true, + name: "add-builders", + builders: []Builder{NewComplain(), NewEnforce()}, + want: []string{"complain", "enforce"}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - Register(tt.names...) - for _, name := range tt.names { - if got := slices.Contains(Builds, Builders[name]); got != tt.wantSuccess { - t.Errorf("Register() = %v, want %v", got, tt.wantSuccess) + r := NewRunner(cfg) + for _, b := range tt.builders { + r.Add(b) + } + if len(r.Tasks) != len(tt.want) { + t.Errorf("Builders.Add() len = %v, want %v", len(r.Tasks), len(tt.want)) + } + for i, name := range tt.want { + if r.Tasks[i].Name() != name { + t.Errorf("Builders.Add() name = %v, want %v", r.Tasks[i].Name(), name) } - } }) } diff --git a/pkg/builder/dbus.go b/pkg/builder/dbus.go new file mode 100644 index 0000000000..728cbb4f6e --- /dev/null +++ b/pkg/builder/dbus.go @@ -0,0 +1,98 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package builder + +import ( + "strings" + + "github.com/roddhjav/apparmor.d/pkg/aa" + "github.com/roddhjav/apparmor.d/pkg/tasks" +) + +var ( + resolve = map[string][]string{ + `"@{p_dbus_system}"`: {"dbus-system", "dbus-system//&unconfined"}, + `"@{p_dbus_session}"`: {"dbus-session", "dbus-session//&unconfined"}, + } +) + +// StackedDbus is a fix for https://gitlab.com/apparmor/apparmor/-/issues/537#note_2699570190 +type StackedDbus struct { + tasks.BaseTask +} + +// NewStackedDbus creates a new StackedDbus builder. +func NewStackedDbus() *StackedDbus { + return &StackedDbus{ + BaseTask: tasks.BaseTask{ + Keyword: "stacked-dbus", + Msg: "Fix: resolve peer label variable in dbus rules", + }, + } +} + +func parse(kind aa.FileKind, profile string) (aa.ParaRules, []string, error) { + var raw string + paragraphs := []string{} + rulesByParagraph := aa.ParaRules{} + + switch kind { + case aa.ProfileKind: + f := &aa.AppArmorProfileFile{} + nb, err := f.Parse(profile) + if err != nil { + return nil, nil, err + } + lines := strings.Split(profile, "\n") + raw = strings.Join(lines[nb:], "\n") + + case aa.AbstractionKind, aa.TunableKind: + raw = profile + } + + r, par, err := aa.ParseRules(raw) + if err != nil { + return nil, nil, err + } + rulesByParagraph = append(rulesByParagraph, r...) + paragraphs = append(paragraphs, par...) + return rulesByParagraph, paragraphs, nil +} + +func (b StackedDbus) Apply(opt *Option, profile string) (string, error) { + if opt.Kind == aa.TunableKind { + return profile, nil + } + + rulesByParagraph, paragraphs, err := parse(opt.Kind, profile) + if err != nil { + return "", err + } + for idx, rules := range rulesByParagraph { + changed := false + newRules := aa.Rules{} + for _, rule := range rules { + switch rule := rule.(type) { + case *aa.Dbus: + if labels, ok := resolve[rule.PeerLabel]; ok { + changed = true + for _, label := range labels { + newRule := *rule + newRule.PeerLabel = label + newRules = append(newRules, &newRule) + } + } else { + newRules = append(newRules, rule) + } + default: + newRules = append(newRules, rule) + } + } + if changed { + profile = strings.ReplaceAll(profile, paragraphs[idx], newRules.String()+"\n") + } + } + return profile, nil +} diff --git a/pkg/builder/debug.go b/pkg/builder/debug.go new file mode 100644 index 0000000000..735f5465e9 --- /dev/null +++ b/pkg/builder/debug.go @@ -0,0 +1,55 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package builder + +import ( + "regexp" + "strings" + + "github.com/roddhjav/apparmor.d/pkg/tasks" +) + +var ( + regDebug = regexp.MustCompile(`(?m)^([ \t]*)(.*)(pi|Pi|pu|PU|p|P|C|c)x(.*),(.*)$`) +) + +type Debug struct { + tasks.BaseTask +} + +// NewDebug creates a new Debug builder. +func NewDebug() *Debug { + return &Debug{ + BaseTask: tasks.BaseTask{ + Keyword: "debug", + Msg: "Build: debug mode enabled", + }, + } +} + +func (b Debug) Apply(opt *Option, profile string) (string, error) { + for _, dir := range []string{"tunables"} { + if ok, _ := opt.File.IsInsideDir(b.RootApparmor.Join(dir)); ok { + return profile, nil + } + } + + lines := strings.Split(profile, "\n") + for i, line := range lines { + trimmed := strings.TrimLeft(line, " \t") + if strings.HasPrefix(trimmed, "#") { + continue + } + if strings.Contains(trimmed, "=") { + continue + } + if strings.HasPrefix(trimmed, "audit") { + continue + } + lines[i] = regDebug.ReplaceAllString(line, `${1}audit ${2}${3}x${4},${5}`) + } + profile = strings.Join(lines, "\n") + return profile, nil +} diff --git a/pkg/builder/docs.go b/pkg/builder/docs.go new file mode 100644 index 0000000000..2c41f00dcc --- /dev/null +++ b/pkg/builder/docs.go @@ -0,0 +1,28 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +// Package builder transforms profile content during the prebuild pipeline. +// +// A builder implements the [Builder] interface, whose [Builder.Apply] method +// receives an [Option] describing the profile being processed and the current +// profile content as a string, and returns the transformed content. Builders +// are stateless and may be invoked concurrently across profiles. +// +// Builders are composed into a pipeline via [Builders], created with +// [NewRunner]. The pipeline exposes a fluent [Builders.Add] for registration +// and [Builders.Run] to apply every registered builder, in order, to a +// profile: +// +// r := builder.NewRunner(cfg). +// Add(builder.NewABI3()). +// Add(builder.NewComplain()). +// Add(builder.NewUserspace()) +// +// out, err := r.Run(file, content) +// +// Order matters: each builder sees the output of the previous one, so a +// builder that rewrites attachments must run before one that depends on the +// resolved form, and mode-changing builders (complain, enforce) should run +// after content-shaping ones. +package builder diff --git a/pkg/builder/enforce.go b/pkg/builder/enforce.go new file mode 100644 index 0000000000..43f2775d54 --- /dev/null +++ b/pkg/builder/enforce.go @@ -0,0 +1,36 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package builder + +import ( + "slices" + + "github.com/roddhjav/apparmor.d/pkg/tasks" + "github.com/roddhjav/apparmor.d/pkg/util" +) + +type Enforce struct { + tasks.BaseTask +} + +// NewEnforce creates a new Enforce builder. +func NewEnforce() *Enforce { + return &Enforce{ + BaseTask: tasks.BaseTask{ + Keyword: "enforce", + Msg: "Build: all profiles have been enforced", + }, + } +} + +func (b Enforce) Apply(opt *Option, profile string) (string, error) { + flags := util.GetFlags(profile) + idx := slices.Index(flags, "complain") + if idx == -1 { + return profile, nil + } + flags = slices.Delete(flags, idx, idx+1) + return util.SetFlags(profile, flags), nil +} diff --git a/pkg/prebuild/builder/fsp.go b/pkg/builder/fsp.go similarity index 53% rename from pkg/prebuild/builder/fsp.go rename to pkg/builder/fsp.go index ed2285de5c..affff245a8 100644 --- a/pkg/prebuild/builder/fsp.go +++ b/pkg/builder/fsp.go @@ -1,31 +1,32 @@ // apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol +// Copyright (C) 2021-2026 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only package builder import ( - "github.com/roddhjav/apparmor.d/pkg/prebuild" + "github.com/roddhjav/apparmor.d/pkg/tasks" "github.com/roddhjav/apparmor.d/pkg/util" ) var ( regFullSystemPolicy = util.ToRegexRepl([]string{ - `r(PU|U)x,`, `rPx,`, + `(PU|U)x,`, `Px,`, }) ) type FullSystemPolicy struct { - prebuild.Base + tasks.BaseTask } -func init() { - RegisterBuilder(&FullSystemPolicy{ - Base: prebuild.Base{ +// NewFSP creates a new FullSystemPolicy builder. +func NewFSP() *FullSystemPolicy { + return &FullSystemPolicy{ + BaseTask: tasks.BaseTask{ Keyword: "fsp", - Msg: "Prevent unconfined transitions in profile rules", + Msg: "Feat: prevent unconfined transitions in profile rules", }, - }) + } } func (b FullSystemPolicy) Apply(opt *Option, profile string) (string, error) { diff --git a/pkg/prebuild/builder/hotfix.go b/pkg/builder/hotfix.go similarity index 59% rename from pkg/prebuild/builder/hotfix.go rename to pkg/builder/hotfix.go index f7e6143b1a..1371cbcabb 100644 --- a/pkg/prebuild/builder/hotfix.go +++ b/pkg/builder/hotfix.go @@ -1,11 +1,11 @@ // apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol +// Copyright (C) 2021-2026 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only package builder import ( - "github.com/roddhjav/apparmor.d/pkg/prebuild" + "github.com/roddhjav/apparmor.d/pkg/tasks" "github.com/roddhjav/apparmor.d/pkg/util" ) @@ -19,16 +19,17 @@ var ( ) type Hotfix struct { - prebuild.Base + tasks.BaseTask } -func init() { - RegisterBuilder(&Hotfix{ - Base: prebuild.Base{ +// NewHotFix creates a new Hotfix builder. +func NewHotFix() *Hotfix { + return &Hotfix{ + BaseTask: tasks.BaseTask{ Keyword: "hotfix", - Msg: "Temporary fix for #74, #80 & #235", + Msg: "Fix: temporary solution for #74, #80 & #235", }, - }) + } } func (b Hotfix) Apply(opt *Option, profile string) (string, error) { diff --git a/pkg/builder/profile-mode.go b/pkg/builder/profile-mode.go new file mode 100644 index 0000000000..57936e1031 --- /dev/null +++ b/pkg/builder/profile-mode.go @@ -0,0 +1,56 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package builder + +import ( + "regexp" + + "github.com/roddhjav/apparmor.d/pkg/prebuild" + "github.com/roddhjav/apparmor.d/pkg/tasks" + "github.com/roddhjav/apparmor.d/pkg/util" +) + +var ( + regProfileName = regexp.MustCompile(`(?m)^profile\s+(\S+)\s+`) +) + +type ProfileMode struct { + tasks.BaseTask + modes map[string]string +} + +// NewProfileMode creates a new ProfileMode builder. +func NewProfileMode() *ProfileMode { + modes := make(map[string]string) + for _, name := range []string{"main", tasks.Distribution} { + for profile, flags := range prebuild.Flags.Read(name) { + if len(flags) > 0 { + modes[profile] = flags[0] + } + } + } + return &ProfileMode{ + BaseTask: tasks.BaseTask{ + Keyword: "profile-mode", + Msg: "Build: set modes (complain, enforce...) as definied in dist/flags", + }, + modes: modes, + } +} + +func (b ProfileMode) Apply(opt *Option, profile string) (string, error) { + matches := regProfileName.FindStringSubmatch(profile) + if matches == nil { + return profile, nil + } + + name := matches[1] + mode, present := b.modes[name] + if !present { + return profile, nil + } + + return util.SetMode(profile, mode) +} diff --git a/pkg/prebuild/builder/userspace.go b/pkg/builder/userspace.go similarity index 62% rename from pkg/prebuild/builder/userspace.go rename to pkg/builder/userspace.go index 20498bb4f5..8a5e5673c8 100644 --- a/pkg/prebuild/builder/userspace.go +++ b/pkg/builder/userspace.go @@ -1,5 +1,5 @@ // apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol +// Copyright (C) 2021-2026 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only package builder @@ -10,7 +10,7 @@ import ( "strings" "github.com/roddhjav/apparmor.d/pkg/aa" - "github.com/roddhjav/apparmor.d/pkg/prebuild" + "github.com/roddhjav/apparmor.d/pkg/tasks" ) const tokATTACHMENT = "@{exec_path}" @@ -20,26 +20,37 @@ var ( ) type Userspace struct { - prebuild.Base + tasks.BaseTask } -func init() { - RegisterBuilder(&Userspace{ - Base: prebuild.Base{ +// NewUserspace creates a new Userspace builder. +func NewUserspace() *Userspace { + return &Userspace{ + BaseTask: tasks.BaseTask{ Keyword: "userspace", - Msg: "Resolve variable in profile attachments", + Msg: "Fix: resolve variable in profile attachments", }, - }) + } } func (b Userspace) Apply(opt *Option, profile string) (string, error) { - for _, dir := range []string{"abstractions", "tunables", "local"} { - if ok, _ := opt.File.IsInsideDir(prebuild.RootApparmord.Join(dir)); ok { + for _, dir := range []string{"abstractions", "tunables", "local", "mappings"} { + if ok, _ := opt.File.IsInsideDir(b.RootApparmor.Join(dir)); ok { return profile, nil } } f := aa.DefaultTunables() + if tasks.Distribution == "arch" { + f.Preamble = append(f.Preamble, &aa.Variable{ + Name: "sbin", Values: []string{"/{,usr/}{,s}bin"}, Define: true, + }) + } else { + f.Preamble = append(f.Preamble, &aa.Variable{ + Name: "sbin", Values: []string{"/{,usr/}sbin"}, Define: true, + }) + } + if _, err := f.Parse(profile); err != nil { return "", err } diff --git a/pkg/configure/attach.go b/pkg/configure/attach.go new file mode 100644 index 0000000000..fbd644cb94 --- /dev/null +++ b/pkg/configure/attach.go @@ -0,0 +1,38 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package configure + +import ( + "strings" + + "github.com/roddhjav/apparmor.d/pkg/tasks" +) + +type ReAttach struct { + tasks.BaseTask +} + +// NewAttach creates a new ReAttach task. +func NewAttach() *ReAttach { + return &ReAttach{ + BaseTask: tasks.BaseTask{ + Keyword: "attach", + Msg: "Configure tunable for re-attached path", + }, + } +} + +func (p ReAttach) Apply() ([]string, error) { + res := []string{} + + // Remove the @{att} tunable that is going to be defined in profile header + path := p.RootApparmor.Join("tunables/multiarch.d/system") + out, err := path.ReadFileAsString() + if err != nil { + return res, err + } + out = strings.ReplaceAll(out, `@{att}=""`, `# @{att}=""`) + return res, path.WriteFile([]byte(out)) +} diff --git a/pkg/configure/configure.go b/pkg/configure/configure.go new file mode 100644 index 0000000000..825bb7548a --- /dev/null +++ b/pkg/configure/configure.go @@ -0,0 +1,135 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package configure + +import ( + "fmt" + "strings" + + "github.com/roddhjav/apparmor.d/pkg/prebuild" + "github.com/roddhjav/apparmor.d/pkg/tasks" +) + +type Configure struct { + tasks.BaseTask +} + +// NewConfigure creates a new Configure task. +func NewConfigure() *Configure { + return &Configure{ + BaseTask: tasks.BaseTask{ + Keyword: "configure", + Msg: "Set distribution specificities", + }, + } +} + +func (p Configure) removeFiles(files []string) error { + for _, name := range files { + if err := p.RootApparmor.Join(name).RemoveAll(); err != nil { + return err + } + } + return nil +} + +func (p Configure) Apply() ([]string, error) { + res := []string{} + + switch tasks.Distribution { + case "arch", "opensuse": + + case "ubuntu": + if err := prebuild.DebianHide.Init(); err != nil { + return res, err + } + + // @{pci_bus} was upstreamed in 5.0, and backported to 4.1, and in Ubuntu 24.04 + path := p.RootApparmor.Join("tunables/multiarch.d/system") + out, err := path.ReadFileAsString() + if err != nil { + return res, err + } + out = strings.ReplaceAll(out, "@{pci_bus}=pci@{hex4}:@{hex2}", "") + if err := path.WriteFile([]byte(out)); err != nil { + return res, err + } + + if tasks.Release["VERSION_CODENAME"] == "noble" { + remove := []string{ + "tunables/multiarch.d/base", + } + if err := p.removeFiles(remove); err != nil { + return res, err + } + } + + case "debian", "whonix": + if err := prebuild.DebianHide.Init(); err != nil { + return res, err + } + + default: + return []string{}, fmt.Errorf("%s is not a supported distribution", tasks.Distribution) + + } + + if p.Version < 4.1 { + remove := []string{ + // Require priority support + "fbwrap", + "fapp", + } + if err := p.removeFiles(remove); err != nil { + return res, err + } + } + if p.Version >= 4.1 { + remove := []string{ + // Remove files upstreamed in 4.1 + "abstractions/devices-usb-read", + "abstractions/devices-usb", + "abstractions/nameservice-strict", + "tunables/multiarch.d/base", + + // Direct upstream contributed profiles, similar to ours + "wg", + } + if err := p.removeFiles(remove); err != nil { + return res, err + } + + // @{pci_bus} was upstreamed in 5.0, and backported to 4.1 + path := p.RootApparmor.Join("tunables/multiarch.d/system") + out, err := path.ReadFileAsString() + if err != nil { + return res, err + } + out = strings.ReplaceAll(out, "@{pci_bus}=pci@{hex4}:@{hex2}", "") + if err := path.WriteFile([]byte(out)); err != nil { + return res, err + } + } + if p.Version >= 5.0 { + remove := []string{ + // Direct upstream contributed profiles, similar to ours + "dig", + "free", + "nslookup", + } + // Ubuntu uses sudo-rs as sudo implementation. + // if tasks.Distribution == "ubuntu" { + // remove = append(remove, + // "su", // su-rs is the new su + // "sudo", // sudo-rs is the new sudo + // ) + // } + if err := p.removeFiles(remove); err != nil { + return res, err + } + + } + return res, nil +} diff --git a/pkg/configure/core.go b/pkg/configure/core.go new file mode 100644 index 0000000000..b5f9a6fe4e --- /dev/null +++ b/pkg/configure/core.go @@ -0,0 +1,54 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +// Package configure provides prebuild tasks that prepare the apparmor.d +// build tree: synchronising directories, ignoring profiles, merging groups, +// applying distribution-specific flags, and resolving systemd defaults. +package configure + +import ( + "fmt" + + "github.com/roddhjav/apparmor.d/pkg/logging" + "github.com/roddhjav/apparmor.d/pkg/tasks" +) + +// Task main directive interface +type Task interface { + tasks.BaseTaskInterface + Apply() ([]string, error) +} + +// Configures executes configure tasks in a pipeline. +type Configures struct { + *tasks.BaseRunner[Task] +} + +// NewRunner creates a new Configures instance. +func NewRunner(t *tasks.TaskConfig) *Configures { + return &Configures{ + BaseRunner: tasks.NewBaseRunner[Task](t), + } +} + +// Run executes all tasks in the pipeline, logging their output. +func (r *Configures) Run() error { + for _, task := range r.Tasks { + msg, err := task.Apply() + if err != nil { + return fmt.Errorf("%s: %w", task.Name(), err) + } + logging.Success("%s", task.Message()) + for _, m := range msg { + logging.Bullet("%s", m) + } + } + return nil +} + +// Add appends a task to the pipeline with fluent interface. +func (r *Configures) Add(task Task) *Configures { + r.BaseRunner.Add(task) + return r +} diff --git a/pkg/prebuild/prepare/core_test.go b/pkg/configure/core_test.go similarity index 54% rename from pkg/prebuild/prepare/core_test.go rename to pkg/configure/core_test.go index ea18d2cd85..2359f09d19 100644 --- a/pkg/prebuild/prepare/core_test.go +++ b/pkg/configure/core_test.go @@ -1,8 +1,8 @@ // apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol +// Copyright (C) 2021-2026 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only -package prepare +package configure import ( "os" @@ -11,7 +11,11 @@ import ( "testing" "github.com/roddhjav/apparmor.d/pkg/paths" - "github.com/roddhjav/apparmor.d/pkg/prebuild" + "github.com/roddhjav/apparmor.d/pkg/tasks" +) + +var ( + cfg = tasks.NewTaskConfig(paths.New(".build")) ) func chdirGitRoot() { @@ -37,62 +41,57 @@ func TestTask_Apply(t *testing.T) { }{ { name: "synchronise", - task: Tasks["synchronise"], + task: NewSynchronise([]*paths.Path{paths.New("apparmor.d"), paths.New("share")}), wantErr: false, - wantFiles: paths.PathList{prebuild.RootApparmord.Join("/groups/_full/systemd")}, + wantFiles: paths.PathList{cfg.RootApparmor.Join("/groups/_full/systemd")}, }, { name: "ignore", - task: Tasks["ignore"], + task: NewIgnore(), wantErr: false, want: "dists/ignore/main.ignore", }, { name: "merge", - task: Tasks["merge"], + task: NewMerge(), wantErr: false, - wantFiles: paths.PathList{prebuild.RootApparmord.Join("aa-log")}, + wantFiles: paths.PathList{cfg.RootApparmor.Join("aa-log")}, }, { name: "configure", - task: Tasks["configure"], + task: NewConfigure(), wantErr: false, }, { name: "setflags", - task: Tasks["setflags"], + task: NewSetFlags(), wantErr: false, want: "dists/flags/main.flags", }, { name: "overwrite", - task: Tasks["overwrite"], + task: NewOverwrite(false), wantErr: false, - wantFiles: paths.PathList{prebuild.RootApparmord.Join("flatpak.apparmor.d")}, + wantFiles: paths.PathList{cfg.RootApparmor.Join("flatpak.apparmor.d")}, }, { name: "systemd-default", - task: Tasks["systemd-default"], - wantErr: false, - wantFiles: paths.PathList{prebuild.Root.Join("systemd/system/dbus.service")}, - }, - { - name: "systemd-early", - task: Tasks["systemd-early"], + task: NewSystemdDefault(), wantErr: false, - wantFiles: paths.PathList{prebuild.Root.Join("systemd/system/pcscd.service")}, + wantFiles: paths.PathList{cfg.Root.Join("systemd/system/dbus.service")}, }, { name: "fsp", - task: Tasks["fsp"], + task: NewFullSystemPolicy(), wantErr: false, - wantFiles: paths.PathList{prebuild.RootApparmord.Join("systemd")}, + wantFiles: paths.PathList{cfg.RootApparmor.Join("systemd")}, }, } chdirGitRoot() - _ = prebuild.Root.RemoveAll() + _ = cfg.Root.RemoveAll() for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + tt.task.SetConfig(cfg) got, err := tt.task.Apply() if (err != nil) != tt.wantErr { t.Errorf("Task.Apply() error = %v, wantErr %v", err, tt.wantErr) @@ -110,26 +109,32 @@ func TestTask_Apply(t *testing.T) { } } -func TestRegister(t *testing.T) { +func TestConfigures_Add(t *testing.T) { tests := []struct { - name string - names []string - wantSuccess bool + name string + tasks []Task + want []string }{ { - name: "test", - names: []string{"synchronise", "ignore"}, - wantSuccess: true, + name: "add-tasks", + tasks: []Task{NewSynchronise(nil), NewIgnore()}, + want: []string{"synchronise", "ignore"}, }, } + c := tasks.NewTaskConfig(paths.New(".build")) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - Register(tt.names...) - for _, name := range tt.names { - if got := slices.Contains(Prepares, Tasks[name]); got != tt.wantSuccess { - t.Errorf("Register() = %v, want %v", got, tt.wantSuccess) + r := NewRunner(c) + for _, task := range tt.tasks { + r.Add(task) + } + if len(r.Tasks) != len(tt.want) { + t.Errorf("Configures.Add() len = %v, want %v", len(r.Tasks), len(tt.want)) + } + for i, name := range tt.want { + if r.Tasks[i].Name() != name { + t.Errorf("Configures.Add() name = %v, want %v", r.Tasks[i].Name(), name) } - } }) } diff --git a/pkg/prebuild/prepare/flags.go b/pkg/configure/flags.go similarity index 73% rename from pkg/prebuild/prepare/flags.go rename to pkg/configure/flags.go index 5a851cbe9d..d4199b625f 100644 --- a/pkg/prebuild/prepare/flags.go +++ b/pkg/configure/flags.go @@ -1,8 +1,8 @@ // apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol +// Copyright (C) 2021-2026 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only -package prepare +package configure import ( "fmt" @@ -10,6 +10,7 @@ import ( "strings" "github.com/roddhjav/apparmor.d/pkg/prebuild" + "github.com/roddhjav/apparmor.d/pkg/tasks" ) var ( @@ -18,23 +19,24 @@ var ( ) type SetFlags struct { - prebuild.Base + tasks.BaseTask } -func init() { - RegisterTask(&SetFlags{ - Base: prebuild.Base{ +// NewSetFlags creates a new SetFlags task. +func NewSetFlags() *SetFlags { + return &SetFlags{ + BaseTask: tasks.BaseTask{ Keyword: "setflags", - Msg: "Set flags on some profiles", + Msg: "Set flags as definied in dist/flags", }, - }) + } } func (p SetFlags) Apply() ([]string, error) { res := []string{} - for _, name := range []string{"main", prebuild.Distribution} { + for _, name := range []string{"main", tasks.Distribution} { for profile, flags := range prebuild.Flags.Read(name) { - file := prebuild.RootApparmord.Join(profile) + file := p.RootApparmor.Join(profile) if !file.Exist() { res = append(res, fmt.Sprintf("Profile %s not found, ignoring", profile)) continue diff --git a/pkg/configure/fsp.go b/pkg/configure/fsp.go new file mode 100644 index 0000000000..e0d5cbb1fb --- /dev/null +++ b/pkg/configure/fsp.go @@ -0,0 +1,107 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package configure + +import ( + "regexp" + + "github.com/roddhjav/apparmor.d/pkg/paths" + "github.com/roddhjav/apparmor.d/pkg/prebuild" + "github.com/roddhjav/apparmor.d/pkg/tasks" +) + +var ( + tunables = map[string]string{ + // Set systemd profiles name + "sd": "sd", + "sdu": "sdu", + "systemd_user": "systemd-user", + "systemd": "systemd", + + // With FSP on apparmor 4.1+, the dbus profiles don't get stacked as they + "dbus_system": "dbus-system", + "dbus_session": "dbus-session", + + // Update name of stacked profiles + "apt_news": "", + "colord": "", + "e2scrub_all": "", + "e2scrub": "", + "fprintd": "", + "fwupd": "", + "fwupdmgr": "", + "geoclue": "", + "irqbalance": "", + "logrotate": "", + "ModemManager": "", + "nm_priv_helper": "", + "pcscd": "", + "polkitd": "", + "power_profiles_daemon": "", + "rsyslogd": "", + "systemd_coredump": "", + "systemd_homed": "", + "systemd_hostnamed": "", + "systemd_importd": "", + "systemd_initctl": "", + "systemd_journal_remote": "", + "systemd_journald": "", + "systemd_localed": "", + "systemd_logind": "", + "systemd_machined": "", + "systemd_networkd": "", + "systemd_oomd": "", + "systemd_resolved": "", + "systemd_rfkill": "", + "systemd_timedated": "", + "systemd_timesyncd": "", + "systemd_userdbd": "", + "upowerd": "", + } +) + +type FullSystemPolicy struct { + tasks.BaseTask +} + +// NewFullSystemPolicy creates a new FullSystemPolicy task. +func NewFullSystemPolicy() *FullSystemPolicy { + return &FullSystemPolicy{ + BaseTask: tasks.BaseTask{ + Keyword: "fsp", + Msg: "Configure AppArmor for full system policy", + }, + } +} + +func (p FullSystemPolicy) Apply() ([]string, error) { + res := []string{} + + // Install full system policy profiles + if err := paths.New("apparmor.d/groups/_full/").CopyFS(p.RootApparmor); err != nil { + return res, err + } + + // Set profile name for FSP + path := p.RootApparmor.Join("tunables/multiarch.d/profiles") + out, err := path.ReadFileAsString() + if err != nil { + return res, err + } + for varname, profile := range tunables { + pattern := regexp.MustCompile(`(@\{p_` + varname + `}=)([^\s]+)`) + if profile == "" { + out = pattern.ReplaceAllString(out, `@{p_`+varname+`}={$2,sd//&$2,$2//&sd}`) + } else { + out = pattern.ReplaceAllString(out, `@{p_`+varname+`}=`+profile) + } + } + if err := path.WriteFile([]byte(out)); err != nil { + return res, err + } + + // Set systemd unit drop-in files + return res, paths.CopyTo(prebuild.SystemdDir.Join("full"), p.Root.Join("systemd")) +} diff --git a/pkg/prebuild/prepare/ignore.go b/pkg/configure/ignore.go similarity index 64% rename from pkg/prebuild/prepare/ignore.go rename to pkg/configure/ignore.go index 2aece5174a..4c21a6e928 100644 --- a/pkg/prebuild/prepare/ignore.go +++ b/pkg/configure/ignore.go @@ -1,34 +1,36 @@ // apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol +// Copyright (C) 2021-2026 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only -package prepare +package configure import ( "github.com/roddhjav/apparmor.d/pkg/paths" "github.com/roddhjav/apparmor.d/pkg/prebuild" + "github.com/roddhjav/apparmor.d/pkg/tasks" ) type Ignore struct { - prebuild.Base + tasks.BaseTask } -func init() { - RegisterTask(&Ignore{ - Base: prebuild.Base{ +// NewIgnore creates a new Ignore task. +func NewIgnore() *Ignore { + return &Ignore{ + BaseTask: tasks.BaseTask{ Keyword: "ignore", Msg: "Ignore profiles and files from:", }, - }) + } } func (p Ignore) Apply() ([]string, error) { res := []string{} - for _, name := range []string{"main", prebuild.Distribution} { + for _, name := range []string{"main", tasks.Distribution} { for _, ignore := range prebuild.Ignore.Read(name) { - profile := prebuild.Root.Join(ignore) + profile := p.Root.Join(ignore) if profile.NotExist() { - files, err := prebuild.RootApparmord.ReadDirRecursiveFiltered(nil, paths.FilterNames(ignore)) + files, err := p.RootApparmor.ReadDirRecursiveFiltered(nil, paths.FilterNames(ignore)) if err != nil { return res, err } diff --git a/pkg/configure/merge.go b/pkg/configure/merge.go new file mode 100644 index 0000000000..a8d189e2e2 --- /dev/null +++ b/pkg/configure/merge.go @@ -0,0 +1,89 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package configure + +import ( + "os" + "path/filepath" + + "github.com/roddhjav/apparmor.d/pkg/paths" + "github.com/roddhjav/apparmor.d/pkg/tasks" +) + +type Merge struct { + tasks.BaseTask +} + +// NewMerge creates a new Merge task. +func NewMerge() *Merge { + return &Merge{ + BaseTask: tasks.BaseTask{ + Keyword: "merge", + Msg: "Merge profiles (from group/, profiles-*-*/) to a unified apparmor.d directory", + }, + } +} + +func (p Merge) Apply() ([]string, error) { + res := []string{} + dirToMerge := []string{ + "groups/*/*", "groups", + "profiles-*-*/*", "profiles-*", + } + + idx := 0 + for idx < len(dirToMerge)-1 { + dirMoved, dirRemoved := dirToMerge[idx], dirToMerge[idx+1] + files, err := filepath.Glob(p.RootApparmor.Join(dirMoved).String()) + if err != nil { + return res, err + } + for _, file := range files { + err := os.Rename(file, p.RootApparmor.Join(filepath.Base(file)).String()) + if err != nil { + return res, err + } + } + + files, err = filepath.Glob(p.RootApparmor.Join(dirRemoved).String()) + if err != nil { + return []string{}, err + } + for _, file := range files { + if err := paths.New(file).RemoveAll(); err != nil { + return res, err + } + } + idx = idx + 2 + } + + // Namespaces directory + nsRoot := p.RootApparmor.Join("namespaces") + if !nsRoot.Exist() { + return res, nil + } + dirs, err := nsRoot.ReadDir(paths.FilterDirectories()) + if err != nil { + return res, err + } + for _, dir := range dirs { + nsName := dir.Base() + files, err := dir.ReadDir(paths.FilterOutDirectories()) + if err != nil { + return res, err + } + for _, file := range files { + destPath := p.RootApparmor.Join(":" + nsName + ":" + file.Base()) + err := os.Rename(file.String(), destPath.String()) + if err != nil { + return res, err + } + } + } + if err := nsRoot.RemoveAll(); err != nil { + return res, err + } + return res, nil +} diff --git a/pkg/prebuild/prepare/overwrite.go b/pkg/configure/overwrite.go similarity index 66% rename from pkg/prebuild/prepare/overwrite.go rename to pkg/configure/overwrite.go index d974b26e45..f60b8e1d33 100644 --- a/pkg/prebuild/prepare/overwrite.go +++ b/pkg/configure/overwrite.go @@ -1,51 +1,52 @@ // apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol +// Copyright (C) 2021-2026 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only -package prepare +package configure import ( "fmt" "os" "github.com/roddhjav/apparmor.d/pkg/prebuild" + "github.com/roddhjav/apparmor.d/pkg/tasks" ) -var ext = "." + prebuild.Pkgname - type Overwrite struct { - prebuild.Base + tasks.BaseTask Optional bool } -func init() { - RegisterTask(&Overwrite{ - Base: prebuild.Base{ +// NewOverwrite creates a new Overwrite task with optional configuration. +func NewOverwrite(optional bool) *Overwrite { + return &Overwrite{ + BaseTask: tasks.BaseTask{ Keyword: "overwrite", Msg: "Overwrite dummy upstream profiles", }, - Optional: false, - }) + Optional: optional, + } } func (p Overwrite) Apply() ([]string, error) { res := []string{} - if prebuild.ABI == 3 { + if p.ABI == 3 { return res, nil } - disableDir := prebuild.RootApparmord.Join("disable") + disableDir := p.RootApparmor.Join("disable") if err := disableDir.Mkdir(); err != nil { return res, err } + ext := "." + p.Pkgname path := prebuild.DistDir.Join("overwrite") if !path.Exist() { return res, fmt.Errorf("%s not found", path) } for _, name := range path.MustReadFilteredFileAsLines() { - origin := prebuild.RootApparmord.Join(name) - dest := prebuild.RootApparmord.Join(name + ext) + origin := p.RootApparmor.Join(name) + dest := p.RootApparmor.Join(name + ext) if !dest.Exist() && p.Optional { continue } diff --git a/pkg/prebuild/prepare/synchronise.go b/pkg/configure/synchronise.go similarity index 50% rename from pkg/prebuild/prepare/synchronise.go rename to pkg/configure/synchronise.go index b6c2dbf5b6..28cc6afcbe 100644 --- a/pkg/prebuild/prepare/synchronise.go +++ b/pkg/configure/synchronise.go @@ -1,41 +1,34 @@ // apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol +// Copyright (C) 2021-2026 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only -package prepare +package configure import ( "github.com/roddhjav/apparmor.d/pkg/paths" - "github.com/roddhjav/apparmor.d/pkg/prebuild" + "github.com/roddhjav/apparmor.d/pkg/tasks" ) type Synchronise struct { - prebuild.Base - Paths []string // File or directory to sync into the build directory. + tasks.BaseTask + Sources []*paths.Path // Files or directories to sync into the build directory. } -func init() { - RegisterTask(&Synchronise{ - Base: prebuild.Base{ +// NewSynchronise creates a new Synchronise task. +func NewSynchronise(sources []*paths.Path) *Synchronise { + return &Synchronise{ + BaseTask: tasks.BaseTask{ Keyword: "synchronise", - Msg: "Initialize a new clean apparmor.d build directory", + Msg: "Initialize a new clean apparmor.d directory", }, - Paths: []string{"apparmor.d", "share"}, - }) + Sources: sources, + } } func (p Synchronise) Apply() ([]string, error) { res := []string{} - if err := prebuild.Root.Join("systemd").RemoveAll(); err != nil { - return res, err - } - if err := prebuild.RootApparmord.RemoveAll(); err != nil { - return res, err - } - - for _, name := range p.Paths { - src := paths.New(name) - dst := prebuild.Root.Join(name) + for _, src := range p.Sources { + dst := p.Root.Join(src.Base()) if err := dst.RemoveAll(); err != nil { return res, err } diff --git a/pkg/configure/systemd.go b/pkg/configure/systemd.go new file mode 100644 index 0000000000..ecfb014b99 --- /dev/null +++ b/pkg/configure/systemd.go @@ -0,0 +1,29 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package configure + +import ( + "github.com/roddhjav/apparmor.d/pkg/paths" + "github.com/roddhjav/apparmor.d/pkg/prebuild" + "github.com/roddhjav/apparmor.d/pkg/tasks" +) + +type SystemdDefault struct { + tasks.BaseTask +} + +// NewSystemdDefault creates a new SystemdDefault task. +func NewSystemdDefault() *SystemdDefault { + return &SystemdDefault{ + BaseTask: tasks.BaseTask{ + Keyword: "systemd-default", + Msg: "Configure systemd unit drop in files to a profile for some units", + }, + } +} + +func (p SystemdDefault) Apply() ([]string, error) { + return []string{}, paths.CopyTo(prebuild.SystemdDir.Join("default"), p.Root.Join("systemd")) +} diff --git a/pkg/prebuild/directive/core.go b/pkg/directive/core.go similarity index 65% rename from pkg/prebuild/directive/core.go rename to pkg/directive/core.go index 6138eec0cd..2d74109dc4 100644 --- a/pkg/prebuild/directive/core.go +++ b/pkg/directive/core.go @@ -1,7 +1,9 @@ // apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol +// Copyright (C) 2021-2026 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only +// Package directive parses and expands "#aa:" comments embedded in profiles +// (dbus, exec, only, exclude, ...) into the corresponding AppArmor rules. package directive import ( @@ -10,28 +12,47 @@ import ( "strings" "github.com/roddhjav/apparmor.d/pkg/paths" - "github.com/roddhjav/apparmor.d/pkg/prebuild" + "github.com/roddhjav/apparmor.d/pkg/tasks" ) var ( // Define the directive keyword globally Keyword = "#aa:" - // Build the profiles with the following directive applied - Directives = map[string]Directive{} - regDirective = regexp.MustCompile(`(?m).*` + Keyword + `([a-z]*)( .*)?`) ) // Directive main interface type Directive interface { - prebuild.BaseInterface + tasks.BaseTaskInterface Apply(opt *Option, profile string) (string, error) } -func Usage() string { +// Directives handles directive registration and execution. +type Directives struct { + *tasks.BaseRunner[Directive] + Directives map[string]Directive +} + +// NewRunner creates a new Directives instance. +func NewRunner(c *tasks.TaskConfig) *Directives { + return &Directives{ + BaseRunner: tasks.NewBaseRunner[Directive](c), + Directives: make(map[string]Directive), + } +} + +// Register adds a directive to the runner. +func (r *Directives) Register(d Directive) *Directives { + r.Add(d) + r.Directives[d.Name()] = d + return r +} + +// Usage returns usage information for all registered directives. +func (r *Directives) Usage() string { res := "Directive:\n" - for _, d := range Directives { + for _, d := range r.Directives { for _, h := range d.Usage() { res += fmt.Sprintf(" %s%s %s\n", Keyword, d.Name(), h) } @@ -39,6 +60,26 @@ func Usage() string { return res } +// Run executes all directives found in the profile via regex. +func (r *Directives) Run(file *paths.Path, profile string) (string, error) { + var err error + for _, match := range regDirective.FindAllStringSubmatch(profile, -1) { + opt := NewOption(file, match) + drtv, ok := r.Directives[opt.Name] + if !ok { + if opt.Name == "lint" { + continue + } + return "", fmt.Errorf("unknown directive '%s' in %s", opt.Name, opt.File) + } + profile, err = drtv.Apply(opt, profile) + if err != nil { + return "", fmt.Errorf("%s %s: %w", drtv.Name(), opt.File, err) + } + } + return profile, nil +} + // Option for the directive type Option struct { Name string @@ -77,7 +118,7 @@ func (o *Option) Clean(input string) string { return strings.Replace(input, o.Raw, o.cleanKeyword(o.Raw), 1) } -// cleanKeyword removes the dirextive keywork (#aa:...) from the input string +// cleanKeyword removes the directive keyword (#aa:...) from the input string func (o *Option) cleanKeyword(input string) string { reg := regexp.MustCompile(`\s*` + Keyword + o.Name + `( .*)?$`) return reg.ReplaceAllString(input, "") @@ -95,23 +136,3 @@ func (o *Option) IsInline() bool { } return inline } - -func RegisterDirective(d Directive) { - Directives[d.Name()] = d -} - -func Run(file *paths.Path, profile string) (string, error) { - var err error - for _, match := range regDirective.FindAllStringSubmatch(profile, -1) { - opt := NewOption(file, match) - drtv, ok := Directives[opt.Name] - if !ok { - return "", fmt.Errorf("unknown directive '%s' in %s", opt.Name, opt.File) - } - profile, err = drtv.Apply(opt, profile) - if err != nil { - return "", fmt.Errorf("%s %s: %w", drtv.Name(), opt.File, err) - } - } - return profile, nil -} diff --git a/pkg/prebuild/directive/core_test.go b/pkg/directive/core_test.go similarity index 80% rename from pkg/prebuild/directive/core_test.go rename to pkg/directive/core_test.go index 229dda6304..fe5de0b874 100644 --- a/pkg/prebuild/directive/core_test.go +++ b/pkg/directive/core_test.go @@ -1,5 +1,5 @@ // apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol +// Copyright (C) 2021-2026 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only package directive @@ -9,6 +9,12 @@ import ( "testing" "github.com/roddhjav/apparmor.d/pkg/paths" + "github.com/roddhjav/apparmor.d/pkg/tasks" +) + +var ( + apparmorDDir = paths.New("../../apparmor.d") + cfg = tasks.NewTaskConfig(paths.New(".build")) ) func TestNewOption(t *testing.T) { @@ -64,7 +70,7 @@ func TestNewOption(t *testing.T) { } } -func TestRun(t *testing.T) { +func TestDirectives_Run(t *testing.T) { tests := []struct { name string file *paths.Path @@ -87,13 +93,14 @@ func TestRun(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := Run(tt.file, tt.profile) + r := NewRunner(cfg).Register(NewDbus()) + got, err := r.Run(tt.file, tt.profile) if (err != nil) != tt.wantErr { - t.Errorf("Run() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("Directives.Run() error = %v, wantErr %v", err, tt.wantErr) return } if got != tt.want { - t.Errorf("Run() = %v, want %v", got, tt.want) + t.Errorf("Directives.Run() = %v, want %v", got, tt.want) } }) } diff --git a/pkg/prebuild/directive/dbus.go b/pkg/directive/dbus.go similarity index 57% rename from pkg/prebuild/directive/dbus.go rename to pkg/directive/dbus.go index 06fedffb51..6652acf55a 100644 --- a/pkg/prebuild/directive/dbus.go +++ b/pkg/directive/dbus.go @@ -1,5 +1,5 @@ // apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol +// Copyright (C) 2021-2026 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only // Dbus directive @@ -18,59 +18,76 @@ import ( "strings" "github.com/roddhjav/apparmor.d/pkg/aa" - "github.com/roddhjav/apparmor.d/pkg/prebuild" + "github.com/roddhjav/apparmor.d/pkg/tasks" ) type Dbus struct { - prebuild.Base + tasks.BaseTask } -func init() { - RegisterDirective(&Dbus{ - Base: prebuild.Base{ +// NewDbus creates a new Dbus directive. +func NewDbus() *Dbus { + return &Dbus{ + BaseTask: tasks.BaseTask{ Keyword: "dbus", Msg: "Dbus directive applied", Help: []string{ "own bus= name= [interface=AARE] [path=AARE]", "talk bus= name= label= [interface=AARE] [path=AARE]", - "common bus= name= label=", + "see bus= name= label= [interface=AARE] [path=AARE]", }, - }}, - ) + }, + } } func (d Dbus) Apply(opt *Option, profile string) (string, error) { var r aa.Rules - action, err := d.sanityCheck(opt) + action, err := d.SanityCheck(opt) if err != nil { return "", err } switch action { case "own": - r = d.own(opt.ArgMap) + r = d.Own(opt.ArgMap) case "talk": - r = d.talk(opt.ArgMap) - case "common": - r = d.common(opt.ArgMap) + r = d.Talk(opt.ArgMap) + case "see": + r = d.See(opt.ArgMap) + } + + bus := opt.ArgMap["bus"] + if strings.Contains(profile, "include ") { + for i, rule := range r { + inc, ok := rule.(*aa.Include) + if !ok || !inc.IsMagic || inc.Path != "abstractions/bus/"+bus+"/own" { + continue + } + r = append(r[:i], r[i+1:]...) + break + } } + header := strings.ReplaceAll(opt.Raw, Keyword, "#aa/") + "\n" aa.IndentationLevel = strings.Count( strings.SplitN(opt.Raw, Keyword, 1)[0], aa.Indentation, ) generatedDbus := r.String() - lenDbus := len(generatedDbus) - generatedDbus = generatedDbus[:lenDbus-1] - profile = strings.ReplaceAll(profile, opt.Raw, generatedDbus) + if action == "see" { + generatedDbus = generatedDbus[:len(generatedDbus)-1] // Remove trailing newlines + } else { + generatedDbus = strings.ReplaceAll(generatedDbus, "\n\n", "\n") + } + profile = strings.ReplaceAll(profile, opt.Raw, header+generatedDbus) return profile, nil } -func (d Dbus) sanityCheck(opt *Option) (string, error) { +func (d Dbus) SanityCheck(opt *Option) (string, error) { if len(opt.ArgList) < 1 { return "", fmt.Errorf("unknown dbus action: %s in %s", opt.Name, opt.File) } action := opt.ArgList[0] - if action != "own" && action != "talk" && action != "common" { + if action != "own" && action != "talk" && action != "see" { return "", fmt.Errorf("unknown dbus action: %s in %s", opt.Name, opt.File) } @@ -88,6 +105,7 @@ func (d Dbus) sanityCheck(opt *Option) (string, error) { if _, present := opt.ArgMap["path"]; !present { opt.ArgMap["path"] = "/" + strings.ReplaceAll(opt.ArgMap["name"], ".", "/") + "{,/**}" } + opt.ArgMap["name-original"] = opt.ArgMap["name"] opt.ArgMap["name"] += "{,.*}" return action, nil } @@ -106,12 +124,12 @@ func getInterfaces(rules map[string]string) []string { return interfaces } -func (d Dbus) own(rules map[string]string) aa.Rules { +func (d Dbus) Own(rules map[string]string) aa.Rules { interfaces := getInterfaces(rules) res := aa.Rules{ &aa.Include{ - IsMagic: true, Path: "abstractions/bus/own-" + rules["bus"], + IsMagic: true, Path: "abstractions/bus/" + rules["bus"] + "/own", }, &aa.Dbus{ Access: []string{"bind"}, Bus: rules["bus"], Name: rules["name"], @@ -135,7 +153,13 @@ func (d Dbus) own(rules map[string]string) aa.Rules { } res = append(res, - // DBus.Properties + // DBus.Properties: reply to properties request from anyone + &aa.Comment{ + Base: aa.Base{ + Comment: " DBus.Properties: reply to properties request from anyone", + IsLineRule: true, + }, + }, &aa.Dbus{ Access: []string{"send", "receive"}, Bus: rules["bus"], Path: rules["path"], Interface: "org.freedesktop.DBus.Properties", @@ -143,7 +167,13 @@ 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.Comment{ + Base: aa.Base{ + Comment: " DBus.Introspectable: allow clients to introspect the service", + IsLineRule: true, + }, + }, &aa.Dbus{ Access: []string{"receive"}, Bus: rules["bus"], Path: rules["path"], Interface: "org.freedesktop.DBus.Introspectable", @@ -151,7 +181,13 @@ func (d Dbus) own(rules map[string]string) aa.Rules { PeerName: `"@{busname}"`, }, - // DBus.ObjectManager + // DBus.ObjectManager: allow clients to enumerate sources + &aa.Comment{ + Base: aa.Base{ + Comment: " DBus.ObjectManager: allow clients to enumerate sources", + IsLineRule: true, + }, + }, &aa.Dbus{ Access: []string{"receive"}, Bus: rules["bus"], Path: rules["path"], Interface: "org.freedesktop.DBus.ObjectManager", @@ -168,55 +204,119 @@ func (d Dbus) own(rules map[string]string) aa.Rules { return res } -func (d Dbus) talk(rules map[string]string) aa.Rules { +func (d Dbus) Talk(rules map[string]string) aa.Rules { interfaces := getInterfaces(rules) - res := aa.Rules{} + peerName := `"{@{busname},` + rules["name"] + `,org.freedesktop.DBus}"` + res := aa.Rules{ + // Unix: allow connection to the profile + &aa.Comment{ + Base: aa.Base{ + Comment: " Unix: allow connection to the profile", + IsLineRule: true, + }, + }, + &aa.Unix{ + Type: "stream", + Address: "none", + PeerLabel: rules["label"], + PeerAddr: "none", + }, + } // Interfaces for _, iface := range interfaces { - res = append(res, &aa.Dbus{ - Access: []string{"send", "receive"}, Bus: rules["bus"], Path: rules["path"], - Interface: iface, - PeerName: `"{@{busname},` + rules["name"] + `}"`, PeerLabel: rules["label"], - }) + res = append(res, + // Interface: send and receive anything to the interface on the specific peer label + &aa.Comment{ + Base: aa.Base{ + Comment: " " + rules["name-original"] + ": send and receive anything to the interface on the specific peer label", + IsLineRule: true, + }, + }, + &aa.Dbus{ + Access: []string{"send", "receive"}, Bus: rules["bus"], Path: rules["path"], + Interface: iface, + PeerName: peerName, PeerLabel: rules["label"], + }, + &aa.Dbus{ + Access: []string{"send"}, Bus: rules["bus"], Path: rules["path"], + Interface: iface, + PeerName: `"` + rules["name"] + `"`, + }, + ) } res = append(res, - // DBus.Properties + // DBus.Properties: read and send properties + &aa.Comment{ + Base: aa.Base{ + Comment: " DBus.Properties: read and send properties", + IsLineRule: true, + }, + }, &aa.Dbus{ Access: []string{"send", "receive"}, Bus: rules["bus"], Path: rules["path"], Interface: "org.freedesktop.DBus.Properties", Member: "{Get,GetAll,Set,PropertiesChanged}", - PeerName: `"{@{busname},` + rules["name"] + `}"`, PeerLabel: rules["label"], + PeerName: peerName, PeerLabel: rules["label"], }, - // DBus.Introspectable + // DBus.Introspectable: allow service introspection + &aa.Comment{ + Base: aa.Base{ + Comment: " DBus.Introspectable: allow service introspection", + IsLineRule: true, + }, + }, &aa.Dbus{ Access: []string{"send"}, Bus: rules["bus"], Path: rules["path"], Interface: "org.freedesktop.DBus.Introspectable", Member: "Introspect", - PeerName: `"{@{busname},` + rules["name"] + `}"`, PeerLabel: rules["label"], + PeerName: peerName, PeerLabel: rules["label"], }, - // DBus.ObjectManager + // DBus.ObjectManager: allow clients to enumerate sources + &aa.Comment{ + Base: aa.Base{ + Comment: " DBus.ObjectManager: allow clients to enumerate sources", + IsLineRule: true, + }, + }, &aa.Dbus{ Access: []string{"send"}, Bus: rules["bus"], Path: rules["path"], Interface: "org.freedesktop.DBus.ObjectManager", Member: "GetManagedObjects", - PeerName: `"{@{busname},` + rules["name"] + `}"`, PeerLabel: rules["label"], + PeerName: peerName, PeerLabel: rules["label"], }, &aa.Dbus{ Access: []string{"receive"}, Bus: rules["bus"], Path: rules["path"], Interface: "org.freedesktop.DBus.ObjectManager", Member: "{InterfacesAdded,InterfacesRemoved}", - PeerName: `"{@{busname},` + rules["name"] + `}"`, PeerLabel: rules["label"], + PeerName: peerName, PeerLabel: rules["label"], }, ) return res } -func (d Dbus) common(rules map[string]string) aa.Rules { +func (d Dbus) See(rules map[string]string) aa.Rules { + peerName := `"{@{busname},` + rules["name"] + `}"` res := aa.Rules{ + nil, + + // Unix: allow connection to the profile + &aa.Comment{ + Base: aa.Base{ + Comment: " Unix: allow connection to the profile", + IsLineRule: true, + }, + }, + &aa.Unix{ + Type: "stream", + Address: "none", + PeerLabel: rules["label"], + PeerAddr: "none", + }, + nil, // DBus.Properties: read all properties from the interface &aa.Comment{ @@ -229,7 +329,7 @@ func (d Dbus) common(rules map[string]string) aa.Rules { Access: []string{"send"}, Bus: rules["bus"], Path: rules["path"], Interface: "org.freedesktop.DBus.Properties", Member: "{Get,GetAll}", - PeerName: `"{@{busname},` + rules["name"] + `}"`, PeerLabel: rules["label"], + PeerName: peerName, PeerLabel: rules["label"], }, nil, @@ -240,26 +340,28 @@ func (d Dbus) common(rules map[string]string) aa.Rules { IsLineRule: true, }, }, + nil, &aa.Dbus{ Access: []string{"receive"}, Bus: rules["bus"], Path: rules["path"], Interface: "org.freedesktop.DBus.Properties", Member: "PropertiesChanged", - PeerName: `"{@{busname},` + rules["name"] + `}"`, PeerLabel: rules["label"], + PeerName: peerName, PeerLabel: rules["label"], }, nil, - // DBus.Introspectable: allow clients to introspect the service + // DBus.Introspectable: allow service introspection &aa.Comment{ Base: aa.Base{ - Comment: " DBus.Introspectable: allow clients to introspect the service", + Comment: " DBus.Introspectable: allow service introspection", IsLineRule: true, }, }, + nil, &aa.Dbus{ Access: []string{"send"}, Bus: rules["bus"], Path: rules["path"], Interface: "org.freedesktop.DBus.Introspectable", Member: "Introspect", - PeerName: `"{@{busname},` + rules["name"] + `}"`, PeerLabel: rules["label"], + PeerName: peerName, PeerLabel: rules["label"], }, } return res diff --git a/pkg/prebuild/directive/dbus_test.go b/pkg/directive/dbus_test.go similarity index 68% rename from pkg/prebuild/directive/dbus_test.go rename to pkg/directive/dbus_test.go index 0844fd7450..778b34d1f5 100644 --- a/pkg/prebuild/directive/dbus_test.go +++ b/pkg/directive/dbus_test.go @@ -1,5 +1,5 @@ // apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol +// Copyright (C) 2021-2026 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only package directive @@ -8,8 +8,9 @@ import ( "testing" ) -const dbusOwnSystemd1 = ` include - +const ( + dbusOwnSystemd1 = ` #aa/dbus own bus=system name=org.freedesktop.systemd1 + include dbus bind bus=system name=org.freedesktop.systemd1{,.*}, dbus receive bus=system path=/org/freedesktop/systemd1{,/**} interface=org.freedesktop.systemd1{,.*} @@ -17,14 +18,17 @@ const dbusOwnSystemd1 = ` include dbus send bus=system path=/org/freedesktop/systemd1{,/**} interface=org.freedesktop.systemd1{,.*} peer=(name="{@{busname},org.freedesktop.DBus}"), + # DBus.Properties: reply to properties request from anyone dbus (send receive) bus=system path=/org/freedesktop/systemd1{,/**} interface=org.freedesktop.DBus.Properties member={Get,GetAll,Set,PropertiesChanged} peer=(name="{@{busname},org.freedesktop.DBus}"), + # DBus.Introspectable: allow clients to introspect the service dbus receive bus=system path=/org/freedesktop/systemd1{,/**} interface=org.freedesktop.DBus.Introspectable member=Introspect peer=(name="@{busname}"), + # DBus.ObjectManager: allow clients to enumerate sources dbus receive bus=system path=/org/freedesktop/systemd1{,/**} interface=org.freedesktop.DBus.ObjectManager member=GetManagedObjects @@ -32,7 +36,102 @@ const dbusOwnSystemd1 = ` include dbus send bus=system path=/org/freedesktop/systemd1{,/**} interface=org.freedesktop.DBus.ObjectManager member={InterfacesAdded,InterfacesRemoved} - peer=(name="{@{busname},org.freedesktop.DBus}"),` + peer=(name="{@{busname},org.freedesktop.DBus}"), +` + + dbusOwnInterface = ` #aa/dbus own bus=session name=com.rastersoft.ding interface+=org.gtk.Actions + include + dbus bind bus=session name=com.rastersoft.ding{,.*}, + dbus receive bus=session path=/com/rastersoft/ding{,/**} + interface=com.rastersoft.ding{,.*} + peer=(name="@{busname}"), + dbus send bus=session path=/com/rastersoft/ding{,/**} + interface=com.rastersoft.ding{,.*} + peer=(name="{@{busname},org.freedesktop.DBus}"), + dbus receive bus=session path=/com/rastersoft/ding{,/**} + interface=org.gtk.Actions + peer=(name="@{busname}"), + dbus send bus=session path=/com/rastersoft/ding{,/**} + interface=org.gtk.Actions + peer=(name="{@{busname},org.freedesktop.DBus}"), + # DBus.Properties: reply to properties request from anyone + dbus (send receive) bus=session path=/com/rastersoft/ding{,/**} + interface=org.freedesktop.DBus.Properties + member={Get,GetAll,Set,PropertiesChanged} + peer=(name="{@{busname},org.freedesktop.DBus}"), + # DBus.Introspectable: allow clients to introspect the service + dbus receive bus=session path=/com/rastersoft/ding{,/**} + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name="@{busname}"), + # DBus.ObjectManager: allow clients to enumerate sources + dbus receive bus=session path=/com/rastersoft/ding{,/**} + interface=org.freedesktop.DBus.ObjectManager + member=GetManagedObjects + peer=(name="{@{busname},com.rastersoft.ding{,.*}}"), + dbus send bus=session path=/com/rastersoft/ding{,/**} + interface=org.freedesktop.DBus.ObjectManager + member={InterfacesAdded,InterfacesRemoved} + peer=(name="{@{busname},org.freedesktop.DBus}"), +` + + dbusTalkAccounts = ` #aa/dbus talk bus=system name=org.freedesktop.Accounts label=accounts-daemon + # Unix: allow connection to the profile + unix type=stream peer=(label=accounts-daemon), + # org.freedesktop.Accounts: send and receive anything to the interface on the specific peer label + dbus (send receive) bus=system path=/org/freedesktop/Accounts{,/**} + interface=org.freedesktop.Accounts{,.*} + peer=(name="{@{busname},org.freedesktop.Accounts{,.*},org.freedesktop.DBus}", label=accounts-daemon), + dbus send bus=system path=/org/freedesktop/Accounts{,/**} + interface=org.freedesktop.Accounts{,.*} + peer=(name="org.freedesktop.Accounts{,.*}"), + # DBus.Properties: read and send properties + dbus (send receive) bus=system path=/org/freedesktop/Accounts{,/**} + interface=org.freedesktop.DBus.Properties + member={Get,GetAll,Set,PropertiesChanged} + peer=(name="{@{busname},org.freedesktop.Accounts{,.*},org.freedesktop.DBus}", label=accounts-daemon), + # DBus.Introspectable: allow service introspection + dbus send bus=system path=/org/freedesktop/Accounts{,/**} + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name="{@{busname},org.freedesktop.Accounts{,.*},org.freedesktop.DBus}", label=accounts-daemon), + # DBus.ObjectManager: allow clients to enumerate sources + dbus send bus=system path=/org/freedesktop/Accounts{,/**} + interface=org.freedesktop.DBus.ObjectManager + member=GetManagedObjects + peer=(name="{@{busname},org.freedesktop.Accounts{,.*},org.freedesktop.DBus}", label=accounts-daemon), + dbus receive bus=system path=/org/freedesktop/Accounts{,/**} + interface=org.freedesktop.DBus.ObjectManager + member={InterfacesAdded,InterfacesRemoved} + peer=(name="{@{busname},org.freedesktop.Accounts{,.*},org.freedesktop.DBus}", label=accounts-daemon), +` + + dbusSeePowerProfiles = ` #aa/dbus see bus=system name=net.hadess.PowerProfiles label=power-profiles-daemon + + # Unix: allow connection to the profile + unix type=stream peer=(label=power-profiles-daemon), + + # DBus.Properties: read all properties from the interface + + dbus send bus=system path=/net/hadess/PowerProfiles{,/**} + interface=org.freedesktop.DBus.Properties + member={Get,GetAll} + peer=(name="{@{busname},net.hadess.PowerProfiles{,.*}}", label=power-profiles-daemon), + + # DBus.Properties: receive property changed events + + dbus receive bus=system path=/net/hadess/PowerProfiles{,/**} + interface=org.freedesktop.DBus.Properties + member=PropertiesChanged + peer=(name="{@{busname},net.hadess.PowerProfiles{,.*}}", label=power-profiles-daemon), + + # DBus.Introspectable: allow service introspection + + dbus send bus=system path=/net/hadess/PowerProfiles{,/**} + interface=org.freedesktop.DBus.Introspectable + member=Introspect + peer=(name="{@{busname},net.hadess.PowerProfiles{,.*}}", label=power-profiles-daemon),` +) func TestDbus_Apply(t *testing.T) { tests := []struct { @@ -73,37 +172,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 - - dbus bind bus=session name=com.rastersoft.ding{,.*}, - dbus receive bus=session path=/com/rastersoft/ding{,/**} - interface=com.rastersoft.ding{,.*} - peer=(name="@{busname}"), - dbus send bus=session path=/com/rastersoft/ding{,/**} - interface=com.rastersoft.ding{,.*} - peer=(name="{@{busname},org.freedesktop.DBus}"), - dbus receive bus=session path=/com/rastersoft/ding{,/**} - interface=org.gtk.Actions - peer=(name="@{busname}"), - dbus send bus=session path=/com/rastersoft/ding{,/**} - interface=org.gtk.Actions - peer=(name="{@{busname},org.freedesktop.DBus}"), - dbus (send receive) bus=session path=/com/rastersoft/ding{,/**} - interface=org.freedesktop.DBus.Properties - member={Get,GetAll,Set,PropertiesChanged} - peer=(name="{@{busname},org.freedesktop.DBus}"), - dbus receive bus=session path=/com/rastersoft/ding{,/**} - interface=org.freedesktop.DBus.Introspectable - member=Introspect - peer=(name="@{busname}"), - dbus receive bus=session path=/com/rastersoft/ding{,/**} - interface=org.freedesktop.DBus.ObjectManager - member=GetManagedObjects - peer=(name="{@{busname},com.rastersoft.ding{,.*}}"), - dbus send bus=session path=/com/rastersoft/ding{,/**} - interface=org.freedesktop.DBus.ObjectManager - member={InterfacesAdded,InterfacesRemoved} - peer=(name="{@{busname},org.freedesktop.DBus}"),`, + want: dbusOwnInterface, }, { name: "talk", @@ -120,28 +189,10 @@ 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{,/**} - interface=org.freedesktop.Accounts{,.*} - peer=(name="{@{busname},org.freedesktop.Accounts{,.*}}", label=accounts-daemon), - dbus (send receive) bus=system path=/org/freedesktop/Accounts{,/**} - interface=org.freedesktop.DBus.Properties - member={Get,GetAll,Set,PropertiesChanged} - peer=(name="{@{busname},org.freedesktop.Accounts{,.*}}", label=accounts-daemon), - dbus send bus=system path=/org/freedesktop/Accounts{,/**} - interface=org.freedesktop.DBus.Introspectable - member=Introspect - peer=(name="{@{busname},org.freedesktop.Accounts{,.*}}", label=accounts-daemon), - dbus send bus=system path=/org/freedesktop/Accounts{,/**} - interface=org.freedesktop.DBus.ObjectManager - member=GetManagedObjects - peer=(name="{@{busname},org.freedesktop.Accounts{,.*}}", label=accounts-daemon), - dbus receive bus=system path=/org/freedesktop/Accounts{,/**} - interface=org.freedesktop.DBus.ObjectManager - member={InterfacesAdded,InterfacesRemoved} - peer=(name="{@{busname},org.freedesktop.Accounts{,.*}}", label=accounts-daemon),`, + want: dbusTalkAccounts, }, { - name: "common", + name: "see", opt: &Option{ Name: "dbus", ArgMap: map[string]string{ @@ -150,33 +201,19 @@ func TestDbus_Apply(t *testing.T) { "label": "power-profiles-daemon", "talk": "", }, - ArgList: []string{"common", "bus=system", "name=net.hadess.PowerProfiles", "power-profiles-daemon"}, + ArgList: []string{"see", "bus=system", "name=net.hadess.PowerProfiles", "power-profiles-daemon"}, File: nil, - Raw: " #aa:dbus common bus=system name=net.hadess.PowerProfiles label=power-profiles-daemon", + Raw: " #aa:dbus see bus=system name=net.hadess.PowerProfiles label=power-profiles-daemon", }, - profile: " #aa:dbus common bus=system name=net.hadess.PowerProfiles label=power-profiles-daemon", - want: ` # DBus.Properties: read all properties from the interface - dbus send bus=system path=/net/hadess/PowerProfiles{,/**} - interface=org.freedesktop.DBus.Properties - member={Get,GetAll} - peer=(name="{@{busname},net.hadess.PowerProfiles{,.*}}", label=power-profiles-daemon), - - # DBus.Properties: receive property changed events - dbus receive bus=system path=/net/hadess/PowerProfiles{,/**} - interface=org.freedesktop.DBus.Properties - member=PropertiesChanged - peer=(name="{@{busname},net.hadess.PowerProfiles{,.*}}", label=power-profiles-daemon), - - # DBus.Introspectable: allow clients to introspect the service - dbus send bus=system path=/net/hadess/PowerProfiles{,/**} - interface=org.freedesktop.DBus.Introspectable - member=Introspect - peer=(name="{@{busname},net.hadess.PowerProfiles{,.*}}", label=power-profiles-daemon),`, + profile: " #aa:dbus see bus=system name=net.hadess.PowerProfiles label=power-profiles-daemon", + want: dbusSeePowerProfiles, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := Directives["dbus"].Apply(tt.opt, tt.profile) + drctv := NewDbus() + drctv.SetConfig(cfg) + got, err := drctv.Apply(tt.opt, tt.profile) if (err != nil) != tt.wantErr { t.Errorf("Dbus.Apply() error = %v, wantErr %v", err, tt.wantErr) return diff --git a/pkg/prebuild/directive/exec.go b/pkg/directive/exec.go similarity index 65% rename from pkg/prebuild/directive/exec.go rename to pkg/directive/exec.go index b348fb46bc..1e0893473f 100644 --- a/pkg/prebuild/directive/exec.go +++ b/pkg/directive/exec.go @@ -1,5 +1,5 @@ // apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol +// Copyright (C) 2021-2026 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only // TODO: Local variables in profile header need to be resolved @@ -12,21 +12,23 @@ import ( "strings" "github.com/roddhjav/apparmor.d/pkg/aa" - "github.com/roddhjav/apparmor.d/pkg/prebuild" + "github.com/roddhjav/apparmor.d/pkg/paths" + "github.com/roddhjav/apparmor.d/pkg/tasks" ) type Exec struct { - prebuild.Base + tasks.BaseTask } -func init() { - RegisterDirective(&Exec{ - Base: prebuild.Base{ +// NewExec creates a new Exec directive. +func NewExec() *Exec { + return &Exec{ + BaseTask: tasks.BaseTask{ Keyword: "exec", Msg: "Exec directive applied", Help: []string{"[P|U|p|u|PU|pu|] profiles..."}, }, - }) + } } func (d Exec) Apply(opt *Option, profileRaw string) (string, error) { @@ -42,8 +44,22 @@ func (d Exec) Apply(opt *Option, profileRaw string) (string, error) { } rules := aa.Rules{} + ignoreDir := paths.FilterNames("tunables", "abstractions", "disable") for name := range opt.ArgMap { - profiletoTransition := prebuild.RootApparmord.Join(name).MustReadFileAsString() + files, err := d.RootApparmor.ReadDirRecursiveFiltered( + paths.NotFilter(ignoreDir), paths.FilterOutDirectories(), paths.FilterNames(name), + ) + if err != nil { + return "", err + } + if len(files) == 0 { + return "", fmt.Errorf("no profile found for exec: %s", name) + } + if len(files) != 1 { + return "", fmt.Errorf("multiple profiles found for exec: %s", name) + } + + profiletoTransition := files[0].MustReadFileAsString() dstProfile := aa.DefaultTunables() if _, err := dstProfile.Parse(profiletoTransition); err != nil { return "", err diff --git a/pkg/prebuild/directive/exec_test.go b/pkg/directive/exec_test.go similarity index 81% rename from pkg/prebuild/directive/exec_test.go rename to pkg/directive/exec_test.go index 255d9a237d..f0b86e9c77 100644 --- a/pkg/prebuild/directive/exec_test.go +++ b/pkg/directive/exec_test.go @@ -1,5 +1,5 @@ // apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol +// Copyright (C) 2021-2026 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only package directive @@ -8,7 +8,6 @@ import ( "testing" "github.com/roddhjav/apparmor.d/pkg/paths" - "github.com/roddhjav/apparmor.d/pkg/prebuild" ) func TestExec_Apply(t *testing.T) { @@ -22,7 +21,7 @@ func TestExec_Apply(t *testing.T) { }{ { name: "exec", - rootApparmord: paths.New("../../../apparmor.d/groups/kde/"), + rootApparmord: apparmorDDir.Join("groups/kde/"), opt: &Option{ Name: "exec", ArgMap: map[string]string{"DiscoverNotifier": ""}, @@ -36,7 +35,7 @@ func TestExec_Apply(t *testing.T) { }, { name: "exec-unconfined", - rootApparmord: paths.New("../../../apparmor.d/groups/polkit/"), + rootApparmord: apparmorDDir.Join("groups/polkit/"), opt: &Option{ Name: "exec", ArgMap: map[string]string{"U": "", "polkit-agent-helper": ""}, @@ -51,8 +50,10 @@ func TestExec_Apply(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - prebuild.RootApparmord = tt.rootApparmord - got, err := Directives["exec"].Apply(tt.opt, tt.profile) + drctv := NewExec() + drctv.SetConfig(cfg) + drctv.RootApparmor = tt.rootApparmord + got, err := drctv.Apply(tt.opt, tt.profile) if (err != nil) != tt.wantErr { t.Errorf("Exec.Apply() error = %v, wantErr %v", err, tt.wantErr) return diff --git a/pkg/directive/filter.go b/pkg/directive/filter.go new file mode 100644 index 0000000000..d906b34024 --- /dev/null +++ b/pkg/directive/filter.go @@ -0,0 +1,141 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package directive + +import ( + "fmt" + "regexp" + "strconv" + "strings" + + "github.com/roddhjav/apparmor.d/pkg/tasks" +) + +type FilterOnly struct { + tasks.BaseTask +} + +type FilterExclude struct { + tasks.BaseTask +} + +// NewFilterOnly creates a new FilterOnly directive. +func NewFilterOnly() *FilterOnly { + return &FilterOnly{ + BaseTask: tasks.BaseTask{ + Keyword: "only", + Msg: "Only directive applied", + Help: []string{"filters..."}, + }, + } +} + +// NewFilterExclude creates a new FilterExclude directive. +func NewFilterExclude() *FilterExclude { + return &FilterExclude{ + BaseTask: tasks.BaseTask{ + Keyword: "exclude", + Msg: "Exclude directive applied", + Help: []string{"filters..."}, + }, + } +} + +func cmp[T float64 | int](refValue T, operator string, value T) bool { + var res bool + switch operator { + case "<": + res = refValue < value + case "<=": + res = refValue <= value + case ">": + res = refValue > value + case ">=": + res = refValue >= value + case "==", "=": + res = refValue == value + } + return res +} + +func compare(refValue any, prefix string, arg string) bool { + pattern := fmt.Sprintf(`^%s(==|[<>]=?|=)(.+)$`, prefix) + re := regexp.MustCompile(pattern) + matches := re.FindStringSubmatch(arg) + if len(matches) < 3 { + return false + } + operator := matches[1] + targetStr := matches[2] + + var res bool + switch refValue := refValue.(type) { + case int: + targetValue, err := strconv.Atoi(targetStr) + if err != nil { + panic(err) + } + res = cmp(refValue, operator, targetValue) + + case float64: + targetValue, err := strconv.ParseFloat(targetStr, 64) + if err != nil { + panic(err) + } + res = cmp(refValue, operator, targetValue) + + default: + panic("unsupported type") + } + + return res +} + +func filterRuleForUs(c *tasks.TaskConfig, opt *Option) bool { + for _, arg := range opt.ArgList { + switch { + case c.RBAC && arg == "RBAC": + return true + case c.Test && arg == "test": + return true + case arg == tasks.Distribution: + return true + case arg == tasks.Family: + return true + case strings.HasPrefix(arg, "abi"): + if compare(c.ABI, "abi", arg) { + return true + } + case strings.HasPrefix(arg, "apparmor"): + if compare(c.Version, "apparmor", arg) { + return true + } + } + } + return false +} + +func filter(c *tasks.TaskConfig, only bool, opt *Option, profile string) (string, error) { + forUs := filterRuleForUs(c, opt) + if only == forUs { + return opt.Clean(profile), nil + } + + if opt.IsInline() { + profile = strings.ReplaceAll(profile, opt.Raw, "") + } else { + regRemoveParagraph := regexp.MustCompile(`(?s)` + opt.Raw + `\n.*?\n\n`) + profile = regRemoveParagraph.ReplaceAllString(profile, "") + } + return profile, nil +} + +func (d FilterOnly) Apply(opt *Option, profile string) (string, error) { + return filter(d.TaskConfig, true, opt, profile) +} + +func (d FilterExclude) Apply(opt *Option, profile string) (string, error) { + return filter(d.TaskConfig, false, opt, profile) +} diff --git a/pkg/directive/filter_test.go b/pkg/directive/filter_test.go new file mode 100644 index 0000000000..c271a28210 --- /dev/null +++ b/pkg/directive/filter_test.go @@ -0,0 +1,400 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package directive + +import ( + "testing" + + "github.com/roddhjav/apparmor.d/pkg/tasks" +) + +func Test_cmp(t *testing.T) { + tests := []struct { + name string + operator string + refValue float64 + value float64 + want bool + }{ + { + name: "3.2 < 5.0", + operator: "<", + refValue: 3.2, + value: 5.0, + want: true, + }, + { + name: "5.0 == 5.0", + operator: "==", + refValue: 5.0, + value: 5.0, + want: true, + }, + { + name: "5.0 >= 4.1", + operator: ">=", + refValue: 5.0, + value: 4.1, + want: true, + }, + { + name: "3.2 < 5.0", + operator: "==", + refValue: 3.2, + value: 5.0, + want: false, + }, + { + name: "3.2 <= 5.0", + operator: "<=", + refValue: 3.2, + value: 5.0, + want: true, + }, + { + name: "4.1 >= 4.1", + operator: ">=", + refValue: 4.1, + value: 4.1, + want: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := cmp(tt.refValue, tt.operator, tt.value) + if got != tt.want { + t.Errorf("cmp() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_compare(t *testing.T) { + tests := []struct { + name string + refValue float64 + arg string + want bool + }{ + { + name: "3.1 < 4.0", + refValue: 3.1, + arg: "apparmor<4.0", + want: true, + }, + { + name: "3.2 < 5.0", + refValue: 3.2, + arg: "apparmor<5.0", + want: true, + }, + { + name: "5.0 == 5.0", + refValue: 5.0, + arg: "apparmor==5.0", + want: true, + }, + { + name: "5.0 >= 4.1", + refValue: 5.0, + arg: "apparmor>=4.1", + want: true, + }, + { + name: "3.2 == 5.0", + refValue: 3.2, + arg: "apparmor==5.0", + want: false, + }, + { + name: "3.2 <= 5.0", + refValue: 3.2, + arg: "apparmor<=5.0", + want: true, + }, + { + name: "4.1 >= 4.1", + refValue: 4.1, + arg: "apparmor>=4.1", + want: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := compare(tt.refValue, "apparmor", tt.arg) + if got != tt.want { + t.Errorf("compare() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestFilterOnly_Apply(t *testing.T) { + tests := []struct { + name string + dist string + family string + opt *Option + profile string + want string + wantErr bool + }{ + { + name: "inline", + dist: "debian", + family: "apt", + opt: &Option{ + Name: "only", + ArgMap: map[string]string{"apt": ""}, + ArgList: []string{"apt"}, + File: nil, + Raw: " @{bin}/arch-audit rPx, #aa:only apt", + }, + profile: " @{bin}/arch-audit rPx, #aa:only apt", + want: " @{bin}/arch-audit rPx,", + }, + { + name: "paragraph", + dist: "arch", + family: "pacman", + opt: &Option{ + Name: "only", + ArgMap: map[string]string{"zypper": ""}, + ArgList: []string{"zypper"}, + File: nil, + Raw: " #aa:only zypper", + }, + profile: ` + /tmp/apt-changelog-@{rand6}/ w, + /tmp/apt-changelog-@{rand6}/*.changelog rw, + owner /tmp/alpm_*/{,**} rw, + owner /tmp/apt-changelog-@{rand6}/.apt-acquire-privs-test.@{rand6} rw, + owner /tmp/packagekit* rw, + + @{run}/systemd/inhibit/*.ref rw, + owner @{run}/systemd/users/@{uid} r, + + #aa:only zypper + @{run}/zypp.pid rwk, + owner @{run}/zypp-rpm.pid rwk, + owner @{run}/zypp/packages/ r, + + owner /dev/shm/AP_0x@{rand6}/{,**} rw, + owner /dev/shm/ r,`, + want: ` + /tmp/apt-changelog-@{rand6}/ w, + /tmp/apt-changelog-@{rand6}/*.changelog rw, + owner /tmp/alpm_*/{,**} rw, + owner /tmp/apt-changelog-@{rand6}/.apt-acquire-privs-test.@{rand6} rw, + owner /tmp/packagekit* rw, + + @{run}/systemd/inhibit/*.ref rw, + owner @{run}/systemd/users/@{uid} r, + + owner /dev/shm/AP_0x@{rand6}/{,**} rw, + owner /dev/shm/ r,`, + }, + } + // c := tasks.NewTaskConfig(paths.New(".build")) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tasks.Distribution = tt.dist + tasks.Family = tt.family + drctv := NewFilterOnly() + drctv.SetConfig(cfg) + got, err := drctv.Apply(tt.opt, tt.profile) + if (err != nil) != tt.wantErr { + t.Errorf("FilterOnly.Apply() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("FilterOnly.Apply() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestFilterExclude_Apply(t *testing.T) { + tests := []struct { + name string + dist string + family string + opt *Option + profile string + want string + wantErr bool + }{ + { + name: "inline", + dist: "debian", + family: "apt", + opt: &Option{ + Name: "exclude", + ArgMap: map[string]string{"debian": ""}, + ArgList: []string{"debian"}, + File: nil, + Raw: " @{bin}/dpkg rPx -> child-dpkg, #aa:exclude debian", + }, + profile: " @{bin}/dpkg rPx -> child-dpkg, #aa:exclude debian", + want: "", + }, + { + name: "inline-keep", + dist: "whonix", + family: "apt", + opt: &Option{ + Name: "exclude", + ArgMap: map[string]string{"debian": ""}, + ArgList: []string{"debian"}, + File: nil, + Raw: " @{bin}/dpkg rPx -> child-dpkg, #aa:exclude debian", + }, + profile: " @{bin}/dpkg rPx -> child-dpkg, #aa:exclude debian", + want: " @{bin}/dpkg rPx -> child-dpkg,", + }, + { + name: "inline-exclude", + dist: "ubuntu", + family: "apt", + opt: &Option{ + Name: "exclude", + ArgMap: map[string]string{"ubuntu": ""}, + ArgList: []string{"ubuntu"}, + File: nil, + Raw: " @{bin}/dpkg rPx -> child-dpkg, #aa:exclude ubuntu", + }, + profile: " @{bin}/dpkg rPx -> child-dpkg, #aa:exclude ubuntu", + want: "", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tasks.Distribution = tt.dist + tasks.Family = tt.family + drctv := NewFilterExclude() + drctv.SetConfig(cfg) + got, err := drctv.Apply(tt.opt, tt.profile) + if (err != nil) != tt.wantErr { + t.Errorf("FilterExclude.Apply() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("FilterExclude.Apply() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestFilterCmp_Apply(t *testing.T) { + tests := []struct { + name string + abi int + version float64 + opt *Option + want string + wantErr bool + }{ + { + name: "apparmor3.1<4.0", + version: 3.1, + opt: &Option{ + Name: "only", + ArgMap: map[string]string{}, + ArgList: []string{"apparmor<4.0"}, + File: nil, + Raw: " /dev/shm/ r, #aa:only apparmor>=4.1", + }, + want: " /dev/shm/ r,", + }, + { + name: "apparmor5.0>=4.1", + version: 5.0, + opt: &Option{ + Name: "only", + ArgMap: map[string]string{}, + ArgList: []string{"apparmor>=4.1"}, + File: nil, + Raw: " priority=100 @{bin}/bwrap Px, #aa:only apparmor>=4.1", + }, + want: " priority=100 @{bin}/bwrap Px,", + }, + { + name: "apparmor4.1>=4.1", + version: 4.1, + opt: &Option{ + Name: "only", + ArgMap: map[string]string{}, + ArgList: []string{"apparmor>=4.1"}, + File: nil, + Raw: " priority=100 @{bin}/bwrap Px, #aa:only apparmor>=4.1", + }, + want: " priority=100 @{bin}/bwrap Px,", + }, + { + name: "apparmor4.0>=4.1", + version: 4.0, + opt: &Option{ + Name: "only", + ArgMap: map[string]string{}, + ArgList: []string{"apparmor>=4.1"}, + File: nil, + Raw: " priority=100 @{bin}/bwrap Px, #aa:only apparmor>=4.1", + }, + want: "", + }, + { + name: "abi3=3", + abi: 3, + opt: &Option{ + Name: "only", + ArgMap: map[string]string{}, + ArgList: []string{"abi==3"}, + File: nil, + Raw: " /dev/shm/ r, #aa:only abi==3", + }, + want: " /dev/shm/ r,", + }, + { + name: "abi 3<4", + abi: 3, + opt: &Option{ + Name: "only", + ArgMap: map[string]string{}, + ArgList: []string{"abi<4"}, + File: nil, + Raw: " /efi/ r, #aa:only abi<4", + }, + want: " /efi/ r,", + }, + { + name: "abi 3>=5", + abi: 3, + opt: &Option{ + Name: "only", + ArgMap: map[string]string{}, + ArgList: []string{"abi>=5"}, + File: nil, + Raw: " /dev/shm/ r, #aa:only abi>=5", + }, + want: "", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cfg.Version = tt.version + cfg.ABI = tt.abi + drctv := NewFilterOnly() + drctv.SetConfig(cfg) + got, err := drctv.Apply(tt.opt, tt.opt.Raw) + if (err != nil) != tt.wantErr { + t.Errorf("FilterOnly.Apply() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("FilterOnly.Apply() = |%v|, want |%v|", got, tt.want) + } + }) + } +} diff --git a/pkg/prebuild/directive/stack.go b/pkg/directive/stack.go similarity index 57% rename from pkg/prebuild/directive/stack.go rename to pkg/directive/stack.go index f806898277..1a20e14f23 100644 --- a/pkg/prebuild/directive/stack.go +++ b/pkg/directive/stack.go @@ -1,5 +1,5 @@ // apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol +// Copyright (C) 2021-2026 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only package directive @@ -10,7 +10,8 @@ import ( "slices" "strings" - "github.com/roddhjav/apparmor.d/pkg/prebuild" + "github.com/roddhjav/apparmor.d/pkg/paths" + "github.com/roddhjav/apparmor.d/pkg/tasks" "github.com/roddhjav/apparmor.d/pkg/util" ) @@ -25,26 +26,28 @@ var ( ) type Stack struct { - prebuild.Base + tasks.BaseTask } -func init() { - RegisterDirective(&Stack{ - Base: prebuild.Base{ +// NewStack creates a new Stack directive. +func NewStack() *Stack { + return &Stack{ + BaseTask: tasks.BaseTask{ Keyword: "stack", Msg: "Stack directive applied", Help: []string{"[X] profiles..."}, }, - }) + } } func (s Stack) Apply(opt *Option, profile string) (string, error) { if len(opt.ArgList) == 0 { return "", fmt.Errorf("no profile to stack") } + cleanRules := regCleanStakedRules t := opt.ArgList[0] if t != "X" { - regCleanStakedRules = slices.Insert(regCleanStakedRules, 0, + cleanRules = slices.Insert(slices.Clone(regCleanStakedRules), 0, util.ToRegexRepl([]string{ `(?m)^.*(|P|p)(|U|u)(|i)x,.*$`, ``, // Remove X transition rules })..., @@ -53,16 +56,33 @@ func (s Stack) Apply(opt *Option, profile string) (string, error) { delete(opt.ArgMap, t) } - res := "" + var res strings.Builder + ignoreDir := paths.FilterNames("tunables", "abstractions", "disable") for name := range opt.ArgMap { - stackedProfile := prebuild.RootApparmord.Join(name).MustReadFileAsString() + files, err := s.RootApparmor.ReadDirRecursiveFiltered( + paths.NotFilter(ignoreDir), paths.FilterOutDirectories(), paths.FilterNames(name), + ) + if err != nil { + return "", err + } + if len(files) == 0 { + return "", fmt.Errorf("no profile found for stack: %s", name) + } + if len(files) != 1 { + return "", fmt.Errorf("multiple profiles found for stack: %s", name) + } + + stackedProfile := files[0].MustReadFileAsString() m := regRules.FindStringSubmatch(stackedProfile) if len(m) < 2 { return "", fmt.Errorf("no profile found in %s", name) } - stackedRules := m[1] - stackedRules = regCleanStakedRules.Replace(stackedRules) - res += " # Stacked profile: " + name + "\n" + stackedRules + "\n" + stackedRules := cleanRules.Replace(m[1]) + res.WriteString(" # Stacked profile: ") + res.WriteString(name) + res.WriteString("\n") + res.WriteString(stackedRules) + res.WriteString("\n") } // Insert the stacked profile at the end of the current profile, remove the stack directive @@ -70,7 +90,7 @@ func (s Stack) Apply(opt *Option, profile string) (string, error) { if len(m) <= 1 { return "", fmt.Errorf("no end of rules found in %s", opt.File) } - profile = strings.ReplaceAll(profile, m[0], res+m[0]) + profile = strings.ReplaceAll(profile, m[0], res.String()+m[0]) profile = strings.ReplaceAll(profile, opt.Raw, "") return profile, nil } diff --git a/pkg/prebuild/directive/stack_test.go b/pkg/directive/stack_test.go similarity index 81% rename from pkg/prebuild/directive/stack_test.go rename to pkg/directive/stack_test.go index 8f99d6f7a4..7c0710fc19 100644 --- a/pkg/prebuild/directive/stack_test.go +++ b/pkg/directive/stack_test.go @@ -1,5 +1,5 @@ // apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol +// Copyright (C) 2021-2026 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only package directive @@ -8,10 +8,11 @@ import ( "testing" "github.com/roddhjav/apparmor.d/pkg/paths" - "github.com/roddhjav/apparmor.d/pkg/prebuild" + "github.com/roddhjav/apparmor.d/pkg/tasks" ) func TestStack_Apply(t *testing.T) { + cfg := tasks.NewTaskConfig(paths.New(".build")) tests := []struct { name string rootApparmord *paths.Path @@ -22,7 +23,7 @@ func TestStack_Apply(t *testing.T) { }{ { name: "stack", - rootApparmord: paths.New("../../../apparmor.d/groups/freedesktop/"), + rootApparmord: apparmorDDir.Join("groups/freedesktop/"), opt: &Option{ Name: "stack", ArgMap: map[string]string{"plymouth": ""}, @@ -68,8 +69,10 @@ profile parent @{exec_path} { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - prebuild.RootApparmord = tt.rootApparmord - got, err := Directives["stack"].Apply(tt.opt, tt.profile) + drctv := NewStack() + drctv.SetConfig(cfg) + drctv.RootApparmor = tt.rootApparmord + got, err := drctv.Apply(tt.opt, tt.profile) if (err != nil) != tt.wantErr { t.Errorf("Stack.Apply() error = %v, wantErr %v", err, tt.wantErr) return diff --git a/pkg/logging/logging.go b/pkg/logging/logging.go index 642dc8273c..f655f42139 100644 --- a/pkg/logging/logging.go +++ b/pkg/logging/logging.go @@ -2,6 +2,8 @@ // Copyright (C) 2023-2024 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only +// Package logging provides coloured, prefixed output helpers for the +// interactive command-line tools (success, warning, error, ...). package logging import ( diff --git a/pkg/logs/loggers.go b/pkg/logs/loggers.go index 53b3fbd3a9..180852339f 100644 --- a/pkg/logs/loggers.go +++ b/pkg/logs/loggers.go @@ -31,15 +31,17 @@ type systemdLog struct { } // GetApparmorLogs return a list of cleaned apparmor logs from a file -func GetApparmorLogs(file io.Reader, profile string) []string { +func GetApparmorLogs(file io.Reader, profile string, namespace string) []string { var logs []string - isAppArmorLog := isAppArmorLogTemplate.Copy() + exp := `apparmor=("DENIED"|"ALLOWED"|"AUDIT")` if profile != "" { - exp := `apparmor=("DENIED"|"ALLOWED"|"AUDIT")` - exp = fmt.Sprintf(exp+`.* (profile="%s.*"|label="%s.*")`, profile, profile) - isAppArmorLog = regexp.MustCompile(exp) + exp += fmt.Sprintf(`.* (profile="%s.*"|label="%s.*")`, profile, profile) } + if namespace != "" { + exp += fmt.Sprintf(`.* namespace="root//%s.*"`, namespace) + } + isAppArmorLog := regexp.MustCompile(exp) scanner := bufio.NewScanner(file) for scanner.Scan() { @@ -55,6 +57,9 @@ func GetApparmorLogs(file io.Reader, profile string) []string { // GetAuditLogs return a reader with the logs entries from Auditd func GetAuditLogs(path string) (io.Reader, error) { + if path == "/dev/stdin" || path == "-" { + return os.Stdin, nil + } file, err := os.Open(filepath.Clean(path)) if err != nil { return nil, err @@ -63,7 +68,7 @@ func GetAuditLogs(path string) (io.Reader, error) { } // GetJournalctlLogs return a reader with the logs entries from Systemd -func GetJournalctlLogs(path string, since string, useFile bool) (io.Reader, error) { +func GetJournalctlLogs(path string, boot string, since string, useFile bool) (io.Reader, error) { var logs []systemdLog var stdout bytes.Buffer var stderr bytes.Buffer @@ -82,9 +87,12 @@ func GetJournalctlLogs(path string, since string, useFile bool) (io.Reader, erro "--identifier=audit", "--identifier=dbus-daemon", "--output=json", "--output-fields=MESSAGE", } - if since == "" { + if boot != "" { + args = append(args, "--boot="+boot) + } else if since == "" { args = append(args, "--boot") - } else { + } + if since != "" { args = append(args, "--since="+since) } cmd := exec.Command("journalctl", args...) @@ -117,21 +125,65 @@ func GetJournalctlLogs(path string, since string, useFile bool) (io.Reader, erro return strings.NewReader(res.String()), nil } +// validateLogFile checks if a file exists, is readable, and is not empty. +func validateLogFile(filename string) error { + info, err := os.Stat(filename) + if err != nil { + return err + } + mode := info.Mode() + if mode&(os.ModeNamedPipe|os.ModeCharDevice) != 0 { + return nil + } + if !mode.IsRegular() { + return fmt.Errorf("not a regular file: %s", filename) + } + if info.Size() == 0 { + return fmt.Errorf("file is empty: %s", filename) + } + return nil +} + // SelectLogFile return the path of the available log file to parse (audit, syslog, .1, .2) -func SelectLogFile(path string) string { - info, err := os.Stat(filepath.Clean(path)) - if err == nil && !info.IsDir() { - return path +func SelectLogFile(input string) (string, error) { + if input == "/dev/stdin" || input == "-" { + return input, nil } + + // If a specific file path is provided + if input != "" { + path := filepath.Clean(input) + + // Check if it's a full path that exists + if _, err := os.Stat(path); err == nil { + if err := validateLogFile(path); err != nil { + return "", err + } + return path, nil + } + + // Try as a suffix to default log files (e.g., "1" -> audit.log.1) + for _, logfile := range LogFiles { + suffixedFile := logfile + "." + input + if _, err := os.Stat(suffixedFile); err == nil { + if err := validateLogFile(suffixedFile); err != nil { + return "", err + } + return suffixedFile, nil + } + } + + return "", fmt.Errorf("log file not found: %s", input) + } + + // No input provided, find first available default log file for _, logfile := range LogFiles { if _, err := os.Stat(logfile); err == nil { - oldLogfile := filepath.Clean(logfile + "." + path) - if _, err := os.Stat(oldLogfile); err == nil { - return oldLogfile - } else { - return logfile + if err := validateLogFile(logfile); err != nil { + return "", err } + return logfile, nil } } - return "" + return "", fmt.Errorf("no log file found") } diff --git a/pkg/logs/loggers_test.go b/pkg/logs/loggers_test.go index 7e0a6002af..2940b0f901 100644 --- a/pkg/logs/loggers_test.go +++ b/pkg/logs/loggers_test.go @@ -7,6 +7,7 @@ package logs import ( "path/filepath" "reflect" + "syscall" "testing" ) @@ -16,10 +17,11 @@ var ( func TestGetJournalctlLogs(t *testing.T) { tests := []struct { - name string - path string - useFile bool - want AppArmorLogs + name string + namespace string + path string + useFile bool + want AppArmorLogs }{ { name: "gsd-xsettings", @@ -49,8 +51,8 @@ func TestGetJournalctlLogs(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - reader, _ := GetJournalctlLogs(tt.path, "", tt.useFile) - if got := New(reader, tt.name); !reflect.DeepEqual(got, tt.want) { + reader, _ := GetJournalctlLogs(tt.path, "", "", tt.useFile) + if got := New(reader, tt.name, tt.namespace); !reflect.DeepEqual(got, tt.want) { t.Errorf("New() = %v, want %v", got, tt.want) } }) @@ -58,30 +60,69 @@ func TestGetJournalctlLogs(t *testing.T) { } func TestSelectLogFile(t *testing.T) { + // canReadPath := func(path string) bool { + // if _, err := os.Stat(path); err == nil { + // if file, err := os.Open(path); err == nil { + // if err := file.Close(); err != nil { + // return false + // } + // return true + // } + // } + // return false + // } + + t.Setenv("TMPDIR", "/tmp/tests") + fifo := filepath.Join(t.TempDir(), "logs.fifo") + if err := syscall.Mkfifo(fifo, 0o600); err != nil { + t.Fatalf("mkfifo: %v", err) + } + tests := []struct { - name string - path string - want string + name string + path string + want string + wantErr bool }{ { - name: "Get audit.log", - path: filepath.Join(testdata, "audit.log"), - want: filepath.Join(testdata, "audit.log"), + name: "Get audit.log", + path: filepath.Join(testdata, "audit.log"), + want: filepath.Join(testdata, "audit.log"), + wantErr: false, }, + // { + // name: "Get /var/log/audit/audit.log.1", + // path: "1", + // want: "/var/log/audit/audit.log.1", + // wantErr: !canReadPath("/var/log/audit/audit.log.1"), + // }, + // { + // name: "Get default log file", + // path: "", + // want: "/var/log/audit/audit.log", + // wantErr: !canReadPath("/var/log/audit/audit.log.1"), + // }, { - name: "Get /var/log/audit/audit.log.1", - path: "1", - want: "/var/log/audit/audit.log.1", + name: "Named pipe (process substitution)", + path: fifo, + want: fifo, + wantErr: false, }, { - name: "Get default log file", - path: "", - want: "/var/log/audit/audit.log", + name: "File not found", + path: "/nonexistent/file", + want: "", + wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := SelectLogFile(tt.path); got != tt.want { + got, err := SelectLogFile(tt.path) + if (err != nil) != tt.wantErr { + t.Errorf("SelectLogFile() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { t.Errorf("SelectLogFile() = %v, want %v", got, tt.want) } }) diff --git a/pkg/logs/logs.go b/pkg/logs/logs.go index 194e6dc030..dfc326bee9 100644 --- a/pkg/logs/logs.go +++ b/pkg/logs/logs.go @@ -2,11 +2,14 @@ // Copyright (C) 2021-2024 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only +// Package logs parses AppArmor denial events from auditd, the systemd +// journal, dmesg, and plain kernel log files (/var/log/kern.log, +// /var/log/messages), and exposes a unified stream consumable by aa-log. package logs import ( + "bufio" "io" - "regexp" "slices" "strings" @@ -34,9 +37,7 @@ const ( ) var ( - quoted bool - isAppArmorLogTemplate = regexp.MustCompile(`apparmor=("DENIED"|"ALLOWED"|"AUDIT")`) - regCleanLogs = util.ToRegexRepl([]string{ + regCleanLogs = util.ToRegexRepl([]string{ // Clean apparmor log file `.*apparmor="`, `apparmor="`, `(peer_|)pid=[0-9]*\s`, " ", @@ -49,9 +50,12 @@ var ( `(?m)^.*/usr/share/locale[^/]?/.*$`, ``, `(?m)^.*/usr/share/zoneinfo[^/]?/.*$`, ``, `(?m)^.*/dev/(null|zero|full|log).*$`, ``, - `(?m)^.*/dev/(u|)random.*$`, ``, }) regResolveLogs = util.ToRegexRepl([]string{ + // Resolve re-attached paths variable + `/att/ns/[^/]+/`, `@{att}/`, + `/att/[^/]+/`, `@{att}/`, + // Resolve user variables `/home/[^/]+/.cache`, `@{user_cache_dirs}`, `/home/[^/]+/.config`, `@{user_config_dirs}`, @@ -64,13 +68,18 @@ var ( `/home/[^/]+/`, `@{HOME}/`, // Resolve system variables - `/att/[^/@]+`, `@{att}/`, + `/usr/bin/gnu`, `@{bin}/`, + `/usr/lib/cargo/bin/coreutils/`, `@{bin}/`, `/usr/lib(32|64|exec)`, `@{lib}`, `/usr/lib`, `@{lib}`, - `/usr/(bin|sbin)`, `@{bin}`, + `/usr/sbin`, `@{sbin}`, + `/usr/bin`, `@{bin}`, `(x86_64|amd64|i386|i686)`, `@{arch}`, `@{arch}-*linux-gnu[^/]?`, `@{multiarch}`, `/usr/etc/`, `@{etc_ro}/`, + `/var/etc/`, `@{etc_rw}/`, + `/boot/(|efi/)`, `@{efi}/`, + `/efi/`, `@{efi}/`, `/var/run/`, `@{run}/`, `/run/`, `@{run}/`, `user/[0-9]*/`, `user/@{uid}/`, @@ -85,7 +94,6 @@ var ( `pci` + strings.Repeat(h, 4) + `:` + strings.Repeat(h, 2), `@{pci_bus}`, `@{pci_bus}/[0-9a-f:*./]*/`, `@{pci}/`, `1000`, `@{uid}`, - `@{att}//`, `@{att}/`, // Some system glob `:not.active.yet`, `@{busname}`, // dbus unique bus name @@ -113,11 +121,15 @@ type AppArmorLog map[string]string // AppArmorLogs describes all apparmor log entries type AppArmorLogs []AppArmorLog -func splitQuoted(r rune) bool { - if r == '"' { - quoted = !quoted - } - return !quoted && r == ' ' +// splitFields splits a string by separator while respecting quoted sections. +func splitFields(s string, sep rune) []string { + var quoted bool + return strings.FieldsFunc(s, func(r rune) bool { + if r == '"' { + quoted = !quoted + } + return !quoted && r == sep + }) } func toQuote(str string) string { @@ -128,24 +140,18 @@ func toQuote(str string) string { } // New returns a new ApparmorLogs list of map from a log file -func New(file io.Reader, profile string) AppArmorLogs { - logs := GetApparmorLogs(file, profile) +func New(file io.Reader, profile string, namespace string) AppArmorLogs { + logs := GetApparmorLogs(file, profile, namespace) // Parse log into ApparmorLog struct - aaLogs := make(AppArmorLogs, 0) + aaLogs := make(AppArmorLogs, 0, len(logs)) toClean := []string{"profile", "name", "target"} for _, log := range logs { - quoted = false - tmp := strings.FieldsFunc(log, splitQuoted) + tmp := splitFields(log, ' ') aa := make(AppArmorLog) for _, item := range tmp { - kv := strings.FieldsFunc(item, func(r rune) bool { - if r == '"' { - quoted = !quoted - } - return !quoted && r == '=' - }) + kv := splitFields(item, '=') if len(kv) >= 2 { key, value := kv[0], kv[1] if slices.Contains(toClean, key) { @@ -154,9 +160,75 @@ func New(file io.Reader, profile string) AppArmorLogs { aa[key] = strings.Trim(value, `"`) } } + + if _, present := aa["family"]; present { + aa["class"] = "net" + } aaLogs = append(aaLogs, aa) } + return aaLogs +} +// Load reads an ApparmorLogs from file written with AppArmorLogs.String. +func Load(file io.Reader, profile string, namespace string) AppArmorLogs { + scanner := bufio.NewScanner(file) + aaLogs := make(AppArmorLogs, 0) + for scanner.Scan() { + log := scanner.Text() + tmp := splitFields(log, ' ') + if len(tmp) < 3 { + continue + } + if profile != "" && !strings.HasPrefix(tmp[1], profile) { + continue + } + aa := AppArmorLog{ + "apparmor": tmp[0], + "profile": tmp[1], + "operation": tmp[2], + } + tmp = slices.Delete(tmp, 0, 3) + isDbus := strings.Contains(aa["operation"], "dbus") + + for idx, item := range tmp { + if strings.Contains(item, "=") { + break + } + + switch idx { + case 0: + if item == "owner" { + aa["fsuid"], aa["ouid"] = "1000", "1000" + aa["FSUID"], aa["OUID"] = "user", "user" + aa["name"] = tmp[idx+1] + } else { + aa["name"] = item + } + + case 1: + if isDbus { + aa["mask"] = item + } + + case 2: + if item == "->" { + aa["target"] = tmp[idx+1] + } + } + } + + for _, item := range tmp { + kv := strings.SplitN(item, "=", 2) + if len(kv) == 2 { + aa[kv[0]] = strings.Trim(kv[1], `"`) + } + } + + if _, present := aa["family"]; present { + aa["class"] = "net" + } + aaLogs = append(aaLogs, aa) + } return aaLogs } @@ -172,18 +244,20 @@ func (aaLogs AppArmorLogs) String() string { keys := []string{ "profile", "label", // Profile name "operation", "name", "target", - "mask", "bus", "path", "interface", "member", // dbus + "mask", "bus", "path", "interface", "member", "method", // dbus "info", "comm", "laddr", "lport", "faddr", "fport", "family", "sock_type", "protocol", "requested_mask", "denied_mask", "signal", "peer", "peer_label", } // Key to not print - ignore := []string{ - "fsuid", "ouid", "FSUID", "OUID", "exe", "SAUID", "sauid", "terminal", - "UID", "AUID", "hostname", "class", + ignore := map[string]bool{ + "fsuid": true, "ouid": true, "FSUID": true, "OUID": true, + "exe": true, "SAUID": true, "sauid": true, "terminal": true, + "UID": true, "AUID": true, "hostname": true, "class": true, } // Color template to use template := map[string]string{ + "namespace": fgBlue, "profile": fgBlue, "label": fgBlue, "operation": fgYellow, @@ -196,6 +270,7 @@ func (aaLogs AppArmorLogs) String() string { "denied_mask": "denied_mask=" + boldRed, "interface": "interface=" + fgWhite, "member": "member=" + fgGreen, + "method": "method=" + fgGreen, } var res strings.Builder @@ -203,8 +278,16 @@ func (aaLogs AppArmorLogs) String() string { seen := map[string]bool{"apparmor": true} res.WriteString(state[log["apparmor"]]) owner := aa.IsOwner(log) + hasNs := false + if ns, present := log["namespace"]; present { + res.WriteString(" " + fgBlue + ":" + getNameSpace(ns) + ":" + log["profile"] + reset) + hasNs = true + } for _, key := range keys { + if hasNs && key == "profile" { + continue + } if item, present := log[key]; present { if key == "name" && owner { res.WriteString(template[key] + " owner" + reset) @@ -219,7 +302,7 @@ func (aaLogs AppArmorLogs) String() string { } for key, value := range log { - if slices.Contains(ignore, key) { + if ignore[key] { continue } if _, present := seen[key]; !present && value != "" { @@ -231,6 +314,17 @@ func (aaLogs AppArmorLogs) String() string { return res.String() } +func getNameSpace(rawNamespace string) string { + return strings.TrimPrefix(rawNamespace, "root//") +} + +func profileKey(name, namespace string) string { + if namespace == "" { + return name + } + return ":" + namespace + ":" + name +} + // ParseToProfiles convert the log data into a new AppArmorProfiles func (aaLogs AppArmorLogs) ParseToProfiles() map[string]*aa.Profile { profiles := make(map[string]*aa.Profile, 0) @@ -241,13 +335,18 @@ func (aaLogs AppArmorLogs) ParseToProfiles() map[string]*aa.Profile { } else { name = log["profile"] } + ns := getNameSpace(log["namespace"]) + key := profileKey(name, ns) - if _, ok := profiles[name]; !ok { - profile := &aa.Profile{Header: aa.Header{Name: name}} + if _, ok := profiles[key]; !ok { + profile := &aa.Profile{Header: aa.Header{ + Name: name, + NameSpace: ns, + }} profile.AddRule(log) - profiles[name] = profile + profiles[key] = profile } else { - profiles[name].AddRule(log) + profiles[key].AddRule(log) } } return profiles diff --git a/pkg/logs/logs_test.go b/pkg/logs/logs_test.go index 6ddd5ac9ec..1675fb598d 100644 --- a/pkg/logs/logs_test.go +++ b/pkg/logs/logs_test.go @@ -25,6 +25,7 @@ var ( "sock_type": "stream", "protocol": "0", "requested_mask": "send receive", + "class": "net", }, } refMan = AppArmorLogs{ @@ -81,7 +82,7 @@ func TestAppArmorEvents(t *testing.T) { want: AppArmorLogs{ { "apparmor": "ALLOWED", - "profile": "@{bin}/httpd2-prefork//vhost_foo", + "profile": "@{sbin}/httpd2-prefork//vhost_foo", "operation": "rename_dest", "name": "@{HOME}/foo.bar.in/httpdocs/apparmor/images/test/image 1.jpg", "comm": "httpd2-prefork", @@ -174,7 +175,7 @@ func TestAppArmorEvents(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { file := strings.NewReader(tt.event) - if got := New(file, ""); !reflect.DeepEqual(got, tt.want) { + if got := New(file, "", ""); !reflect.DeepEqual(got, tt.want) { t.Errorf("New() = %v, want %v", got, tt.want) } }) @@ -183,9 +184,10 @@ func TestAppArmorEvents(t *testing.T) { func TestNew(t *testing.T) { tests := []struct { - name string - path string - want AppArmorLogs + name string + namespace string + path string + want AppArmorLogs }{ { name: "dnsmasq", @@ -286,19 +288,114 @@ func TestNew(t *testing.T) { "FSUID": "user", "OUID": "user", }, + { + "apparmor": "ALLOWED", + "operation": "link", + "class": "file", + "profile": "startplasma", + "name": "@{user_cache_dirs}/ksycoca5_de_LQ6f0J2qZg4vOKgw2NbXuW7iuVU=.rSxlFV", + "target": "@{user_cache_dirs}/#@{int}", + "comm": "startplasma-way", + "denied_mask": "k", + "requested_mask": "k", + "fsuid": "1000", + "ouid": "1000", + "FSUID": "seeker", + "OUID": "seeker", + }, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { file, _ := os.Open(tt.path) - if got := New(file, tt.name); !reflect.DeepEqual(got, tt.want) { + if got := New(file, tt.name, tt.namespace); !reflect.DeepEqual(got, tt.want) { t.Errorf("New() = %v, want %v", got, tt.want) } }) } } +func TestLoad(t *testing.T) { + tests := []struct { + name string + namespace string + path string + want AppArmorLogs + }{ + { + name: "dnsmasq", + path: filepath.Join(testdata, "aa-log"), + want: AppArmorLogs{ + { + "apparmor": "DENIED", + "profile": "dnsmasq", + "operation": "open", + "name": "@{PROC}/sys/kernel/osrelease", + "comm": "dnsmasq", + "requested_mask": "r", + "denied_mask": "r", + }, + { + "apparmor": "DENIED", + "profile": "dnsmasq", + "operation": "open", + "name": "@{PROC}/1/environ", + "comm": "dnsmasq", + "requested_mask": "r", + "denied_mask": "r", + }, + { + "apparmor": "DENIED", + "profile": "dnsmasq", + "operation": "open", + "name": "@{PROC}/cmdline", + "comm": "dnsmasq", + "requested_mask": "r", + "denied_mask": "r", + }, + }, + }, + { + name: "kmod", + path: filepath.Join(testdata, "aa-log"), + want: refKmod, + }, + { + name: "man", + path: filepath.Join(testdata, "aa-log"), + want: refMan, + }, + { + name: "power-profiles-daemon", + path: filepath.Join(testdata, "aa-log"), + want: AppArmorLogs{ + { + "addr": "?", + "apparmor": "ALLOWED", + "bus": "system", + "interface": "org.freedesktop.DBus", + "mask": "send", + "member": "AddMatch", + "name": "org.freedesktop.DBus", + "operation": "dbus_method_call", + "path": "/org/freedesktop/DBus", + "peer_label": "dbus-daemon", + "profile": "power-profiles-daemon", + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + file, _ := os.Open(tt.path) + if got := Load(file, tt.name, tt.namespace); !reflect.DeepEqual(got, tt.want) { + t.Errorf("Load() = %v, want %v", got, tt.want) + } + }) + } +} + func TestAppArmorLogs_String(t *testing.T) { tests := []struct { name string @@ -373,6 +470,58 @@ func TestAppArmorLogs_ParseToProfiles(t *testing.T) { }, }, }, + { + name: "namespace-separated", + aaLogs: AppArmorLogs{ + { + "apparmor": "ALLOWED", + "profile": "podman", + "operation": "file_inherit", + "comm": "podman", + "family": "unix", + "sock_type": "stream", + "protocol": "0", + "requested_mask": "send receive", + "class": "net", + }, + { + "apparmor": "ALLOWED", + "namespace": "root//podman", + "profile": "podman", + "operation": "file_inherit", + "comm": "exe", + "family": "unix", + "sock_type": "dgram", + "protocol": "0", + "requested_mask": "send receive", + "class": "net", + }, + }, + want: map[string]*aa.Profile{ + "podman": { + Header: aa.Header{Name: "podman"}, + Rules: aa.Rules{ + &aa.Unix{ + Base: aa.Base{FileInherit: true}, + Access: []string{"send", "receive"}, + Type: "stream", + Protocol: "0", + }, + }, + }, + ":podman:podman": { + Header: aa.Header{Name: "podman", NameSpace: "podman"}, + Rules: aa.Rules{ + &aa.Unix{ + Base: aa.Base{FileInherit: true}, + Access: []string{"send", "receive"}, + Type: "dgram", + Protocol: "0", + }, + }, + }, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/pkg/paths/constructors.go b/pkg/paths/constructors.go index e3b70c9212..2c6f6caef7 100644 --- a/pkg/paths/constructors.go +++ b/pkg/paths/constructors.go @@ -1,36 +1,11 @@ -/* - * This file is part of PathsHelper library. - * - * Copyright 2018 Arduino AG (http://www.arduino.cc/) - * - * PathsHelper library is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * As a special exception, you may use this file as part of a free software - * library without restriction. Specifically, if other files instantiate - * templates or use macros or inline functions from this file, or you compile - * this file and link it with other files to produce an executable, this - * file does not by itself cause the resulting executable to be covered by - * the GNU General Public License. This exception does not however - * invalidate any other reasons why the executable file might be covered by - * the GNU General Public License. - */ +// This file is part of PathsHelper library. +// Copyright (C) 2018-2025 Arduino AG (http://www.arduino.cc/) +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only package paths import ( - "io/ioutil" "os" ) @@ -49,7 +24,7 @@ func TempDir() *Path { // the new directory. If dir is the empty string, TempDir uses the // default directory for temporary files func MkTempDir(dir, prefix string) (*Path, error) { - path, err := ioutil.TempDir(dir, prefix) + path, err := os.MkdirTemp(dir, prefix) if err != nil { return nil, err } @@ -66,7 +41,7 @@ func MkTempFile(dir *Path, prefix string) (*os.File, error) { if dir != nil { tmpDir = dir.String() } - return ioutil.TempFile(tmpDir, prefix) + return os.CreateTemp(tmpDir, prefix) } // Getwd returns a rooted path name corresponding to the current diff --git a/pkg/paths/doc.go b/pkg/paths/doc.go new file mode 100644 index 0000000000..e89b739754 --- /dev/null +++ b/pkg/paths/doc.go @@ -0,0 +1,15 @@ +// This file is part of PathsHelper library. +// Copyright (C) 2018-2025 Arduino AG (http://www.arduino.cc/) +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +// Package paths provides a set of utilities to work with file paths in a +// platform-independent way. It includes functions for creating temporary +// directories and files, handling null paths, and more. It is designed to be +// used in Go applications that require file system operations without worrying +// about platform-specific details. +// +// Based on go-paths-helper (GPL2 version) with minor modifications and +// improvements. See https://github.com/arduino/go-paths-helper for more +// details and documentation. +package paths diff --git a/pkg/paths/helper.go b/pkg/paths/helper.go new file mode 100644 index 0000000000..d490503a95 --- /dev/null +++ b/pkg/paths/helper.go @@ -0,0 +1,57 @@ +// This file is part of PathsHelper library. +// Copyright (C) 2018-2025 Arduino AG (http://www.arduino.cc/) +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package paths + +import ( + "fmt" + "regexp" +) + +var ( + Comment = `#` + regFilter = []*regexp.Regexp{ + regexp.MustCompile(`\s*` + Comment + `.*`), + regexp.MustCompile(`(?m)^(?:[\t\s]*(?:\r?\n|\r))+`), + } +) + +// Filter out comments and empty lines from a string. +func Filter(src string) string { + for _, re := range regFilter { + src = re.ReplaceAllLiteralString(src, "") + } + return src +} + +// PathListFromArgs resolves CLI-style arguments into a PathList. Each arg may +// be a file path, a directory (recursed into, skipping README.md), or a bare +// name looked up under magicRoot. +func PathListFromArgs(args []string, magicRoot *Path) (PathList, error) { + res := PathList{} + for _, arg := range args { + path := New(arg) + switch { + case !path.Exist(): + magic := magicRoot.Join(arg) + if !magic.Exist() { + return nil, fmt.Errorf("file %s not found", path) + } + res = append(res, magic) + case path.IsDir(): + files, err := path.ReadDirRecursiveFiltered(nil, + FilterOutDirectories(), + FilterOutNames("README.md"), + ) + if err != nil { + return nil, err + } + res = append(res, files...) + default: + res = append(res, path) + } + } + return res, nil +} diff --git a/pkg/paths/helper_test.go b/pkg/paths/helper_test.go new file mode 100644 index 0000000000..1f70a91a72 --- /dev/null +++ b/pkg/paths/helper_test.go @@ -0,0 +1,158 @@ +// This file is part of PathsHelper library. +// Copyright (C) 2018-2025 Arduino AG (http://www.arduino.cc/) +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package paths + +import ( + "os" + "testing" +) + +func tempDir(t *testing.T) *Path { + t.Helper() + if err := os.MkdirAll("/tmp/tests", 0o755); err != nil { + t.Fatalf("mkdir /tmp/tests: %v", err) + } + t.Setenv("TMPDIR", "/tmp/tests") + return New(t.TempDir()) +} + +func TestFilter(t *testing.T) { + tests := []struct { + name string + src string + want string + }{ + { + name: "comment", + src: "# comment", + want: "", + }, + { + name: "comment with space", + src: " # comment", + want: "", + }, + { + name: "no comment", + src: "no comment", + want: "no comment", + }, + { + name: "no comment # comment", + src: "no comment # comment", + want: "no comment", + }, + { + name: "empty", + src: ` + +`, + want: ``, + }, + { + name: "main", + src: ` +# Common profile flags definition for all distributions +# File format: one profile by line using the format: ' ' + +bwrap attach_disconnected,mediate_deleted,complain +bwrap-app attach_disconnected,complain + +akonadi_akonotes_resource complain # Dev +gnome-disks complain + +`, + want: `bwrap attach_disconnected,mediate_deleted,complain +bwrap-app attach_disconnected,complain +akonadi_akonotes_resource complain +gnome-disks complain +`, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotLine := Filter(tt.src) + if gotLine != tt.want { + t.Errorf("Filter() got = |%v|, want |%v|", gotLine, tt.want) + } + }) + } +} + +func TestPathListFromArgs(t *testing.T) { + tests := []struct { + name string + setup func(t *testing.T, dir *Path) []string + wantLen int + wantErr bool + }{ + { + name: "single file", + setup: func(t *testing.T, dir *Path) []string { + p := dir.Join("foo") + if err := p.WriteFile([]byte("x")); err != nil { + t.Fatalf("write: %v", err) + } + return []string{p.String()} + }, + wantLen: 1, + }, + { + name: "directory filters README.md", + setup: func(t *testing.T, dir *Path) []string { + for _, name := range []string{"a", "sub/b", "README.md"} { + p := dir.Join(name) + if err := p.Parent().MkdirAll(); err != nil { + t.Fatalf("mkdir: %v", err) + } + if err := p.WriteFile([]byte("x")); err != nil { + t.Fatalf("write: %v", err) + } + } + return []string{dir.String()} + }, + wantLen: 2, + }, + { + name: "missing path errors", + setup: func(t *testing.T, dir *Path) []string { + return []string{dir.Join("missing").String()} + }, + wantErr: true, + }, + { + name: "missing path resolves via magicRoot", + setup: func(t *testing.T, dir *Path) []string { + if err := dir.Join("named").WriteFile([]byte("x")); err != nil { + t.Fatalf("write: %v", err) + } + return []string{"named"} + }, + wantLen: 1, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + dir := tempDir(t) + args := tt.setup(t, dir) + got, err := PathListFromArgs(args, dir) + if (err != nil) != tt.wantErr { + t.Fatalf("PathListFromArgs() error = %v, wantErr %v", err, tt.wantErr) + } + if tt.wantErr { + return + } + if len(got) != tt.wantLen { + t.Errorf("PathListFromArgs() returned %d entries, want %d: %v", len(got), tt.wantLen, got) + } + for _, p := range got { + if p.Base() == "README.md" { + t.Errorf("README.md was not filtered out: %v", got) + } + } + }) + } +} diff --git a/pkg/paths/list.go b/pkg/paths/list.go index fbab13c5f5..9f9975670c 100644 --- a/pkg/paths/list.go +++ b/pkg/paths/list.go @@ -1,31 +1,7 @@ -/* - * This file is part of PathsHelper library. - * - * Copyright 2018 Arduino AG (http://www.arduino.cc/) - * - * PathsHelper library is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * As a special exception, you may use this file as part of a free software - * library without restriction. Specifically, if other files instantiate - * templates or use macros or inline functions from this file, or you compile - * this file and link it with other files to produce an executable, this - * file does not by itself cause the resulting executable to be covered by - * the GNU General Public License. This exception does not however - * invalidate any other reasons why the executable file might be covered by - * the GNU General Public License. - */ +// This file is part of PathsHelper library. +// Copyright (C) 2018-2025 Arduino AG (http://www.arduino.cc/) +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only package paths @@ -63,6 +39,20 @@ func (p *PathList) AsStrings() []string { return res } +// Equals returns true if the current PathList is equal to the +// PathList passed as argument +func (p *PathList) Equals(other PathList) bool { + if len(*p) != len(other) { + return false + } + for i, path := range *p { + if !path.EqualsTo(other[i]) { + return false + } + } + return true +} + // FilterDirs remove all entries except directories func (p *PathList) FilterDirs() { res := (*p)[:0] diff --git a/pkg/paths/list_test.go b/pkg/paths/list_test.go new file mode 100644 index 0000000000..190915ffca --- /dev/null +++ b/pkg/paths/list_test.go @@ -0,0 +1,424 @@ +// This file is part of PathsHelper library. +// Copyright (C) 2018-2025 Arduino AG (http://www.arduino.cc/) +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package paths + +import ( + "fmt" + "testing" +) + +func TestPathList_New(t *testing.T) { + tests := []struct { + name string + args []string + want string + len int + }{ + { + name: "empty", + args: nil, + want: "[]", + len: 0, + }, + { + name: "single", + args: []string{"test"}, + want: "[test]", + len: 1, + }, + { + name: "three", + args: []string{"a", "b", "c"}, + want: "[a b c]", + len: 3, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + list := NewPathList(tt.args...) + if len(list) != tt.len { + t.Fatalf("got len %d, want %d", len(list), tt.len) + } + if got := fmt.Sprintf("%s", list); got != tt.want { + t.Errorf("got %v, want %v", got, tt.want) + } + }) + } +} + +func TestPathList_Contains(t *testing.T) { + list := NewPathList("a", "b", "c") + tests := []struct { + name string + path string + want bool + }{ + { + name: "not-present", + path: "d", + want: false, + }, + { + name: "present", + path: "a", + want: true, + }, + { + name: "equivalent-not-considered", + path: "d/../a", + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := list.Contains(New(tt.path)); got != tt.want { + t.Errorf("got %v, want %v", got, tt.want) + } + }) + } +} + +func TestPathList_ContainsEquivalentTo(t *testing.T) { + list := NewPathList("a", "b", "c") + tests := []struct { + name string + path string + want bool + }{ + { + name: "not-present", + path: "d", + want: false, + }, + { + name: "present", + path: "a", + want: true, + }, + { + name: "equivalent", + path: "d/../a", + want: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := list.ContainsEquivalentTo(New(tt.path)); got != tt.want { + t.Errorf("got %v, want %v", got, tt.want) + } + }) + } +} + +func TestPathList_Equals(t *testing.T) { + base := NewPathList("a", "b", "c") + tests := []struct { + name string + a PathList + b PathList + want bool + }{ + { + name: "clone", + a: base, + b: base.Clone(), + want: true, + }, + { + name: "different-len", + a: base, + b: NewPathList("a", "b"), + want: false, + }, + { + name: "different-content", + a: base, + b: NewPathList("a", "b", "d"), + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.a.Equals(tt.b); got != tt.want { + t.Errorf("got %v, want %v", got, tt.want) + } + }) + } +} + +func TestPathList_AddIfMissing(t *testing.T) { + tests := []struct { + name string + start []string + add string + want string + }{ + { + name: "add-new", + start: []string{"a", "b", "c"}, + add: "d", + want: "[a b c d]", + }, + { + name: "skip-existing", + start: []string{"a", "b", "c", "d"}, + add: "b", + want: "[a b c d]", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + list := NewPathList(tt.start...) + list.AddIfMissing(New(tt.add)) + if got := fmt.Sprintf("%s", list); got != tt.want { + t.Errorf("got %v, want %v", got, tt.want) + } + }) + } +} + +func TestPathList_AddAllMissing(t *testing.T) { + tests := []struct { + name string + start []string + add []string + want string + }{ + { + name: "mix-new-and-existing", + start: []string{"a", "b", "c", "d"}, + add: []string{"a", "e", "i", "o", "u"}, + want: "[a b c d e i o u]", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + list := NewPathList(tt.start...) + list.AddAllMissing(NewPathList(tt.add...)) + if got := fmt.Sprintf("%s", list); got != tt.want { + t.Errorf("got %v, want %v", got, tt.want) + } + }) + } +} + +func TestPathList_Sort(t *testing.T) { + tests := []struct { + name string + entries []string + before string + after string + }{ + { + name: "unsorted", + entries: []string{ + "pointless", "spare", "carve", "unwieldy", "empty", + "bow", "tub", "grease", "error", "energetic", + "depend", "property", + }, + before: "[pointless spare carve unwieldy empty bow tub grease error energetic depend property]", + after: "[bow carve depend empty energetic error grease pointless property spare tub unwieldy]", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + list := NewPathList(tt.entries...) + if got := fmt.Sprintf("%s", list); got != tt.before { + t.Errorf("before: got %v, want %v", got, tt.before) + } + list.Sort() + if got := fmt.Sprintf("%s", list); got != tt.after { + t.Errorf("after: got %v, want %v", got, tt.after) + } + }) + } +} + +var testFilterList = []string{ + "aaaa", + "bbbb", + "cccc", + "dddd", + "eeff", + "aaaa/bbbb", + "eeee/ffff", + "gggg/hhhh", +} + +func TestPathList_FilterPrefix(t *testing.T) { + tests := []struct { + name string + prefixes []string + want string + }{ + { + name: "single-a", + prefixes: []string{"a"}, + want: "[aaaa]", + }, + { + name: "single-b", + prefixes: []string{"b"}, + want: "[bbbb aaaa/bbbb]", + }, + { + name: "two-a-b", + prefixes: []string{"a", "b"}, + want: "[aaaa bbbb aaaa/bbbb]", + }, + { + name: "no-match", + prefixes: []string{"test"}, + want: "[]", + }, + { + name: "empty", + prefixes: nil, + want: "[]", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + list := NewPathList(testFilterList...) + list.FilterPrefix(tt.prefixes...) + if got := fmt.Sprintf("%s", list); got != tt.want { + t.Errorf("got %v, want %v", got, tt.want) + } + }) + } +} + +func TestPathList_FilterOutPrefix(t *testing.T) { + tests := []struct { + name string + prefixes []string + want string + }{ + { + name: "single-b", + prefixes: []string{"b"}, + want: "[aaaa cccc dddd eeff eeee/ffff gggg/hhhh]", + }, + { + name: "multi", + prefixes: []string{"b", "c", "h"}, + want: "[aaaa dddd eeff eeee/ffff]", + }, + { + name: "empty", + prefixes: nil, + want: "[aaaa bbbb cccc dddd eeff aaaa/bbbb eeee/ffff gggg/hhhh]", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + list := NewPathList(testFilterList...) + list.FilterOutPrefix(tt.prefixes...) + if got := fmt.Sprintf("%s", list); got != tt.want { + t.Errorf("got %v, want %v", got, tt.want) + } + }) + } +} + +func TestPathList_FilterSuffix(t *testing.T) { + tests := []struct { + name string + suffixes []string + want string + }{ + { + name: "single-a", + suffixes: []string{"a"}, + want: "[aaaa]", + }, + { + name: "two-a-h", + suffixes: []string{"a", "h"}, + want: "[aaaa gggg/hhhh]", + }, + { + name: "no-match", + suffixes: []string{"test"}, + want: "[]", + }, + { + name: "empty", + suffixes: nil, + want: "[]", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + list := NewPathList(testFilterList...) + list.FilterSuffix(tt.suffixes...) + if got := fmt.Sprintf("%s", list); got != tt.want { + t.Errorf("got %v, want %v", got, tt.want) + } + }) + } +} + +func TestPathList_FilterOutSuffix(t *testing.T) { + tests := []struct { + name string + suffixes []string + want string + }{ + { + name: "single-a", + suffixes: []string{"a"}, + want: "[bbbb cccc dddd eeff aaaa/bbbb eeee/ffff gggg/hhhh]", + }, + { + name: "two-a-h", + suffixes: []string{"a", "h"}, + want: "[bbbb cccc dddd eeff aaaa/bbbb eeee/ffff]", + }, + { + name: "no-match", + suffixes: []string{"test"}, + want: "[aaaa bbbb cccc dddd eeff aaaa/bbbb eeee/ffff gggg/hhhh]", + }, + { + name: "empty", + suffixes: nil, + want: "[aaaa bbbb cccc dddd eeff aaaa/bbbb eeee/ffff gggg/hhhh]", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + list := NewPathList(testFilterList...) + list.FilterOutSuffix(tt.suffixes...) + if got := fmt.Sprintf("%s", list); got != tt.want { + t.Errorf("got %v, want %v", got, tt.want) + } + }) + } +} + +func TestPathList_Filter(t *testing.T) { + tests := []struct { + name string + fn func(p *Path) bool + want string + }{ + { + name: "base-equals-bbbb", + fn: func(p *Path) bool { return p.Base() == "bbbb" }, + want: "[bbbb aaaa/bbbb]", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + list := NewPathList(testFilterList...) + list.Filter(tt.fn) + if got := fmt.Sprintf("%s", list); got != tt.want { + t.Errorf("got %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/paths/paths.go b/pkg/paths/paths.go index 9126118506..214ba09d10 100644 --- a/pkg/paths/paths.go +++ b/pkg/paths/paths.go @@ -1,31 +1,7 @@ -/* - * This file is part of PathsHelper library. - * - * Copyright 2018 Arduino AG (http://www.arduino.cc/) - * - * PathsHelper library is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * As a special exception, you may use this file as part of a free software - * library without restriction. Specifically, if other files instantiate - * templates or use macros or inline functions from this file, or you compile - * this file and link it with other files to produce an executable, this - * file does not by itself cause the resulting executable to be covered by - * the GNU General Public License. This exception does not however - * invalidate any other reasons why the executable file might be covered by - * the GNU General Public License. - */ +// This file is part of PathsHelper library. +// Copyright (C) 2018-2025 Arduino AG (http://www.arduino.cc/) +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only package paths @@ -39,8 +15,6 @@ import ( "strings" "syscall" "time" - - "github.com/roddhjav/apparmor.d/pkg/util" ) // Path represents a path @@ -210,6 +184,17 @@ func (p *Path) IsInsideDir(dir *Path) (bool, error) { rel != ".", nil } +// IsInsideAnyDir returns true if the current path is inside any of the +// provided dirs. +func (p *Path) IsInsideAnyDir(dirs []*Path) bool { + for _, d := range dirs { + if inside, _ := p.IsInsideDir(d); inside { + return true + } + } + return false +} + // Parent returns all but the last element of path, typically the path's // directory or the parent directory if the path is already a directory func (p *Path) Parent() *Path { @@ -254,6 +239,14 @@ func (p *Path) MkTempDir(prefix string) (*Path, error) { return MkTempDir(p.path, prefix) } +func (p *Path) IsSymlink() (bool, error) { + info, err := p.Lstat() + if err != nil { + return false, err + } + return info.Mode()&os.ModeSymlink != 0, nil +} + // FollowSymLink transforms the current path to the path pointed by the // symlink if path is a symlink, otherwise it does nothing func (p *Path) FollowSymLink() error { @@ -391,7 +384,11 @@ func CopyTo(src *Path, dst *Path) error { // CopyFS copies the file system fsys into the directory dir, // creating dir if necessary. It is the exivalent of os.CopyFS with Path. func (p *Path) CopyFS(dst *Path) error { - return os.CopyFS(dst.String(), os.DirFS(p.String())) + err := os.CopyFS(dst.String(), os.DirFS(p.String())) + if err != nil { + return fmt.Errorf("copying %s to %s: %s", p, dst, err) + } + return nil } // CopyDirTo recursively copies the directory denoted by the current path to @@ -543,7 +540,7 @@ func (p *Path) MustReadFilteredFileAsLines() []string { } txt := string(data) txt = strings.ReplaceAll(txt, "\r\n", "\n") - txt = util.Filter(txt) + txt = Filter(txt) res := strings.Split(txt, "\n") if slices.Contains(res, "") { idx := slices.Index(res, "") @@ -636,9 +633,7 @@ func (p *Path) String() string { func (p *Path) Canonical() *Path { canonical := p.Clone() // https://github.com/golang/go/issues/17084#issuecomment-246645354 - if err := canonical.FollowSymLink(); err != nil { - return nil - } + _ = canonical.FollowSymLink() if absPath, err := canonical.Abs(); err == nil { canonical = absPath } diff --git a/pkg/paths/paths_test.go b/pkg/paths/paths_test.go new file mode 100644 index 0000000000..40a39d6f6d --- /dev/null +++ b/pkg/paths/paths_test.go @@ -0,0 +1,1062 @@ +// This file is part of PathsHelper library. +// Copyright (C) 2018-2025 Arduino AG (http://www.arduino.cc/) +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package paths + +import ( + "bytes" + "path/filepath" + "strings" + "testing" +) + +var testdataRoot = "../../tests/testdata/paths" + +func pathEqualsTo(t *testing.T, expected string, actual *Path) { + t.Helper() + got := filepath.ToSlash(actual.String()) + if got != expected { + t.Errorf("got %v, want %v", got, expected) + } +} + +func makeTestPath(parts []string) *Path { + p := New(testdataRoot, "fileset") + for _, part := range parts { + p = p.Join(part) + } + return p +} + +func TestPath_IsInsideAnyDir(t *testing.T) { + tests := []struct { + name string + p string + dirs []string + want bool + }{ + { + name: "empty dirs", + p: "/a/b/c", + dirs: nil, + want: false, + }, + { + name: "direct child", + p: "/a/b/c", + dirs: []string{"/a/b"}, + want: true, + }, + { + name: "nested descendant", + p: "/a/b/c/d/e", + dirs: []string{"/a/b"}, + want: true, + }, + { + name: "sibling not under", + p: "/a/bc/d", + dirs: []string{"/a/b"}, + want: false, + }, + { + name: "equal path is not under", + p: "/a/b", + dirs: []string{"/a/b"}, + want: false, + }, + { + name: "matches one of many", + p: "/x/y/z", + dirs: []string{"/a", "/x", "/p"}, + want: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var dirs []*Path + for _, d := range tt.dirs { + dirs = append(dirs, New(d)) + } + if got := New(tt.p).IsInsideAnyDir(dirs); got != tt.want { + t.Errorf("IsInsideAnyDir(%q, %v) = %v, want %v", tt.p, tt.dirs, got, tt.want) + } + }) + } +} + +func TestPath_New(t *testing.T) { + tests := []struct { + name string + args []string + want string + wantNil bool + }{ + { + name: "single", + args: []string{"path"}, + want: "path", + }, + { + name: "join", + args: []string{"path", "path"}, + want: filepath.Join("path", "path"), + }, + { + name: "no-args", + args: nil, + wantNil: true, + }, + { + name: "empty-string", + args: []string{""}, + wantNil: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := New(tt.args...) + if tt.wantNil { + if got != nil { + t.Errorf("expected nil, got %v", got) + } + return + } + if got.String() != tt.want { + t.Errorf("got %v, want %v", got.String(), tt.want) + } + }) + } +} + +// testPathCases drives the per-method tests over shared filesystem fixtures. +var testPathCases = []struct { + name string + joinParts []string // parts joined onto testdataRoot/fileset + wantPath string // forward-slash path string expected + wantIsDir bool + wantExist bool + wantExistOK bool // whether ExistCheck should return err==nil + wantIsDirOK bool // whether IsDirCheck should return err==nil +}{ + { + name: "fileset-dir", + joinParts: nil, + wantPath: testdataRoot + "/fileset", + wantIsDir: true, + wantExist: true, + wantExistOK: true, + wantIsDirOK: true, + }, + { + name: "subdir", + joinParts: []string{"folder"}, + wantPath: testdataRoot + "/fileset/folder", + wantIsDir: true, + wantExist: true, + wantExistOK: true, + wantIsDirOK: true, + }, + { + name: "regular-file", + joinParts: []string{"file"}, + wantPath: testdataRoot + "/fileset/file", + wantIsDir: false, + wantExist: true, + wantExistOK: true, + wantIsDirOK: true, + }, + { + name: "nonexistent", + joinParts: []string{"file", "notexistent"}, + wantPath: testdataRoot + "/fileset/file/notexistent", + wantIsDir: false, + wantExist: false, + wantExistOK: true, + wantIsDirOK: false, + }, +} + +func TestPath_Join(t *testing.T) { + for _, tt := range testPathCases { + t.Run(tt.name, func(t *testing.T) { + p := makeTestPath(tt.joinParts) + pathEqualsTo(t, tt.wantPath, p) + }) + } +} + +func TestPath_IsDirCheck(t *testing.T) { + for _, tt := range testPathCases { + t.Run(tt.name, func(t *testing.T) { + p := makeTestPath(tt.joinParts) + isDir, err := p.IsDirCheck() + if isDir != tt.wantIsDir { + t.Errorf("IsDirCheck() isDir = %v, want %v", isDir, tt.wantIsDir) + } + if (err == nil) != tt.wantIsDirOK { + t.Errorf("IsDirCheck() err = %v, wantOK = %v", err, tt.wantIsDirOK) + } + }) + } +} + +func TestPath_IsDir(t *testing.T) { + for _, tt := range testPathCases { + t.Run(tt.name, func(t *testing.T) { + p := makeTestPath(tt.joinParts) + if got := p.IsDir(); got != tt.wantIsDir { + t.Errorf("IsDir() = %v, want %v", got, tt.wantIsDir) + } + }) + } +} + +func TestPath_IsNotDir(t *testing.T) { + for _, tt := range testPathCases { + t.Run(tt.name, func(t *testing.T) { + p := makeTestPath(tt.joinParts) + // IsNotDir returns true only when the path exists and is not a directory + want := tt.wantExist && !tt.wantIsDir + if got := p.IsNotDir(); got != want { + t.Errorf("IsNotDir() = %v, want %v", got, want) + } + }) + } +} + +func TestPath_ExistCheck(t *testing.T) { + for _, tt := range testPathCases { + t.Run(tt.name, func(t *testing.T) { + p := makeTestPath(tt.joinParts) + exist, err := p.ExistCheck() + if exist != tt.wantExist { + t.Errorf("ExistCheck() exist = %v, want %v", exist, tt.wantExist) + } + if (err == nil) != tt.wantExistOK { + t.Errorf("ExistCheck() err = %v, wantOK = %v", err, tt.wantExistOK) + } + }) + } +} + +func TestPath_Exist(t *testing.T) { + for _, tt := range testPathCases { + t.Run(tt.name, func(t *testing.T) { + p := makeTestPath(tt.joinParts) + if got := p.Exist(); got != tt.wantExist { + t.Errorf("Exist() = %v, want %v", got, tt.wantExist) + } + }) + } +} + +func TestPath_NotExist(t *testing.T) { + for _, tt := range testPathCases { + t.Run(tt.name, func(t *testing.T) { + p := makeTestPath(tt.joinParts) + want := !tt.wantExist + if got := p.NotExist(); got != want { + t.Errorf("NotExist() = %v, want %v", got, want) + } + }) + } +} + +func TestPath_ReadDir(t *testing.T) { + tests := []struct { + name string + parts []string + want []string + }{ + { + name: "subfolder", + parts: []string{"folder"}, + want: []string{ + testdataRoot + "/fileset/folder/.hidden", + testdataRoot + "/fileset/folder/file2", + testdataRoot + "/fileset/folder/file3", + testdataRoot + "/fileset/folder/subfolder", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := makeTestPath(tt.parts) + list, err := p.ReadDir() + if err != nil { + t.Fatal(err) + } + if len(list) != len(tt.want) { + t.Fatalf("got len %d, want %d", len(list), len(tt.want)) + } + for i, want := range tt.want { + pathEqualsTo(t, want, list[i]) + } + }) + } +} + +func TestPathList_FilterDirsOnReadDir(t *testing.T) { + tests := []struct { + name string + parts []string + want []string + }{ + { + name: "folder", + parts: []string{"folder"}, + want: []string{ + testdataRoot + "/fileset/folder/subfolder", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + list, err := makeTestPath(tt.parts).ReadDir() + if err != nil { + t.Fatal(err) + } + list.FilterDirs() + if len(list) != len(tt.want) { + t.Fatalf("got len %d, want %d", len(list), len(tt.want)) + } + for i, w := range tt.want { + pathEqualsTo(t, w, list[i]) + } + }) + } +} + +func TestPathList_FilterOutHiddenFilesOnReadDir(t *testing.T) { + tests := []struct { + name string + parts []string + want []string + }{ + { + name: "folder", + parts: []string{"folder"}, + want: []string{ + testdataRoot + "/fileset/folder/file2", + testdataRoot + "/fileset/folder/file3", + testdataRoot + "/fileset/folder/subfolder", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + list, err := makeTestPath(tt.parts).ReadDir() + if err != nil { + t.Fatal(err) + } + list.FilterOutHiddenFiles() + if len(list) != len(tt.want) { + t.Fatalf("got len %d, want %d", len(list), len(tt.want)) + } + for i, w := range tt.want { + pathEqualsTo(t, w, list[i]) + } + }) + } +} + +func TestPathList_FilterOutPrefixOnReadDir(t *testing.T) { + tests := []struct { + name string + parts []string + prefixes []string + want []string + }{ + { + name: "folder-prefix-file", + parts: []string{"folder"}, + prefixes: []string{"file"}, + want: []string{ + testdataRoot + "/fileset/folder/.hidden", + testdataRoot + "/fileset/folder/subfolder", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + list, err := makeTestPath(tt.parts).ReadDir() + if err != nil { + t.Fatal(err) + } + list.FilterOutPrefix(tt.prefixes...) + if len(list) != len(tt.want) { + t.Fatalf("got len %d, want %d", len(list), len(tt.want)) + } + for i, w := range tt.want { + pathEqualsTo(t, w, list[i]) + } + }) + } +} + +func TestPath_FollowSymLink(t *testing.T) { + tests := []struct { + name string + parts []string + entry string + wantIsDir bool + }{ + { + name: "symlink-to-folder", + parts: nil, + entry: "symlinktofolder", + wantIsDir: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + dir := makeTestPath(tt.parts) + files, err := dir.ReadDir() + if err != nil { + t.Fatal(err) + } + var match *Path + for _, file := range files { + if file.Base() == tt.entry { + match = file + break + } + } + if match == nil { + t.Fatalf("%s not found under %s", tt.entry, dir) + } + if err := match.FollowSymLink(); err != nil { + t.Fatal(err) + } + isDir, err := match.IsDirCheck() + if err != nil { + t.Fatal(err) + } + if isDir != tt.wantIsDir { + t.Errorf("IsDirCheck() = %v, want %v", isDir, tt.wantIsDir) + } + }) + } +} + +func TestPath_IsInsideDir(t *testing.T) { + tests := []struct { + name string + a *Path + b *Path + want bool + }{ + { + name: "abs-self", + a: New("/a/b/c"), + b: New("/a/b/c"), + want: false, + }, + { + name: "abs-parent-inside-child", + a: New("/a/b/c"), + b: New("/a/b/c/d"), + want: false, + }, + { + name: "abs-child-inside-parent", + a: New("/a/b/c/d"), + b: New("/a/b/c"), + want: true, + }, + { + name: "abs-deep-parent-inside-child", + a: New("/a/b/c"), + b: New("/a/b/c/d/e"), + want: false, + }, + { + name: "abs-deep-child-inside-parent", + a: New("/a/b/c/d/e"), + b: New("/a/b/c"), + want: true, + }, + + { + name: "rel-self", + a: New("a/b/c"), + b: New("a/b/c"), + want: false, + }, + { + name: "rel-parent-inside-child", + a: New("a/b/c"), + b: New("a/b/c/d"), + want: false, + }, + { + name: "rel-child-inside-parent", + a: New("a/b/c/d"), + b: New("a/b/c"), + want: true, + }, + { + name: "rel-deep-parent-inside-child", + a: New("a/b/c"), + b: New("a/b/c/d/e"), + want: false, + }, + { + name: "rel-deep-child-inside-parent", + a: New("a/b/c/d/e"), + b: New("a/b/c"), + want: true, + }, + { + name: "rel-normalized-inside", + a: New("f/../a/b/c/d/e"), + b: New("a/b/c"), + want: true, + }, + { + name: "rel-parent-not-inside-normalized", + a: New("a/b/c"), + b: New("f/../a/b/c/d/e"), + want: false, + }, + { + name: "rel-trailing-dotdot-inside", + a: New("a/b/c/d/e/f/.."), + b: New("a/b/c"), + want: true, + }, + { + name: "rel-parent-not-inside-trailing-dotdot", + a: New("a/b/c"), + b: New("a/b/c/d/e/f/.."), + want: false, + }, + + { + name: "unrelated-1", + a: New("/home/megabug/a15/packages"), + b: New("/home/megabug/aide/arduino-1.8.6/hardware/arduino/avr"), + want: false, + }, + { + name: "unrelated-2", + a: New("/home/megabug/aide/arduino-1.8.6/hardware/arduino/avr"), + b: New("/home/megabug/a15/packages"), + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + isInside, err := tt.a.IsInsideDir(tt.b) + if err != nil { + t.Fatal(err) + } + if isInside != tt.want { + t.Errorf("%s IsInsideDir(%s) = %v, want %v", tt.a, tt.b, isInside, tt.want) + } + }) + } +} + +func TestPath_ReadFileAsLines(t *testing.T) { + tests := []struct { + name string + path []string + want []string + }{ + { + name: "anotherFile", + path: []string{"fileset", "anotherFile"}, + want: []string{"line 1", "line 2", "", "line 3"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := New(testdataRoot) + for _, part := range tt.path { + p = p.Join(part) + } + lines, err := p.ReadFileAsLines() + if err != nil { + t.Fatal(err) + } + if len(lines) != len(tt.want) { + t.Fatalf("got len %d, want %d", len(lines), len(tt.want)) + } + for i, want := range tt.want { + if lines[i] != want { + t.Errorf("line[%d]: got %v, want %v", i, lines[i], want) + } + } + }) + } +} + +func TestPath_CanonicalTempDir(t *testing.T) { + tests := []struct { + name string + }{ + { + name: "tempdir-canonical", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if TempDir().String() != TempDir().Canonical().String() { + t.Errorf("got %v, want %v", TempDir().Canonical().String(), TempDir().String()) + } + }) + } +} + +func TestCopyDir(t *testing.T) { + tests := []struct { + name string + }{ + { + name: "copy-fileset", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tmp, err := MkTempDir("", "") + if err != nil { + t.Fatal(err) + } + defer tmp.RemoveAll() + + src := New(testdataRoot, "fileset") + if err := src.CopyDirTo(tmp.Join("dest")); err != nil { + t.Fatalf("copying dir: %v", err) + } + + exist, err := tmp.Join("dest", "folder", "subfolder", "file4").ExistCheck() + if !exist { + t.Error("expected true") + } + if err != nil { + t.Fatal(err) + } + + isdir, err := tmp.Join("dest", "folder", "subfolder", "file4").IsDirCheck() + if isdir { + t.Error("expected false") + } + if err != nil { + t.Fatal(err) + } + + if err := src.CopyDirTo(tmp.Join("dest")); err == nil { + t.Fatal("copying dir to already existing") + } + + if err := src.Join("file").CopyDirTo(tmp.Join("dest2")); err == nil { + t.Fatal("copying file as dir") + } + }) + } +} + +func TestPath_Parents(t *testing.T) { + tests := []struct { + name string + in string + want []string + }{ + { + name: "absolute", + in: "/a/very/long/path", + want: []string{"/a/very/long/path", "/a/very/long", "/a/very", "/a", "/"}, + }, + { + name: "relative", + in: "a/very/relative/path", + want: []string{"a/very/relative/path", "a/very/relative", "a/very", "a", "."}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + parents := New(tt.in).Parents() + if len(parents) != len(tt.want) { + t.Fatalf("got len %d, want %d", len(parents), len(tt.want)) + } + for i, want := range tt.want { + pathEqualsTo(t, want, parents[i]) + } + }) + } +} + +func TestPathList_FilterDirs(t *testing.T) { + tests := []struct { + name string + parts []string + wantBefore []string + wantAfter []string + }{ + { + name: "fileset", + parts: nil, + wantBefore: []string{ + testdataRoot + "/fileset/anotherFile", + testdataRoot + "/fileset/file", + testdataRoot + "/fileset/folder", + testdataRoot + "/fileset/symlinktofolder", + testdataRoot + "/fileset/test.txt", + testdataRoot + "/fileset/test.txt.gz", + }, + wantAfter: []string{ + testdataRoot + "/fileset/folder", + testdataRoot + "/fileset/symlinktofolder", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := makeTestPath(tt.parts) + list, err := p.ReadDir() + if err != nil { + t.Fatal(err) + } + if len(list) != len(tt.wantBefore) { + t.Fatalf("got len %d, want %d", len(list), len(tt.wantBefore)) + } + for i, want := range tt.wantBefore { + pathEqualsTo(t, want, list[i]) + } + list.FilterDirs() + if len(list) != len(tt.wantAfter) { + t.Fatalf("got len %d, want %d", len(list), len(tt.wantAfter)) + } + for i, want := range tt.wantAfter { + pathEqualsTo(t, want, list[i]) + } + }) + } +} + +func TestPathList_FilterOutDirs(t *testing.T) { + tests := []struct { + name string + readFn func() (PathList, error) + wantBefore []string + wantAfter []string + }{ + { + name: "fileset", + readFn: func() (PathList, error) { + return New(testdataRoot, "fileset").ReadDir() + }, + wantBefore: []string{ + testdataRoot + "/fileset/anotherFile", + testdataRoot + "/fileset/file", + testdataRoot + "/fileset/folder", + testdataRoot + "/fileset/symlinktofolder", + testdataRoot + "/fileset/test.txt", + testdataRoot + "/fileset/test.txt.gz", + }, + wantAfter: []string{ + testdataRoot + "/fileset/anotherFile", + testdataRoot + "/fileset/file", + testdataRoot + "/fileset/test.txt", + testdataRoot + "/fileset/test.txt.gz", + }, + }, + { + name: "broken_symlink-dir_1", + readFn: func() (PathList, error) { + return New(testdataRoot, "broken_symlink", "dir_1").ReadDirRecursive() + }, + wantBefore: []string{ + testdataRoot + "/broken_symlink/dir_1/broken_link", + testdataRoot + "/broken_symlink/dir_1/file2", + testdataRoot + "/broken_symlink/dir_1/linked_dir", + testdataRoot + "/broken_symlink/dir_1/linked_dir/file1", + testdataRoot + "/broken_symlink/dir_1/linked_file", + testdataRoot + "/broken_symlink/dir_1/real_dir", + testdataRoot + "/broken_symlink/dir_1/real_dir/file1", + }, + wantAfter: []string{ + testdataRoot + "/broken_symlink/dir_1/broken_link", + testdataRoot + "/broken_symlink/dir_1/file2", + testdataRoot + "/broken_symlink/dir_1/linked_dir/file1", + testdataRoot + "/broken_symlink/dir_1/linked_file", + testdataRoot + "/broken_symlink/dir_1/real_dir/file1", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + list, err := tt.readFn() + if err != nil { + t.Fatal(err) + } + if len(list) != len(tt.wantBefore) { + t.Fatalf("got len %d, want %d", len(list), len(tt.wantBefore)) + } + for i, want := range tt.wantBefore { + pathEqualsTo(t, want, list[i]) + } + list.FilterOutDirs() + if len(list) != len(tt.wantAfter) { + t.Fatalf("got len %d, want %d", len(list), len(tt.wantAfter)) + } + for i, want := range tt.wantAfter { + pathEqualsTo(t, want, list[i]) + } + }) + } +} + +func TestPath_EquivalentTo(t *testing.T) { + wd, err := Getwd() + if err != nil { + t.Fatal(err) + } + tests := []struct { + name string + a *Path + b *Path + want bool + }{ + { + name: "redundant-parent", + a: New("file1"), + b: New("file1", "somethingelse", ".."), + want: true, + }, + { + name: "redundant-nested", + a: New("file1", "abc"), + b: New("file1", "abc", "def", ".."), + want: true, + }, + { + name: "abs-vs-relative", + a: wd.Join("file1"), + b: New("file1"), + want: true, + }, + { + name: "abs-vs-normalized-relative", + a: wd.Join("file1"), + b: New("file1", "abc", ".."), + want: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.a.EquivalentTo(tt.b); got != tt.want { + t.Errorf("EquivalentTo: got %v, want %v", got, tt.want) + } + }) + } +} + +func TestCanonicalize(t *testing.T) { + wd, err := Getwd() + if err != nil { + t.Fatal(err) + } + + tests := []struct { + name string + in *Path + want string + }{ + { + name: "existing-file", + in: New(testdataRoot, "fileset", "anotherFile"), + want: wd.Join(testdataRoot, "fileset", "anotherFile").String(), + }, + { + name: "nonexistent-file", + in: New(testdataRoot, "fileset", "nonexistentFile"), + want: wd.Join(testdataRoot, "fileset", "nonexistentFile").String(), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := tt.in.Canonical() + if got.String() != tt.want { + t.Errorf("got %v, want %v", got.String(), tt.want) + } + }) + } +} + +func TestPath_RelTo(t *testing.T) { + tests := []struct { + name string + a *Path + b *Path + want string + wantErr bool + }{ + { + name: "descendant-to-ancestor", + a: New("/my/abs/path/123/456"), + b: New("/my/abs/path"), + want: "../..", + }, + { + name: "ancestor-to-descendant", + a: New("/my/abs/path"), + b: New("/my/abs/path/123/456"), + want: "123/456", + }, + { + name: "relative-mismatch", + a: New("my/path"), + b: New("/other/path"), + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + res, err := tt.a.RelTo(tt.b) + if (err != nil) != tt.wantErr { + t.Fatalf("RelTo() err = %v, wantErr %v", err, tt.wantErr) + } + if tt.wantErr { + if res != nil { + t.Errorf("expected nil, got %v", res) + } + return + } + pathEqualsTo(t, tt.want, res) + }) + } +} + +func TestPath_RelFrom(t *testing.T) { + tests := []struct { + name string + a *Path + b *Path + want string + wantErr bool + }{ + { + name: "descendant-from-ancestor", + a: New("/my/abs/path/123/456"), + b: New("/my/abs/path"), + want: "123/456", + }, + { + name: "ancestor-from-descendant", + a: New("/my/abs/path"), + b: New("/my/abs/path/123/456"), + want: "../..", + }, + { + name: "relative-mismatch", + a: New("my/path"), + b: New("/other/path"), + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + res, err := tt.a.RelFrom(tt.b) + if (err != nil) != tt.wantErr { + t.Fatalf("RelFrom() err = %v, wantErr %v", err, tt.wantErr) + } + if tt.wantErr { + if res != nil { + t.Errorf("expected nil, got %v", res) + } + return + } + pathEqualsTo(t, tt.want, res) + }) + } +} + +func TestWriteToTempFile(t *testing.T) { + tests := []struct { + name string + prefix string + data []byte + }{ + { + name: "prefix-test", + prefix: "prefix", + data: []byte("test"), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tmpDir := New(testdataRoot, "fileset", "tmp") + if err := tmpDir.MkdirAll(); err != nil { + t.Fatal(err) + } + defer tmpDir.RemoveAll() + + tmp, err := WriteToTempFile(tt.data, tmpDir, tt.prefix) + if err != nil { + t.Fatal(err) + } + defer tmp.Remove() + + if !strings.HasPrefix(tmp.Base(), tt.prefix) { + t.Errorf("base %q does not have prefix %q", tmp.Base(), tt.prefix) + } + isInside, err := tmp.IsInsideDir(tmpDir) + if err != nil { + t.Fatal(err) + } + if !isInside { + t.Error("expected true") + } + data, err := tmp.ReadFile() + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(data, tt.data) { + t.Errorf("got %v, want %v", data, tt.data) + } + }) + } +} + +func TestCopyToSamePath(t *testing.T) { + tests := []struct { + name string + content []byte + }{ + { + name: "same-file", + content: []byte("hello"), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tmpDir := New(t.TempDir()) + srcFile := tmpDir.Join("test_file") + dstFile := srcFile + + if err := srcFile.WriteFile(tt.content); err != nil { + t.Fatal(err) + } + content, err := srcFile.ReadFile() + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(content, tt.content) { + t.Errorf("got %v, want %v", content, tt.content) + } + + err = srcFile.CopyTo(dstFile) + if err == nil { + t.Fatal("expected error") + } + if !strings.Contains(err.Error(), "are the same file") { + t.Errorf("%q does not contain %q", err.Error(), "are the same file") + } + }) + } +} diff --git a/pkg/paths/process.go b/pkg/paths/process.go index ebfe713435..20fad233e4 100644 --- a/pkg/paths/process.go +++ b/pkg/paths/process.go @@ -1,31 +1,7 @@ -// // This file is part of PathsHelper library. -// -// Copyright 2023 Arduino AG (http://www.arduino.cc/) -// -// PathsHelper library is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -// -// As a special exception, you may use this file as part of a free software -// library without restriction. Specifically, if other files instantiate -// templates or use macros or inline functions from this file, or you compile -// this file and link it with other files to produce an executable, this -// file does not by itself cause the resulting executable to be covered by -// the GNU General Public License. This exception does not however -// invalidate any other reasons why the executable file might be covered by -// the GNU General Public License. -// +// Copyright (C) 2018-2025 Arduino AG (http://www.arduino.cc/) +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only package paths @@ -55,8 +31,7 @@ func NewProcess(extraEnv []string, args ...string) (*Process, error) { cmd: exec.Command(args[0], args[1:]...), } p.cmd.Env = append(os.Environ(), extraEnv...) - tellCommandNotToSpawnShell(p.cmd) // windows specific - tellCommandToStartOnNewProcessGroup(p.cmd) // linux specific + tellCommandToStartOnNewProcessGroup(p.cmd) // linux and macosx specific // This is required because some tools detects if the program is running // from terminal by looking at the stdin/out bindings. @@ -65,12 +40,6 @@ func NewProcess(extraEnv []string, args ...string) (*Process, error) { return p, nil } -// TellCommandNotToSpawnShell avoids that the specified Cmd display a small -// command prompt while runnning on Windows. It has no effects on other OS. -func (p *Process) TellCommandNotToSpawnShell() { - tellCommandNotToSpawnShell(p.cmd) -} - // NewProcessFromPath creates a command from the provided executable path, // additional environment vars (in addition to the system default ones) // and command line arguments. @@ -86,10 +55,10 @@ func (p *Process) RedirectStdoutTo(out io.Writer) { p.cmd.Stdout = out } -// RedirectStderrTo will redirect the process' stdout to the specified +// RedirectStderrTo will redirect the process' stderr to the specified // writer. Any previous redirection will be overwritten. -func (p *Process) RedirectStderrTo(out io.Writer) { - p.cmd.Stderr = out +func (p *Process) RedirectStderrTo(err io.Writer) { + p.cmd.Stderr = err } // StdinPipe returns a pipe that will be connected to the command's standard @@ -138,6 +107,21 @@ func (p *Process) Wait() error { return p.cmd.Wait() } +// WaitWithinContext wait for the process to complete. If the given context is canceled +// before the normal process termination, the process is killed. +func (p *Process) WaitWithinContext(ctx context.Context) error { + completed := make(chan struct{}) + defer close(completed) + go func() { + select { + case <-ctx.Done(): + p.Kill() + case <-completed: + } + }() + return p.Wait() +} + // Signal sends a signal to the Process. Sending Interrupt on Windows is not implemented. func (p *Process) Signal(sig os.Signal) error { return p.cmd.Process.Signal(sig) @@ -188,16 +172,7 @@ func (p *Process) RunWithinContext(ctx context.Context) error { if err := p.Start(); err != nil { return err } - completed := make(chan struct{}) - defer close(completed) - go func() { - select { - case <-ctx.Done(): - p.Kill() - case <-completed: - } - }() - return p.Wait() + return p.WaitWithinContext(ctx) } // RunAndCaptureOutput starts the specified command and waits for it to complete. If the given context @@ -212,6 +187,17 @@ func (p *Process) RunAndCaptureOutput(ctx context.Context) ([]byte, []byte, erro return stdout.Bytes(), stderr.Bytes(), err } +// RunAndCaptureCombinedOutput starts the specified command and waits for it to complete. If the given context +// is canceled before the normal process termination, the process is killed. The standard output and +// standard error of the process are captured and returned combined at process termination. +func (p *Process) RunAndCaptureCombinedOutput(ctx context.Context) ([]byte, error) { + out := &bytes.Buffer{} + p.RedirectStdoutTo(out) + p.RedirectStderrTo(out) + err := p.RunWithinContext(ctx) + return out.Bytes(), err +} + // GetArgs returns the command arguments func (p *Process) GetArgs() []string { return p.cmd.Args diff --git a/pkg/paths/process_linux.go b/pkg/paths/process_linux.go index 5735a85c38..c56f8a025f 100644 --- a/pkg/paths/process_linux.go +++ b/pkg/paths/process_linux.go @@ -1,31 +1,7 @@ -// // This file is part of PathsHelper library. -// -// Copyright 2023 Arduino AG (http://www.arduino.cc/) -// -// PathsHelper library is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -// -// As a special exception, you may use this file as part of a free software -// library without restriction. Specifically, if other files instantiate -// templates or use macros or inline functions from this file, or you compile -// this file and link it with other files to produce an executable, this -// file does not by itself cause the resulting executable to be covered by -// the GNU General Public License. This exception does not however -// invalidate any other reasons why the executable file might be covered by -// the GNU General Public License. -// +// Copyright (C) 2018-2025 Arduino AG (http://www.arduino.cc/) +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only //go:build !windows @@ -36,10 +12,6 @@ import ( "syscall" ) -func tellCommandNotToSpawnShell(_ *exec.Cmd) { - // no op -} - func tellCommandToStartOnNewProcessGroup(oscmd *exec.Cmd) { // https://groups.google.com/g/golang-nuts/c/XoQ3RhFBJl8 diff --git a/pkg/paths/process_test.go b/pkg/paths/process_test.go new file mode 100644 index 0000000000..932dda84b1 --- /dev/null +++ b/pkg/paths/process_test.go @@ -0,0 +1,64 @@ +// This file is part of PathsHelper library. +// Copyright (C) 2018-2025 Arduino AG (http://www.arduino.cc/) +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package paths + +import ( + "context" + "runtime" + "testing" + "time" +) + +func TestProcess_RunWithinContext(t *testing.T) { + // Build `delay` helper inside testdata/delay + builder, err := NewProcess(nil, "go", "build") + if err != nil { + t.Fatal(err) + } + builder.SetDir(testdataRoot + "/delay") + if err := builder.Run(); err != nil { + t.Fatal(err) + } + + // Run delay and test if the process is terminated correctly due to context + process, err := NewProcess(nil, testdataRoot+"/delay/delay") + if err != nil { + t.Fatal(err) + } + start := time.Now() + ctx, cancel := context.WithTimeout(context.Background(), 250*time.Millisecond) + err = process.RunWithinContext(ctx) + if err == nil { + t.Fatal("expected error") + } + if elapsed := time.Since(start); elapsed >= 500*time.Millisecond { + t.Errorf("%v not less than %v", elapsed, 500*time.Millisecond) + } + cancel() +} + +func TestProcess_KillProcessGroupOnLinux(t *testing.T) { + if runtime.GOOS != "linux" { + t.Skip("skipping test on non-linux system") + } + + p, err := NewProcess(nil, "bash", "-c", "sleep 5 ; echo -n 5") + if err != nil { + t.Fatal(err) + } + start := time.Now() + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + + _, _, err = p.RunAndCaptureOutput(ctx) + if err == nil || err.Error() != "signal: killed" { + t.Fatalf("got %v, want signal: killed", err) + } + // Assert that the process was killed within the timeout + if elapsed := time.Since(start); elapsed >= 2*time.Second { + t.Errorf("%v not less than %v", elapsed, 2*time.Second) + } +} diff --git a/pkg/paths/readdir.go b/pkg/paths/readdir.go index 985fed5464..d4ff88fe67 100644 --- a/pkg/paths/readdir.go +++ b/pkg/paths/readdir.go @@ -1,31 +1,7 @@ -/* - * This file is part of PathsHelper library. - * - * Copyright 2018-2022 Arduino AG (http://www.arduino.cc/) - * - * PathsHelper library is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * As a special exception, you may use this file as part of a free software - * library without restriction. Specifically, if other files instantiate - * templates or use macros or inline functions from this file, or you compile - * this file and link it with other files to produce an executable, this - * file does not by itself cause the resulting executable to be covered by - * the GNU General Public License. This exception does not however - * invalidate any other reasons why the executable file might be covered by - * the GNU General Public License. - */ +// This file is part of PathsHelper library. +// Copyright (C) 2018-2025 Arduino AG (http://www.arduino.cc/) +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only package paths diff --git a/pkg/paths/readdir_test.go b/pkg/paths/readdir_test.go new file mode 100644 index 0000000000..ee467d1331 --- /dev/null +++ b/pkg/paths/readdir_test.go @@ -0,0 +1,458 @@ +// This file is part of PathsHelper library. +// Copyright (C) 2018-2025 Arduino AG (http://www.arduino.cc/) +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package paths + +import ( + "fmt" + "io/fs" + "os" + "testing" + "time" +) + +// filesetAll is the expected full list of entries in `fileset` when read recursively and sorted. +var filesetAll = []string{ + testdataRoot + "/fileset/anotherFile", + testdataRoot + "/fileset/file", + testdataRoot + "/fileset/folder", + testdataRoot + "/fileset/folder/.hidden", + testdataRoot + "/fileset/folder/file2", + testdataRoot + "/fileset/folder/file3", + testdataRoot + "/fileset/folder/subfolder", + testdataRoot + "/fileset/folder/subfolder/file4", + testdataRoot + "/fileset/symlinktofolder", + testdataRoot + "/fileset/symlinktofolder/.hidden", + testdataRoot + "/fileset/symlinktofolder/file2", + testdataRoot + "/fileset/symlinktofolder/file3", + testdataRoot + "/fileset/symlinktofolder/subfolder", + testdataRoot + "/fileset/symlinktofolder/subfolder/file4", + testdataRoot + "/fileset/test.txt", + testdataRoot + "/fileset/test.txt.gz", +} + +func TestPath_ReadDirRecursive(t *testing.T) { + tests := []struct { + name string + parts []string + want []string + }{ + {name: "fileset", parts: []string{"fileset"}, want: filesetAll}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := New(testdataRoot) + for _, part := range tt.parts { + p = p.Join(part) + } + list, err := p.ReadDirRecursive() + if err != nil { + t.Fatal(err) + } + if len(list) != len(tt.want) { + t.Fatalf("got len %d, want %d", len(list), len(tt.want)) + } + for i, want := range tt.want { + pathEqualsTo(t, want, list[i]) + } + }) + } +} + +func TestReadDirRecursiveSymLinkLoop(t *testing.T) { + tests := []struct { + name string + fn func(tmp *Path) (PathList, error) + }{ + { + name: "ReadDirRecursive", + fn: func(tmp *Path) (PathList, error) { return tmp.ReadDirRecursive() }, + }, + { + name: "ReadDirRecursiveFiltered", + fn: func(tmp *Path) (PathList, error) { return tmp.ReadDirRecursiveFiltered(nil) }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tmp, err := MkTempDir("", "") + if err != nil { + t.Fatal(err) + } + defer tmp.RemoveAll() + + folder := tmp.Join("folder") + if err := os.Symlink(tmp.String(), folder.String()); err != nil { + t.Fatal(err) + } + + l, err := tt.fn(tmp) + if err == nil { + t.Fatal("expected error") + } + fmt.Println(err) + if l != nil { + t.Errorf("expected nil, got %v", l) + } + }) + } +} + +func TestPath_ReadDirFiltered(t *testing.T) { + tests := []struct { + name string + filters []ReadDirFilter + want []string + }{ + { + name: "no-filter", + filters: nil, + want: []string{ + testdataRoot + "/fileset/folder/.hidden", + testdataRoot + "/fileset/folder/file2", + testdataRoot + "/fileset/folder/file3", + testdataRoot + "/fileset/folder/subfolder", + }, + }, + { + name: "only-directories", + filters: []ReadDirFilter{FilterDirectories()}, + want: []string{ + testdataRoot + "/fileset/folder/subfolder", + }, + }, + { + name: "filter-out-file-prefix", + filters: []ReadDirFilter{FilterOutPrefixes("file")}, + want: []string{ + testdataRoot + "/fileset/folder/.hidden", + testdataRoot + "/fileset/folder/subfolder", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + folderPath := New(testdataRoot + "/fileset/folder") + list, err := folderPath.ReadDir(tt.filters...) + if err != nil { + t.Fatal(err) + } + if len(list) != len(tt.want) { + t.Fatalf("got len %d, want %d", len(list), len(tt.want)) + } + for i, want := range tt.want { + pathEqualsTo(t, want, list[i]) + } + }) + } +} + +func TestPath_ReadDirRecursiveFiltered(t *testing.T) { + tests := []struct { + name string + recurseFiltr ReadDirFilter + filters []ReadDirFilter + want []string + }{ + { + name: "no-filters", + recurseFiltr: nil, + filters: nil, + want: filesetAll, + }, + { + name: "recurse-only-filter-out-dirs", + recurseFiltr: FilterOutDirectories(), + filters: nil, + want: []string{ + testdataRoot + "/fileset/anotherFile", + testdataRoot + "/fileset/file", + testdataRoot + "/fileset/folder", // <- listed but not traversed + testdataRoot + "/fileset/symlinktofolder", // <- listed but not traversed + testdataRoot + "/fileset/test.txt", + testdataRoot + "/fileset/test.txt.gz", + }, + }, + { + name: "recurse-nil-filter-out-dirs", + recurseFiltr: nil, + filters: []ReadDirFilter{FilterOutDirectories()}, + want: []string{ + testdataRoot + "/fileset/anotherFile", + testdataRoot + "/fileset/file", + testdataRoot + "/fileset/folder/.hidden", + testdataRoot + "/fileset/folder/file2", + testdataRoot + "/fileset/folder/file3", + testdataRoot + "/fileset/folder/subfolder/file4", + testdataRoot + "/fileset/symlinktofolder/.hidden", + testdataRoot + "/fileset/symlinktofolder/file2", + testdataRoot + "/fileset/symlinktofolder/file3", + testdataRoot + "/fileset/symlinktofolder/subfolder/file4", + testdataRoot + "/fileset/test.txt", + testdataRoot + "/fileset/test.txt.gz", + }, + }, + { + name: "both-filter-out-dirs", + recurseFiltr: FilterOutDirectories(), + filters: []ReadDirFilter{FilterOutDirectories()}, + want: []string{ + testdataRoot + "/fileset/anotherFile", + testdataRoot + "/fileset/file", + testdataRoot + "/fileset/test.txt", + testdataRoot + "/fileset/test.txt.gz", + }, + }, + { + name: "recurse-filter-sub-filter-suffix-3", + recurseFiltr: FilterOutPrefixes("sub"), + filters: []ReadDirFilter{FilterOutSuffixes("3")}, + want: []string{ + testdataRoot + "/fileset/anotherFile", + testdataRoot + "/fileset/file", + testdataRoot + "/fileset/folder", + testdataRoot + "/fileset/folder/.hidden", + testdataRoot + "/fileset/folder/file2", + testdataRoot + "/fileset/folder/subfolder", // <- subfolder skipped by Prefix("sub") + testdataRoot + "/fileset/symlinktofolder", + testdataRoot + "/fileset/symlinktofolder/.hidden", + testdataRoot + "/fileset/symlinktofolder/file2", + testdataRoot + "/fileset/symlinktofolder/subfolder", // <- subfolder skipped by Prefix("sub") + testdataRoot + "/fileset/test.txt", + testdataRoot + "/fileset/test.txt.gz", + }, + }, + { + name: "recurse-sub-and-filter-suffix3-prefix-fil", + recurseFiltr: FilterOutPrefixes("sub"), + filters: []ReadDirFilter{ + AndFilter(FilterOutSuffixes("3"), FilterOutPrefixes("fil")), + }, + want: []string{ + testdataRoot + "/fileset/anotherFile", + testdataRoot + "/fileset/folder", + testdataRoot + "/fileset/folder/.hidden", + testdataRoot + "/fileset/folder/subfolder", + testdataRoot + "/fileset/symlinktofolder", + testdataRoot + "/fileset/symlinktofolder/.hidden", + testdataRoot + "/fileset/symlinktofolder/subfolder", + testdataRoot + "/fileset/test.txt", + testdataRoot + "/fileset/test.txt.gz", + }, + }, + { + name: "recurse-sub-and-filter-suffix3-prefix-fil-suffix-gz", + recurseFiltr: FilterOutPrefixes("sub"), + filters: []ReadDirFilter{ + AndFilter(FilterOutSuffixes("3"), FilterOutPrefixes("fil"), FilterOutSuffixes(".gz")), + }, + want: []string{ + testdataRoot + "/fileset/anotherFile", + testdataRoot + "/fileset/folder", + testdataRoot + "/fileset/folder/.hidden", + testdataRoot + "/fileset/folder/subfolder", + testdataRoot + "/fileset/symlinktofolder", + testdataRoot + "/fileset/symlinktofolder/.hidden", + testdataRoot + "/fileset/symlinktofolder/subfolder", + testdataRoot + "/fileset/test.txt", + }, + }, + { + name: "or-filter-prefix-sub-or-suffix-tofolder", + recurseFiltr: OrFilter(FilterPrefixes("sub"), FilterSuffixes("tofolder")), + filters: nil, + want: []string{ + testdataRoot + "/fileset/anotherFile", + testdataRoot + "/fileset/file", + testdataRoot + "/fileset/folder", + testdataRoot + "/fileset/symlinktofolder", + testdataRoot + "/fileset/symlinktofolder/.hidden", + testdataRoot + "/fileset/symlinktofolder/file2", + testdataRoot + "/fileset/symlinktofolder/file3", + testdataRoot + "/fileset/symlinktofolder/subfolder", + testdataRoot + "/fileset/symlinktofolder/subfolder/file4", + testdataRoot + "/fileset/test.txt", + testdataRoot + "/fileset/test.txt.gz", + }, + }, + { + name: "filter-names-folder", + recurseFiltr: nil, + filters: []ReadDirFilter{FilterNames("folder")}, + want: []string{ + testdataRoot + "/fileset/folder", + }, + }, + { + name: "recurse-symlinktofolder-filter-out-hidden", + recurseFiltr: FilterNames("symlinktofolder"), + filters: []ReadDirFilter{FilterOutNames(".hidden")}, + want: []string{ + testdataRoot + "/fileset/anotherFile", + testdataRoot + "/fileset/file", + testdataRoot + "/fileset/folder", + testdataRoot + "/fileset/symlinktofolder", + testdataRoot + "/fileset/symlinktofolder/file2", + testdataRoot + "/fileset/symlinktofolder/file3", + testdataRoot + "/fileset/symlinktofolder/subfolder", + testdataRoot + "/fileset/test.txt", + testdataRoot + "/fileset/test.txt.gz", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + testdata := New(testdataRoot, "fileset") + l, err := testdata.ReadDirRecursiveFiltered(tt.recurseFiltr, tt.filters...) + if err != nil { + t.Fatal(err) + } + l.Sort() + if len(l) != len(tt.want) { + t.Fatalf("got len %d, want %d", len(l), len(tt.want)) + } + for i, want := range tt.want { + pathEqualsTo(t, want, l[i]) + } + }) + } +} + +func TestPath_ReadDirRecursiveLoopDetection(t *testing.T) { + loopsPath := New(testdataRoot, "loops") + unbuondedReaddir := func(testdir string) (PathList, error) { + var files PathList + var err error + done := make(chan bool) + go func() { + files, err = loopsPath.Join(testdir).ReadDirRecursive() + done <- true + }() + deadline := time.After(5 * time.Second) + tick := time.NewTicker(10 * time.Millisecond) + defer tick.Stop() + finished := false + for !finished { + select { + case <-done: + finished = true + case <-deadline: + t.Fatalf("Infinite symlink loop while loading sketch") + case <-tick.C: + } + } + return files, err + } + + loopTests := []struct { + name string + dir string + }{ + {name: "loop_1", dir: "loop_1"}, + {name: "loop_2", dir: "loop_2"}, + {name: "loop_3", dir: "loop_3"}, + {name: "loop_4", dir: "loop_4"}, + } + for _, tt := range loopTests { + t.Run(tt.name, func(t *testing.T) { + l, err := unbuondedReaddir(tt.dir) + if err == nil || err.Error() != "directories symlink loop detected" { + t.Fatalf("loop not detected in %s: got %v, want directories symlink loop detected", tt.dir, err) + } + if l != nil { + t.Errorf("expected nil, got %v", l) + } + }) + } + + regularTests := []struct { + name string + dir string + want []string + }{ + { + name: "regular_1", + dir: "regular_1", + want: []string{ + testdataRoot + "/loops/regular_1/dir1", + testdataRoot + "/loops/regular_1/dir1/file1", + testdataRoot + "/loops/regular_1/dir2", + testdataRoot + "/loops/regular_1/dir2/file1", + }, + }, + { + name: "regular_2", + dir: "regular_2", + want: []string{ + testdataRoot + "/loops/regular_2/dir1", + testdataRoot + "/loops/regular_2/dir1/file1", + testdataRoot + "/loops/regular_2/dir2", + testdataRoot + "/loops/regular_2/dir2/dir1", + testdataRoot + "/loops/regular_2/dir2/dir1/file1", + testdataRoot + "/loops/regular_2/dir2/file2", + }, + }, + { + name: "regular_3", + dir: "regular_3", + want: []string{ + testdataRoot + "/loops/regular_3/dir1", + testdataRoot + "/loops/regular_3/dir1/file1", + testdataRoot + "/loops/regular_3/dir2", + testdataRoot + "/loops/regular_3/dir2/dir1", + testdataRoot + "/loops/regular_3/dir2/dir1/file1", + testdataRoot + "/loops/regular_3/dir2/file2", + testdataRoot + "/loops/regular_3/link", // broken symlink reported in files + }, + }, + } + for _, tt := range regularTests { + t.Run(tt.name, func(t *testing.T) { + l, err := unbuondedReaddir(tt.dir) + if err != nil { + t.Fatal(err) + } + if len(l) != len(tt.want) { + t.Fatalf("got len %d, want %d", len(l), len(tt.want)) + } + l.Sort() + for i, want := range tt.want { + pathEqualsTo(t, want, l[i]) + } + }) + } + + t.Run("regular_4_with_permission_error", func(t *testing.T) { + dir1 := loopsPath.Join("regular_4_with_permission_error", "dir1") + + l, err := unbuondedReaddir("regular_4_with_permission_error") + if err != nil { + t.Fatal(err) + } + if len(l) == 0 { + t.Error("expected non-empty list") + } + + dir1Stat, err := dir1.Stat() + if err != nil { + t.Fatal(err) + } + if err := dir1.Chmod(fs.FileMode(0)); err != nil { + t.Fatal(err) + } + t.Cleanup(func() { + dir1.Chmod(dir1Stat.Mode()) + }) + + l, err = unbuondedReaddir("regular_4_with_permission_error") + if err == nil { + t.Fatal("expected error") + } + if l != nil { + t.Errorf("expected nil, got %v", l) + } + }) + +} diff --git a/pkg/prebuild/builder/abi.go b/pkg/prebuild/builder/abi.go deleted file mode 100644 index 818edbb76e..0000000000 --- a/pkg/prebuild/builder/abi.go +++ /dev/null @@ -1,35 +0,0 @@ -// apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol -// SPDX-License-Identifier: GPL-2.0-only - -package builder - -import ( - "github.com/roddhjav/apparmor.d/pkg/prebuild" - "github.com/roddhjav/apparmor.d/pkg/util" -) - -var ( - regAbi4To3 = util.ToRegexRepl([]string{ - `abi/4.0`, `abi/3.0`, - ` userns,`, ` # userns,`, - ` mqueue`, ` # mqueue`, - }) -) - -type ABI3 struct { - prebuild.Base -} - -func init() { - RegisterBuilder(&ABI3{ - Base: prebuild.Base{ - Keyword: "abi3", - Msg: "Convert all profiles from abi 4.0 to abi 3.0", - }, - }) -} - -func (b ABI3) Apply(opt *Option, profile string) (string, error) { - return regAbi4To3.Replace(profile), nil -} diff --git a/pkg/prebuild/builder/attach.go b/pkg/prebuild/builder/attach.go deleted file mode 100644 index f7f0c9bed8..0000000000 --- a/pkg/prebuild/builder/attach.go +++ /dev/null @@ -1,55 +0,0 @@ -// apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol -// SPDX-License-Identifier: GPL-2.0-only - -package builder - -import ( - "strings" - - "github.com/roddhjav/apparmor.d/pkg/prebuild" -) - -type ReAttach struct { - prebuild.Base -} - -func init() { - RegisterBuilder(&ReAttach{ - Base: prebuild.Base{ - Keyword: "attach", - Msg: "Re-attach disconnected path", - }, - }) -} - -// Apply will re-attach the disconnected path -// - Add the attach_disconnected.path flag on all frofile with the attach_disconnected flag -// - Replace the base abstraction by attached/base -// - Replace the consoles abstraction by attached/consoles -// - For compatibility, non disconnected profile will have the @{att} variable set to / -func (b ReAttach) Apply(opt *Option, profile string) (string, error) { - var insert string - var origin = "profile " + opt.Name - - if strings.Contains(profile, "attach_disconnected") { - insert = "@{att} = /att/" + opt.Name + "/\n" - profile = strings.ReplaceAll(profile, - "attach_disconnected", - "attach_disconnected,attach_disconnected.path=@{att}", - ) - profile = strings.ReplaceAll(profile, - "include ", - "include ", - ) - profile = strings.ReplaceAll(profile, - "include ", - "include ", - ) - - } else { - insert = "@{att} = /\n" - } - - return strings.Replace(profile, origin, insert+origin, 1), nil -} diff --git a/pkg/prebuild/builder/complain.go b/pkg/prebuild/builder/complain.go deleted file mode 100644 index dbd9b3478e..0000000000 --- a/pkg/prebuild/builder/complain.go +++ /dev/null @@ -1,48 +0,0 @@ -// apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol -// SPDX-License-Identifier: GPL-2.0-only - -package builder - -import ( - "regexp" - "slices" - "strings" - - "github.com/roddhjav/apparmor.d/pkg/prebuild" -) - -var ( - regFlags = regexp.MustCompile(`flags=\(([^)]+)\)`) - regProfileHeader = regexp.MustCompile(` {\n`) -) - -type Complain struct { - prebuild.Base -} - -func init() { - RegisterBuilder(&Complain{ - Base: prebuild.Base{ - Keyword: "complain", - Msg: "Set complain flag on all profiles", - }, - }) -} - -func (b Complain) Apply(opt *Option, profile string) (string, error) { - flags := []string{} - matches := regFlags.FindStringSubmatch(profile) - if len(matches) != 0 { - flags = strings.Split(matches[1], ",") - if slices.Contains(flags, "complain") { - return profile, nil - } - } - flags = append(flags, "complain") - strFlags := " flags=(" + strings.Join(flags, ",") + ") {\n" - - // Remove all flags definition, then set manifest' flags - profile = regFlags.ReplaceAllLiteralString(profile, "") - return regProfileHeader.ReplaceAllLiteralString(profile, strFlags), nil -} diff --git a/pkg/prebuild/builder/core.go b/pkg/prebuild/builder/core.go deleted file mode 100644 index bfc1aa0256..0000000000 --- a/pkg/prebuild/builder/core.go +++ /dev/null @@ -1,66 +0,0 @@ -// apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol -// SPDX-License-Identifier: GPL-2.0-only - -package builder - -import ( - "fmt" - "strings" - - "github.com/roddhjav/apparmor.d/pkg/paths" - "github.com/roddhjav/apparmor.d/pkg/prebuild" -) - -var ( - // Build the profiles with the following directive applied - Builds = []Builder{} - - // Available builders - Builders = map[string]Builder{} -) - -// Builder main directive interface -type Builder interface { - prebuild.BaseInterface - Apply(opt *Option, profile string) (string, error) -} - -// Option for a builder -type Option struct { - Name string - File *paths.Path -} - -func NewOption(file *paths.Path) *Option { - return &Option{ - Name: strings.TrimSuffix(file.Base(), ".apparmor.d"), - File: file, - } -} - -func Register(names ...string) { - for _, name := range names { - if b, present := Builders[name]; present { - Builds = append(Builds, b) - } else { - panic(fmt.Sprintf("Unknown builder: %s", name)) - } - } -} - -func RegisterBuilder(d Builder) { - Builders[d.Name()] = d -} - -func Run(file *paths.Path, profile string) (string, error) { - var err error - opt := NewOption(file) - for _, b := range Builds { - profile, err = b.Apply(opt, profile) - if err != nil { - return "", fmt.Errorf("%s %s: %w", b.Name(), opt.File, err) - } - } - return profile, nil -} diff --git a/pkg/prebuild/builder/enforce.go b/pkg/prebuild/builder/enforce.go deleted file mode 100644 index a7ce90a7a8..0000000000 --- a/pkg/prebuild/builder/enforce.go +++ /dev/null @@ -1,47 +0,0 @@ -// apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol -// SPDX-License-Identifier: GPL-2.0-only - -package builder - -import ( - "slices" - "strings" - - "github.com/roddhjav/apparmor.d/pkg/prebuild" -) - -type Enforce struct { - prebuild.Base -} - -func init() { - RegisterBuilder(&Enforce{ - Base: prebuild.Base{ - Keyword: "enforce", - Msg: "All profiles have been enforced", - }, - }) -} - -func (b Enforce) Apply(opt *Option, profile string) (string, error) { - matches := regFlags.FindStringSubmatch(profile) - if len(matches) == 0 { - return profile, nil - } - - flags := strings.Split(matches[1], ",") - idx := slices.Index(flags, "complain") - if idx == -1 { - return profile, nil - } - flags = slices.Delete(flags, idx, idx+1) - strFlags := "{\n" - if len(flags) >= 1 { - strFlags = " flags=(" + strings.Join(flags, ",") + ") {\n" - } - - // Remove all flags definition, then set new flags - profile = regFlags.ReplaceAllLiteralString(profile, "") - return regProfileHeader.ReplaceAllLiteralString(profile, strFlags), nil -} diff --git a/pkg/prebuild/cli/cli.go b/pkg/prebuild/cli/cli.go index 779cd5c0c4..43410874ea 100644 --- a/pkg/prebuild/cli/cli.go +++ b/pkg/prebuild/cli/cli.go @@ -2,37 +2,46 @@ // Copyright (C) 2023-2024 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only +// Package cli provides the command line interface for prebuilding apparmor.d profiles. +// It is separated from the main package as it is also used by downstream projects. package cli import ( "flag" "fmt" - "strings" + "os" + "github.com/roddhjav/apparmor.d/pkg/builder" + "github.com/roddhjav/apparmor.d/pkg/configure" + "github.com/roddhjav/apparmor.d/pkg/directive" "github.com/roddhjav/apparmor.d/pkg/logging" "github.com/roddhjav/apparmor.d/pkg/paths" - "github.com/roddhjav/apparmor.d/pkg/prebuild" - "github.com/roddhjav/apparmor.d/pkg/prebuild/builder" - "github.com/roddhjav/apparmor.d/pkg/prebuild/directive" - "github.com/roddhjav/apparmor.d/pkg/prebuild/prepare" + "github.com/roddhjav/apparmor.d/pkg/runtime" + "github.com/roddhjav/apparmor.d/pkg/tasks" ) const ( - nilABI = 0 - nilVer = 0.0 - usage = `aa-prebuild [-h] [--complain | --enforce] [--full] [--abi 3|4] [--version V] [--file FILE] + nilABI = 0 + nilVer = 0.0 + nilBuild = "" + nilSrc = "" + usage = `aa-prebuild [-h] [--status] [--abi 3|4|5] [--version V] [--fsp] [--src DIR] [--buildir DIR] 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. - -v, --version V Target apparmor version. - -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. + -s, --status Show the status of enabled build tasks. + -a, --abi ABI Target apparmor ABI. + -v, --version V Target apparmor version. + -f, --fsp Configure AppArmor for full system policy and RBAC. + -S, --src DIR Profile source directory (default: apparmor.d/). + -b, --buildir DIR Destination root build directory (default: .build/). + --test Enable test mode. + --debug Enable debug mode. ` ) @@ -40,149 +49,168 @@ var ( help bool complain bool enforce bool - full bool + status bool + fsp bool + debug bool + test bool abi int version float64 - file string + src string + buildir string ) func init() { flag.BoolVar(&help, "h", false, "Show this help message and exit.") 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(&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.") flag.BoolVar(&enforce, "enforce", false, "Set enforce flag on all profiles.") + flag.BoolVar(&status, "s", false, "Show the status of enabled build tasks.") + flag.BoolVar(&status, "status", false, "Show the status of enabled build tasks.") + flag.BoolVar(&fsp, "f", false, "Configure AppArmor for full system policy and RBAC.") + flag.BoolVar(&fsp, "fsp", false, "Configure AppArmor for full system policy and RBAC.") flag.IntVar(&abi, "a", nilABI, "Target apparmor ABI.") flag.IntVar(&abi, "abi", nilABI, "Target apparmor ABI.") flag.Float64Var(&version, "v", nilVer, "Target apparmor version.") flag.Float64Var(&version, "version", nilVer, "Target apparmor version.") - flag.StringVar(&file, "F", "", "Only prebuild a given file.") - flag.StringVar(&file, "file", "", "Only prebuild a given file.") + flag.StringVar(&src, "S", nilSrc, "Profile source directory.") + flag.StringVar(&src, "src", nilSrc, "Profile source directory.") + flag.StringVar(&buildir, "b", nilBuild, "Destination root build directory.") + flag.StringVar(&buildir, "buildir", nilBuild, "Destination root build directory.") + flag.BoolVar(&debug, "debug", false, "Enable debug mode.") + flag.BoolVar(&test, "test", false, "Enable test mode.") } -func Configure() { - flag.Usage = func() { - fmt.Printf("%s\n%s\n%s\n%s", usage, - prebuild.Help("Prepare", prepare.Tasks), - prebuild.Help("Build", builder.Builders), - directive.Usage(), - ) - } +// ParseFlags parses command line flags. Must be called before GetPrebuildRoot(). +func ParseFlags() { + flag.Usage = func() { fmt.Print(usage) } flag.Parse() if help { flag.Usage() - return + os.Exit(0) } +} - if full && paths.New("apparmor.d/groups/_full").Exist() { - prepare.Register("fsp") - builder.Register("fsp") - } else if prebuild.SystemdDir.Exist() { - prepare.Register("systemd-early") +func GetPrebuildRoot() *paths.Path { + if buildir != nilBuild { + return paths.New(buildir) } + return paths.New(".build") +} + +func Configure(r *runtime.Runners) *runtime.Runners { + // Register all directives (always available) + r.Directives. + Register(directive.NewDbus()). + Register(directive.NewExec()). + Register(directive.NewFilterOnly()). + Register(directive.NewFilterExclude()). + Register(directive.NewStack()) if complain { - builder.Register("complain") + r.Builders.Add(builder.NewComplain()) + if debug { + r.Builders.Add(builder.NewDebug()) + } + r.Test = test } else if enforce { - builder.Register("enforce") + r.Builders.Add(builder.NewEnforce()) } + if fsp && paths.New("apparmor.d/groups/_full").Exist() { + r.Configures.Add(configure.NewFullSystemPolicy()) + r.Builders.Add(builder.NewFSP()) + r.RBAC = true + } + + // Set modes (complain, enforce...) as definied in dist/flags + r.Builders.Add(builder.NewProfileMode()) + if abi != nilABI { - prebuild.ABI = abi + r.ABI = abi } - switch prebuild.ABI { + switch r.ABI { case 3: - builder.Register("abi3") // Convert all profiles from abi 4.0 to abi 3.0 + r.Builders. + Add(builder.NewABI3()). // Convert all profiles from abi 4.0 to abi 3.0 + Add(builder.NewAPPARMOR40()) // Convert all profiles from apparmor 4.1 to 4.0 or less + case 4: - // builder.Register("attach") // Re-attach disconnected path + // priority support was added in 4.1 + if r.Version == 4.0 { + r.Builders.Add(builder.NewAPPARMOR40()) + } + + // Re-attach disconnected path + if tasks.Distribution == "ubuntu" && r.Version >= 4.1 { + // Ignored on ubuntu 25.04+ due to a memory leak that fully prevent + // profiles compilation with re-attached paths. + // See https://bugs.launchpad.net/ubuntu/+source/linux/+bug/2098730 + + // Use stacked-dbus builder to resolve dbus rules + r.Builders.Add(builder.NewStackedDbus()) + + } else { + if !r.DownStream { + r.Configures.Add(configure.NewAttach()) + } + r.Builders.Add(builder.NewAttach()) + } + + case 5: + r.Builders.Add(builder.NewABI5()) // Convert all profiles from abi 4.0 to abi 5.0 + + // Re-attach disconnected path + if tasks.Distribution == "ubuntu" { + // Ignored on ubuntu 25.04+ due to a memory leak that fully prevent + // profiles compilation with re-attached paths. + // See https://bugs.launchpad.net/ubuntu/+source/linux/+bug/2098730 + + // Use stacked-dbus builder to resolve dbus rules + r.Builders.Add(builder.NewStackedDbus()) + + } else { + if !r.DownStream { + r.Configures.Add(configure.NewAttach()) + } + r.Builders.Add(builder.NewAttach()) + + } + default: - logging.Fatal("Invalid ABI version: %d", prebuild.ABI) + logging.Fatal("Invalid ABI version: %d", r.ABI) } if version != nilVer { - prebuild.Version = version - } - if file != "" { - sync, _ := prepare.Tasks["synchronise"].(*prepare.Synchronise) - sync.Paths = []string{file} - overwrite, _ := prepare.Tasks["overwrite"].(*prepare.Overwrite) - overwrite.Optional = true + r.Version = version } -} -func Prebuild() { - logging.Step("Building apparmor.d profiles for %s on ABI%d.", prebuild.Distribution, prebuild.ABI) - if prebuild.Version != nilVer { - logging.Success("AppArmor version targeted: %.1f", prebuild.Version) - } - if err := Prepare(); err != nil { - logging.Fatal("%s", err.Error()) - } - if err := Build(); err != nil { - logging.Fatal("%s", err.Error()) + if status { + fmt.Printf("%s\n%s\n%s", + r.Configures.Help("Enabled configure"), + r.Builders.Help("Enabled build"), + r.Directives.Usage(), + ) + os.Exit(0) } + return r } -func Prepare() error { - for _, task := range prepare.Prepares { - msg, err := task.Apply() - if err != nil { - return err - } - if file != "" && task.Name() == "setflags" { - continue - } - logging.Success("%s", task.Message()) - logging.Indent = " " - for _, line := range msg { - if strings.Contains(line, "not found") { - logging.Warning("%s", line) - } else { - logging.Bullet("%s", line) - } - } - logging.Indent = "" +func Prebuild(r *runtime.Runners) { + logging.Step("Building apparmor.d profiles for %s", tasks.Distribution) + if r.Test { + logging.Warning("Test mode enabled") } - return nil -} - -func Build() error { - files, _ := prebuild.RootApparmord.ReadDirRecursiveFiltered(nil, paths.FilterOutDirectories()) - for _, file := range files { - if !file.Exist() { - continue - } - profile, err := file.ReadFileAsString() - if err != nil { - return err - } - profile, err = builder.Run(file, profile) - if err != nil { - return err - } - profile, err = directive.Run(file, profile) - if err != nil { - return err - } - if err := file.WriteFile([]byte(profile)); err != nil { - return err - } + logging.Success("AppArmor ABI targeted: %d", r.ABI) + logging.Success("AppArmor version targeted: %.1f", r.Version) + if fsp { + logging.Success("Full system policy enabled") } - - logging.Success("Build tasks:") - logging.Indent = " " - for _, task := range builder.Builds { - logging.Bullet("%s", task.Message()) + if err := r.Configure(); err != nil { + logging.Fatal("%s", err.Error()) } - logging.Indent = "" - logging.Success("Directives processed:") - logging.Indent = " " - for _, dir := range directive.Directives { - logging.Bullet("%s%s", directive.Keyword, dir.Name()) + if err := r.Build(); err != nil { + logging.Fatal("%s", err.Error()) } - logging.Indent = "" - return nil } diff --git a/pkg/prebuild/cli/cli_test.go b/pkg/prebuild/cli/cli_test.go deleted file mode 100644 index dab3100204..0000000000 --- a/pkg/prebuild/cli/cli_test.go +++ /dev/null @@ -1,110 +0,0 @@ -// apparmor.d - Full set of apparmor profiles -// Copyright (C) 2023-2024 Alexandre Pujol -// SPDX-License-Identifier: GPL-2.0-only - -package cli - -import ( - "os" - "os/exec" - "testing" - - "github.com/roddhjav/apparmor.d/pkg/paths" - "github.com/roddhjav/apparmor.d/pkg/prebuild" - "github.com/roddhjav/apparmor.d/pkg/prebuild/builder" - "github.com/roddhjav/apparmor.d/pkg/prebuild/prepare" -) - -func setTestBuildDirectories(name string) { - testRoot := paths.New("/tmp/tests") - prebuild.Root = testRoot.Join(name) - prebuild.RootApparmord = prebuild.Root.Join("apparmor.d") -} - -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_Prebuild(t *testing.T) { - tests := []struct { - name string - wantErr bool - full bool - complain bool - enforce bool - dist string - }{ - { - name: "Build for Archlinux", - wantErr: false, - full: false, - complain: true, - enforce: false, - dist: "arch", - }, - { - name: "Build for Ubuntu", - wantErr: false, - full: true, - complain: false, - enforce: true, - dist: "ubuntu", - }, - { - name: "Build for Debian", - wantErr: false, - full: true, - complain: false, - enforce: false, - dist: "debian", - }, - { - name: "Build for OpenSUSE Tumbleweed", - wantErr: false, - full: true, - complain: true, - enforce: false, - dist: "opensuse", - }, - } - chdirGitRoot() - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - setTestBuildDirectories(tt.dist) - prebuild.Distribution = tt.dist - prepare.Prepares = []prepare.Task{} - prepare.Register( - "synchronise", "ignore", "merge", - "configure", "setflags", "systemd-default", - ) - - if full { - prepare.Register("fsp") - builder.Register("fsp") - } else { - prepare.Register("systemd-early") - } - - if complain { - builder.Register("complain") - } else if enforce { - builder.Register("enforce") - } - - if err := Prepare(); (err != nil) != tt.wantErr { - t.Errorf("Prepare() error = %v, wantErr %v", err, tt.wantErr) - } - if err := Build(); (err != nil) != tt.wantErr { - t.Errorf("Build() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} diff --git a/pkg/prebuild/core.go b/pkg/prebuild/core.go deleted file mode 100644 index 8c2410d108..0000000000 --- a/pkg/prebuild/core.go +++ /dev/null @@ -1,39 +0,0 @@ -// apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol -// SPDX-License-Identifier: GPL-2.0-only - -package prebuild - -import "fmt" - -type BaseInterface interface { - Message() string - Name() string - Usage() []string -} - -type Base struct { - Msg string - Keyword string - Help []string -} - -func (b Base) Name() string { - return b.Keyword -} - -func (b Base) Usage() []string { - return b.Help -} - -func (b Base) Message() string { - return b.Msg -} - -func Help[T BaseInterface](name string, tasks map[string]T) string { - res := fmt.Sprintf("%s tasks:\n", name) - for _, t := range tasks { - res += fmt.Sprintf(" %s - %s\n", t.Name(), t.Message()) - } - return res -} diff --git a/pkg/prebuild/core_test.go b/pkg/prebuild/core_test.go deleted file mode 100644 index 5abf0a9c14..0000000000 --- a/pkg/prebuild/core_test.go +++ /dev/null @@ -1,62 +0,0 @@ -// apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol -// SPDX-License-Identifier: GPL-2.0-only - -package prebuild - -import ( - "slices" - "strings" - "testing" -) - -func TestBase_Helpers(t *testing.T) { - tests := []struct { - name string - b Base - want string - }{ - { - name: "base", - b: Base{Keyword: "test", Help: []string{"test"}, Msg: "test"}, - want: "test", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := tt.b.Name(); got != tt.want { - t.Errorf("Base.Name() = %v, want %v", got, tt.want) - } - if got := tt.b.Usage(); !slices.Equal(got, []string{tt.want}) { - t.Errorf("Base.Usage() = %v, want %v", got, tt.want) - } - if got := tt.b.Message(); got != tt.want { - t.Errorf("Base.Message() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestHelp(t *testing.T) { - tests := []struct { - name string - tasks map[string]Base - want string - }{ - { - name: "one", - tasks: map[string]Base{ - "one": {Keyword: "one", Help: []string{"one"}, Msg: "one"}, - "two": {Keyword: "two", Help: []string{"two"}, Msg: "two"}, - }, - want: `one`, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := Help(tt.name, tt.tasks); !strings.Contains(got, tt.want) { - t.Errorf("Help() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/pkg/prebuild/directive/filter.go b/pkg/prebuild/directive/filter.go deleted file mode 100644 index a6513f37ea..0000000000 --- a/pkg/prebuild/directive/filter.go +++ /dev/null @@ -1,76 +0,0 @@ -// apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol -// SPDX-License-Identifier: GPL-2.0-only - -package directive - -import ( - "fmt" - "regexp" - "slices" - "strings" - - "github.com/roddhjav/apparmor.d/pkg/prebuild" -) - -type FilterOnly struct { - prebuild.Base -} - -type FilterExclude struct { - prebuild.Base -} - -func init() { - RegisterDirective(&FilterOnly{ - Base: prebuild.Base{ - Keyword: "only", - Msg: "Only directive applied", - Help: []string{"filters..."}, - }, - }) - RegisterDirective(&FilterExclude{ - Base: prebuild.Base{ - Keyword: "exclude", - Msg: "Exclude directive applied", - Help: []string{"filters..."}, - }, - }) -} - -func filterRuleForUs(opt *Option) bool { - abiStr := fmt.Sprintf("abi%d", prebuild.ABI) - if slices.Contains(opt.ArgList, abiStr) { - return true - } - versionStr := fmt.Sprintf("apparmor%.1f", prebuild.Version) - if slices.Contains(opt.ArgList, versionStr) { - return true - } - return slices.Contains(opt.ArgList, prebuild.Distribution) || slices.Contains(opt.ArgList, prebuild.Family) -} - -func filter(only bool, opt *Option, profile string) (string, error) { - if only && filterRuleForUs(opt) { - return opt.Clean(profile), nil - } - if !only && !filterRuleForUs(opt) { - return opt.Clean(profile), nil - } - - if opt.IsInline() { - profile = strings.ReplaceAll(profile, opt.Raw, "") - } else { - regRemoveParagraph := regexp.MustCompile(`(?s)` + opt.Raw + `\n.*?\n\n`) - profile = regRemoveParagraph.ReplaceAllString(profile, "") - } - return profile, nil -} - -func (d FilterOnly) Apply(opt *Option, profile string) (string, error) { - return filter(true, opt, profile) -} - -func (d FilterExclude) Apply(opt *Option, profile string) (string, error) { - return filter(false, opt, profile) -} diff --git a/pkg/prebuild/directive/filter_test.go b/pkg/prebuild/directive/filter_test.go deleted file mode 100644 index ebbd5ef5c0..0000000000 --- a/pkg/prebuild/directive/filter_test.go +++ /dev/null @@ -1,148 +0,0 @@ -// apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol -// SPDX-License-Identifier: GPL-2.0-only - -package directive - -import ( - "testing" - - "github.com/roddhjav/apparmor.d/pkg/prebuild" -) - -func TestFilterOnly_Apply(t *testing.T) { - tests := []struct { - name string - dist string - family string - opt *Option - profile string - want string - wantErr bool - }{ - { - name: "inline", - dist: "debian", - family: "apt", - opt: &Option{ - Name: "only", - ArgMap: map[string]string{"apt": ""}, - ArgList: []string{"apt"}, - File: nil, - Raw: " @{bin}/arch-audit rPx, #aa:only apt", - }, - profile: " @{bin}/arch-audit rPx, #aa:only apt", - want: " @{bin}/arch-audit rPx,", - }, - { - name: "paragraph", - dist: "arch", - family: "pacman", - opt: &Option{ - Name: "only", - ArgMap: map[string]string{"zypper": ""}, - ArgList: []string{"zypper"}, - File: nil, - Raw: " #aa:only zypper", - }, - profile: ` - /tmp/apt-changelog-@{rand6}/ w, - /tmp/apt-changelog-@{rand6}/*.changelog rw, - owner /tmp/alpm_*/{,**} rw, - owner /tmp/apt-changelog-@{rand6}/.apt-acquire-privs-test.@{rand6} rw, - owner /tmp/packagekit* rw, - - @{run}/systemd/inhibit/*.ref rw, - owner @{run}/systemd/users/@{uid} r, - - #aa:only zypper - @{run}/zypp.pid rwk, - owner @{run}/zypp-rpm.pid rwk, - owner @{run}/zypp/packages/ r, - - owner /dev/shm/AP_0x@{rand6}/{,**} rw, - owner /dev/shm/ r,`, - want: ` - /tmp/apt-changelog-@{rand6}/ w, - /tmp/apt-changelog-@{rand6}/*.changelog rw, - owner /tmp/alpm_*/{,**} rw, - owner /tmp/apt-changelog-@{rand6}/.apt-acquire-privs-test.@{rand6} rw, - owner /tmp/packagekit* rw, - - @{run}/systemd/inhibit/*.ref rw, - owner @{run}/systemd/users/@{uid} r, - - owner /dev/shm/AP_0x@{rand6}/{,**} rw, - owner /dev/shm/ r,`, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - prebuild.Distribution = tt.dist - prebuild.Family = tt.family - got, err := Directives["only"].Apply(tt.opt, tt.profile) - if (err != nil) != tt.wantErr { - t.Errorf("FilterOnly.Apply() error = %v, wantErr %v", err, tt.wantErr) - return - } - if got != tt.want { - t.Errorf("FilterOnly.Apply() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestFilterExclude_Apply(t *testing.T) { - tests := []struct { - name string - dist string - family string - opt *Option - profile string - want string - wantErr bool - }{ - { - name: "inline", - dist: "debian", - family: "apt", - opt: &Option{ - Name: "exclude", - ArgMap: map[string]string{"debian": ""}, - ArgList: []string{"debian"}, - File: nil, - Raw: " @{bin}/dpkg rPx -> child-dpkg, #aa:exclude debian", - }, - profile: " @{bin}/dpkg rPx -> child-dpkg, #aa:exclude debian", - want: "", - }, - { - name: "inline-keep", - dist: "whonix", - family: "apt", - opt: &Option{ - Name: "exclude", - ArgMap: map[string]string{"debian": ""}, - ArgList: []string{"debian"}, - File: nil, - Raw: " @{bin}/dpkg rPx -> child-dpkg, #aa:exclude debian", - }, - profile: " @{bin}/dpkg rPx -> child-dpkg, #aa:exclude debian", - want: " @{bin}/dpkg rPx -> child-dpkg,", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - prebuild.Distribution = tt.dist - prebuild.Family = tt.family - got, err := Directives["exclude"].Apply(tt.opt, tt.profile) - if (err != nil) != tt.wantErr { - t.Errorf("FilterExclude.Apply() error = %v, wantErr %v", err, tt.wantErr) - return - } - if got != tt.want { - t.Errorf("FilterExclude.Apply() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/pkg/prebuild/directories.go b/pkg/prebuild/directories.go index d5d5a72660..d6cca0d3e2 100644 --- a/pkg/prebuild/directories.go +++ b/pkg/prebuild/directories.go @@ -1,27 +1,15 @@ // apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol +// Copyright (C) 2021-2026 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only +// Package prebuild defines the directory layout, manifest readers, and +// shared state used by the prebuild pipeline that turns the source profiles +// into a distribution-ready tree. package prebuild import "github.com/roddhjav/apparmor.d/pkg/paths" var ( - // AppArmor ABI version - ABI = 0 - - // AppArmor version - Version = 4.0 - - // Pkgname is the name of the package - Pkgname = "apparmor.d" - - // Root is the root directory for the build (default: .build) - Root *paths.Path = paths.New(".build") - - // RootApparmord is the final built apparmor.d directory (default: .build/apparmor.d) - RootApparmord *paths.Path = Root.Join("apparmor.d") - // DistDir is the directory where the distribution specific files are stored DistDir *paths.Path = paths.New("dists") @@ -37,8 +25,8 @@ var ( // DebianDir is the directory where the debian specific files are stored DebianDir *paths.Path = paths.New("debian") - // DebianHide is the path to the debian/apparmor.d.hide file - DebianHide = DebianHider{path: DebianDir.Join("apparmor.d.hide")} + // DebianHide is the path to the debian/common.hide file + DebianHide = DebianHider{path: DebianDir.Join("common.hide")} Ignore = Ignorer{} Flags = Flagger{} diff --git a/pkg/prebuild/files.go b/pkg/prebuild/files.go index 504f05c1c0..ceef034125 100644 --- a/pkg/prebuild/files.go +++ b/pkg/prebuild/files.go @@ -11,9 +11,13 @@ 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/hostname /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/configure.go b/pkg/prebuild/prepare/configure.go deleted file mode 100644 index a6e9544850..0000000000 --- a/pkg/prebuild/prepare/configure.go +++ /dev/null @@ -1,76 +0,0 @@ -// apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol -// SPDX-License-Identifier: GPL-2.0-only - -package prepare - -import ( - "fmt" - - "github.com/roddhjav/apparmor.d/pkg/prebuild" -) - -type Configure struct { - prebuild.Base -} - -func init() { - RegisterTask(&Configure{ - Base: prebuild.Base{ - Keyword: "configure", - Msg: "Set distribution specificities", - }, - }) -} - -func (p Configure) Apply() ([]string, error) { - res := []string{} - - switch prebuild.Distribution { - case "arch", "opensuse": - - case "ubuntu": - if err := prebuild.DebianHide.Init(); err != nil { - return res, err - } - - if prebuild.Version < 3.0 { - if err := prebuild.DistDir.Join("ubuntu").CopyFS(prebuild.RootApparmord); err != nil { - return res, err - } - } - - case "debian", "whonix": - if err := prebuild.DebianHide.Init(); err != nil { - return res, err - } - - if prebuild.Version < 4.1 { - // Copy Debian specific abstractions - if err := prebuild.DistDir.Join("ubuntu").CopyFS(prebuild.RootApparmord); err != nil { - return res, err - } - } - - default: - return []string{}, fmt.Errorf("%s is not a supported distribution", prebuild.Distribution) - - } - - if prebuild.Version == 4.1 { - // Remove files upstreamed in 4.1 - remove := []string{ - "abstractions/devices-usb-read", - "abstractions/devices-usb", - "abstractions/nameservice-strict", - "tunables/multiarch.d/base", - "wg", // Upstream version is identical - } - for _, name := range remove { - if err := prebuild.RootApparmord.Join(name).RemoveAll(); err != nil { - return res, err - } - } - } - return res, nil -} diff --git a/pkg/prebuild/prepare/core.go b/pkg/prebuild/prepare/core.go deleted file mode 100644 index 74d7778ed5..0000000000 --- a/pkg/prebuild/prepare/core.go +++ /dev/null @@ -1,39 +0,0 @@ -// apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol -// SPDX-License-Identifier: GPL-2.0-only - -package prepare - -import ( - "fmt" - - "github.com/roddhjav/apparmor.d/pkg/prebuild" -) - -var ( - // Prepare the build directory with the following tasks - Prepares = []Task{} - - // Available prepare tasks - Tasks = map[string]Task{} -) - -// Task main directive interface -type Task interface { - prebuild.BaseInterface - Apply() ([]string, error) -} - -func Register(names ...string) { - for _, name := range names { - if b, present := Tasks[name]; present { - Prepares = append(Prepares, b) - } else { - panic(fmt.Sprintf("Unknown task: %s", name)) - } - } -} - -func RegisterTask(t Task) { - Tasks[t.Name()] = t -} diff --git a/pkg/prebuild/prepare/fsp.go b/pkg/prebuild/prepare/fsp.go deleted file mode 100644 index e46efe0e83..0000000000 --- a/pkg/prebuild/prepare/fsp.go +++ /dev/null @@ -1,62 +0,0 @@ -// apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol -// SPDX-License-Identifier: GPL-2.0-only - -package prepare - -import ( - "strings" - - "github.com/roddhjav/apparmor.d/pkg/paths" - "github.com/roddhjav/apparmor.d/pkg/prebuild" - "github.com/roddhjav/apparmor.d/pkg/util" -) - -type FullSystemPolicy struct { - prebuild.Base -} - -func init() { - RegisterTask(&FullSystemPolicy{ - Base: prebuild.Base{ - Keyword: "fsp", - Msg: "Configure AppArmor for full system policy", - }, - }) -} - -func (p FullSystemPolicy) Apply() ([]string, error) { - res := []string{} - - // Install full system policy profiles - if err := paths.New("apparmor.d/groups/_full/").CopyFS(prebuild.Root.Join("apparmor.d")); err != nil { - return res, err - } - - // Set systemd profile name - path := prebuild.RootApparmord.Join("tunables/multiarch.d/profiles") - out, err := path.ReadFileAsString() - if err != nil { - return res, err - } - out = strings.ReplaceAll(out, "@{p_systemd}=unconfined", "@{p_systemd}=systemd") - out = strings.ReplaceAll(out, "@{p_systemd_user}=unconfined", "@{p_systemd_user}=systemd-user") - if err := path.WriteFile([]byte(out)); err != nil { - return res, err - } - - // Fix conflicting x modifiers in abstractions - FIXME: Temporary solution - path = prebuild.RootApparmord.Join("abstractions/gstreamer") - out, err = path.ReadFileAsString() - if err != nil { - return res, err - } - regFixConflictX := util.ToRegexRepl([]string{`.*gst-plugin-scanner.*`, ``}) - out = regFixConflictX.Replace(out) - if err := path.WriteFile([]byte(out)); err != nil { - return res, err - } - - // Set systemd unit drop-in files - return res, paths.CopyTo(prebuild.SystemdDir.Join("full"), prebuild.Root.Join("systemd")) -} diff --git a/pkg/prebuild/prepare/merge.go b/pkg/prebuild/prepare/merge.go deleted file mode 100644 index d2c7200035..0000000000 --- a/pkg/prebuild/prepare/merge.go +++ /dev/null @@ -1,61 +0,0 @@ -// apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol -// SPDX-License-Identifier: GPL-2.0-only - -package prepare - -import ( - "os" - "path/filepath" - - "github.com/roddhjav/apparmor.d/pkg/paths" - "github.com/roddhjav/apparmor.d/pkg/prebuild" -) - -type Merge struct { - prebuild.Base -} - -func init() { - RegisterTask(&Merge{ - Base: prebuild.Base{ - Keyword: "merge", - Msg: "Merge profiles (from group/, profiles-*-*/) to a unified apparmor.d directory", - }, - }) -} - -func (p Merge) Apply() ([]string, error) { - res := []string{} - dirToMerge := []string{ - "groups/*/*", "groups", - "profiles-*-*/*", "profiles-*", - } - - idx := 0 - for idx < len(dirToMerge)-1 { - dirMoved, dirRemoved := dirToMerge[idx], dirToMerge[idx+1] - files, err := filepath.Glob(prebuild.RootApparmord.Join(dirMoved).String()) - if err != nil { - return res, err - } - for _, file := range files { - err := os.Rename(file, prebuild.RootApparmord.Join(filepath.Base(file)).String()) - if err != nil { - return res, err - } - } - - files, err = filepath.Glob(prebuild.RootApparmord.Join(dirRemoved).String()) - if err != nil { - return []string{}, err - } - for _, file := range files { - if err := paths.New(file).RemoveAll(); err != nil { - return res, err - } - } - idx = idx + 2 - } - return res, nil -} diff --git a/pkg/prebuild/prepare/systemd.go b/pkg/prebuild/prepare/systemd.go deleted file mode 100644 index b7646e4bf2..0000000000 --- a/pkg/prebuild/prepare/systemd.go +++ /dev/null @@ -1,41 +0,0 @@ -// apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol -// SPDX-License-Identifier: GPL-2.0-only - -package prepare - -import ( - "github.com/roddhjav/apparmor.d/pkg/paths" - "github.com/roddhjav/apparmor.d/pkg/prebuild" -) - -type SystemdDefault struct { - prebuild.Base -} - -type SystemdEarly struct { - prebuild.Base -} - -func init() { - RegisterTask(&SystemdDefault{ - Base: prebuild.Base{ - Keyword: "systemd-default", - Msg: "Configure systemd unit drop in files to a profile for some units", - }, - }) - RegisterTask(&SystemdEarly{ - Base: prebuild.Base{ - Keyword: "systemd-early", - Msg: "Configure systemd unit drop in files to ensure some service start after apparmor", - }, - }) -} - -func (p SystemdDefault) Apply() ([]string, error) { - return []string{}, paths.CopyTo(prebuild.SystemdDir.Join("default"), prebuild.Root.Join("systemd")) -} - -func (p SystemdEarly) Apply() ([]string, error) { - return []string{}, paths.CopyTo(prebuild.SystemdDir.Join("early"), prebuild.Root.Join("systemd")) -} diff --git a/pkg/runtime/runners.go b/pkg/runtime/runners.go new file mode 100644 index 0000000000..65330a875f --- /dev/null +++ b/pkg/runtime/runners.go @@ -0,0 +1,98 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +// Package runtime wires the configure, builder, and directive runners into +// a single pipeline executed by prebuild and aa-install. +package runtime + +import ( + "strings" + + "github.com/roddhjav/apparmor.d/pkg/builder" + "github.com/roddhjav/apparmor.d/pkg/configure" + "github.com/roddhjav/apparmor.d/pkg/directive" + "github.com/roddhjav/apparmor.d/pkg/logging" + "github.com/roddhjav/apparmor.d/pkg/paths" + "github.com/roddhjav/apparmor.d/pkg/tasks" +) + +// Runners groups all runners used during install or prebuild jobs. +type Runners struct { + *tasks.TaskConfig + Configures *configure.Configures + Builders *builder.Builders + Directives *directive.Directives +} + +// NewRunners groups all runners used during install. +func NewRunners(config *tasks.TaskConfig) *Runners { + return &Runners{ + TaskConfig: config, + Configures: configure.NewRunner(config), + Builders: builder.NewRunner(config), + Directives: directive.NewRunner(config), + } +} + +// Configure runs all configure tasks. +func (r *Runners) Configure() error { + for _, task := range r.Configures.Tasks { + msg, err := task.Apply() + if err != nil { + return err + } + logging.Success("%s", task.Message()) + logging.Indent = " " + for _, line := range msg { + if strings.Contains(line, "not found") { + logging.Warning("%s", line) + } else { + logging.Bullet("%s", line) + } + } + logging.Indent = "" + } + return nil +} + +// Build runs all build tasks and processes all directives. +func (r *Runners) Build() error { + files, _ := r.Builders.RootApparmor.ReadDirRecursiveFiltered(nil, paths.FilterOutDirectories()) + for _, file := range files { + if !file.Exist() { + continue + } + profile, err := file.ReadFileAsString() + if err != nil { + return err + } + profile, err = r.Builders.Run(file, profile) + if err != nil { + return err + } + profile, err = r.Directives.Run(file, profile) + if err != nil { + return err + } + if err := file.WriteFile([]byte(profile)); err != nil { + return err + } + } + + logging.Success("Build tasks:") + logging.Indent = " " + for _, task := range r.Builders.Tasks { + logging.Bullet("%s", task.Message()) + } + if len(r.Directives.Directives) > 0 { + logging.Indent = "" + logging.Success("Directives processed:") + logging.Indent = " " + for _, d := range r.Directives.Directives { + logging.Bullet("%s%s", directive.Keyword, d.Name()) + } + logging.Indent = "" + } + return nil +} diff --git a/pkg/runtime/runners_test.go b/pkg/runtime/runners_test.go new file mode 100644 index 0000000000..12efb10abd --- /dev/null +++ b/pkg/runtime/runners_test.go @@ -0,0 +1,93 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2023-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package runtime + +import ( + "os" + "os/exec" + "testing" + + "github.com/roddhjav/apparmor.d/pkg/configure" + "github.com/roddhjav/apparmor.d/pkg/directive" + "github.com/roddhjav/apparmor.d/pkg/paths" + "github.com/roddhjav/apparmor.d/pkg/tasks" +) + +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 TestRunners_Build(t *testing.T) { + tests := []struct { + name string + wantErr bool + abi int + dist string + }{ + { + name: "Build for Archlinux", + wantErr: false, + abi: 4, + dist: "arch", + }, + { + name: "Build for Ubuntu", + wantErr: false, + abi: 4, + dist: "ubuntu", + }, + { + name: "Build for Debian", + wantErr: false, + abi: 4, + dist: "debian", + }, + { + name: "Build for OpenSUSE Tumbleweed", + wantErr: false, + abi: 4, + dist: "opensuse", + }, + } + chdirGitRoot() + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tasks.Distribution = tt.dist + root := paths.New("/tmp/tests").Join(tt.dist) + cfg := tasks.NewTaskConfig(root) + cfg.ABI = tt.abi + cfg.Test = true + r := NewRunners(cfg) + + // Add required configure tasks + r.Configures. + Add(configure.NewSynchronise([]*paths.Path{paths.New("apparmor.d")})). + Add(configure.NewMerge()) + + // Register all directives + r.Directives. + Register(directive.NewDbus()). + Register(directive.NewExec()). + Register(directive.NewFilterOnly()). + Register(directive.NewFilterExclude()). + Register(directive.NewStack()) + + if err := r.Configure(); (err != nil) != tt.wantErr { + t.Errorf("Runners.Configure() error = %v, wantErr %v", err, tt.wantErr) + } + if err := r.Build(); (err != nil) != tt.wantErr { + t.Errorf("Runners.Build() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/pkg/tasks/config.go b/pkg/tasks/config.go new file mode 100644 index 0000000000..26ceaa1175 --- /dev/null +++ b/pkg/tasks/config.go @@ -0,0 +1,46 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package tasks + +import "github.com/roddhjav/apparmor.d/pkg/paths" + +type TaskConfig struct { + // AppArmor ABI version + ABI int + + // AppArmor version + Version float64 + + // Tells the build we are a downstream project using apparmor.d as dependency + DownStream bool + + // Either or not RBAC is enabled + RBAC bool + + // Either or not we are in test mode + Test bool + + // Pkgname is the name of the package + Pkgname string + + // Root is the root directory for the runner (e.g. .build) + Root *paths.Path + + // RootApparmor is the source apparmor.d directory (e.g. .build/apparmor.d) + RootApparmor *paths.Path +} + +func NewTaskConfig(root *paths.Path) *TaskConfig { + return &TaskConfig{ + ABI: 0, + Version: 4.0, + DownStream: false, + RBAC: false, + Test: false, + Pkgname: "apparmor.d", + Root: root, + RootApparmor: root.Join("apparmor.d"), + } +} diff --git a/pkg/prebuild/os.go b/pkg/tasks/os.go similarity index 76% rename from pkg/prebuild/os.go rename to pkg/tasks/os.go index 8ef8fb79e8..1cf2238992 100644 --- a/pkg/prebuild/os.go +++ b/pkg/tasks/os.go @@ -1,8 +1,8 @@ // apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol +// Copyright (C) 2021-2026 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only -package prebuild +package tasks import ( "os" @@ -16,6 +16,15 @@ var ( Distribution = getDistribution() Release = getOSRelease() Family = getFamily() + + // DebianDir is the directory where the debian specific files are stored + // DebianDir *paths.Path = paths.New("debian") + + // // DebianHide is the path to the debian/common.hide file + // DebianHide = DebianHider{path: DebianDir.Join("common.hide")} + + // Ignore = Ignorer{} + // Flags = Flagger{} ) var ( @@ -27,7 +36,7 @@ var ( "opensuse": {"suse", "opensuse-tumbleweed"}, "whonix": {}, } - famillyDists = map[string][]string{ + familyDists = map[string][]string{ "apt": {"debian", "ubuntu", "whonix"}, "pacman": {"arch"}, "zypper": {"opensuse"}, @@ -81,9 +90,9 @@ func getDistribution() string { } func getFamily() string { - for familly, dist := range famillyDists { + for family, dist := range familyDists { if slices.Contains(dist, Distribution) { - return familly + return family } } return "" diff --git a/pkg/prebuild/os_test.go b/pkg/tasks/os_test.go similarity index 98% rename from pkg/prebuild/os_test.go rename to pkg/tasks/os_test.go index 8f9bd338fe..63824d253e 100644 --- a/pkg/prebuild/os_test.go +++ b/pkg/tasks/os_test.go @@ -1,8 +1,8 @@ // apparmor.d - Full set of apparmor profiles -// Copyright (C) 2021-2024 Alexandre Pujol +// Copyright (C) 2021-2026 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only -package prebuild +package tasks import ( "reflect" diff --git a/pkg/tasks/runner.go b/pkg/tasks/runner.go new file mode 100644 index 0000000000..f5e1deb078 --- /dev/null +++ b/pkg/tasks/runner.go @@ -0,0 +1,56 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +// Package tasks defines the generic Task and Runner abstractions reused by +// the configure, builder, and directive pipelines, and exposes the +// distribution detection used to drive distribution-specific behaviour. +package tasks + +import ( + "fmt" +) + +// Runner provides a fluent interface for building and executing task pipelines. +type Runner[T BaseTaskInterface] interface { + // Add appends a task to the execution pipeline + Add(task T) Runner[T] + + // Run executes all tasks in order, stopping on first error + Run() error + + // Help returns usage information for all registered tasks + Help(name string) string +} + +// BaseRunner provides common runner implementation for task pipelines. +type BaseRunner[T BaseTaskInterface] struct { + *TaskConfig + Tasks []T +} + +// NewBaseRunner creates a new BaseRunner instance. +func NewBaseRunner[T BaseTaskInterface](config *TaskConfig) *BaseRunner[T] { + r := &BaseRunner[T]{ + TaskConfig: config, + Tasks: make([]T, 0), + } + return r +} + +// Add appends a task to the execution pipeline. +func (r *BaseRunner[T]) Add(task T) *BaseRunner[T] { + task.SetConfig(r.TaskConfig) + r.Tasks = append(r.Tasks, task) + return r +} + +func (r *BaseRunner[T]) Help(name string) string { + res := fmt.Sprintf("%s tasks:\n", name) + for _, t := range r.Tasks { + res += fmt.Sprintf(" %s - %s\n", t.Name(), t.Message()) + } + return res +} + +// Run is not implemented in BaseRunner - concrete runners must implement their own Run method. diff --git a/pkg/tasks/task.go b/pkg/tasks/task.go new file mode 100644 index 0000000000..14a6bece93 --- /dev/null +++ b/pkg/tasks/task.go @@ -0,0 +1,35 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package tasks + +type BaseTaskInterface interface { + Message() string + Name() string + Usage() []string + SetConfig(c *TaskConfig) +} + +type BaseTask struct { + *TaskConfig + Msg string + Keyword string + Help []string +} + +func (b BaseTask) Name() string { + return b.Keyword +} + +func (b *BaseTask) SetConfig(c *TaskConfig) { + b.TaskConfig = c +} + +func (b BaseTask) Usage() []string { + return b.Help +} + +func (b BaseTask) Message() string { + return b.Msg +} diff --git a/pkg/tasks/task_test.go b/pkg/tasks/task_test.go new file mode 100644 index 0000000000..f3520b18f0 --- /dev/null +++ b/pkg/tasks/task_test.go @@ -0,0 +1,291 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package tasks + +import ( + "slices" + "strings" + "testing" + + "github.com/roddhjav/apparmor.d/pkg/paths" +) + +func TestBaseTask_Name(t *testing.T) { + tests := []struct { + name string + b BaseTask + want string + }{ + { + name: "simple", + b: BaseTask{Keyword: "test"}, + want: "test", + }, + { + name: "with-dashes", + b: BaseTask{Keyword: "test-task"}, + want: "test-task", + }, + { + name: "empty", + b: BaseTask{Keyword: ""}, + want: "", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.b.Name(); got != tt.want { + t.Errorf("BaseTask.Name() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestBaseTask_Usage(t *testing.T) { + tests := []struct { + name string + b BaseTask + want []string + }{ + { + name: "single", + b: BaseTask{Help: []string{"test"}}, + want: []string{"test"}, + }, + { + name: "multiple", + b: BaseTask{Help: []string{"line1", "line2", "line3"}}, + want: []string{"line1", "line2", "line3"}, + }, + { + name: "empty", + b: BaseTask{Help: []string{}}, + want: []string{}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.b.Usage(); !slices.Equal(got, tt.want) { + t.Errorf("BaseTask.Usage() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestBaseTask_Message(t *testing.T) { + tests := []struct { + name string + b BaseTask + want string + }{ + { + name: "simple", + b: BaseTask{Msg: "test message"}, + want: "test message", + }, + { + name: "empty", + b: BaseTask{Msg: ""}, + want: "", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.b.Message(); got != tt.want { + t.Errorf("BaseTask.Message() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestBaseTask_SetConfig(t *testing.T) { + tests := []struct { + name string + root string + wantAA string + }{ + { + name: "standard", + root: "/tmp/build", + wantAA: "/tmp/build/apparmor.d", + }, + { + name: "root", + root: "/", + wantAA: "/apparmor.d", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + root := paths.New(tt.root) + config := NewTaskConfig(root) + task := &BaseTask{} + task.SetConfig(config) + + if task.Root.String() != tt.root { + t.Errorf("BaseTask.SetConfig() Root = %v, want %v", task.Root, tt.root) + } + if task.RootApparmor.String() != tt.wantAA { + t.Errorf("BaseTask.SetConfig() RootApparmor = %v, want %v", task.RootApparmor, tt.wantAA) + } + }) + } +} + +func TestNewTaskConfig(t *testing.T) { + tests := []struct { + name string + root string + wantRoot string + wantAA string + }{ + { + name: "standard", + root: "/tmp/build", + wantRoot: "/tmp/build", + wantAA: "/tmp/build/apparmor.d", + }, + { + name: "root", + root: "/", + wantRoot: "/", + wantAA: "/apparmor.d", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + root := paths.New(tt.root) + got := NewTaskConfig(root) + if got.Root.String() != tt.wantRoot { + t.Errorf("NewTaskConfig().Root = %v, want %v", got.Root, tt.wantRoot) + } + if got.RootApparmor.String() != tt.wantAA { + t.Errorf("NewTaskConfig().RootApparmor = %v, want %v", got.RootApparmor, tt.wantAA) + } + }) + } +} + +func TestNewBaseRunner(t *testing.T) { + tests := []struct { + name string + root string + }{ + { + name: "standard", + root: "/tmp/test", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + root := paths.New(tt.root) + config := NewTaskConfig(root) + runner := NewBaseRunner[*BaseTask](config) + + if runner == nil { + t.Fatal("NewBaseRunner() returned nil") + } + if runner.Root.String() != tt.root { + t.Errorf("NewBaseRunner().Root = %v, want %v", runner.Root, tt.root) + } + if len(runner.Tasks) != 0 { + t.Errorf("NewBaseRunner().Tasks length = %v, want 0", len(runner.Tasks)) + } + }) + } +} + +func TestBaseRunner_Add(t *testing.T) { + tests := []struct { + name string + tasks []*BaseTask + wantCount int + }{ + { + name: "single", + tasks: []*BaseTask{ + {Keyword: "task1", Help: []string{"help1"}, Msg: "msg1"}, + }, + wantCount: 1, + }, + { + name: "multiple", + tasks: []*BaseTask{ + {Keyword: "task1", Help: []string{"help1"}, Msg: "msg1"}, + {Keyword: "task2", Help: []string{"help2"}, Msg: "msg2"}, + {Keyword: "task3", Help: []string{"help3"}, Msg: "msg3"}, + }, + wantCount: 3, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + root := paths.New("/tmp/test") + config := NewTaskConfig(root) + runner := NewBaseRunner[*BaseTask](config) + + for _, task := range tt.tasks { + runner.Add(task) + } + + if len(runner.Tasks) != tt.wantCount { + t.Errorf("BaseRunner.Add() tasks length = %v, want %v", len(runner.Tasks), tt.wantCount) + } + + // Verify tasks received config + for i, task := range runner.Tasks { + if task.Root.String() != root.String() { + t.Errorf("Task[%d] config not set, Root = %v, want %v", i, task.Root, root) + } + } + }) + } +} + +func TestBaseRunner_Help(t *testing.T) { + tests := []struct { + name string + runnerName string + tasks []*BaseTask + wantStrings []string + }{ + { + name: "single", + runnerName: "test-runner", + tasks: []*BaseTask{ + {Keyword: "build", Help: []string{"build help"}, Msg: "Build the project"}, + }, + wantStrings: []string{"test-runner tasks:", "build", "Build the project"}, + }, + { + name: "multiple", + runnerName: "suite", + tasks: []*BaseTask{ + {Keyword: "build", Help: []string{"build help"}, Msg: "Build the project"}, + {Keyword: "test", Help: []string{"test help"}, Msg: "Run tests"}, + }, + wantStrings: []string{"suite tasks:", "build", "Build the project", "test", "Run tests"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + root := paths.New("/tmp/test") + config := NewTaskConfig(root) + runner := NewBaseRunner[*BaseTask](config) + + for _, task := range tt.tasks { + runner.Add(task) + } + + got := runner.Help(tt.runnerName) + + for _, want := range tt.wantStrings { + if !strings.Contains(got, want) { + t.Errorf("BaseRunner.Help() missing expected string %q\nGot: %s", want, got) + } + } + }) + } +} diff --git a/pkg/util/apparmor.go b/pkg/util/apparmor.go new file mode 100644 index 0000000000..0bc19bbe2a --- /dev/null +++ b/pkg/util/apparmor.go @@ -0,0 +1,52 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2024 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package util + +import ( + "fmt" + "os" + "os/exec" + + "github.com/roddhjav/apparmor.d/pkg/paths" +) + +func cmd(command string, args ...string) error { + cmd := exec.Command(command, args...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + return fmt.Errorf("%s failed: %w", command, err) + } + return nil +} + +func ReloadProfiles(files paths.PathList) error { + args := []string{"--replace"} + for _, file := range files { + args = append(args, file.String()) + } + return cmd("apparmor_parser", args...) +} + +func ReloadAppArmor() error { + _ = cmd("apparmor_parser", "--purge-cache") + + isActive := cmd("systemctl", "is-active", "--quiet", "apparmor.service") == nil + var err error + if isActive { + err = cmd("systemctl", "reload", "apparmor.service") + } else { + err = cmd("systemctl", "start", "apparmor.service") + } + + if err != nil { + err2 := cmd("journalctl", "--no-pager", "--since=-5m", "--unit", "apparmor.service") + if err2 != nil { + return err2 + } + return fmt.Errorf("failed to reload apparmor service: %w", err) + } + return nil +} diff --git a/pkg/util/profiles.go b/pkg/util/profiles.go new file mode 100644 index 0000000000..0069bb5cdd --- /dev/null +++ b/pkg/util/profiles.go @@ -0,0 +1,76 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2023-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +// Package util gathers small, dependency-free helpers shared across the +// codebase: profile flag manipulation, and AppArmor userspace utilities +// such as profile reload. +package util + +import ( + "fmt" + "regexp" + "slices" + "strings" +) + +var ( + regFlags = regexp.MustCompile(`flags=\(([^)]+)\)`) + regProfileHeader = regexp.MustCompile(`(?m)^([ \t]*profile [^\n]*?) \{\n`) + ProfileModes = []string{ + "enforce", "complain", "kill", "default_allow", "unconfined", "prompt", + } +) + +// GetFlags parses the flags from a profile string. +func GetFlags(profile string) []string { + matches := regFlags.FindStringSubmatch(profile) + if len(matches) == 0 { + return nil + } + return strings.Split(matches[1], ",") +} + +// SetFlags replaces flags in a profile string. If flags is empty, removes the flags clause. +func SetFlags(profile string, flags []string) string { + profile = regFlags.ReplaceAllLiteralString(profile, "") + profile = strings.ReplaceAll(profile, " {\n", " {\n") + if len(flags) == 0 { + return profile + } + flagsStr := "${1} flags=(" + strings.Join(flags, ",") + ") {\n" + return regProfileHeader.ReplaceAllString(profile, flagsStr) +} + +// IsUnconfined reports whether any profile in the given content has the unconfined mode flag set. +func IsUnconfined(profile string) bool { + for _, match := range regFlags.FindAllStringSubmatch(profile, -1) { + for f := range strings.SplitSeq(match[1], ",") { + if strings.TrimSpace(f) == "unconfined" { + return true + } + } + } + return false +} + +// SetMode sets the given mode in the profile string, removing any conflicting mode flags. +func SetMode(profile string, mode string) (string, error) { + if !slices.Contains(ProfileModes, mode) { + return profile, fmt.Errorf("unknown profile mode: %s", mode) + } + + flags := GetFlags(profile) + + // Remove all conflicting mode flags + flags = slices.DeleteFunc(flags, func(f string) bool { + return slices.Contains(ProfileModes, f) + }) + + // "enforce" is the default (no mode flag needed), otherwise add the mode + if mode != "enforce" { + flags = append(flags, mode) + } + + return SetFlags(profile, flags), nil +} diff --git a/pkg/util/profiles_test.go b/pkg/util/profiles_test.go new file mode 100644 index 0000000000..4304501095 --- /dev/null +++ b/pkg/util/profiles_test.go @@ -0,0 +1,205 @@ +// apparmor.d - Full set of apparmor profiles +// Copyright (C) 2023-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package util + +import ( + "reflect" + "testing" +) + +func TestGetFlags(t *testing.T) { + tests := []struct { + name string + profile string + want []string + }{ + { + name: "no flags", + profile: "profile foo /usr/bin/foo {\n", + want: nil, + }, + { + name: "single flag", + profile: "profile foo /usr/bin/foo flags=(complain) {\n", + want: []string{"complain"}, + }, + { + name: "multiple flags", + profile: "profile foo /usr/bin/foo flags=(attach_disconnected,complain) {\n", + want: []string{"attach_disconnected", "complain"}, + }, + { + name: "empty profile", + profile: "", + want: nil, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := GetFlags(tt.profile); !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetFlags() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestSetFlags(t *testing.T) { + tests := []struct { + name string + profile string + flags []string + want string + }{ + { + name: "add flags to profile without flags", + profile: "profile foo /usr/bin/foo {\n", + flags: []string{"complain"}, + want: "profile foo /usr/bin/foo flags=(complain) {\n", + }, + { + name: "add flags to profile with if statement", + profile: "profile foo /usr/bin/foo {\n if true {\n /bin/true rix,\n }\n}\n", + flags: []string{"complain"}, + want: "profile foo /usr/bin/foo flags=(complain) {\n if true {\n /bin/true rix,\n }\n}\n", + }, + { + name: "add multiple flags", + profile: "profile foo /usr/bin/foo {\n", + flags: []string{"attach_disconnected", "complain"}, + want: "profile foo /usr/bin/foo flags=(attach_disconnected,complain) {\n", + }, + { + name: "replace existing flags", + profile: "profile foo /usr/bin/foo flags=(complain) {\n", + flags: []string{"enforce"}, + want: "profile foo /usr/bin/foo flags=(enforce) {\n", + }, + { + name: "remove flags with empty slice", + profile: "profile foo /usr/bin/foo flags=(complain) {\n", + flags: []string{}, + want: "profile foo /usr/bin/foo {\n", + }, + { + name: "remove flags with nil", + profile: "profile foo /usr/bin/foo flags=(complain) {\n", + flags: nil, + want: "profile foo /usr/bin/foo {\n", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := SetFlags(tt.profile, tt.flags); got != tt.want { + t.Errorf("SetFlags() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestIsUnconfined(t *testing.T) { + tests := []struct { + name string + profile string + want bool + }{ + { + name: "no flags", + profile: "profile foo /usr/bin/foo {\n}\n", + want: false, + }, + { + name: "unconfined only", + profile: "profile foo /usr/bin/foo flags=(unconfined) {\n}\n", + want: true, + }, + { + name: "unconfined with other flags", + profile: "profile foo /usr/bin/foo flags=(attach_disconnected, unconfined) {\n}\n", + want: true, + }, + { + name: "complain only", + profile: "profile foo /usr/bin/foo flags=(complain) {\n}\n", + want: false, + }, + { + name: "substring should not match", + profile: "profile foo /usr/bin/foo flags=(unconfinedx) {\n}\n", + want: false, + }, + { + name: "second profile is unconfined", + profile: "profile a /usr/bin/a {\n}\nprofile b /usr/bin/b flags=(unconfined) {\n}\n", + want: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := IsUnconfined(tt.profile); got != tt.want { + t.Errorf("IsUnconfined() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestSetMode(t *testing.T) { + tests := []struct { + name string + profile string + mode string + want string + wantErr bool + }{ + { + name: "set complain mode", + profile: "profile foo /usr/bin/foo {\n", + mode: "complain", + want: "profile foo /usr/bin/foo flags=(complain) {\n", + }, + { + name: "set enforce mode removes mode flags", + profile: "profile foo /usr/bin/foo flags=(complain) {\n", + mode: "enforce", + want: "profile foo /usr/bin/foo {\n", + }, + { + name: "replace complain with kill", + profile: "profile foo /usr/bin/foo flags=(complain) {\n", + mode: "kill", + want: "profile foo /usr/bin/foo flags=(kill) {\n", + }, + { + name: "preserve non-mode flags when setting mode", + profile: "profile foo /usr/bin/foo flags=(attach_disconnected,complain) {\n", + mode: "enforce", + want: "profile foo /usr/bin/foo flags=(attach_disconnected) {\n", + }, + { + name: "preserve non-mode flags when changing mode", + profile: "profile foo /usr/bin/foo flags=(attach_disconnected,complain) {\n", + mode: "kill", + want: "profile foo /usr/bin/foo flags=(attach_disconnected,kill) {\n", + }, + { + name: "unknown mode returns error", + profile: "profile foo /usr/bin/foo {\n", + mode: "invalid", + want: "profile foo /usr/bin/foo {\n", + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := SetMode(tt.profile, tt.mode) + if (err != nil) != tt.wantErr { + t.Errorf("SetMode() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("SetMode() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/util/tools.go b/pkg/util/tools.go index 749a97e629..0aaab53d3e 100644 --- a/pkg/util/tools.go +++ b/pkg/util/tools.go @@ -10,11 +10,6 @@ import ( ) var ( - Comment = `#` - regFilter = ToRegexRepl([]string{ - `\s*` + Comment + `.*`, ``, - `(?m)^(?:[\t\s]*(?:\r?\n|\r))+`, ``, - }) regHex = map[string]*regexp.Regexp{ "name": regexp.MustCompile(`name=[0-9A-F]+`), "comm": regexp.MustCompile(`comm=[0-9A-F]+`), @@ -63,7 +58,3 @@ func DecodeHexInString(str string) string { return str } -// Filter out comments and empty line from a string -func Filter(src string) string { - return regFilter.Replace(src) -} diff --git a/pkg/util/tools_test.go b/pkg/util/tools_test.go index e8b2bb8373..bc74e6999d 100644 --- a/pkg/util/tools_test.go +++ b/pkg/util/tools_test.go @@ -88,65 +88,3 @@ func TestRegexReplList_Replace(t *testing.T) { } } -func Test_Filter(t *testing.T) { - tests := []struct { - name string - src string - want string - }{ - { - name: "comment", - src: "# comment", - want: "", - }, - { - name: "comment with space", - src: " # comment", - want: "", - }, - { - name: "no comment", - src: "no comment", - want: "no comment", - }, - { - name: "no comment # comment", - src: "no comment # comment", - want: "no comment", - }, - { - name: "empty", - src: ` - -`, - want: ``, - }, - { - name: "main", - src: ` -# Common profile flags definition for all distributions -# File format: one profile by line using the format: ' ' - -bwrap attach_disconnected,mediate_deleted,complain -bwrap-app attach_disconnected,complain - -akonadi_akonotes_resource complain # Dev -gnome-disks complain - -`, - want: `bwrap attach_disconnected,mediate_deleted,complain -bwrap-app attach_disconnected,complain -akonadi_akonotes_resource complain -gnome-disks complain -`, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - gotLine := Filter(tt.src) - if gotLine != tt.want { - t.Errorf("FilterComment() got = |%v|, want |%v|", gotLine, tt.want) - } - }) - } -} diff --git a/requirements.txt b/requirements.txt index d30bccf196..39b3613053 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1 @@ -mkdocs -mkdocs-git-committers-plugin-2 -mkdocs-git-revision-date-localized-plugin -mkdocs-material -mkdocs-minify-plugin +zensical diff --git a/share/bash-completion/completions/aa-mode b/share/bash-completion/completions/aa-mode new file mode 100644 index 0000000000..c89dd5c5c5 --- /dev/null +++ b/share/bash-completion/completions/aa-mode @@ -0,0 +1,24 @@ +# aa-mode completion + +_aa-mode() { + COMPREPLY=() + local cur="${COMP_WORDS[COMP_CWORD]}" + local args=( + -e --enforce + -c --complain + -k --kill + -a --default-allow + -u --unconfined + -p --prompt + --no-reload + -h --help + ) + COMPREPLY+=($(compgen -W "${args[*]}" -- ${cur})) + COMPREPLY+=($(compgen -W "$(__aa_profiles)" -- ${cur})) +} + +__aa_profiles() { + find -L /etc/apparmor.d -maxdepth 1 -type f -printf '%P\n' | sort +} + +complete -F _aa-mode aa-mode diff --git a/share/man/man1/aa-mode.1 b/share/man/man1/aa-mode.1 new file mode 100644 index 0000000000..5ec024e55d --- /dev/null +++ b/share/man/man1/aa-mode.1 @@ -0,0 +1,73 @@ +.\" Automatically generated by Pandoc 3.1.11.1 +.\" +.TH "aa\-mode" "1" "April 2026" "" "" +.SH NAME +aa\-mode \- Switch AppArmor profiles mode. +.SH SYNOPSIS +\f[B]aa\-mode\f[R] [\f[I]options\&...\f[R]] +(\f[B]\-e\f[R]|\f[B]\-c\f[R]|\f[B]\-k\f[R]|\f[B]\-a\f[R]|\f[B]\-u\f[R]|\f[B]\-p\f[R]) +[\f[I]profiles\&...\f[R]] +.SH DESCRIPTION +Switch AppArmor profiles mode. +It modifies the profile flags and reloads the profiles with +\f[CR]apparmor_parser(8)\f[R]. +.PP +If a profile name is given without a path, it is looked up in +\f[CR]/etc/apparmor.d/\f[R]. +If a directory is given, all profiles in it are processed recursively. +.PP +Exactly one mode option must be given. +.SH OPTIONS +.TP +\f[I]profiles\f[R] +One or more profile paths or names to switch. +.TP +\f[CR]\-\-enforce\f[R], \f[CR]\-e\f[R] +Set the profile in \f[B]enforce\f[R] mode. +.TP +\f[CR]\-\-complain\f[R], \f[CR]\-c\f[R] +Set the profile in \f[B]complain\f[R] mode. +.TP +\f[CR]\-\-kill\f[R], \f[CR]\-k\f[R] +Set the profile in \f[B]kill\f[R] mode. +.TP +\f[CR]\-\-default\-allow\f[R], \f[CR]\-a\f[R] +Set the profile in \f[B]default_allow\f[R] mode. +.TP +\f[CR]\-\-unconfined\f[R], \f[CR]\-u\f[R] +Set the profile in \f[B]unconfined\f[R] mode. +.TP +\f[CR]\-\-prompt\f[R], \f[CR]\-p\f[R] +Set the profile in \f[B]prompt\f[R] mode. +.TP +\f[CR]\-\-no\-reload\f[R] +Do not reload the profile after modifying it. +.TP +\f[CR]\-\-help\f[R], \f[CR]\-h\f[R] +Print the program usage. +.SH USAGE +To switch a profile to complain mode: +.IP +.EX +aa\-mode \-c dnsmasq +.EE +.PP +To switch a profile to enforce mode: +.IP +.EX +aa\-mode \-\-enforce /etc/apparmor.d/dnsmasq +.EE +.PP +To switch all profiles in a directory to complain mode without +reloading: +.IP +.EX +aa\-mode \-\-complain \-\-no\-reload /etc/apparmor.d/ +.EE +.SH SEE ALSO +\f[CR]apparmor_parser(8)\f[R], \f[CR]apparmor(7)\f[R], +\f[CR]apparmor.d(5)\f[R],\f[CR]aa\-log(1)\f[R], +\f[CR]aa\-enforce(1)\f[R], \f[CR]aa\-complain(1)\f[R], and +https://apparmor.pujol.io. +.SH AUTHORS +aa\-mode was written by Alexandre Pujol (alexandre\[at]pujol.io). diff --git a/share/man/man1/aa-mode.md b/share/man/man1/aa-mode.md new file mode 100644 index 0000000000..10758b62a7 --- /dev/null +++ b/share/man/man1/aa-mode.md @@ -0,0 +1,79 @@ +% aa-mode(1) +% aa-mode was written by Alexandre Pujol (alexandre@pujol.io) +% April 2026 + +# NAME + +aa-mode - Switch AppArmor profiles mode. + +# SYNOPSIS + +**aa-mode** [*options...*] (**-e**|**-c**|**-k**|**-a**|**-u**|**-p**) [*profiles...*] + +# DESCRIPTION + +Switch AppArmor profiles mode. It modifies the profile flags and reloads the profiles with `apparmor_parser(8)`. + +If a profile name is given without a path, it is looked up in `/etc/apparmor.d/`. If a directory is given, all profiles in it are processed recursively. + +Exactly one mode option must be given. + +# OPTIONS + +*profiles* + +: One or more profile paths or names to switch. + +`--enforce`, `-e` + +: Set the profile in **enforce** mode. + +`--complain`, `-c` + +: Set the profile in **complain** mode. + +`--kill`, `-k` + +: Set the profile in **kill** mode. + +`--default-allow`, `-a` + +: Set the profile in **default_allow** mode. + +`--unconfined`, `-u` + +: Set the profile in **unconfined** mode. + +`--prompt`, `-p` + +: Set the profile in **prompt** mode. + +`--no-reload` + +: Do not reload the profile after modifying it. + +`--help`, `-h` + +: Print the program usage. + +# USAGE + +To switch a profile to complain mode: +```sh +aa-mode -c dnsmasq +``` + +To switch a profile to enforce mode: +```sh +aa-mode --enforce /etc/apparmor.d/dnsmasq +``` + +To switch all profiles in a directory to complain mode without reloading: +```sh +aa-mode --complain --no-reload /etc/apparmor.d/ +``` + +# SEE ALSO + +`apparmor_parser(8)`, `apparmor(7)`, `apparmor.d(5)`,`aa-log(1)`, `aa-enforce(1)`, `aa-complain(1)`, and +https://apparmor.pujol.io. diff --git a/share/man/man8/aa-log.8 b/share/man/man8/aa-log.8 index 42c9a3560f..f19f669dcd 100644 --- a/share/man/man8/aa-log.8 +++ b/share/man/man8/aa-log.8 @@ -1,10 +1,10 @@ -.\" Automatically generated by Pandoc 3.1.9 +.\" Automatically generated by Pandoc 3.5 .\" -.TH "aa-log" "8" "September 2024" "" "" +.TH "aa\-log" "8" "December 2025" "" .SH NAME -aa-log \[em] Review AppArmor generated messages in a colorful way. +aa\-log \- Review AppArmor generated messages in a colorful way. .SH SYNOPSIS -\f[B]aa-log\f[R] [\f[I]options\&...\f[R]] [\f[I]profile\f[R]] +\f[B]aa\-log\f[R] [\f[I]options\&...\f[R]] [\f[I]profile\f[R]] .SH DESCRIPTION Review AppArmor generated messages in a colourful way. Support logs from \f[I]auditd\f[R], \f[I]systemd\f[R], \f[I]syslog\f[R] @@ -13,48 +13,67 @@ as well as \f[I]dbus session\f[R] events. It can be given an optional profile name to filter the output with. .PP It can be used to generate AppArmor rules from the logs and it therefore -an alternative to \f[CR]aa-logprof(8)\f[R]. +an alternative to \f[CR]aa\-logprof(8)\f[R]. The generated rules should be manually reviewed and inserted into the profile. .PP Default logs are read from \f[CR]/var/log/audit/audit.log\f[R]. Other files in \f[CR]/var/log/audit/\f[R] can easily be checked: -\f[B]aa-log -f 1\f[R] parses \f[CR]audit.log.1\f[R] +\f[B]aa\-log \-f 1\f[R] parses \f[CR]audit.log.1\f[R] +.PP +Use \f[CR]aa\-log \-f \-\f[R] to read from standard input. +.PP +Logs written with \f[CR]aa\-log\f[R] can be read again with +\f[CR]aa\-log \-l\f[R]. .SH OPTIONS -\f[B]aa-log\f[R] [\f[I]options\&...\f[R]] [\f[I]profile\f[R]] +\f[B]aa\-log\f[R] [\f[I]options\&...\f[R]] [\f[I]profile\f[R]] .TP [\f[I]profile\f[R]] Optional profile name to filter the output with. .TP -\f[CR]--file\f[R], \f[CR]-f\f[R] +\f[CR]\-\-file\f[R], \f[CR]\-f\f[R] Set a logfile or a suffix to the default log file. .TP -\f[CR]--systemd\f[R], \f[CR]-s\f[R] +\f[CR]\-\-systemd\f[R], \f[CR]\-s\f[R] Parse systemd logs from journalctl. Provides all AppArmor logs since the last boot. .TP -\f[CR]--rules\f[R], \f[CR]-r\f[R] +\f[CR]\-\-namespace\f[R], \f[CR]\-n\f[R] +Filter the log to the specified AppArmor namespace. +.TP +\f[CR]\-\-rules\f[R], \f[CR]\-r\f[R] Convert the log into AppArmor rules. .TP -\f[CR]--raw\f[R], \f[CR]-R\f[R] +\f[CR]\-\-raw\f[R], \f[CR]\-R\f[R] Print the raw log without any formatting. Useful for reporting logs. .TP -\f[CR]--help\f[R], \f[CR]-h\f[R] +\f[CR]\-\-since\f[R], \f[CR]\-S\f[R] +Show entries not older than the specified date. +It currently only supports log from journalctl (with +\f[CR]\-\-systemd\f[R]) +.TP +\f[CR]\-\-boot\f[R], \f[CR]\-b\f[R] +Show entries from the specified boot ID. +.TP +\f[CR]\-\-load\f[R], \f[CR]\-l\f[R] +Load logs from the default \f[CR]aa\-log\f[R] output. +.TP +\f[CR]\-\-help\f[R], \f[CR]\-h\f[R] Print the program usage. .SH USAGE To read the AppArmor log from \f[CR]/var/log/audit/audit.log\f[R]: .IP .EX -aa-log +aa\-log .EE .PP To optionally filter a given profile name: -\f[CR]aa-log \f[R] (your shell will autocomplete the +\f[CR]aa\-log \f[R] (your shell will autocomplete the profile name): .IP .EX -$ aa-log dnsmasq +$ aa\-log dnsmasq DENIED dnsmasq open /proc/sys/kernel/osrelease comm=dnsmasq requested_mask=r denied_mask=r DENIED dnsmasq open /proc/1/environ comm=dnsmasq requested_mask=r denied_mask=r DENIED dnsmasq open /proc/cmdline comm=dnsmasq requested_mask=r denied_mask=r @@ -63,7 +82,7 @@ DENIED dnsmasq open /proc/cmdline comm=dnsmasq requested_mask=r denied_mask=r To generate AppArmor rule: .IP .EX -$ aa-log -r dnsmasq +$ aa\-log \-r dnsmasq profile dnsmasq { \[at]{PROC}/\[at]{pid}/environ r, \[at]{PROC}/cmdline r, @@ -71,9 +90,9 @@ profile dnsmasq { } .EE .SH SEE ALSO -\f[CR]aa-logprof(8)\f[R], \f[CR]apparmor(7)\f[R], -\f[CR]apparmor.d(5)\f[R], \f[CR]aa-genprof(1)\f[R], -\f[CR]aa-enforce(1)\f[R], \f[CR]aa-complain(1)\f[R], -\f[CR]aa-disable(1)\f[R], and https://apparmor.pujol.io. +\f[CR]aa\-logprof(8)\f[R], \f[CR]apparmor(7)\f[R], +\f[CR]apparmor.d(5)\f[R], \f[CR]aa\-genprof(1)\f[R], +\f[CR]aa\-enforce(1)\f[R], \f[CR]aa\-complain(1)\f[R], +\f[CR]aa\-disable(1)\f[R], and https://apparmor.pujol.io. .SH AUTHORS -aa-log was written by Alexandre Pujol (alexandre\[at]pujol.io). +aa\-log was written by Alexandre Pujol (alexandre\[at]pujol.io). diff --git a/share/man/man8/aa-log.md b/share/man/man8/aa-log.md index 0b7fe8afa4..1df69eee98 100644 --- a/share/man/man8/aa-log.md +++ b/share/man/man8/aa-log.md @@ -1,14 +1,14 @@ % aa-log(8) % aa-log was written by Alexandre Pujol (alexandre@pujol.io) -% September 2024 +% December 2025 # NAME -aa-log — Review AppArmor generated messages in a colorful way. +aa-log - Review AppArmor generated messages in a colorful way. # SYNOPSIS -**aa-log** [*options…*] [*profile*] +**aa-log** [*options...*] [*profile*] # DESCRIPTION @@ -20,6 +20,10 @@ It can be used to generate AppArmor rules from the logs and it therefore an alte Default logs are read from `/var/log/audit/audit.log`. Other files in `/var/log/audit/` can easily be checked: **aa-log -f 1** parses `audit.log.1` +Use `aa-log -f -` to read from standard input. + +Logs written with `aa-log` can be read again with `aa-log -l`. + # OPTIONS **aa-log** [*options…*] [*profile*] @@ -36,6 +40,10 @@ Default logs are read from `/var/log/audit/audit.log`. Other files in `/var/log/ : Parse systemd logs from journalctl. Provides all AppArmor logs since the last boot. +`--namespace`, `-n` + +: Filter the log to the specified AppArmor namespace. + `--rules`, `-r` : Convert the log into AppArmor rules. @@ -44,6 +52,18 @@ Default logs are read from `/var/log/audit/audit.log`. Other files in `/var/log/ : Print the raw log without any formatting. Useful for reporting logs. +`--since`, `-S` + +: Show entries not older than the specified date. It currently only supports log from journalctl (with `--systemd`) + +`--boot`, `-b` + +: Show entries from the specified boot ID. + +`--load`, `-l` + +: Load logs from the default `aa-log` output. + `--help`, `-h` : Print the program usage. diff --git a/share/zsh/site-functions/_aa-mode.zsh b/share/zsh/site-functions/_aa-mode.zsh new file mode 100644 index 0000000000..3e42711524 --- /dev/null +++ b/share/zsh/site-functions/_aa-mode.zsh @@ -0,0 +1,23 @@ +#compdef aa-mode +#autoload + +_aa-mode() { + local IFS=$'\n' + _arguments : \ + {-e,--enforce}'[set the profile in enforce mode]' \ + {-c,--complain}'[set the profile in complain mode]' \ + {-k,--kill}'[set the profile in kill mode]' \ + {-a,--default-allow}'[set the profile in default_allow mode]' \ + {-u,--unconfined}'[set the profile in unconfined mode]' \ + {-p,--prompt}'[set the profile in prompt mode]' \ + '--no-reload[do not reload the profile after modifying it]' \ + {-h,--help}'[display help information]' + + _values -C 'profile names' ${$(__aa_profiles):-""} +} + +__aa_profiles() { + find -L /etc/apparmor.d -maxdepth 1 -type f -printf '%P\n' | sort +} + +_aa-mode diff --git a/systemd/default/user/at-spi-dbus-bus.service b/systemd/default/user/at-spi-dbus-bus.service deleted file mode 100644 index 9c1fad5330..0000000000 --- a/systemd/default/user/at-spi-dbus-bus.service +++ /dev/null @@ -1,2 +0,0 @@ -[Service] -AppArmorProfile=dbus-accessibility diff --git a/systemd/default/user/org.freedesktop.IBus.session.GNOME.service b/systemd/default/user/org.freedesktop.IBus.session.GNOME.service deleted file mode 100644 index 818d5cdf35..0000000000 --- a/systemd/default/user/org.freedesktop.IBus.session.GNOME.service +++ /dev/null @@ -1,2 +0,0 @@ -[Service] -AppArmorProfile=ibus-daemon diff --git a/systemd/early/system/haveged.service b/systemd/early/system/haveged.service deleted file mode 100644 index 544fb7da8d..0000000000 --- a/systemd/early/system/haveged.service +++ /dev/null @@ -1,2 +0,0 @@ -[Unit] -After=apparmor.service diff --git a/systemd/early/system/multipathd.service b/systemd/early/system/multipathd.service deleted file mode 100644 index 544fb7da8d..0000000000 --- a/systemd/early/system/multipathd.service +++ /dev/null @@ -1,2 +0,0 @@ -[Unit] -After=apparmor.service diff --git a/systemd/early/system/pcscd.service b/systemd/early/system/pcscd.service deleted file mode 100644 index 544fb7da8d..0000000000 --- a/systemd/early/system/pcscd.service +++ /dev/null @@ -1,2 +0,0 @@ -[Unit] -After=apparmor.service diff --git a/systemd/early/system/systemd-journald.service b/systemd/early/system/systemd-journald.service deleted file mode 100644 index cd28405714..0000000000 --- a/systemd/early/system/systemd-journald.service +++ /dev/null @@ -1,2 +0,0 @@ -[Unit] -After=apparmor.service \ No newline at end of file diff --git a/systemd/early/system/systemd-networkd.service b/systemd/early/system/systemd-networkd.service deleted file mode 100644 index cd28405714..0000000000 --- a/systemd/early/system/systemd-networkd.service +++ /dev/null @@ -1,2 +0,0 @@ -[Unit] -After=apparmor.service \ No newline at end of file diff --git a/systemd/early/system/systemd-timesyncd.service b/systemd/early/system/systemd-timesyncd.service deleted file mode 100644 index cd28405714..0000000000 --- a/systemd/early/system/systemd-timesyncd.service +++ /dev/null @@ -1,2 +0,0 @@ -[Unit] -After=apparmor.service \ No newline at end of file diff --git a/systemd/full/system/ModemManager.service b/systemd/full/system/ModemManager.service index 03d3528901..2d1593f199 100644 --- a/systemd/full/system/ModemManager.service +++ b/systemd/full/system/ModemManager.service @@ -1,2 +1,2 @@ [Service] -NoNewPrivileges=no \ No newline at end of file +AppArmorProfile=&ModemManager diff --git a/systemd/full/system/apport-coredump-hook@.service b/systemd/full/system/apport-coredump-hook@.service new file mode 100644 index 0000000000..73bbc99d82 --- /dev/null +++ b/systemd/full/system/apport-coredump-hook@.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=&apport \ No newline at end of file diff --git a/systemd/full/system/apt-news.service b/systemd/full/system/apt-news.service new file mode 100644 index 0000000000..d7bf885ddc --- /dev/null +++ b/systemd/full/system/apt-news.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=&apt_news diff --git a/systemd/full/system/archlinux-keyring-wkd-sync.service b/systemd/full/system/archlinux-keyring-wkd-sync.service index 03d3528901..b887685568 100644 --- a/systemd/full/system/archlinux-keyring-wkd-sync.service +++ b/systemd/full/system/archlinux-keyring-wkd-sync.service @@ -1,2 +1,2 @@ [Service] -NoNewPrivileges=no \ No newline at end of file +AppArmorProfile=&archlinux-keyring-wkd-sync diff --git a/systemd/full/system/bluetooth.service b/systemd/full/system/bluetooth.service index 03d3528901..5cccff422a 100644 --- a/systemd/full/system/bluetooth.service +++ b/systemd/full/system/bluetooth.service @@ -1,2 +1,2 @@ [Service] -NoNewPrivileges=no \ No newline at end of file +AppArmorProfile=&bluetoothd \ No newline at end of file diff --git a/systemd/full/system/cloud-init-hotplugd.service b/systemd/full/system/cloud-init-hotplugd.service new file mode 100644 index 0000000000..a2a121fc37 --- /dev/null +++ b/systemd/full/system/cloud-init-hotplugd.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=&cloud-init-hotplugd.service diff --git a/systemd/full/system/colord.service b/systemd/full/system/colord.service new file mode 100644 index 0000000000..9a64fbc26c --- /dev/null +++ b/systemd/full/system/colord.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=&colord diff --git a/systemd/full/system/dbus-org.freedesktop.hostname1.service b/systemd/full/system/dbus-org.freedesktop.hostname1.service index 03d3528901..6d078aea95 100644 --- a/systemd/full/system/dbus-org.freedesktop.hostname1.service +++ b/systemd/full/system/dbus-org.freedesktop.hostname1.service @@ -1,2 +1,2 @@ [Service] -NoNewPrivileges=no \ No newline at end of file +AppArmorProfile=&systemd-hostnamed \ No newline at end of file diff --git a/systemd/full/system/dbus-org.freedesktop.import1.service b/systemd/full/system/dbus-org.freedesktop.import1.service index 03d3528901..0ab519541e 100644 --- a/systemd/full/system/dbus-org.freedesktop.import1.service +++ b/systemd/full/system/dbus-org.freedesktop.import1.service @@ -1,2 +1,2 @@ [Service] -NoNewPrivileges=no \ No newline at end of file +AppArmorProfile=&systemd-importd \ No newline at end of file diff --git a/systemd/full/system/dbus-org.freedesktop.locale1.service b/systemd/full/system/dbus-org.freedesktop.locale1.service index 03d3528901..2765950805 100644 --- a/systemd/full/system/dbus-org.freedesktop.locale1.service +++ b/systemd/full/system/dbus-org.freedesktop.locale1.service @@ -1,2 +1,2 @@ [Service] -NoNewPrivileges=no \ No newline at end of file +AppArmorProfile=&systemd-localed \ No newline at end of file diff --git a/systemd/full/system/dbus-org.freedesktop.login1.service b/systemd/full/system/dbus-org.freedesktop.login1.service index 03d3528901..c5728915c9 100644 --- a/systemd/full/system/dbus-org.freedesktop.login1.service +++ b/systemd/full/system/dbus-org.freedesktop.login1.service @@ -1,2 +1,2 @@ [Service] -NoNewPrivileges=no \ No newline at end of file +AppArmorProfile=&systemd-logind \ No newline at end of file diff --git a/systemd/full/system/dbus-org.freedesktop.machine1.service b/systemd/full/system/dbus-org.freedesktop.machine1.service index 03d3528901..315b1b2301 100644 --- a/systemd/full/system/dbus-org.freedesktop.machine1.service +++ b/systemd/full/system/dbus-org.freedesktop.machine1.service @@ -1,2 +1,2 @@ [Service] -NoNewPrivileges=no \ No newline at end of file +AppArmorProfile=&systemd-machined \ No newline at end of file diff --git a/systemd/full/system/dbus-org.freedesktop.timedate1.service b/systemd/full/system/dbus-org.freedesktop.timedate1.service index 03d3528901..ab04c5a456 100644 --- a/systemd/full/system/dbus-org.freedesktop.timedate1.service +++ b/systemd/full/system/dbus-org.freedesktop.timedate1.service @@ -1,2 +1,2 @@ [Service] -NoNewPrivileges=no \ No newline at end of file +AppArmorProfile=&systemd-timedated \ No newline at end of file diff --git a/systemd/full/system/debug-shell.service b/systemd/full/system/debug-shell.service new file mode 100644 index 0000000000..f895f79410 --- /dev/null +++ b/systemd/full/system/debug-shell.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=debug-shell.service \ No newline at end of file diff --git a/systemd/full/system/dmesg.service b/systemd/full/system/dmesg.service new file mode 100644 index 0000000000..d4647117b8 --- /dev/null +++ b/systemd/full/system/dmesg.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=dmesg.service \ No newline at end of file diff --git a/systemd/full/system/e2scrub@.service b/systemd/full/system/e2scrub@.service index 03d3528901..7340b76105 100644 --- a/systemd/full/system/e2scrub@.service +++ b/systemd/full/system/e2scrub@.service @@ -1,2 +1,2 @@ [Service] -NoNewPrivileges=no \ No newline at end of file +AppArmorProfile=&e2scrub \ No newline at end of file diff --git a/systemd/full/system/e2scrub_reap.service b/systemd/full/system/e2scrub_reap.service index 03d3528901..b903d2f0a7 100644 --- a/systemd/full/system/e2scrub_reap.service +++ b/systemd/full/system/e2scrub_reap.service @@ -1,2 +1,2 @@ [Service] -NoNewPrivileges=no \ No newline at end of file +AppArmorProfile=&e2scrub_all \ No newline at end of file diff --git a/systemd/full/system/fprintd.service b/systemd/full/system/fprintd.service index 03d3528901..5f1f063faf 100644 --- a/systemd/full/system/fprintd.service +++ b/systemd/full/system/fprintd.service @@ -1,2 +1,2 @@ [Service] -NoNewPrivileges=no \ No newline at end of file +AppArmorProfile=&fprintd \ No newline at end of file diff --git a/systemd/full/system/fwupd-refresh.service b/systemd/full/system/fwupd-refresh.service index fa215b3f02..acd28a5a4a 100644 --- a/systemd/full/system/fwupd-refresh.service +++ b/systemd/full/system/fwupd-refresh.service @@ -1,4 +1,2 @@ [Service] -ProtectKernelModules=no -RestrictRealtime=no -ProtectKernelModules=no +AppArmorProfile=&fwupdmgr \ No newline at end of file diff --git a/systemd/full/system/fwupd.service b/systemd/full/system/fwupd.service new file mode 100644 index 0000000000..5054a73d66 --- /dev/null +++ b/systemd/full/system/fwupd.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=&fwupd \ No newline at end of file diff --git a/systemd/full/system/geoclue.service b/systemd/full/system/geoclue.service index 4ba897659b..2c10e32f5a 100644 --- a/systemd/full/system/geoclue.service +++ b/systemd/full/system/geoclue.service @@ -1,6 +1,2 @@ [Service] -NoNewPrivileges=no -MemoryDenyWriteExecute=no -ProtectKernelTunables=no -ProtectKernelModules=no -RestrictRealtime=no +AppArmorProfile=&geoclue \ No newline at end of file diff --git a/systemd/full/system/grub-common.service b/systemd/full/system/grub-common.service new file mode 100644 index 0000000000..8520aea760 --- /dev/null +++ b/systemd/full/system/grub-common.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=grub-common.service \ No newline at end of file diff --git a/systemd/full/system/irqbalance.service b/systemd/full/system/irqbalance.service index 03d3528901..eab67fa448 100644 --- a/systemd/full/system/irqbalance.service +++ b/systemd/full/system/irqbalance.service @@ -1,2 +1,2 @@ [Service] -NoNewPrivileges=no \ No newline at end of file +AppArmorProfile=&irqbalance \ No newline at end of file diff --git a/systemd/full/system/ldconfig.service b/systemd/full/system/ldconfig.service new file mode 100644 index 0000000000..1b2a9c287a --- /dev/null +++ b/systemd/full/system/ldconfig.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=ldconfig.service \ No newline at end of file diff --git a/systemd/full/system/logrotate.service b/systemd/full/system/logrotate.service new file mode 100644 index 0000000000..bc984e0255 --- /dev/null +++ b/systemd/full/system/logrotate.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=&logrotate \ No newline at end of file diff --git a/systemd/full/system/low-memory-monitor.service b/systemd/full/system/low-memory-monitor.service deleted file mode 100644 index dabf76f3a5..0000000000 --- a/systemd/full/system/low-memory-monitor.service +++ /dev/null @@ -1,3 +0,0 @@ -[Service] -NoNewPrivileges=no - diff --git a/systemd/full/system/man-db.service b/systemd/full/system/man-db.service new file mode 100644 index 0000000000..d3a78dd80e --- /dev/null +++ b/systemd/full/system/man-db.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=man-db.service \ No newline at end of file diff --git a/systemd/full/system/nm-priv-helper.service b/systemd/full/system/nm-priv-helper.service index 03d3528901..53f99edd04 100644 --- a/systemd/full/system/nm-priv-helper.service +++ b/systemd/full/system/nm-priv-helper.service @@ -1,2 +1,2 @@ [Service] -NoNewPrivileges=no \ No newline at end of file +AppArmorProfile=&nm-priv-helper diff --git a/systemd/full/system/paccache.service b/systemd/full/system/paccache.service deleted file mode 100644 index 03d3528901..0000000000 --- a/systemd/full/system/paccache.service +++ /dev/null @@ -1,2 +0,0 @@ -[Service] -NoNewPrivileges=no \ No newline at end of file diff --git a/systemd/full/system/passim.service b/systemd/full/system/passim.service deleted file mode 100644 index 03d3528901..0000000000 --- a/systemd/full/system/passim.service +++ /dev/null @@ -1,2 +0,0 @@ -[Service] -NoNewPrivileges=no \ No newline at end of file diff --git a/systemd/full/system/pcscd.service b/systemd/full/system/pcscd.service new file mode 100644 index 0000000000..8d39f3f26e --- /dev/null +++ b/systemd/full/system/pcscd.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=&pcscd diff --git a/systemd/full/system/polkit.service b/systemd/full/system/polkit.service index 03d3528901..b21a28baac 100644 --- a/systemd/full/system/polkit.service +++ b/systemd/full/system/polkit.service @@ -1,2 +1,2 @@ [Service] -NoNewPrivileges=no \ No newline at end of file +AppArmorProfile=&polkitd diff --git a/systemd/full/system/power-profiles-daemon.service b/systemd/full/system/power-profiles-daemon.service new file mode 100644 index 0000000000..45c5ed93b6 --- /dev/null +++ b/systemd/full/system/power-profiles-daemon.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=&power-profiles-daemon \ No newline at end of file diff --git a/systemd/full/system/reflector.service b/systemd/full/system/reflector.service deleted file mode 100644 index 03d3528901..0000000000 --- a/systemd/full/system/reflector.service +++ /dev/null @@ -1,2 +0,0 @@ -[Service] -NoNewPrivileges=no \ No newline at end of file diff --git a/systemd/full/system/rngd.service b/systemd/full/system/rngd.service index 03d3528901..c52a85d0c8 100644 --- a/systemd/full/system/rngd.service +++ b/systemd/full/system/rngd.service @@ -1,2 +1,2 @@ [Service] -NoNewPrivileges=no \ No newline at end of file +AppArmorProfile=&rngd diff --git a/systemd/full/system/rsyslog.service b/systemd/full/system/rsyslog.service new file mode 100644 index 0000000000..6b49a73f09 --- /dev/null +++ b/systemd/full/system/rsyslog.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=&rsyslogd diff --git a/systemd/full/system/secureboot-db.service b/systemd/full/system/secureboot-db.service new file mode 100644 index 0000000000..722781b8a6 --- /dev/null +++ b/systemd/full/system/secureboot-db.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=secureboot-db.service diff --git a/systemd/full/system/shadow.service b/systemd/full/system/shadow.service index dabf76f3a5..52d2f644c3 100644 --- a/systemd/full/system/shadow.service +++ b/systemd/full/system/shadow.service @@ -1,3 +1,2 @@ [Service] -NoNewPrivileges=no - +AppArmorProfile=&shadow.service diff --git a/systemd/full/system/snapd.system-shutdown.service b/systemd/full/system/snapd.system-shutdown.service new file mode 100644 index 0000000000..7953d522a6 --- /dev/null +++ b/systemd/full/system/snapd.system-shutdown.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=snapd.system-shutdown.service \ No newline at end of file diff --git a/systemd/full/system/system-update-cleanup.service b/systemd/full/system/system-update-cleanup.service new file mode 100644 index 0000000000..24c914f77f --- /dev/null +++ b/systemd/full/system/system-update-cleanup.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=system-update-cleanup.service \ No newline at end of file diff --git a/systemd/full/system/systemd-coredump@.service b/systemd/full/system/systemd-coredump@.service new file mode 100644 index 0000000000..d136247092 --- /dev/null +++ b/systemd/full/system/systemd-coredump@.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=&systemd-coredump diff --git a/systemd/full/system/systemd-homed.service b/systemd/full/system/systemd-homed.service index 03d3528901..65d4ae62e5 100644 --- a/systemd/full/system/systemd-homed.service +++ b/systemd/full/system/systemd-homed.service @@ -1,2 +1,2 @@ [Service] -NoNewPrivileges=no \ No newline at end of file +AppArmorProfile=&systemd-homed diff --git a/systemd/full/system/systemd-hostnamed.service b/systemd/full/system/systemd-hostnamed.service index 03d3528901..6d078aea95 100644 --- a/systemd/full/system/systemd-hostnamed.service +++ b/systemd/full/system/systemd-hostnamed.service @@ -1,2 +1,2 @@ [Service] -NoNewPrivileges=no \ No newline at end of file +AppArmorProfile=&systemd-hostnamed \ No newline at end of file diff --git a/systemd/full/system/systemd-initctl.service b/systemd/full/system/systemd-initctl.service new file mode 100644 index 0000000000..e44c8767fe --- /dev/null +++ b/systemd/full/system/systemd-initctl.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=&systemd-initctl \ No newline at end of file diff --git a/systemd/full/system/systemd-journal-remote.service b/systemd/full/system/systemd-journal-remote.service new file mode 100644 index 0000000000..e08cf75a9f --- /dev/null +++ b/systemd/full/system/systemd-journal-remote.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=&systemd-journal-remote \ No newline at end of file diff --git a/systemd/full/system/systemd-journald.service b/systemd/full/system/systemd-journald.service index 0316a67c89..48f5a0156a 100644 --- a/systemd/full/system/systemd-journald.service +++ b/systemd/full/system/systemd-journald.service @@ -1,3 +1,2 @@ [Service] -NoNewPrivileges=no -ProtectClock=no \ No newline at end of file +AppArmorProfile=&systemd-journald \ No newline at end of file diff --git a/systemd/full/system/systemd-journald@.service b/systemd/full/system/systemd-journald@.service index 0316a67c89..48f5a0156a 100644 --- a/systemd/full/system/systemd-journald@.service +++ b/systemd/full/system/systemd-journald@.service @@ -1,3 +1,2 @@ [Service] -NoNewPrivileges=no -ProtectClock=no \ No newline at end of file +AppArmorProfile=&systemd-journald \ No newline at end of file diff --git a/systemd/full/system/systemd-localed.service b/systemd/full/system/systemd-localed.service index 03d3528901..2765950805 100644 --- a/systemd/full/system/systemd-localed.service +++ b/systemd/full/system/systemd-localed.service @@ -1,2 +1,2 @@ [Service] -NoNewPrivileges=no \ No newline at end of file +AppArmorProfile=&systemd-localed \ No newline at end of file diff --git a/systemd/full/system/systemd-logind.service b/systemd/full/system/systemd-logind.service index 0316a67c89..c5728915c9 100644 --- a/systemd/full/system/systemd-logind.service +++ b/systemd/full/system/systemd-logind.service @@ -1,3 +1,2 @@ [Service] -NoNewPrivileges=no -ProtectClock=no \ No newline at end of file +AppArmorProfile=&systemd-logind \ No newline at end of file diff --git a/systemd/full/system/systemd-machined.service b/systemd/full/system/systemd-machined.service index 03d3528901..315b1b2301 100644 --- a/systemd/full/system/systemd-machined.service +++ b/systemd/full/system/systemd-machined.service @@ -1,2 +1,2 @@ [Service] -NoNewPrivileges=no \ No newline at end of file +AppArmorProfile=&systemd-machined \ No newline at end of file diff --git a/systemd/full/system/systemd-networkd.service b/systemd/full/system/systemd-networkd.service index 03d3528901..3f4b608491 100644 --- a/systemd/full/system/systemd-networkd.service +++ b/systemd/full/system/systemd-networkd.service @@ -1,2 +1,2 @@ [Service] -NoNewPrivileges=no \ No newline at end of file +AppArmorProfile=&systemd-networkd diff --git a/systemd/full/system/systemd-nsresourced.service b/systemd/full/system/systemd-nsresourced.service new file mode 100644 index 0000000000..2dc668b80d --- /dev/null +++ b/systemd/full/system/systemd-nsresourced.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=&systemd-nsresourced diff --git a/systemd/full/system/systemd-oomd.service b/systemd/full/system/systemd-oomd.service new file mode 100644 index 0000000000..c384626ee6 --- /dev/null +++ b/systemd/full/system/systemd-oomd.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=&systemd-oomd diff --git a/systemd/full/system/systemd-resolved.service b/systemd/full/system/systemd-resolved.service index 03d3528901..fd36871e46 100644 --- a/systemd/full/system/systemd-resolved.service +++ b/systemd/full/system/systemd-resolved.service @@ -1,2 +1,2 @@ [Service] -NoNewPrivileges=no \ No newline at end of file +AppArmorProfile=&systemd-resolved diff --git a/systemd/full/system/systemd-rfkill.service b/systemd/full/system/systemd-rfkill.service new file mode 100644 index 0000000000..4abf222d5c --- /dev/null +++ b/systemd/full/system/systemd-rfkill.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=&systemd-rfkill diff --git a/systemd/full/system/systemd-timedated.service b/systemd/full/system/systemd-timedated.service index 03d3528901..78dd0193d1 100644 --- a/systemd/full/system/systemd-timedated.service +++ b/systemd/full/system/systemd-timedated.service @@ -1,2 +1,2 @@ [Service] -NoNewPrivileges=no \ No newline at end of file +AppArmorProfile=&systemd-timedated diff --git a/systemd/full/system/systemd-timesyncd.service b/systemd/full/system/systemd-timesyncd.service new file mode 100644 index 0000000000..0cd6fefbfb --- /dev/null +++ b/systemd/full/system/systemd-timesyncd.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=&systemd-timesyncd diff --git a/systemd/full/system/systemd-userdbd.service b/systemd/full/system/systemd-userdbd.service index 03d3528901..d3771658d3 100644 --- a/systemd/full/system/systemd-userdbd.service +++ b/systemd/full/system/systemd-userdbd.service @@ -1,2 +1,2 @@ [Service] -NoNewPrivileges=no \ No newline at end of file +AppArmorProfile=&systemd-userdbd diff --git a/systemd/full/system/upower.service b/systemd/full/system/upower.service index 03d3528901..082e8f0fa0 100644 --- a/systemd/full/system/upower.service +++ b/systemd/full/system/upower.service @@ -1,2 +1,2 @@ [Service] -NoNewPrivileges=no \ No newline at end of file +AppArmorProfile=&upowerd diff --git a/systemd/full/system/usb_modeswitch@.service b/systemd/full/system/usb_modeswitch@.service new file mode 100644 index 0000000000..0eca1db25c --- /dev/null +++ b/systemd/full/system/usb_modeswitch@.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=usb_modeswitch.service \ No newline at end of file diff --git a/systemd/full/user/filter-chain.service b/systemd/full/user/filter-chain.service new file mode 100644 index 0000000000..4dd212f513 --- /dev/null +++ b/systemd/full/user/filter-chain.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=&pipewire \ No newline at end of file diff --git a/systemd/full/user/pipewire-media-session.service b/systemd/full/user/pipewire-media-session.service deleted file mode 100644 index c392e82fe4..0000000000 --- a/systemd/full/user/pipewire-media-session.service +++ /dev/null @@ -1,5 +0,0 @@ -[Service] -NoNewPrivileges=no -MemoryDenyWriteExecute=no -LockPersonality=no -RestrictNamespaces=no diff --git a/systemd/full/user/pipewire-pulse.service b/systemd/full/user/pipewire-pulse.service new file mode 100644 index 0000000000..1d35a493ef --- /dev/null +++ b/systemd/full/user/pipewire-pulse.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=&pipewire-pulse \ No newline at end of file diff --git a/systemd/full/user/pipewire.service b/systemd/full/user/pipewire.service new file mode 100644 index 0000000000..4dd212f513 --- /dev/null +++ b/systemd/full/user/pipewire.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=&pipewire \ No newline at end of file diff --git a/systemd/full/user/wireplumber.service b/systemd/full/user/wireplumber.service new file mode 100644 index 0000000000..c47175f403 --- /dev/null +++ b/systemd/full/user/wireplumber.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=&wireplumber \ No newline at end of file diff --git a/systemd/full/user/wireplumber@.service b/systemd/full/user/wireplumber@.service new file mode 100644 index 0000000000..c47175f403 --- /dev/null +++ b/systemd/full/user/wireplumber@.service @@ -0,0 +1,2 @@ +[Service] +AppArmorProfile=&wireplumber \ No newline at end of file diff --git a/tests/autopkgtest/autopkgtest.sh b/tests/autopkgtest/autopkgtest.sh new file mode 100755 index 0000000000..6e316f09f7 --- /dev/null +++ b/tests/autopkgtest/autopkgtest.sh @@ -0,0 +1,96 @@ +#!/usr/bin/env bash +# Run autopkgtest in a VM +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# Ubuntu: +# just img ubuntu 25.10 test +# just create ubuntu25.10 test +# just halt ubuntu25.10 test +# just autopkgtest ubuntu25.10 +# +# Debian: +# just img debian 13 test +# just create debian13 test +# just halt debian13 test +# just autopkgtest debian13 + +set -eu -o pipefail + +readonly COMMAND="$1" +readonly OSINFO="$2" +readonly FLAVOR="test" +readonly VERBOSE=${VERBOSE:-0} + +# The maximum the host can handle +readonly CPUS=16 +readonly RAM=16384 +readonly TIMEOUT=1800 + +# As defined in Justfile +readonly PREFIX="$PREFIX" +readonly VM_DIR="$VM_DIR" +readonly USER="$USER" +readonly PASSWORD="$PASSWORD" +readonly SSH_OPT="$SSH_OPT" + +readonly OUTPUT=".logs/autopkgtest/" +readonly VM_PATH="$VM_DIR/${PREFIX}${OSINFO}-${FLAVOR}.qcow2" +readonly PACKAGES_FILE="tests/autopkgtest/src-packages" +readonly reset='\e[0m' red='\e[0;31m' magenta='\e[0;35m' + +_message() { printf '%b%s%b\n' "$magenta" "$*" "$reset" >&2; } +_verbose() { printf '%b>%b %s\n' "$magenta" "$reset" "$*" >&2; } +_log() { printf '%b%s%b\n' "$red" "$*" "$reset" >&2; } + +_run() { + local pkg="" + coproc C { unbuffer -p ./tests/autopkgtest/autopkgtest.sh test "$OSINFO" 2>&1; } + CMD_PID=$! + while IFS= read -r line <&"${C[0]}"; do + line="${line%$'\r'}" + if [[ $VERBOSE -eq 0 ]]; then + _verbose "$line" + fi + if [[ $line == *">>>> Testing package "* ]]; then + pkg="${line#*">>>> Testing package "}" + pkg="-${pkg%% <<<<*}" + fi + if [[ $line == "Press Enter to resume running tests." ]]; then + # shellcheck disable=SC2086 + ssh -n $SSH_OPT -p 10022 "$USER@localhost" sudo aa-log --raw | while IFS= read -r log; do + _log "$log" + echo "$log" >>"$OUTPUT/aa-log-$(date +%Y%m%d-%H%M%S)$pkg" + done + printf '\n' >&"${C[1]}" # send Enter back over the PTY + fi + done + wait $CMD_PID +} + +_autopkgtest() { + local start_from="openvpn" + local end_at="xfsprogs" + mapfile -t packages <"$PACKAGES_FILE" + + for pkg in "${packages[@]}"; do + [[ "$pkg" < "$start_from" ]] && continue + [[ "$pkg" > "$end_at" ]] && break + _message ">>>> Testing package $pkg <<<<" + autopkgtest "$pkg" --shell --timeout=$TIMEOUT --timeout-factor=4.0 \ + -- qemu --cpus=$CPUS --ram-size=$RAM \ + --user="$USER" --password="$PASSWORD" \ + "$VM_PATH" || true + done +} + +main() { + case "$COMMAND" in + run) _run ;; + test) _autopkgtest ;; + *) exit 1 ;; + esac +} + +mkdir -p "$OUTPUT" +main "$@" diff --git a/tests/autopkgtest/src-packages b/tests/autopkgtest/src-packages new file mode 100644 index 0000000000..657f7fa44f --- /dev/null +++ b/tests/autopkgtest/src-packages @@ -0,0 +1,467 @@ +abook +accountsservice +acpi +acpid +adduser +adequate +akonadi +akonadi-calendar +akonadi-search +alacarte +alsa-utils +amd64-microcode +amule +anacron +android-platform-system-core +android-platform-tools +apport +appstream +apt +apt-file +apt-forktracer +apt-listchanges +apt-show-versions +apt-xapian-index +aptdaemon +aptitude +arandr +archivemount +arduino +arduino-builder +arduino-ctags +aspell +at +at-spi2-core +atool +atril +audit +avahi +baloo-kf5 +baobab +base-files +bcron +bind9 +blueman +bluez +bmon +bolt +borgbackup +borgbackup2 +breezy +brltty +btop +btrfs-progs +busybox +calibre +ccze +cheese +cifs-utils +claws-mail +cmus +cockpit +colord +command-not-found +compton +conky +console-setup +containerd +containerd-app +convertall +coreutils +coreutils-from +cpu-checker +cpuid +cracklib2 +cron +cronie +cryptsetup +cups +cups-browsed +cups-filters +cups-pdf +cups-pk-helper +d-conf +dconf +dconf-editor +ddclient +ddcutil +debconf +debian-security-support +debianutils +deborphan +debsecan +debsums +debtags +deja-dup +desktop-file-utils +devscripts +dfc +dh-runit +dhcpcd +dictionaries-common +dino-im +dkms +dleyna +dleyna-renderer +dleyna-server +dlocate +dmidecode +docker.io +docker.io-app +dolphin +dosfstools +dpkg +dput +dput-ng +dunst +e2fsprogs +earlyoom +edid-decode +eject +elinks +engrampa +epiphany-browser +etckeeper +evince +evolution-data-server +exim4 +exo +f3 +fail2ban +fatresize +ffmpeg +ffmpegthumbnailer +file-roller +filezilla +finalrd +firefox +firejail +firewalld +flameshot +flatpak +foliate +font-manager +fontconfig +foomatic-filters +fping +fprintd +fritzing +fuse +fuse-overlayfs +fuse3 +fuseiso +fwupd +fwupd-snap +gajim +gamemode +ganyremote +gcr +gcr4 +gdisk +gdk-pixbuf +gdm3 +geoclue-2.0 +gimp +git +git-buildpackage +git-filter-repo +gitg +gjs +glib-networking +glib2.0 +glibc +gnome-boxes +gnome-browser-connector +gnome-calculator +gnome-calendar +gnome-characters +gnome-clocks +gnome-console +gnome-contacts +gnome-control-center +gnome-disk-utility +gnome-firmware +gnome-font-viewer +gnome-initial-setup +gnome-keyring +gnome-logs +gnome-maps +gnome-music +gnome-online-accounts +gnome-remote-desktop +gnome-session +gnome-settings-daemon +gnome-shell +gnome-shell-extension-desktop-icons-ng +gnome-shell-extension-gsconnect +gnome-shell-extension-manager +gnome-software +gnome-sushi +gnome-system-monitor +gnome-terminal +gnome-text-editor +gnome-tour +gnome-tweaks +gnome-user-share +gnome-weather +gnupg2 +google-android-installers +gpa +gparted +gpodder +grub-legacy-ec2 +grub2 +gsimplecal +gsmartcontrol +gtk+3.0 +gtk4 +gvfs +hardinfo +haveged +hdparm +hexchat +highlight +homebank +hostname +hplip +htop +hugo +hw-probe +hwinfo +i3lock +i3lock-fancy +ibus +ibus-table +iio-sensor-proxy +im-config +imv +init-system-helpers +initramfs-tools +intel-microcode +inxi +ioping +ipcalc +iproute2 +irqbalance +iw +iwd +jackd2 +jekyll +jgmenu +jmtpfs +kanyremote +kbd +kconfig +kde-cli-tools +kded +kdepim-runtime +kdump-tools +keepassxc +kerneloops +kexec-tools +kglobalaccel +kinfocenter +klibc +kmail +kmod +knotes +kodi +konsole +kservice +kwallet-kf5 +kwalletcli +kwalletmanager +kwin +labwc +landscape-client +libcaca +libcap-ng +libebook-tools-perl +libfile-mimeinfo-perl +libgnomekbd +libhugetlbfs +libreoffice +libvirt +libvirt-dbus +light +light-locker +linux +linux-base +lm-sensors +logrotate +loupe +low-memory-monitor +lsb +lsb-release-minimal +lsscsi +lvm2 +lxappearance +lxqt-about +lxqt-config +lxqt-globalkeys +lxqt-notificationd +lxqt-panel +lxqt-powermanagement +lxqt-runner +lxqt-session +lynx +macchanger +makedumpfile +man-db +mate-notification-daemon +mdadm +mdevctl +mediainfo +merkaartor +mesa-demos +metadata-cleaner +minitube +mkcert +mkvtoolnix +modemmanager +molly-guard +monitorix +mono +mousepad +mpd +mpv +msr-tools +mtools +mtr +multipath-tools +mumble +mutt +mutter +nautilus +nautilus-dropbox +needrestart +nemo +net-tools +netplan.io +network-manager +network-manager-openvpn +networkd-dispatcher +nfs-utils +nftables +nmap +ntfs-3g +numlockx +nvidia-graphics-drivers-470 +nvidia-graphics-drivers-470-server +nvidia-graphics-drivers-535 +nvidia-graphics-drivers-535-server +nvidia-graphics-drivers-550 +nvidia-graphics-drivers-550-server +nvidia-graphics-drivers-565-server +nvidia-graphics-drivers-570 +nvidia-graphics-drivers-570-server +nvidia-graphics-drivers-575 +nvidia-graphics-drivers-575-server +nvidia-settings +nvtop +obconf +obexfs +obexftp +obexpushd +okular +open-iscsi +openbox +opensc +openssh +openvpn +orage +os-prober +packagekit +pam +parted +password-store +pavucontrol +pciutils +pcsc-lite +picom +pinentry +pipewire +pkgbinarymangler +plank +plasma-browser-integration +plasma-desktop +plasma-disks +plasma-workspace +plocate +plymouth +policykit-1 +policykit-1-gnome +pollinate +poppler +popularity-contest +power-profiles-daemon +powerdevil +powermgmt-base +procps +psi +psi-plus +psmisc +pulseaudio +pulseeffects +python3-defaults +qbittorrent +qemu +qnapi +qpdfview +qt5ct +qt6-tools +qtchooser +qtox +qttools-opensource-src +quiterss +reboot-notifier +reiserfsprogs +remmina +repo +reportbug +reprepro +ristretto +rng-tools-debian +rng-tools5 +rpcbind +rpi-imager +rsyslog +rtkit +rust-gping +s3fs-fuse +samba +scrcpy +scrot +sdcv +sddm +seahorse +session-migration +shadow +shim-signed +simple-scan +slirp4netns +smartmontools +smplayer +smtube +snapd +sysstat +system-config-printer +systemd +systemd-cron +sysvinit +telepathy-mission-control-5 +texinfo +thin-provisioning-tools +ubuntu-advantage-tools +ubuntu-drivers-common +ubuntu-fan +ubuntu-release-upgrader +unattended-upgrades +update-manager +update-notifier +usbutils +util-linux +wireless-tools +wireshark +x11-xserver-utils +xfsprogs diff --git a/tests/check.sh b/tests/check.sh index 3ddda98278..2265cf91ee 100644 --- a/tests/check.sh +++ b/tests/check.sh @@ -1,174 +1,693 @@ #!/usr/bin/env bash # apparmor.d - Full set of apparmor profiles -# Copyright (C) 2024 Alexandre Pujol +# Copyright (C) 2024-2025 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only -# Usage: make check +# Usage: just check # shellcheck disable=SC2044 set -eu -o pipefail -readonly APPARMORD="apparmor.d" -readonly HEADERS=( - "# apparmor.d - Full set of apparmor profiles" - "# Copyright (C) " - "# SPDX-License-Identifier: GPL-2.0-only" -) - -_die() { - echo -e "\033[1;31m ✗ Error: \033[0m$*" - exit 1 +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 +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() { + local name="$1" file="$2" + shift 2 + printf '%bwarning%b %s(%b%s%b): %s\n' "$fgYellow" "$reset" "$name" "$fgWhite" "$file" "$reset" "$*" +} +_err() { + local name="$1" file="$2" + shift 2 + printf ' %berror%b %s(%b%s%b): %s\n' "$fgRed" "$reset" "$name" "$fgWhite" "$file" "$reset" "$*" + echo "true" >"$RES" } -_ensure_header() { - local file="$1" - for header in "${HEADERS[@]}"; do - if ! grep -q "^$header" "$file"; then - _die "$file does not contain '$header'" +_in_array() { + local item needle="$1" + shift + for item in "$@"; do + if [[ "${item}" == "${needle}" ]]; then + return 0 fi done + return 1 +} + +_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 + if _in_array "$check" "${_check_is_disabled[@]}"; then + return 1 + fi + return 0 + fi + return 1 } -_ensure_indentation() { +_wait() { + local -n job=$1 + job=$((job + 1)) + if ((job >= MAX_JOBS)); then + wait -n + job=$((job - 1)) + fi +} + +_IGNORE_LINT_BLOCK=false +readonly _IGNORE_LINT="#aa:lint ignore" +_ignore_lint() { + local checks line="$1" + + if [[ "$line" =~ ^[[:space:]]*$_IGNORE_LINT=.*$ ]]; then + # Start of an ignore block (or file-wide if in header) + checks="${line#*"$_IGNORE_LINT="}" + 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 + _IGNORE_LINT_BLOCK=false + _check_is_disabled=() + + elif [[ $_IGNORE_LINT_BLOCK == true ]]; then + # Nothing to do, we are in a block/paragraph + return 0 + + elif [[ "$line" == *"$_IGNORE_LINT="* ]]; then + # Inline ignore (or file-wide if in header) + checks="${line#*"$_IGNORE_LINT="}" + 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 + # Do not clear if file-wide ignore is set + if ! $_FILE_IGNORE_ALL; then + _check_is_disabled=() + fi + fi +} + +_check() { local file="$1" - local in_profile=false - local first_line_after_profile=true - 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)) + _ignore_lint "$line" - if [[ "$line" =~ $'\t' ]]; then - _die "$file:$line_number: tabs are not allowed." + # Style check + if [[ $line_number -lt 10 ]]; then + _check_header fi + _check_tabs + _check_trailing + _check_indentation + _check_vim + _check_udev - if [[ "$line" =~ ^profile ]]; then - in_profile=true - first_line_after_profile=true + # The following checks do not apply to commented lines + [[ "$line" =~ ^[[:space:]]*# ]] && continue + if [[ "$line" =~ ,[[:space:]]*# ]]; then + line="${line%%#*}" + fi - elif [[ "$line" =~ [[:space:]]+$ ]]; then - _die "$file:$line_number: line has trailing whitespace." + # Rules checks + _check_abstractions + _check_directory_mark + _check_equivalent + _check_too_wide + _check_transition + _check_useless + _check_tunables - elif $in_profile; then - if $first_line_after_profile; then - local leading_spaces="${line%%[! ]*}" - local num_spaces=${#leading_spaces} - if ((num_spaces != 2)); then - _die "$file: profile must have a two-space indentation." - fi - first_line_after_profile=false + # Guidelines check + _check_abi + _check_include + _check_profile + _check_subprofiles + done <"$file" + + # Results + _res_abi + _res_include + _res_profile + _res_subprofiles + _res_header + _res_vim +} + +# Rules checks: security, compatibility, and rule issues + +readonly ABS="abstractions" +readonly ABS_DANGEROUS=(dbus dbus-session dbus-system dbus-accessibility user-tmp) +declare -A ABS_DEPRECATED=( + ["nameservice"]="nameservice-strict" + ["bash"]="shells" + ["X"]="X-strict" + ["gtk"]="gtk-strict" + ["wayland"]="wayland-strict" + ["dbus-accessibility-strict"]="bus-accessibility" + ["dbus-network-manager-strict"]="network-manager-observe" + ["dbus-session-strict"]="bus-session" + ["dbus-system-strict"]="bus-system" + ["gnome"]="gnome-strict" + ["kde"]="kde-strict" +) +declare -A ABS_AUTOMATIC=( + ["base-strict"]="base" + ["attached/base"]="base" + ["attached/consoles"]="consoles" + ["attached/nameservice-strict"]="nameservice-strict" + ["bus/accessibility/own"]="" + ["bus/session/own"]="" + ["bus/system/own"]="" +) + +_check_abstractions() { + _is_enabled abstractions || return 0 + + local absname + for absname in "${ABS_DANGEROUS[@]}"; do + if [[ "$line" == *"<$ABS/$absname>"* ]]; then + _err abstractions "$file:$line_number" "dangerous abstraction '<$ABS/$absname>'" + fi + done + for absname in "${!ABS_DEPRECATED[@]}"; do + if [[ "$line" == *"<$ABS/$absname>"* ]]; then + _err abstractions "$file:$line_number" "deprecated abstraction '<$ABS/$absname>', use '<$ABS/${ABS_DEPRECATED[$absname]}>' instead" + fi + done + for absname in "${!ABS_AUTOMATIC[@]}"; do + if [[ "$line" == *"<$ABS/$absname>"* ]]; then + msg="the '<$ABS/$absname>' abstraction" + if [[ -z "${ABS_AUTOMATIC[$absname]}" ]]; then + msg+=" is automatically included when needed and does not need to be used" else - local leading_spaces="${line%%[! ]*}" - local num_spaces=${#leading_spaces} - - if ((num_spaces % 2 != 0)); then - ok=false - for offset in 5 11; do - num_spaces=$((num_spaces - offset)) - if ((num_spaces < 0)); then - break - fi - if ((num_spaces % 2 == 0)); then - ok=true - break - fi - done - - if ! $ok; then - _die "$file:$line_number: invalid indentation." + msg+=" should not be used directly, use '<$ABS/${ABS_AUTOMATIC[$absname]}>' instead" + fi + _err abstractions "$file:$line_number" "$msg" + fi + done + if [[ "$line" == *"<$ABS/ubuntu-"*">"* ]]; then + _err abstractions "$file:$line_number" "deprecated, ubuntu only abstraction '<$ABS/$absname>'" + fi +} + +readonly DIRECTORIES=('@{HOME}' '@{MOUNTS}' '@{bin}' '@{sbin}' '@{lib}' '@{tmp}' '_dirs}' '_DIR}') +_check_directory_mark() { + _is_enabled directory-mark || return 0 + for pattern in "${DIRECTORIES[@]}"; do + if [[ "$line" == *"$pattern"* ]]; then + [[ "$line" == *'='* ]] && continue + if [[ ! "$line" == *"$pattern/"* ]]; then + _err directory-mark "$file:$line_number" "missing directory mark: '$pattern' instead of '$pattern/'" + fi + fi + done +} + +declare -A EQUIVALENTS=( + ["awk"]="{m,g,}awk" + ["gawk"]="{m,g,}awk" + ["grep"]="{,e}grep" + ["gs"]="gs{,.bin}" + ["which"]="which{,.debianutils}" + ["xtables-legacy-multi"]="xtables-{nft,legacy}-multi" + ["xtables-nft-multi"]="xtables-{nft,legacy}-multi" +) +_check_equivalent() { + _is_enabled equivalent || return 0 + local prgmname + for prgmname in "${!EQUIVALENTS[@]}"; do + if [[ "$line" == *"/$prgmname "* ]]; then + if [[ ! "$line" == *"${EQUIVALENTS[$prgmname]}"* ]]; then + _err equivalent "$file:$line_number" "missing equivalent program: '@{bin}/$prgmname' instead of '@{bin}/${EQUIVALENTS[$prgmname]}'" + fi + fi + done +} + +readonly TOOWIDE=('/' '/tmp/' '/var/tmp/' '@{tmp}/' '/etc/' '/dev/shm/' '@{run}/user/@{uid}/') +_check_too_wide() { + _is_enabled too-wide || return 0 + if [[ "$line" == *" file,"* ]]; then + _warn too-wide "$file:$line_number" "rule too wide: 'file,'" + fi + for path in "${TOOWIDE[@]}"; do + for pattern in "$path**" "$path*" "$path{,**}"; do + if [[ "$line" == *" $pattern "* ]]; then + _warn too-wide "$file:$line_number" "rule too wide: '$pattern'" + fi + done + done +} + +readonly TRANSITION_MUST_CI=( # Must transition to 'ix' or 'Cx' + chgrp chmod chown cp find head install link ln ls mkdir mktemp mv rm rmdir + sed shred stat tail tee test timeout touch truncate unlink +) +readonly TRANSITION_MUST_PC=( # Must transition to 'Px' + ischroot who +) +readonly TRANSITION_MUST_C=( # Must transition to 'Cx' + sysctl kmod pgrep pkill pkexec sudo systemctl udevadm + fusermount fusermount3 fusermount{,3} + nvim vim sensible-editor +) +_check_transition() { + _is_enabled transition || return 0 + if [[ "$line" =~ [pP]ix, ]]; then + _err transition "$file:$line_number" "'Pix' transition leads to nondeterministic confinement" + fi + for prgmname in "${!TRANSITION_MUST_CI[@]}"; do + if [[ "$line" =~ "/${TRANSITION_MUST_CI[$prgmname]} ".*([uU]x|[pP][uU]x|[pP]x) ]]; then + _err transition "$file:$line_number" \ + "@{bin}/${TRANSITION_MUST_CI[$prgmname]} should be used inherited: 'ix' | 'Cx'" + fi + done + for prgmname in "${!TRANSITION_MUST_PC[@]}"; do + if [[ "$line" =~ "/${TRANSITION_MUST_PC[$prgmname]} ".*(Pix|ix) ]]; then + _err transition "$file:$line_number" \ + "@{bin}/${TRANSITION_MUST_PC[$prgmname]} should transition to another (sub)profile with 'Px' or 'Cx'" + fi + done + for prgmname in "${!TRANSITION_MUST_C[@]}"; do + if [[ "$line" =~ "/${TRANSITION_MUST_C[$prgmname]} ".*([pP]ix|[uU]x|[pP][uU]x|ix) ]]; then + _warn transition "$file:$line_number" \ + "@{bin}/${TRANSITION_MUST_C[$prgmname]} should transition to a subprofile with 'Cx'" + fi + done +} + +readonly USELESS=( + 'ptrace readby' 'ptrace (readby)' + '/usr/share/locale/' + '@{sys}/devices/system/cpu/online' + '@{sys}/devices/system/cpu/possible' + '@{sys}/kernel/mm/transparent_hugepage/hpage_pmd_size' + '@{PROC}/@{pid}/auxv' '@{PROC}/@{pid}/maps' '@{PROC}/@{pid}/status' '@{PROC}/cpuinfo' + '@{PROC}/filesystems' '@{PROC}/meminfo' '@{PROC}/stat' + '@{PROC}/sys/kernel/cap_last_cap' '@{PROC}/sys/kernel/ngroups_max' + '@{PROC}/sys/kernel/version' '@{PROC}/sys/vm/overcommit_memory' + '/dev/full' '/dev/zero' +) +_check_useless() { + _is_enabled useless || return 0 + for rule in "${!USELESS[@]}"; do + if [[ "$line" == *"${USELESS[$rule]}"* ]]; then + _err useless "$file:$line_number" "rule already included in the base abstraction, remove it" + fi + done +} + +declare -A TUNABLES=( + # User variables + ["(@\{HOME\}/|/home/[^/]+/).cache"]="@{user_cache_dirs}" + ["(@\{HOME\}/|/home/[^/]+/).config"]="@{user_config_dirs}" + ["(@\{HOME\}/|/home/[^/]+/).local/share"]="@{user_share_dirs}" + ["(@\{HOME\}/|/home/[^/]+/).local/state"]="@{user_state_dirs}" + ["(@\{HOME\}/|/home/[^/]+/).local/bin"]="@{user_bin_dirs}" + ["(@\{HOME\}/|/home/[^/]+/).local/lib"]="@{user_lib_dirs}" + ["(@\{HOME\}/|/home/[^/]+/).ssh"]="@{HOME}/@{XDG_SSH_DIR}" + ["(@\{HOME\}/|/home/[^/]+/).gnupg"]="@{HOME}/@{XDG_GPG_DIR}" + ["/home/[^/]+/"]="@{HOME}/" + + # System variables + ["/usr/lib(|32|64|exec)"]='@{lib}' + ["/usr/sbin"]='@{sbin}' + ["/usr/bin"]='@{bin}' + ["(x86_64|amd64|i386|i686)"]='@{arch}' + ["(@\{arch\}|x86_64|amd64|i386|i686)-*linux-gnu[^/]?"]='@{multiarch}' + ["/usr/etc/"]='@{etc_ro}/' + ["/boot/(|efi/)"]="@{efi}/" + ["/efi/"]="@{efi}/" + ["/var/run/"]='@{run}/' + ["/run/"]='@{run}/' + ["user/[0-9]*/"]='user/@{uid}/' + ["/tmp/user/[^/]+/"]='@{tmp}/' + ["/sys/"]='@{sys}/' + ["/proc/"]='@{PROC}/' + ["1000"]="@{uid}" + + # Some system glob + [":not.active.yet"]="@{busname}" + [":1.[0-9]*"]="@{busname}" + ["peer=\([^)]*:\*[^)]*\)"]="@{busname}" + ["(@\{bin\}|/usr/bin)/(|ba|da)sh "]="@{sh_path}" + ["@\{lib\}/modules/[^/*]+/"]="@{lib}/modules/*/" +) +_check_tunables() { + _is_enabled tunables || return 0 + for pattern in "${!TUNABLES[@]}"; do + rpattern="$pattern" + [[ "$rpattern" == /* ]] && rpattern=" $rpattern" + if [[ "$line" =~ $rpattern ]]; then + match="${BASH_REMATCH[0]}" + _err tunables "$file:$line_number" "variable '${TUNABLES[$pattern]}' must be used instead of: $match" + fi + done +} + +# Guidelines check: https://apparmor.pujol.io/development/guidelines/ + +RES_ABI=false +readonly ABI_SYNTAX='abi ,' +_check_abi() { + _is_enabled abi || return 0 + if [[ "$line" == *"$ABI_SYNTAX" ]]; then + RES_ABI=true + fi +} +_res_abi() { + _is_enabled abi || return 0 + if ! $RES_ABI; then + _err abi "$file" "missing 'abi ,'" + fi +} + +RES_INCLUDE=false +_check_include() { + _is_enabled include || return 0 + if [[ "$line" == *"${include}"* ]]; then + RES_INCLUDE=true + fi +} +_res_include() { + _is_enabled include || return 0 + if ! $RES_INCLUDE; then + _err include "$file" "missing '$include'" + fi +} + +RES_PROFILE=false +_check_profile() { + _is_enabled profile || return 0 + if [[ "$file" == *"/namespaces/"* ]]; then + ns="${file#*namespaces/}" + ns="${ns%%/*}" + if [[ "$line" =~ ^"profile :$ns:$name" ]]; then + RES_PROFILE=true + fi + else + if [[ "$line" =~ ^"profile $name" ]]; then + RES_PROFILE=true + fi + fi +} +_res_profile() { + _is_enabled profile || return 0 + if ! $RES_PROFILE; then + if [[ "$file" == *"/namespaces/"* ]]; then + ns="${file#*namespaces/}" + ns="${ns%%/*}" + _err profile "$file" "missing profile name: 'profile :$ns:$name'" + else + _err profile "$file" "missing profile name: 'profile $name'" + fi + fi +} + +# Style check + +readonly HEADERS=( + "# apparmor.d - Full set of apparmor profiles" + "# Copyright (C) " + "# SPDX-License-Identifier: GPL-2.0-only" +) +_RES_HEADER=(false false false) +_check_header() { + _is_enabled header || return 0 + for idx in "${!HEADERS[@]}"; do + if [[ "$line" == "${HEADERS[$idx]}"* ]]; then + _RES_HEADER[idx]=true + break + fi + done +} +_res_header() { + _is_enabled header || return 0 + for idx in "${!_RES_HEADER[@]}"; do + if ${_RES_HEADER[$idx]}; then + continue + fi + _err header "$file" "missing header: '${HEADERS[$idx]}'" + done +} + +_check_tabs() { + _is_enabled tabs || return 0 + if [[ "$line" =~ $'\t' ]]; then + _err tabs "$file:$line_number" "tabs are not allowed" + fi +} + +_check_trailing() { + _is_enabled trailing || return 0 + if [[ "$line" =~ [[:space:]]+$ ]]; then + _err trailing "$file:$line_number" "line has trailing whitespace" + fi +} + +_CHECK_IN_PROFILE=false +_CHECK_FIRST_LINE_AFTER_PROFILE=true +_check_indentation() { + _is_enabled indentation || return 0 + if [[ "$line" =~ ^profile ]]; then + _CHECK_IN_PROFILE=true + _CHECK_FIRST_LINE_AFTER_PROFILE=true + + elif $_CHECK_IN_PROFILE; then + if $_CHECK_FIRST_LINE_AFTER_PROFILE; then + local leading_spaces="${line%%[! ]*}" + local num_spaces=${#leading_spaces} + if ((num_spaces != 2)); then + _err indentation "$file:$line_number" "profile must have a two-space indentation" + fi + _CHECK_FIRST_LINE_AFTER_PROFILE=false + + else + local leading_spaces="${line%%[! ]*}" + local num_spaces=${#leading_spaces} + + if ((num_spaces % 2 != 0)); then + ok=false + for offset in 5 11; do + num_spaces=$((num_spaces - offset)) + if ((num_spaces < 0)); then + break fi + if ((num_spaces % 2 == 0)); then + ok=true + break + fi + done + + if ! $ok; then + _err indentation "$file:$line_number" "invalid indentation" fi fi fi - done <"$file" + fi } -_ensure_include() { - local file="$1" - local include="$2" - if ! grep -q "^ *${include}$" "$file"; then - _die "$file does not contain '$include'" +_CHEK_IN_SUBPROFILE=false +declare -A _RES_SUBPROFILES +_check_subprofiles() { + _is_enabled subprofiles || return 0 + if [[ "$line" =~ ^(' ')+'profile '(.*)' {' ]]; then + indentation="${BASH_REMATCH[1]}" + subprofile="${BASH_REMATCH[2]}" + subprofile="${subprofile%% *}" + if [[ "$file" == *"/namespaces/"* ]]; then + ns="${file#*namespaces/}" + ns="${ns%%/*}" + include="${indentation}include if exists " + else + include="${indentation}include if exists " + fi + _RES_SUBPROFILES["$subprofile"]="$name//$subprofile does not contain '$include'" + _CHEK_IN_SUBPROFILE=true + elif $_CHEK_IN_SUBPROFILE; then + if [[ "$line" == *"$include" ]]; then + _RES_SUBPROFILES["$subprofile"]=true + fi fi } +_res_subprofiles() { + _is_enabled subprofiles || return 0 + for msg in "${_RES_SUBPROFILES[@]}"; do + if [[ $msg == true ]]; then + continue + fi + _err subprofiles "$file" "$msg" + done +} -_ensure_abi() { - local file="$1" - if ! grep -q "^ *abi ," "$file"; then - _die "$file does not contain 'abi ,'" +readonly VIM_SYNTAX="# vim:syntax=apparmor" +RES_VIM=false +_check_vim() { + _is_enabled vim || return 0 + if [[ "$line" =~ ^"$VIM_SYNTAX" ]]; then + RES_VIM=true + fi +} +_res_vim() { + _is_enabled vim || return 0 + if ! $RES_VIM; then + _err vim "$file" "missing vim syntax: '$VIM_SYNTAX'" fi } -_ensure_vim() { - local file="$1" - if ! grep -q "^# vim:syntax=apparmor" "$file"; then - _die "$file does not contain '# vim:syntax=apparmor'" +_check_udev() { + _is_enabled udev || return 0 + if [[ "$line" == *"@{run}/udev/data/"* ]]; then + if [[ "$line" != *"#"* ]]; then + _err udev "$file:$line_number" "udev data path without a description comment" + fi fi } +check_sbin() { + local file name jobs + mapfile -t sbin <"$SBIN_LIST" + _msg "Ensuring '@{bin}' and '@{sbin}' are correctly used in profiles" + + jobs=0 + for name in "${sbin[@]}"; do + ( + mapfile -t files < <( + grep --line-number --recursive -P "(^|[[:space:]])@{bin}/$name([[:space:]]|$)(?!.*$_IGNORE_LINT=sbin)" "$APPARMORD" | + cut -d: -f1,2 + ) + for file in "${files[@]}"; do + _err sbin "$file" "contains '@{bin}/$name' instead of '@{sbin}/$name'" + done + ) & + _wait jobs + done + wait + + local pattern='[[:alnum:]_.-]+' # Pattern for valid file names + jobs=0 + mapfile -t files < <(grep --line-number --recursive -E "(^|[[:space:]])@{sbin}/$pattern([[:space:]]|$)" "$APPARMORD" | cut -d: -f1,2) + for file in "${files[@]}"; do + ( + while read -r match; do + name="${match/\@\{sbin\}\//}" + if ! _in_array "$name" "${sbin[@]}"; then + _err bin "$file" "contains '@{sbin}/$name' but it is not in sbin.list" + fi + done < <(grep --only-matching -E "@\{sbin\}/$pattern" "${file%%:*}") + ) & + _wait jobs + done + wait +} + check_profiles() { - echo -e "\033[1m â‹… \033[0mChecking if all profiles contain:" - echo " - apparmor.d header & license" - echo " - Check indentation: 2 spaces" - echo " - Check for trailing whitespaces" - echo " - 'abi ,'" - echo " - 'profile '" - echo " - 'include if exists '" - echo " - include if exists local for subprofiles" - echo " - vim:syntax=apparmor" - directories=("$APPARMORD/groups/*" "$APPARMORD/profiles-*-*") - # shellcheck disable=SC2068 - for dir in ${directories[@]}; do - for file in $(find "$dir" -maxdepth 1 -type f); do - case "$file" in */README.md) continue ;; esac + _msg "Checking profiles" + mapfile -t files < <( + find "$APPARMORD" \( -path "$APPARMORD/abstractions" -o -path "$APPARMORD/local" -o -path "$APPARMORD/tunables" -o -path "$APPARMORD/mappings" \) \ + -prune -o -type f -print + ) + jobs=0 + WITH_CHECK=( + abstractions directory-mark equivalent too-wide useless transition tunables + abi include profile header tabs trailing indentation subprofiles vim udev + ) + for file in "${files[@]}"; do + ( name="$(basename "$file")" name="${name/.apparmor.d/}" - include="include if exists " - _ensure_header "$file" - _ensure_indentation "$file" - _ensure_include "$file" "$include" - _ensure_abi "$file" - _ensure_vim "$file" - if ! grep -q "^profile $name" "$file"; then - _die "$name does not contain 'profile $name'" + if [[ "$file" == *"/namespaces/"* ]]; then + ns="${file#*namespaces/}" + ns="${ns%%/*}" + include="include if exists " + else + include="include if exists " fi - mapfile -t subrofiles < <(grep "^ *profile*" "$file" | awk '{print $2}') - for subprofile in "${subrofiles[@]}"; do - include="include if exists " - if ! grep -q "^ *${include}$" "$file"; then - _die "$name: $name//$subprofile does not contain '$include'" - fi - done - done + _check "$file" + ) & + _wait jobs done + wait } check_abstractions() { - echo -e "\033[1m â‹… \033[0mChecking if all abstractions contain:" - echo " - apparmor.d header & license" - echo " - Check indentation: 2 spaces" - echo " - Check for trailing whitespaces" - echo " - 'abi ,'" - echo " - 'include if exists '" - echo " - vim:syntax=apparmor" - directories=( - "$APPARMORD/abstractions/" "$APPARMORD/abstractions/app/" - "$APPARMORD/abstractions/attached/" - "$APPARMORD/abstractions/bus/" "$APPARMORD/abstractions/common/" + _msg "Checking abstractions" + mapfile -t files < <(find "$APPARMORD/abstractions" -type f -not -path "$APPARMORD/abstractions/*.d/*" 2>/dev/null || true) + jobs=0 + WITH_CHECK=( + abstractions directory-mark equivalent too-wide tunables + abi include header tabs trailing indentation vim udev ) - for dir in "${directories[@]}"; do - for file in $(find "$dir" -maxdepth 1 -type f); do + for file in "${files[@]}"; do + ( name="$(basename "$file")" - root="${dir/${APPARMORD}\/abstractions\//}" - include="include if exists " - _ensure_header "$file" - _ensure_indentation "$file" - _ensure_include "$file" "$include" - _ensure_abi "$file" - _ensure_vim "$file" - done + absdir="${file/${APPARMORD}\//}" + include="include if exists <${absdir}.d>" + _check "$file" + ) & + _wait jobs + done + wait + + mapfile -t files < <( + find "$APPARMORD/abstractions" -type f -path "$APPARMORD/abstractions/*.d/*" 2>/dev/null || true + find "$APPARMORD/mappings" -type f 2>/dev/null || true + ) + # shellcheck disable=SC2034 + jobs=0 + WITH_CHECK=( + abstractions directory-mark equivalent too-wide tunables + header tabs trailing indentation vim udev + ) + for file in "${files[@]}"; do + _check "$file" & + _wait jobs done + wait } +check_sbin check_profiles check_abstractions + +FAIL=$(cat "$RES") +if [[ "$FAIL" == "true" ]]; then + exit 1 +fi diff --git a/tests/cloud-init/archlinux-cosmic.user-data.yml b/tests/cloud-init/archlinux-cosmic.user-data.yml index 70d446076a..bd04af3146 100644 --- a/tests/cloud-init/archlinux-cosmic.user-data.yml +++ b/tests/cloud-init/archlinux-cosmic.user-data.yml @@ -1,38 +1,6 @@ #cloud-config -packages: - # Install core packages - - apparmor - - audit - - base-devel - - firewalld - - qemu-guest-agent - - rng-tools - - spice-vdagent - - # Install usefull core packages - - bash-completion - - git - - htop - - man - - pass - - python-notify2 - - vim - - wget - - # Install basic services - - networkmanager - - cups - - cups-pdf - - system-config-printer - - # Install Graphical Interface - - cosmic - - # Install Applications - - firefox - - chromium - - terminator +packages: *cosmic-packages runcmd: # Regenerate grub.cfg @@ -53,20 +21,7 @@ runcmd: - systemctl enable systemd-timesyncd.service write_files: - # Enable AppArmor in kernel parameters - - path: /etc/default/grub - append: true - content: | - GRUB_CMDLINE_LINUX_DEFAULT="$GRUB_CMDLINE_LINUX_DEFAULT lsm=landlock,lockdown,yama,integrity,apparmor,bpf apparmor.debug=1" - - # Set some bash aliases - - path: /etc/skel/.bashrc - append: true - content: | - [[ -f ~/.bash_aliases ]] && source ~/.bash_aliases - - # Setup shared directory - - path: /etc/fstab - append: true - content: | - 0a31bc478ef8e2461a4b1cc10a24cc4 /home/user/Projects/apparmor.d virtiofs defaults 0 1 + - *grub-enable-apparmor # Enable AppArmor in kernel parameters + - *setup-bash-aliases # Set some bash aliases + - *shared-directory # Setup shared directory + - *disable-printk-ratelimit # Disable printk rate limiting diff --git a/tests/cloud-init/archlinux-gnome.user-data.yml b/tests/cloud-init/archlinux-gnome.user-data.yml index 1fa1c9c1d8..3b0fa4d337 100644 --- a/tests/cloud-init/archlinux-gnome.user-data.yml +++ b/tests/cloud-init/archlinux-gnome.user-data.yml @@ -1,40 +1,6 @@ #cloud-config -packages: - # Install core packages - - apparmor - - base-devel - - firewalld - - qemu-guest-agent - - rng-tools - - spice-vdagent - - # Install usefull core packages - - bash-completion - - git - - htop - - man - - pass - - python-notify2 - - vim - - wget - - # Install basic services - - networkmanager - - cups - - cups-pdf - - system-config-printer - - # Install Graphical Interface - - gnome - - gnome-extra - - seahorse - - alacarte - - # Install Applications - - firefox - - chromium - - terminator +packages: *gnome-packages runcmd: # Regenerate grub.cfg @@ -55,20 +21,7 @@ runcmd: - systemctl enable systemd-timesyncd.service write_files: - # Enable AppArmor in kernel parameters - - path: /etc/default/grub - append: true - content: | - GRUB_CMDLINE_LINUX_DEFAULT="$GRUB_CMDLINE_LINUX_DEFAULT lsm=landlock,lockdown,yama,integrity,apparmor,bpf apparmor.debug=1" - - # Set some bash aliases - - path: /etc/skel/.bashrc - append: true - content: | - [[ -f ~/.bash_aliases ]] && source ~/.bash_aliases - - # Setup shared directory - - path: /etc/fstab - append: true - content: | - 0a31bc478ef8e2461a4b1cc10a24cc4 /home/user/Projects/apparmor.d virtiofs defaults 0 1 + - *grub-enable-apparmor # Enable AppArmor in kernel parameters + - *setup-bash-aliases # Set some bash aliases + - *shared-directory # Setup shared directory + - *disable-printk-ratelimit # Disable printk rate limiting diff --git a/tests/cloud-init/archlinux-kde.user-data.yml b/tests/cloud-init/archlinux-kde.user-data.yml index 5953eab2e2..30374d8571 100644 --- a/tests/cloud-init/archlinux-kde.user-data.yml +++ b/tests/cloud-init/archlinux-kde.user-data.yml @@ -1,42 +1,6 @@ #cloud-config -packages: - # Install core packages - - apparmor - - base-devel - - firewalld - - qemu-guest-agent - - rng-tools - - spice-vdagent - - # Install usefull core packages - - bash-completion - - git - - htop - - man - - pass - - python-notify2 - - vim - - wget - - # Install basic services - - networkmanager - - cups - - cups-pdf - - system-config-printer - - # Install Graphical Interface - - plasma-meta - - sddm - - ark - - dolphin - - konsole - - okular - - # Install Applications - - firefox - - chromium - - terminator +packages: *kde-packages runcmd: # Regenerate grub.cfg @@ -57,20 +21,7 @@ runcmd: - systemctl enable systemd-timesyncd.service write_files: - # Enable AppArmor in kernel parameters - - path: /etc/default/grub - append: true - content: | - GRUB_CMDLINE_LINUX_DEFAULT="$GRUB_CMDLINE_LINUX_DEFAULT lsm=landlock,lockdown,yama,integrity,apparmor,bpf apparmor.debug=1" - - # Set some bash aliases - - path: /etc/skel/.bashrc - append: true - content: | - [[ -f ~/.bash_aliases ]] && source ~/.bash_aliases - - # Setup shared directory - - path: /etc/fstab - append: true - content: | - 0a31bc478ef8e2461a4b1cc10a24cc4 /home/user/Projects/apparmor.d virtiofs defaults 0 1 + - *grub-enable-apparmor # Enable AppArmor in kernel parameters + - *setup-bash-aliases # Set some bash aliases + - *shared-directory # Setup shared directory + - *disable-printk-ratelimit # Disable printk rate limiting diff --git a/tests/cloud-init/archlinux-lxqt.user-data.yml b/tests/cloud-init/archlinux-lxqt.user-data.yml new file mode 100644 index 0000000000..aa9eec4b58 --- /dev/null +++ b/tests/cloud-init/archlinux-lxqt.user-data.yml @@ -0,0 +1,29 @@ +#cloud-config + +packages: *lxqt-packages + +# lxqt-wayland-session kwin + +runcmd: + # Regenerate grub.cfg + - grub-mkconfig -o /boot/grub/grub.cfg + + # Remove swapfile + - swapoff -a + - rm -rf /swap/ + - sed -e "/swap/d" -i /etc/fstab + + # Enable core services + - systemctl enable apparmor + - systemctl enable auditd + - systemctl enable sddm + - systemctl enable NetworkManager + - systemctl enable rngd + - systemctl enable avahi-daemon + - systemctl enable systemd-timesyncd.service + +write_files: + - *grub-enable-apparmor # Enable AppArmor in kernel parameters + - *setup-bash-aliases # Set some bash aliases + - *shared-directory # Setup shared directory + - *disable-printk-ratelimit # Disable printk rate limiting diff --git a/tests/cloud-init/archlinux-server.user-data.yml b/tests/cloud-init/archlinux-server.user-data.yml index e0edaca167..a810996ec3 100644 --- a/tests/cloud-init/archlinux-server.user-data.yml +++ b/tests/cloud-init/archlinux-server.user-data.yml @@ -1,22 +1,6 @@ #cloud-config -packages: - # Install core packages - - apparmor - - base-devel - - qemu-guest-agent - - rng-tools - - spice-vdagent - - # Install usefull core packages - - bash-completion - - git - - htop - - man - - pass - - python-notify2 - - vim - - wget +packages: *core-packages runcmd: # Regenerate grub.cfg @@ -34,34 +18,8 @@ runcmd: - systemctl enable systemd-timesyncd.service write_files: - # Enable AppArmor in kernel parameters - - path: /etc/default/grub - append: true - content: | - GRUB_CMDLINE_LINUX_DEFAULT="$GRUB_CMDLINE_LINUX_DEFAULT lsm=landlock,lockdown,yama,integrity,apparmor,bpf apparmor.debug=1" - - # Set some bash aliases - - path: /etc/skel/.bashrc - append: true - content: | - [[ -f ~/.bash_aliases ]] && source ~/.bash_aliases - - # Setup shared directory - - path: /etc/fstab - append: true - content: | - 0a31bc478ef8e2461a4b1cc10a24cc4 /home/user/Projects/apparmor.d virtiofs defaults 0 1 - - # Network configuration - - path: /etc/systemd/network/20-wired.network - owner: "root:root" - permissions: "0644" - content: | - [Match] - Name=en* - - [Network] - DHCP=yes - - [DHCPv4] - RouteMetric=10 + - *grub-enable-apparmor # Enable AppArmor in kernel parameters + - *setup-bash-aliases # Set some bash aliases + - *shared-directory # Setup shared directory + - *systemd-netword # Network configuration for server + - *disable-printk-ratelimit # Disable printk rate limiting diff --git a/tests/cloud-init/archlinux-xfce.user-data.yml b/tests/cloud-init/archlinux-xfce.user-data.yml index e9f4a78a64..580754103f 100644 --- a/tests/cloud-init/archlinux-xfce.user-data.yml +++ b/tests/cloud-init/archlinux-xfce.user-data.yml @@ -1,40 +1,6 @@ #cloud-config -packages: - # Install core packages - - apparmor - - base-devel - - firewalld - - qemu-guest-agent - - rng-tools - - spice-vdagent - - # Install usefull core packages - - bash-completion - - git - - htop - - man - - pass - - python-notify2 - - vim - - wget - - # Install basic services - - networkmanager - - cups - - cups-pdf - - system-config-printer - - # Install Graphical Interface - - xfce4 - - xfce4-goodies - - lightdm - - lightdm-gtk-greeter - - # Install Applications - - firefox - - chromium - - terminator +packages: *xfce-packages runcmd: # Regenerate grub.cfg @@ -55,20 +21,7 @@ runcmd: - systemctl enable systemd-timesyncd.service write_files: - # Enable AppArmor in kernel parameters - - path: /etc/default/grub - append: true - content: | - GRUB_CMDLINE_LINUX_DEFAULT="$GRUB_CMDLINE_LINUX_DEFAULT lsm=landlock,lockdown,yama,integrity,apparmor,bpf" - - # Set some bash aliases - - path: /etc/skel/.bashrc - append: true - content: | - [[ -f ~/.bash_aliases ]] && source ~/.bash_aliases - - # Setup shared directory - - path: /etc/fstab - append: true - content: | - 0a31bc478ef8e2461a4b1cc10a24cc4 /home/user/Projects/apparmor.d virtiofs defaults 0 1 + - *grub-enable-apparmor # Enable AppArmor in kernel parameters + - *setup-bash-aliases # Set some bash aliases + - *shared-directory # Setup shared directory + - *disable-printk-ratelimit # Disable printk rate limiting diff --git a/tests/cloud-init/archlinux.yml b/tests/cloud-init/archlinux.yml new file mode 100644 index 0000000000..8662fc2ea9 --- /dev/null +++ b/tests/cloud-init/archlinux.yml @@ -0,0 +1,207 @@ +#cloud-config + +core-packages: &core-packages + - apparmor + - base-devel + - bash-completion + - docker + - git + - htop + - just + - man + - pass + - python-notify2 + - qemu-guest-agent + - rng-tools + - spice-vdagent + - vim + - wget + +gnome-packages: &gnome-packages + # Core packages for Archlinux + - apparmor + - base-devel + - bash-completion + - docker + - git + - htop + - just + - linux-firmware + - man + - pass + - python-notify2 + - qemu-guest-agent + - rng-tools + - spice-vdagent + - vim + - wget + + # Desktop packages for Archlinux + - networkmanager + - cups + - cups-pdf + - system-config-printer + - chromium + - firefox + - spice-vdagent + - terminator + + # Install Graphical Interface + - alacarte + - gnome + - gnome-extra + - ptyxis + - seahorse + +kde-packages: &kde-packages + # Core packages for Archlinux + - apparmor + - base-devel + - bash-completion + - docker + - git + - htop + - just + - linux-firmware + - man + - pass + - python-notify2 + - qemu-guest-agent + - rng-tools + - spice-vdagent + - vim + - wget + + # Desktop packages for Archlinux + - networkmanager + - cups + - cups-pdf + - system-config-printer + - chromium + - firefox + - spice-vdagent + - terminator + + # Install Graphical Interface + - plasma-meta + - sddm + - ark + - dolphin + - konsole + - okular + +lxqt-packages: &lxqt-packages + # Core packages for Archlinux + - apparmor + - base-devel + - bash-completion + - docker + - git + - htop + - just + - linux-firmware + - man + - pass + - python-notify2 + - qemu-guest-agent + - rng-tools + - spice-vdagent + - vim + - wget + + # Desktop packages for Archlinux + - networkmanager + - cups + - cups-pdf + - system-config-printer + - chromium + - firefox + - spice-vdagent + - terminator + + # Install Graphical Interface + - lxqt + - breeze-icons + - sddm + +xfce-packages: &xfce-packages + # Core packages for Archlinux + - apparmor + - base-devel + - bash-completion + - docker + - git + - htop + - just + - linux-firmware + - man + - pass + - python-notify2 + - qemu-guest-agent + - rng-tools + - spice-vdagent + - vim + - wget + + # Desktop packages for Archlinux + - networkmanager + - cups + - cups-pdf + - system-config-printer + - chromium + - firefox + - spice-vdagent + - terminator + + # Install Graphical Interface + - xfce4 + - xfce4-goodies + - lightdm + - lightdm-gtk-greeter + + +cosmic-packages: &cosmic-packages + # Core packages for Archlinux + - apparmor + - base-devel + - bash-completion + - docker + - git + - htop + - just + - linux-firmware + - man + - pass + - python-notify2 + - qemu-guest-agent + - rng-tools + - spice-vdagent + - vim + - wget + + # Desktop packages for Archlinux + - networkmanager + - cups + - cups-pdf + - system-config-printer + - chromium + - firefox + - spice-vdagent + - terminator + + # Install Graphical Interface + - cosmic + +# Enable AppArmor in kernel parameters +grub-enable-apparmor: &grub-enable-apparmor + path: /etc/default/grub + append: true + content: | + GRUB_CMDLINE_LINUX_DEFAULT="$GRUB_CMDLINE_LINUX_DEFAULT lsm=landlock,lockdown,yama,integrity,apparmor,bpf apparmor.debug=1" + +# Set some bash aliases +setup-bash-aliases: &setup-bash-aliases + path: /etc/skel/.bashrc + append: true + content: | + [[ -f ~/.bash_aliases ]] && source ~/.bash_aliases diff --git a/tests/cloud-init/common.yml b/tests/cloud-init/common.yml index ac619c879a..180460ef05 100644 --- a/tests/cloud-init/common.yml +++ b/tests/cloud-init/common.yml @@ -7,6 +7,7 @@ users: - name: ${username} plain_text_passwd: ${password} shell: /bin/bash + groups: ["${group}"] ssh_authorized_keys: - ${ssh_key} lock_passwd: false @@ -15,3 +16,41 @@ users: package_update: true package_upgrade: true package_reboot_if_required: false + +# Mount shared directory +shared-directory: &shared-directory + path: /etc/fstab + append: true + content: | + 0a31bc478ef8e2461a4b1cc10a24cc4 /home/user/Projects/apparmor.d virtiofs defaults 0 1 + +# Network configuration for server +systemd-netword: &systemd-netword + path: /etc/systemd/network/20-wired.network + owner: "root:root" + permissions: "0644" + content: | + [Match] + Name=en* + + [Network] + DHCP=yes + + [DHCPv4] + RouteMetric=10 + +# Disable printk rate limiting +disable-printk-ratelimit: &disable-printk-ratelimit + path: /etc/sysctl.d/99-ratelimit.conf + permissions: "0644" + content: | + kernel.printk_ratelimit=0 + kernel.printk_ratelimit_burst=1000 + +# Autopkgtest setup-testbed script +setup-testbed: &setup-testbed + source: + uri: https://salsa.debian.org/ci-team/autopkgtest/-/raw/master/setup-commands/setup-testbed + path: /usr/bin/setup-testbed + permissions: '0755' + diff --git a/tests/cloud-init/debian.yml b/tests/cloud-init/debian.yml new file mode 100644 index 0000000000..1a7d701b8c --- /dev/null +++ b/tests/cloud-init/debian.yml @@ -0,0 +1,99 @@ +#cloud-config + +# Core packages for Debian +core-packages: &core-packages + - apparmor-profiles + - apparmor-utils + - auditd + - build-essential + - config-package-dev + - debhelper + - devscripts + - docker.io + - golang-go + - htop + - just + - libpam-apparmor + - lintian + - qemu-guest-agent + - rsync + - systemd-container + - systemd-coredump + - systemd-homed + - systemd-oomd + - unattended-upgrades + - vim + +gnome-packages: &gnome-packages + # Core packages for Debian + - apparmor-profiles + - apparmor-utils + - auditd + - build-essential + - config-package-dev + - debhelper + - devscripts + - docker.io + - golang-go + - htop + - just + - libpam-apparmor + - lintian + - qemu-guest-agent + - rsync + - systemd-container + - systemd-coredump + - systemd-homed + - systemd-oomd + - unattended-upgrades + - vim + + # Gnome packages for Debian + - spice-vdagent + - task-gnome-desktop + - terminator + - loupe + - ptyxis + +kde-packages: &kde-packages + # Core packages for Debian + - apparmor-profiles + - apparmor-utils + - auditd + - build-essential + - config-package-dev + - debhelper + - devscripts + - docker.io + - golang-go + - htop + - just + - libpam-apparmor + - lintian + - qemu-guest-agent + - rsync + - systemd-container + - systemd-coredump + - systemd-homed + - systemd-oomd + - unattended-upgrades + - vim + + # KDE packages for Debian + - spice-vdagent + - task-kde-desktop + - plasma-workspace-wayland + - terminator + +desktop-runcmd: &desktop-runcmd + # Enable auditd systemd socket + - systemctl enable systemd-journald-audit.socket + + # Install the default kernel and remove the cloud one + - | + export DEBIAN_FRONTEND=noninteractive + apt install -y linux-image-amd64 linux-headers-amd64 + echo "linux-image-$(uname -r) linux-image-$(uname -r)/prerm/removing-running-kernel boolean false" | debconf-set-selections + apt remove -y --purge linux-image-$(uname -r) + apt autoremove -y --purge + update-grub diff --git a/tests/cloud-init/debian12-gnome.user-data.yml b/tests/cloud-init/debian12-gnome.user-data.yml deleted file mode 100644 index 5ce6cedf50..0000000000 --- a/tests/cloud-init/debian12-gnome.user-data.yml +++ /dev/null @@ -1,45 +0,0 @@ -#cloud-config - -packages: - - apparmor-profiles - - auditd - - build-essential - - config-package-dev - - debhelper - - devscripts - - htop - - qemu-guest-agent - - rsync - - spice-vdagent - - task-gnome-desktop - - vim - -runcmd: - - apt-get update -y - - apt-get install -y -t bookworm-backports golang-go - -write_files: - # Add backports repository - - path: /etc/apt/sources.list - append: true - content: deb http://deb.debian.org/debian bookworm-backports main contrib non-free - - # Setup shared directory - - path: /etc/fstab - append: true - content: | - 0a31bc478ef8e2461a4b1cc10a24cc4 /home/user/Projects/apparmor.d virtiofs defaults 0 1 - - # Network configuration - - path: /etc/systemd/network/20-wired.network - owner: "root:root" - permissions: "0644" - content: | - [Match] - Name=en* - - [Network] - DHCP=yes - - [DHCPv4] - RouteMetric=10 diff --git a/tests/cloud-init/debian12-kde.user-data.yml b/tests/cloud-init/debian12-kde.user-data.yml deleted file mode 100644 index 451068db10..0000000000 --- a/tests/cloud-init/debian12-kde.user-data.yml +++ /dev/null @@ -1,31 +0,0 @@ -#cloud-config - -packages: - - apparmor-profiles - - auditd - - build-essential - - config-package-dev - - debhelper - - devscripts - - htop - - qemu-guest-agent - - rsync - - spice-vdagent - - vim - - task-kde-desktop - -runcmd: - - apt-get update -y - - apt-get install -y -t bookworm-backports golang-go - -write_files: - # Add backports repository - - path: /etc/apt/sources.list - append: true - content: deb http://deb.debian.org/debian bookworm-backports main contrib non-free - - # Setup shared directory - - path: /etc/fstab - append: true - content: | - 0a31bc478ef8e2461a4b1cc10a24cc4 /home/user/Projects/apparmor.d virtiofs defaults 0 1 diff --git a/tests/cloud-init/debian12-server.user-data.yml b/tests/cloud-init/debian12-server.user-data.yml deleted file mode 100644 index aef29f5794..0000000000 --- a/tests/cloud-init/debian12-server.user-data.yml +++ /dev/null @@ -1,43 +0,0 @@ -#cloud-config - -packages: - - apparmor-profiles - - auditd - - build-essential - - config-package-dev - - debhelper - - devscripts - - htop - - qemu-guest-agent - - rsync - - vim - -runcmd: - - apt-get update -y - - apt-get install -y -t bookworm-backports golang-go - -write_files: - # Add backports repository - - path: /etc/apt/sources.list - append: true - content: deb http://deb.debian.org/debian bookworm-backports main contrib non-free - - # Setup shared directory - - path: /etc/fstab - append: true - content: | - 0a31bc478ef8e2461a4b1cc10a24cc4 /home/user/Projects/apparmor.d virtiofs defaults 0 1 - - # Network configuration - - path: /etc/systemd/network/20-wired.network - owner: "root:root" - permissions: "0644" - content: | - [Match] - Name=en* - - [Network] - DHCP=yes - - [DHCPv4] - RouteMetric=10 diff --git a/tests/cloud-init/debian13-gnome.user-data.yml b/tests/cloud-init/debian13-gnome.user-data.yml new file mode 100644 index 0000000000..2533afee84 --- /dev/null +++ b/tests/cloud-init/debian13-gnome.user-data.yml @@ -0,0 +1,10 @@ +#cloud-config + +packages: *gnome-packages + +runcmd: *desktop-runcmd + +write_files: + - *shared-directory # Setup shared directory + - *systemd-netword # Network configuration for server + - *disable-printk-ratelimit # Disable printk rate limiting diff --git a/tests/cloud-init/debian13-kde.user-data.yml b/tests/cloud-init/debian13-kde.user-data.yml new file mode 100644 index 0000000000..2540ad46c4 --- /dev/null +++ b/tests/cloud-init/debian13-kde.user-data.yml @@ -0,0 +1,10 @@ +#cloud-config + +packages: *kde-packages + +runcmd: *desktop-runcmd + +write_files: + - *shared-directory # Setup shared directory + - *systemd-netword # Network configuration for server + - *disable-printk-ratelimit # Disable printk rate limiting diff --git a/tests/cloud-init/debian13-server.user-data.yml b/tests/cloud-init/debian13-server.user-data.yml index 1400584baa..9e40454a66 100644 --- a/tests/cloud-init/debian13-server.user-data.yml +++ b/tests/cloud-init/debian13-server.user-data.yml @@ -1,36 +1,13 @@ #cloud-config -packages: - - apparmor-profiles - - auditd - - build-essential - - config-package-dev - - debhelper - - devscripts - - golang-go - - htop - - qemu-guest-agent - - rsync - - vim +packages: *core-packages -write_files: - - # Setup shared directory - - path: /etc/fstab - append: true - content: | - 0a31bc478ef8e2461a4b1cc10a24cc4 /home/user/Projects/apparmor.d virtiofs defaults 0 1 +runcmd: + # Enable auditd systemd socket + - systemctl enable systemd-journald-audit.socket - # Network configuration - - path: /etc/systemd/network/20-wired.network - owner: "root:root" - permissions: "0644" - content: | - [Match] - Name=en* - - [Network] - DHCP=yes +write_files: + - *shared-directory # Setup shared directory + - *systemd-netword # Network configuration for server + - *disable-printk-ratelimit # Disable printk rate limiting - [DHCPv4] - RouteMetric=10 diff --git a/tests/cloud-init/debian13-test.user-data.yml b/tests/cloud-init/debian13-test.user-data.yml new file mode 100644 index 0000000000..57dba4089d --- /dev/null +++ b/tests/cloud-init/debian13-test.user-data.yml @@ -0,0 +1,20 @@ +#cloud-config + +packages: + - apparmor-profiles + - apparmor-utils + - auditd + - htop + - libpam-apparmor + - qemu-guest-agent + - vim + +runcmd: + - systemctl enable systemd-journald-audit.socket + - /usr/bin/setup-testbed + - apt-get update + +write_files: + - *systemd-netword # Network configuration for server + - *disable-printk-ratelimit # Disable printk rate limiting + - *setup-testbed # Autopkgtest setup-testbed script diff --git a/tests/cloud-init/opensuse-gnome.user-data.yml b/tests/cloud-init/opensuse-gnome.user-data.yml index 406b4445da..99ce8b5a3a 100644 --- a/tests/cloud-init/opensuse-gnome.user-data.yml +++ b/tests/cloud-init/opensuse-gnome.user-data.yml @@ -1,21 +1,23 @@ #cloud-config -packages: - - apparmor-profiles - - bash-completion - - distribution-release - - git - - go - - golang-packaging - - htop - - make - - rpmbuild - - rsync - - vim +packages: *gnome-packages + +runcmd: + # Replace SELinux by AppArmor in kernel parameters + - sed -i 's/security=selinux selinux=1/apparmor=1 apparmor.debug=1/g' /etc/default/grub + + # Regenerate grub.cfg + - grub2-mkconfig -o /boot/grub2/grub.cfg + + # Ensure auditd is enabled + - systemctl enable systemd-journald-audit.socket write_files: - # Setup shared directory - - path: /etc/fstab + - *shared-directory # Setup shared directory + - *disable-printk-ratelimit # Disable printk rate limiting + + - path: /etc/sysconfig/displaymanager append: true content: | - 0a31bc478ef8e2461a4b1cc10a24cc4 /home/user/Projects/apparmor.d virtiofs defaults 0 1 + DISPLAYMANAGER="gdm" + diff --git a/tests/cloud-init/opensuse-kde.user-data.yml b/tests/cloud-init/opensuse-kde.user-data.yml index 406b4445da..f43d3cd438 100644 --- a/tests/cloud-init/opensuse-kde.user-data.yml +++ b/tests/cloud-init/opensuse-kde.user-data.yml @@ -1,21 +1,21 @@ #cloud-config -packages: - - apparmor-profiles - - bash-completion - - distribution-release - - git - - go - - golang-packaging - - htop - - make - - rpmbuild - - rsync - - vim +packages: *kde-packages + +# apparmor.debug=1 +runcmd: + # Replace SELinux by AppArmor in kernel parameters + - sed -i 's/security=selinux selinux=1/apparmor=1/g' /etc/default/grub + + # Regenerate grub.cfg + - grub2-mkconfig -o /boot/grub2/grub.cfg write_files: - # Setup shared directory - - path: /etc/fstab + - *shared-directory # Setup shared directory + - *disable-printk-ratelimit # Disable printk rate limiting + + - path: /etc/sysconfig/displaymanager append: true content: | - 0a31bc478ef8e2461a4b1cc10a24cc4 /home/user/Projects/apparmor.d virtiofs defaults 0 1 + DISPLAYMANAGER="sddm" + diff --git a/tests/cloud-init/opensuse-server.user-data.yml b/tests/cloud-init/opensuse-server.user-data.yml index 7699fb0747..4acaab83fd 100644 --- a/tests/cloud-init/opensuse-server.user-data.yml +++ b/tests/cloud-init/opensuse-server.user-data.yml @@ -1,36 +1,15 @@ #cloud-config -packages: - - apparmor-profiles - - bash-completion - - distribution-release - - git - - go - - golang-packaging - - htop - - make - - rpmbuild - - rsync - - vim +packages: *core-packages -write_files: - - # Setup shared directory - - path: /etc/fstab - append: true - content: | - 0a31bc478ef8e2461a4b1cc10a24cc4 /home/user/Projects/apparmor.d virtiofs defaults 0 1 +runcmd: + # Replace SELinux by AppArmor in kernel parameters + - sed -i 's/security=selinux selinux=1/apparmor=1 apparmor.debug=1/g' /etc/default/grub - # Network configuration - - path: /etc/systemd/network/20-wired.network - owner: "root:root" - permissions: "0644" - content: | - [Match] - Name=en* + # Regenerate grub.cfg + - grub2-mkconfig -o /boot/grub2/grub.cfg - [Network] - DHCP=yes - - [DHCPv4] - RouteMetric=10 +write_files: + - *shared-directory # Setup shared directory + - *systemd-netword # Network configuration for server + - *disable-printk-ratelimit # Disable printk rate limiting diff --git a/tests/cloud-init/opensuse.yml b/tests/cloud-init/opensuse.yml new file mode 100644 index 0000000000..ab0954c6ae --- /dev/null +++ b/tests/cloud-init/opensuse.yml @@ -0,0 +1,70 @@ +#cloud-config + +# Core packages for OpenSUSE +core-packages: &core-packages + - pattern:apparmor + - apparmor-profiles + - bash-completion + - distribution-release + - docker + - git + - go + - golang-packaging + - htop + - just + - rpmbuild + - rsync + - systemd-container + - systemd-homed + - vim + +gnome-packages: &gnome-packages + # Core packages for OpenSUSE + - pattern:apparmor + - apparmor-profiles + - bash-completion + - distribution-release + - docker + - git + - go + - golang-packaging + - htop + - just + - rpmbuild + - rsync + - systemd-container + - systemd-homed + - vim + + # Gnome packages for OpenSUSE + - pattern:gnome + - gdm + - spice-vdagent + - terminator + - loupe + - ptyxis + +kde-packages: &kde-packages + # Core packages for OpenSUSE + - pattern:apparmor + - apparmor-profiles + - bash-completion + - distribution-release + - docker + - git + - go + - golang-packaging + - htop + - just + - rpmbuild + - rsync + - systemd-container + - systemd-homed + - vim + + # KDE packages for OpenSUSE + - pattern:kde_plasma + - pattern:kde + - sddm + - spice-vdagent + - terminator diff --git a/tests/cloud-init/ubuntu.yml b/tests/cloud-init/ubuntu.yml new file mode 100644 index 0000000000..b433c60bc6 --- /dev/null +++ b/tests/cloud-init/ubuntu.yml @@ -0,0 +1,121 @@ +#cloud-config + +core-packages: &core-packages + - acpid + - apparmor-profiles + - apparmor-utils + - arptables + - auditd + - build-essential + - config-package-dev + - debhelper + - devscripts + - dkms + - docker.io + - golang-go + - htop + - just + - libpam-apparmor + - lintian + - pipx + - qemu-guest-agent + - rsync + - systemd-container + - systemd-coredump + - systemd-homed + - systemd-oomd + - unattended-upgrades + - vim + +desktop-packages: &desktop-packages + # Core packages for Ubuntu + - apparmor-profiles + - apparmor-utils + - auditd + - build-essential + - config-package-dev + - debhelper + - devscripts + - docker.io + - golang-go + - htop + - just + - libpam-apparmor + - lintian + - pipx + - qemu-guest-agent + - rsync + - systemd-container + - systemd-coredump + - systemd-homed + - systemd-oomd + - unattended-upgrades + - vim + + # Desktop packages for Ubuntu + - spice-vdagent + - terminator + - ubuntu-desktop + - loupe + - ptyxis + - gparted + +kubuntu-packages: &kubuntu-packages + # Core packages for Ubuntu + - apparmor-profiles + - apparmor-utils + - auditd + - build-essential + - config-package-dev + - debhelper + - devscripts + - docker.io + - golang-go + - htop + - just + - libpam-apparmor + - lintian + - pipx + - qemu-guest-agent + - rsync + - systemd-container + - systemd-coredump + - systemd-homed + - systemd-oomd + - unattended-upgrades + - vim + + # Desktop packages for Ubuntu + - spice-vdagent + - terminator + - kubuntu-desktop + - plasma-workspace-wayland + +desktop-runcmd: &desktop-runcmd + # Add missing snap packages + - snap install snap-store + - snap install snapd-desktop-integration + - snap install --edge desktop-security-center + + # Remove default filesystem and related tools not used with the suggested + # storage layout. These may yet be required if different partitioning schemes + # are used. + - apt-get -y purge btrfs-progs xfsprogs + + # Remove other packages present by default in Ubuntu Server but not + # normally present in Ubuntu Desktop. + - >- + apt-get -y purge + byobu dmeventd finalrd gawk kpartx landscape-common lxd-agent-loader + mdadm motd-news-config ncurses-term open-iscsi open-vm-tools + screen sg3-utils sosreport ssh-import-id sssd tmux + + # Finally, remove things only installed as dependencies of other things + # we have already removed. + - apt-get -y autoremove + + # Ensure systemd-networkd is disabled + - systemctl disable systemd-networkd-wait-online.service + + # Ensure auditd is enabled + - systemctl enable systemd-journald-audit.socket diff --git a/tests/cloud-init/ubuntu24-desktop.user-data.yml b/tests/cloud-init/ubuntu24-desktop.user-data.yml deleted file mode 100644 index d1b1f169cc..0000000000 --- a/tests/cloud-init/ubuntu24-desktop.user-data.yml +++ /dev/null @@ -1,47 +0,0 @@ -#cloud-config - -# Based on https://github.com/canonical/autoinstall-desktop - -packages: - - apparmor-profiles - - build-essential - - config-package-dev - - debhelper - - devscripts - - golang-go - - linux-generic-hwe-24.04 - - qemu-guest-agent - - rsync - - spice-vdagent - - terminator - - ubuntu-desktop - - vim - -runcmd: - # Add missing snap packages - - snap install snap-store - - snap install snapd-desktop-integration - - # Remove default filesystem and related tools not used with the suggested - # storage layout. These may yet be required if different partitioning schemes - # are used. - - apt-get -y purge btrfs-progs xfsprogs - - # Remove other packages present by default in Ubuntu Server but not - # normally present in Ubuntu Desktop. - - >- - apt-get -y purge - byobu dmeventd finalrd gawk kpartx landscape-common lxd-agent-loader - mdadm motd-news-config ncurses-term open-iscsi open-vm-tools - screen sg3-utils sosreport ssh-import-id sssd tmux - - # Finally, remove things only installed as dependencies of other things - # we have already removed. - - apt-get -y autoremove - -write_files: - # Setup shared directory - - path: /etc/fstab - append: true - content: | - 0a31bc478ef8e2461a4b1cc10a24cc4 /home/user/Projects/apparmor.d virtiofs defaults 0 1 diff --git a/tests/cloud-init/ubuntu24-server.user-data.yml b/tests/cloud-init/ubuntu24-server.user-data.yml deleted file mode 100644 index 8e9c7bd389..0000000000 --- a/tests/cloud-init/ubuntu24-server.user-data.yml +++ /dev/null @@ -1,35 +0,0 @@ -#cloud-config - -packages: - - apparmor-profiles - - auditd - - build-essential - - config-package-dev - - debhelper - - devscripts - - golang-go - - htop - - qemu-guest-agent - - rsync - - vim - -write_files: - # Setup shared directory - - path: /etc/fstab - append: true - content: | - 0a31bc478ef8e2461a4b1cc10a24cc4 /home/user/Projects/apparmor.d virtiofs defaults 0 1 - - # Network configuration - - path: /etc/systemd/network/20-wired.network - owner: "root:root" - permissions: "0644" - content: | - [Match] - Name=en* - - [Network] - DHCP=yes - - [DHCPv4] - RouteMetric=10 diff --git a/tests/cloud-init/ubuntu24.04-desktop.user-data.yml b/tests/cloud-init/ubuntu24.04-desktop.user-data.yml new file mode 100644 index 0000000000..6ce097d2c1 --- /dev/null +++ b/tests/cloud-init/ubuntu24.04-desktop.user-data.yml @@ -0,0 +1,9 @@ +#cloud-config + +packages: *desktop-packages + +runcmd: *desktop-runcmd + +write_files: + - *shared-directory # Setup shared directory + - *disable-printk-ratelimit # Disable printk rate limiting diff --git a/tests/cloud-init/ubuntu24.04-kubuntu.user-data.yml b/tests/cloud-init/ubuntu24.04-kubuntu.user-data.yml new file mode 100644 index 0000000000..4f78d253e2 --- /dev/null +++ b/tests/cloud-init/ubuntu24.04-kubuntu.user-data.yml @@ -0,0 +1,10 @@ +#cloud-config + +packages: *kubuntu-packages + +runcmd: *desktop-runcmd + +write_files: + - *shared-directory # Setup shared directory + - *systemd-netword # Network configuration for server + - *disable-printk-ratelimit # Disable printk rate limiting diff --git a/tests/cloud-init/ubuntu24.04-server.user-data.yml b/tests/cloud-init/ubuntu24.04-server.user-data.yml new file mode 100644 index 0000000000..0a4e22ba50 --- /dev/null +++ b/tests/cloud-init/ubuntu24.04-server.user-data.yml @@ -0,0 +1,8 @@ +#cloud-config + +packages: *core-packages + +write_files: + - *shared-directory # Setup shared directory + - *systemd-netword # Network configuration for server + - *disable-printk-ratelimit # Disable printk rate limiting diff --git a/tests/cloud-init/ubuntu25-desktop.user-data.yml b/tests/cloud-init/ubuntu25-desktop.user-data.yml deleted file mode 100644 index 881e9b4e97..0000000000 --- a/tests/cloud-init/ubuntu25-desktop.user-data.yml +++ /dev/null @@ -1,47 +0,0 @@ -#cloud-config - -# Based on https://github.com/canonical/autoinstall-desktop - -packages: - - apparmor-profiles - - build-essential - - config-package-dev - - debhelper - - devscripts - - golang-go - - linux-generic-hwe-24.04 - - qemu-guest-agent - - rsync - - spice-vdagent - - terminator - - ubuntu-desktop - - vim - -runcmd: - - snap install snap-store - - snap install snapd-desktop-integration - - snap install --edge desktop-security-center - - # Remove default filesystem and related tools not used with the suggested - # storage layout. These may yet be required if different partitioning schemes - # are used. - - apt-get -y purge btrfs-progs xfsprogs - - # Remove other packages present by default in Ubuntu Server but not - # normally present in Ubuntu Desktop. - - >- - apt-get -y purge - byobu dmeventd finalrd gawk kpartx landscape-common lxd-agent-loader - mdadm motd-news-config ncurses-term open-iscsi open-vm-tools - screen sg3-utils sosreport ssh-import-id sssd tmux - - # Finally, remove things only installed as dependencies of other things - # we have already removed. - - apt-get -y autoremove - -write_files: - # Setup shared directory - - path: /etc/fstab - append: true - content: | - 0a31bc478ef8e2461a4b1cc10a24cc4 /home/user/Projects/apparmor.d virtiofs defaults 0 1 diff --git a/tests/cloud-init/ubuntu25.10-desktop.user-data.yml b/tests/cloud-init/ubuntu25.10-desktop.user-data.yml new file mode 100644 index 0000000000..6ce097d2c1 --- /dev/null +++ b/tests/cloud-init/ubuntu25.10-desktop.user-data.yml @@ -0,0 +1,9 @@ +#cloud-config + +packages: *desktop-packages + +runcmd: *desktop-runcmd + +write_files: + - *shared-directory # Setup shared directory + - *disable-printk-ratelimit # Disable printk rate limiting diff --git a/tests/cloud-init/ubuntu26.04-desktop.user-data.yml b/tests/cloud-init/ubuntu26.04-desktop.user-data.yml new file mode 100644 index 0000000000..6ce097d2c1 --- /dev/null +++ b/tests/cloud-init/ubuntu26.04-desktop.user-data.yml @@ -0,0 +1,9 @@ +#cloud-config + +packages: *desktop-packages + +runcmd: *desktop-runcmd + +write_files: + - *shared-directory # Setup shared directory + - *disable-printk-ratelimit # Disable printk rate limiting diff --git a/tests/cloud-init/ubuntu26.04-kubuntu.user-data.yml b/tests/cloud-init/ubuntu26.04-kubuntu.user-data.yml new file mode 100644 index 0000000000..4f78d253e2 --- /dev/null +++ b/tests/cloud-init/ubuntu26.04-kubuntu.user-data.yml @@ -0,0 +1,10 @@ +#cloud-config + +packages: *kubuntu-packages + +runcmd: *desktop-runcmd + +write_files: + - *shared-directory # Setup shared directory + - *systemd-netword # Network configuration for server + - *disable-printk-ratelimit # Disable printk rate limiting diff --git a/tests/cloud-init/ubuntu26.04-server.user-data.yml b/tests/cloud-init/ubuntu26.04-server.user-data.yml new file mode 100644 index 0000000000..0a4e22ba50 --- /dev/null +++ b/tests/cloud-init/ubuntu26.04-server.user-data.yml @@ -0,0 +1,8 @@ +#cloud-config + +packages: *core-packages + +write_files: + - *shared-directory # Setup shared directory + - *systemd-netword # Network configuration for server + - *disable-printk-ratelimit # Disable printk rate limiting diff --git a/tests/cloud-init/ubuntu26.04-test.user-data.yml b/tests/cloud-init/ubuntu26.04-test.user-data.yml new file mode 100644 index 0000000000..1d20baf79b --- /dev/null +++ b/tests/cloud-init/ubuntu26.04-test.user-data.yml @@ -0,0 +1,20 @@ +#cloud-config + +packages: + - apparmor-profiles + - apparmor-utils + - auditd + - debian-keyring + - htop + - libpam-apparmor + - qemu-guest-agent + - vim + +runcmd: + - /usr/bin/setup-testbed + - apt-get update + +write_files: + - *systemd-netword # Network configuration for server + - *disable-printk-ratelimit # Disable printk rate limiting + - *setup-testbed # Autopkgtest setup-testbed script diff --git a/tests/cmd/main.go b/tests/cmd/bootstrap/main.go similarity index 100% rename from tests/cmd/main.go rename to tests/cmd/bootstrap/main.go diff --git a/tests/cmd/tests.go b/tests/cmd/bootstrap/tests.go similarity index 100% rename from tests/cmd/tests.go rename to tests/cmd/bootstrap/tests.go diff --git a/tests/cmd/tldr.go b/tests/cmd/bootstrap/tldr.go similarity index 100% rename from tests/cmd/tldr.go rename to tests/cmd/bootstrap/tldr.go diff --git a/tests/integration/apt/apt.bats b/tests/integration/apt/apt.bats index a436f6e9f2..3f13d4ea46 100644 --- a/tests/integration/apt/apt.bats +++ b/tests/integration/apt/apt.bats @@ -5,10 +5,6 @@ load ../common -setup_file() { - skip -} - @test "apt: Update the list of available packages and versions" { sudo apt update } @@ -25,14 +21,26 @@ setup_file() { sudo apt install -y pass } -@test "apt: Remove a package (using 'purge' instead also removes its configuration files)" { - sudo apt remove -y pass +@test "apt: Remove a package and its configuration files" { + sudo apt purge -y pass } @test "apt: Upgrade all installed packages to their newest available versions" { sudo apt upgrade -y } +@test "apt: Upgrade installed packages, but remove obsolete packages and install additional packages to meet new dependencies" { + sudo apt dist-upgrade -y +} + +@test "apt: Clean the local repository - removing package files (.deb) from interrupted downloads that can no longer be downloaded" { + sudo apt autoclean -y +} + +@test "apt: Remove all packages that are no longer needed" { + sudo apt autoremove -y +} + @test "apt: List all packages" { apt list } @@ -41,6 +49,6 @@ setup_file() { apt list --installed } -@test "apt-moo: Print a cow easter egg" { +@test "apt: Print a cow easter egg" { apt moo } diff --git a/tests/integration/apt/dpkg-query.bats b/tests/integration/apt/dpkg-query.bats new file mode 100644 index 0000000000..39259e0a09 --- /dev/null +++ b/tests/integration/apt/dpkg-query.bats @@ -0,0 +1,27 @@ +#!/usr/bin/env bats +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +load ../common + +@test "dpkg-query: List all installed packages" { + dpkg-query --list +} + +@test "dpkg-query: List installed packages matching a pattern" { + dpkg-query --list 'libc6*' +} + +@test "dpkg-query: List all files installed by a package" { + dpkg-query --listfiles libc6 +} + +@test "dpkg-query: Show information about a package" { + dpkg-query --status libc6 +} + +@test "dpkg-query: Search for packages that own files matching a pattern" { + dpkg-query --search /etc/ld.so.conf.d +} + diff --git a/tests/integration/apt/dpkg-reconfigure.bats b/tests/integration/apt/dpkg-reconfigure.bats new file mode 100644 index 0000000000..f6aec98ea4 --- /dev/null +++ b/tests/integration/apt/dpkg-reconfigure.bats @@ -0,0 +1,12 @@ +#!/usr/bin/env bats +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +load ../common + +@test "dpkg-reconfigure: Reconfigure one or more packages" { + sudo apt install -y pass + sudo dpkg-reconfigure pass +} + diff --git a/tests/integration/common.bash b/tests/integration/common.bash index ed167d4f93..f31988062e 100644 --- a/tests/integration/common.bash +++ b/tests/integration/common.bash @@ -9,7 +9,7 @@ load "$BATS_LIB_PATH/bats-support/load" export SYSTEMD_PAGER= # Ignore the profile not managed by apparmor.d -IGNORE=(php-fpm snapd/snap-confine) +IGNORE=(/usr/sbin/mysqld php-fpm snapd/snap-confine snap.vault.vaultd /dev/pts/0) # User password for sudo commands export PASSWORD=${PASSWORD:-user} @@ -110,8 +110,8 @@ aa_check() { now=$(date +%s) duration=$((now - _START + 1)) logs=$(aa-log --raw --systemd --since "-${duration}s") - for profile in "${IGNORE[@]}"; do - logs=$(echo "$logs" | grep -v "$profile") + for pattern in "${IGNORE[@]}"; do + logs=$(echo "$logs" | grep -v "$pattern") done aa_start diff --git a/tests/integration/flatpak.bats b/tests/integration/flatpak.bats index b61024d063..691db788b0 100644 --- a/tests/integration/flatpak.bats +++ b/tests/integration/flatpak.bats @@ -30,6 +30,14 @@ load common flatpak info org.vim.Vim } +@test "flatpak: List exported files" { + flatpak documents +} + +@test "flatpak: List dynamic permissions" { + flatpak permissions +} + # @test "flatpak: Run an installed application" { # _timeout flatpak run org.vim.Vim # } diff --git a/tests/integration/pacman/paccache.bats b/tests/integration/pacman/paccache.bats new file mode 100644 index 0000000000..b2e1369e2e --- /dev/null +++ b/tests/integration/pacman/paccache.bats @@ -0,0 +1,22 @@ +#!/usr/bin/env bats +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +load ../common + +@test "paccache: Perform a dry-run and show the number of candidate packages for deletion" { + sudo paccache -d +} + +@test "paccache: Move candidate packages to a directory instead of deleting them" { + sudo paccache -m "$USER_BUILD_DIRS" +} + +@test "paccache: Remove all but the 3 most recent package versions from the `pacman` cache" { + sudo paccache -r +} + +@test "paccache: Set the number of package versions to keep" { + sudo paccache -rk 3 +} diff --git a/tests/integration/pacman/pacman-key.bats b/tests/integration/pacman/pacman-key.bats new file mode 100644 index 0000000000..82e34a3791 --- /dev/null +++ b/tests/integration/pacman/pacman-key.bats @@ -0,0 +1,34 @@ +#!/usr/bin/env bats +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +load ../common + +@test "pacman-key: Initialize the 'pacman' keyring" { + sudo pacman-key --init +} + +@test "pacman-key: Add the default Arch Linux keys" { + sudo pacman-key --populate +} + +@test "pacman-key: List keys from the public keyring" { + pacman-key --list-keys +} + +@test "pacman-key: Receive a key from a key server" { + sudo pacman-key --recv-keys 06A26D531D56C42D66805049C5469996F0DF68EC +} + +@test "pacman-key: Print the fingerprint of a specific key" { + pacman-key --finger 06A26D531D56C42D66805049C5469996F0DF68EC +} + +@test "pacman-key: Sign an imported key locally" { + sudo pacman-key --lsign-key 06A26D531D56C42D66805049C5469996F0DF68EC +} + +@test "pacman-key: Remove a specific key" { + sudo pacman-key --delete 06A26D531D56C42D66805049C5469996F0DF68EC +} diff --git a/tests/integration/pacman/pacman.bats b/tests/integration/pacman/pacman.bats new file mode 100644 index 0000000000..575a65bc16 --- /dev/null +++ b/tests/integration/pacman/pacman.bats @@ -0,0 +1,34 @@ +#!/usr/bin/env bats +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +load ../common + +@test "pacman: Synchronize and update all packages" { + sudo pacman -Syu --noconfirm +} + +@test "pacman: Install a new package" { + sudo pacman -S --noconfirm pass pass-otp +} + +@test "pacman: Remove a package and its dependencies" { + sudo pacman -Rs --noconfirm pass-otp +} + +@test "pacman: List installed packages and versions" { + pacman -Q +} + +@test "pacman: List only the explicitly installed packages and versions" { + pacman -Qe +} + +@test "pacman: List orphan packages (installed as dependencies but not actually required by any package)" { + pacman -Qtdq +} + +@test "pacman: Empty the entire 'pacman' cache" { + sudo pacman -Scc --noconfirm +} diff --git a/tests/integration/procps/free.bats b/tests/integration/procps/free.bats new file mode 100644 index 0000000000..dcc216bfa8 --- /dev/null +++ b/tests/integration/procps/free.bats @@ -0,0 +1,18 @@ +#!/usr/bin/env bats +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +load ../common + +@test "free: Display system memory" { + free +} + +@test "free: Display memory in GB" { + free -g +} + +@test "free: Display memory in human-readable units" { + free -h +} diff --git a/tests/integration/procps/pgrep.bats b/tests/integration/procps/pgrep.bats new file mode 100644 index 0000000000..9fd6b92f80 --- /dev/null +++ b/tests/integration/procps/pgrep.bats @@ -0,0 +1,19 @@ +#!/usr/bin/env bats +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +load ../common + +@test "pgrep: Return PIDs of any running processes with a matching command string" { + pgrep systemd +} + +@test "pgrep: Search for processes including their command-line options" { + pgrep --full 'systemd' +} + +@test "pgrep: Search for processes run by a specific user" { + pgrep --euid root systemd-udevd +} + diff --git a/tests/integration/procps/pidof.bats b/tests/integration/procps/pidof.bats new file mode 100644 index 0000000000..ec20cbe86a --- /dev/null +++ b/tests/integration/procps/pidof.bats @@ -0,0 +1,19 @@ +#!/usr/bin/env bats +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +load ../common + +@test "pidof: List all process IDs with given name" { + pidof systemd + pidof bash +} + +@test "pidof: List a single process ID with given name" { + pidof -s bash +} + +@test "pidof: List process IDs including scripts with given name" { + pidof -x bash +} diff --git a/tests/integration/procps/sysctl.bats b/tests/integration/procps/sysctl.bats index 2f284070ab..66720c4340 100644 --- a/tests/integration/procps/sysctl.bats +++ b/tests/integration/procps/sysctl.bats @@ -21,6 +21,6 @@ load ../common sysctl fs.file-max } -@test "sysctl: Apply changes from `/etc/sysctl.conf`" { - sysctl -p +@test "sysctl: Apply changes from '/etc/sysctl.conf'" { + sudo sysctl -p } diff --git a/tests/integration/procps/uptime.bats b/tests/integration/procps/uptime.bats new file mode 100644 index 0000000000..7d9361d5a6 --- /dev/null +++ b/tests/integration/procps/uptime.bats @@ -0,0 +1,18 @@ +#!/usr/bin/env bats +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +load ../common + +@test "uptime: Print current time, uptime, number of logged-in users and other information" { + uptime +} + +@test "uptime: Show only the amount of time the system has been booted for" { + uptime --pretty +} + +@test "uptime: Print the date and time the system booted up at" { + uptime --since +} diff --git a/tests/integration/procps/vmstat.bats b/tests/integration/procps/vmstat.bats new file mode 100644 index 0000000000..e5900a3240 --- /dev/null +++ b/tests/integration/procps/vmstat.bats @@ -0,0 +1,25 @@ +#!/usr/bin/env bats +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +load ../common + +@test "vmstat: Display virtual memory statistics" { + vmstat + vmstat --active + vmstat --forks +} + +@test "vmstat: Display disk statistics" { + vmstat --disk + vmstat --disk-sum +} + +@test "vmstat: Display slabinfo" { + sudo vmstat --slabs +} + +@test "vmstat: Display reports every second for 3 times" { + vmstat 1 3 +} diff --git a/tests/integration/systemd/bootctl.bats b/tests/integration/systemd/bootctl.bats new file mode 100644 index 0000000000..2dfb39a7f5 --- /dev/null +++ b/tests/integration/systemd/bootctl.bats @@ -0,0 +1,22 @@ +#!/usr/bin/env bats +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +load ../common + +@test "bootctl: Show information about the system firmware and the bootloaders" { + sudo bootctl status +} + +@test "bootctl: Show all available bootloader entries" { + sudo bootctl list +} + +@test "bootctl: Install 'systemd-boot' into the EFI system partition" { + sudo bootctl install +} + +@test "bootctl: Remove all installed versions of 'systemd-boot' from the EFI system partition" { + sudo bootctl remove +} diff --git a/tests/integration/systemd/busctl.bats b/tests/integration/systemd/busctl.bats new file mode 100644 index 0000000000..ef3e973e92 --- /dev/null +++ b/tests/integration/systemd/busctl.bats @@ -0,0 +1,27 @@ +#!/usr/bin/env bats +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +load ../common + +@test "busctl: Show all peers on the bus, by their service names" { + busctl list +} + +@test "busctl: Show process information and credentials of a bus service, a process, or the owner of the bus (if no parameter is specified)" { + busctl status 1 + busctl status org.freedesktop.DBus +} + +@test "busctl: Show an object tree of one or more services (or all services if no service is specified)" { + busctl tree org.freedesktop.DBus +} + +@test "busctl: Show interfaces, methods, properties and signals of the specified object on the specified service" { + busctl introspect org.freedesktop.login1 /org/freedesktop/login1 +} + +@test "busctl: Retrieve the current value of one or more object properties" { + busctl get-property org.freedesktop.login1 /org/freedesktop/login1 org.freedesktop.login1.Manager Docked +} diff --git a/tests/integration/systemd/homectl.bats b/tests/integration/systemd/homectl.bats index 0bdd625c4c..bb3b382270 100644 --- a/tests/integration/systemd/homectl.bats +++ b/tests/integration/systemd/homectl.bats @@ -16,7 +16,7 @@ setup_file() { } @test "homectl: Create a user account and their associated home directory" { - sudo homectl create user2 + printf "user2\nuser2" | sudo homectl create user2 } @test "homectl: List user accounts and their associated home directories" { diff --git a/tests/integration/systemd/journalctl.bats b/tests/integration/systemd/journalctl.bats new file mode 100644 index 0000000000..9eeb7c9fe0 --- /dev/null +++ b/tests/integration/systemd/journalctl.bats @@ -0,0 +1,30 @@ +#!/usr/bin/env bats +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +load ../common + +@test "journalctl: Show all messages with priority level 3 (errors) from this boot" { + sudo journalctl -b --priority=3 +} + +@test "journalctl: Show only the last N lines of the journal" { + sudo journalctl --lines 100 +} + +@test "journalctl: Show all messages by a specific [u]nit" { + sudo journalctl --unit apparmor.service +} + +@test "journalctl: Show all messages by a specific process" { + sudo journalctl _PID=1 +} + +@test "journalctl: Show all messages by a specific executable" { + sudo journalctl /usr/bin/bootctl +} + +@test "journalctl: Delete journal logs which are older than 10 seconds" { + sudo journalctl --vacuum-time=10s +} diff --git a/tests/integration/systemd/localectl.bats b/tests/integration/systemd/localectl.bats new file mode 100644 index 0000000000..71dfd2e069 --- /dev/null +++ b/tests/integration/systemd/localectl.bats @@ -0,0 +1,27 @@ +#!/usr/bin/env bats +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +load ../common + +@test "localectl: Show the current settings of the system locale and keyboard mapping" { + localectl +} + +@test "localectl: List available locales" { + localectl list-locales +} + +@test "localectl: Set a system locale variable" { + sudo localectl set-locale LANG=en_US.UTF-8 +} + +@test "localectl: List available keymaps" { + localectl list-keymaps || true +} + +@test "localectl: Set the system keyboard mapping for the console and X11" { + sudo localectl set-keymap uk || true +} + diff --git a/tests/integration/systemd/machinectl.bats b/tests/integration/systemd/machinectl.bats new file mode 100644 index 0000000000..18771ae729 --- /dev/null +++ b/tests/integration/systemd/machinectl.bats @@ -0,0 +1,26 @@ +#!/usr/bin/env bats +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +load ../common + +@test "importctl: Import an image as a machine" { + sudo importctl pull-tar --force --class=machine -N https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64-root.tar.xz noble || true +} + +@test "machinectl: Display a list of available images" { + sudo machinectl list-images +} + +@test "machinectl: Start a machine as a service using systemd-nspawn" { + sudo machinectl start noble || true +} + +@test "machinectl: Display a list of running machines" { + sudo machinectl list +} + +@test "machinectl: Stop a running machine" { + sudo machinectl stop noble || true +} diff --git a/tests/integration/systemd/networkctl.bats b/tests/integration/systemd/networkctl.bats new file mode 100644 index 0000000000..81418ba01f --- /dev/null +++ b/tests/integration/systemd/networkctl.bats @@ -0,0 +1,18 @@ +#!/usr/bin/env bats +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +load ../common + +@test "networkctl: List existing links with their status" { + sudo networkctl list +} + +@test "networkctl: Show an overall network status" { + sudo networkctl status +} + +@test "networkctl: Reload configuration files (.netdev and .network)" { + sudo networkctl reload +} diff --git a/tests/integration/utils/chsh.bats b/tests/integration/utils/chsh.bats index ccdadc6e3c..a23799def0 100644 --- a/tests/integration/utils/chsh.bats +++ b/tests/integration/utils/chsh.bats @@ -10,10 +10,10 @@ load ../common } @test "chsh: Set a specific login shell for the current user" { - echo "$PASSWORD" | chsh --shell /usr/bin/bash + echo "$PASSWORD" | chsh --shell /usr/bin/bash || true } # bats test_tags=chsh @test "chsh: Set a login shell for a specific user" { - sudo chsh --shell /usr/bin/sh root + sudo chsh --shell /usr/bin/sh root || true } diff --git a/tests/integration/utils/cpupower.bats b/tests/integration/utils/cpupower.bats new file mode 100644 index 0000000000..b22a9e53b0 --- /dev/null +++ b/tests/integration/utils/cpupower.bats @@ -0,0 +1,26 @@ +#!/usr/bin/env bats +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2026 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +load ../common + +@test "cpupower: List CPUs" { + sudo cpupower --cpu all info || true +} + +@test "cpupower: Print information about all cores" { + sudo cpupower --cpu all info || true +} + +@test "cpupower: Set all CPUs to a power-saving frequency governor" { + sudo cpupower --cpu all frequency-set --governor powersave || true +} + +@test "cpupower: Print CPU 0's available frequency governors" { + sudo cpupower --cpu 0 frequency-info --governors || true +} + +@test "cpupower: Print CPU 4's frequency from the hardware, in a human-readable format" { + sudo cpupower --cpu 0 frequency-info --hwfreq --human || true +} diff --git a/tests/integration/utils/fstrim.bats b/tests/integration/utils/fstrim.bats new file mode 100644 index 0000000000..dff1083e2c --- /dev/null +++ b/tests/integration/utils/fstrim.bats @@ -0,0 +1,14 @@ +#!/usr/bin/env bats +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +load ../common + +@test "fstrim: Trim unused blocks on all mounted partitions that support it" { + sudo fstrim --all +} + +@test "fstrim: Trim unused blocks on a specified partition" { + sudo fstrim --verbose / +} diff --git a/tests/integration/utils/hwclock.bats b/tests/integration/utils/hwclock.bats index 88c981c315..a3dcdc31a3 100644 --- a/tests/integration/utils/hwclock.bats +++ b/tests/integration/utils/hwclock.bats @@ -6,14 +6,14 @@ load ../common @test "hwclock: Display the current time as reported by the hardware clock" { - hwclock + sudo hwclock || true } @test "hwclock: Write the current software clock time to the hardware clock (sometimes used during system setup)" { - hwclock --systohc + sudo hwclock --systohc || true } @test "hwclock: Write the current hardware clock time to the software clock" { - hwclock --hctosys + sudo hwclock --hctosys || true } diff --git a/tests/integration/utils/lsfd.bats b/tests/integration/utils/lsfd.bats new file mode 100644 index 0000000000..bf0c4de0c7 --- /dev/null +++ b/tests/integration/utils/lsfd.bats @@ -0,0 +1,19 @@ +#!/usr/bin/env bats +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +load ../common + +@test "lsfd: List all open file descriptors" { + lsfd +} + +@test "lsfd: List all files kept open by a specific program" { + sudo lsfd --filter 'PID == 1' +} + +@test "lsfd: List open IPv4 or IPv6 sockets" { + sudo lsfd -i4 + sudo lsfd -i6 +} diff --git a/tests/integration/utils/lsipc.bats b/tests/integration/utils/lsipc.bats new file mode 100644 index 0000000000..a18126982b --- /dev/null +++ b/tests/integration/utils/lsipc.bats @@ -0,0 +1,16 @@ +#!/usr/bin/env bats +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +load ../common + +@test "lsipc: Show information about all active IPC facilities" { + lsipc +} + +@test "lsipc: Show information about active shared memory segments, message queues or sempahore sets" { + lsipc --shmems + lsipc --queues + lsipc --semaphores +} diff --git a/tests/integration/utils/lslocks.bats b/tests/integration/utils/lslocks.bats new file mode 100644 index 0000000000..042834cae5 --- /dev/null +++ b/tests/integration/utils/lslocks.bats @@ -0,0 +1,22 @@ +#!/usr/bin/env bats +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +load ../common + +@test "lslocks: List all local system locks" { + sudo lslocks +} + +@test "lslocks: List locks producing a raw output (no columns), and without column headers" { + sudo lslocks --raw --noheadings +} + +@test "lslocks: List locks by PID input" { + sudo lslocks --pid "$(sudo lslocks --raw --noheadings --output PID | head -1)" +} + +@test "lslocks: List locks with JSON output to stdout" { + lslocks --json +} diff --git a/tests/integration/utils/lslogins.bats b/tests/integration/utils/lslogins.bats new file mode 100644 index 0000000000..aa2df69b4a --- /dev/null +++ b/tests/integration/utils/lslogins.bats @@ -0,0 +1,27 @@ +#!/usr/bin/env bats +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +load ../common + +@test "lslogins: Display users in the system" { + lslogins + sudo lslogins +} + +@test "lslogins: Display user accounts" { + lslogins --user-accs +} + +@test "lslogins: Display last logins" { + lslogins --last +} + +@test "lslogins: Display system accounts" { + lslogins --system-accs +} + +@test "lslogins: Display supplementary groups" { + lslogins --supp-groups +} diff --git a/tests/integration/utils/lsns.bats b/tests/integration/utils/lsns.bats new file mode 100644 index 0000000000..c7e6563e2e --- /dev/null +++ b/tests/integration/utils/lsns.bats @@ -0,0 +1,31 @@ +#!/usr/bin/env bats +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +load ../common + +@test "lsns: List all namespaces" { + lsns + sudo lsns +} + +@test "lsns: List namespaces in JSON format" { + sudo lsns --json +} + +@test "lsns: List namespaces associated with the specified process" { + sudo lsns --task 1 +} + +@test "lsns: List the specified type of namespaces only" { + sudo lsns --type mnt + sudo lsns --type net + sudo lsns --type ipc + sudo lsns --type user + sudo lsns --type pid + sudo lsns --type uts + sudo lsns --type cgroup + sudo lsns --type time +} + diff --git a/tests/integration/utils/lspci.bats b/tests/integration/utils/lspci.bats index 1b86dd41f6..facf379a98 100644 --- a/tests/integration/utils/lspci.bats +++ b/tests/integration/utils/lspci.bats @@ -7,6 +7,7 @@ load ../common @test "lspci: Show a brief list of devices" { lspci + sudo lspci } @test "lspci: Display additional info" { @@ -21,6 +22,10 @@ load ../common lspci -s 00:00.0 } +@test "lspci: Query the PCI ID database for unknown ID's via DNS" { + sudo lspci -q +} + @test "lspci: Dump info in a readable form" { lspci -vm } diff --git a/tests/integration/whois.bats b/tests/integration/whois.bats new file mode 100644 index 0000000000..fd1cba5fac --- /dev/null +++ b/tests/integration/whois.bats @@ -0,0 +1,19 @@ +#!/usr/bin/env bats +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2025 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +load common + +@test "whois: Get information about a domain name" { + whois google.fr +} + +@test "whois: Get information about an IP address" { + whois 8.8.8.8 +} + +@test "whois: Get abuse contact for an IP address" { + whois -b 8.8.8.8 +} + diff --git a/tests/packer/builds.pkr.hcl b/tests/packer/builds.pkr.hcl index 674a295b10..6d8ab6d474 100644 --- a/tests/packer/builds.pkr.hcl +++ b/tests/packer/builds.pkr.hcl @@ -3,14 +3,16 @@ # SPDX-License-Identifier: GPL-2.0-only locals { - name = "${var.prefix}${var.dist}-${var.flavor}" + name = "${var.prefix}${var.dist}${var.release}-${var.flavor}" + osinfo = "${var.dist}${var.release}" + group = contains(["debian", "ubuntu"], var.dist) ? "sudo" : "wheel" } source "qemu" "default" { disk_image = true - iso_url = var.DM[var.dist].img_url - iso_checksum = "file:${var.DM[var.dist].img_checksum}" - iso_target_path = pathexpand("${var.iso_dir}/${basename("${var.DM[var.dist].img_url}")}") + iso_url = var.DM[local.osinfo].img_url + iso_checksum = "file:${var.DM[local.osinfo].img_checksum}" + iso_target_path = pathexpand("${var.iso_dir}/${basename("${var.DM[local.osinfo].img_url}")}") cpu_model = "host" cpus = var.cpus memory = var.ram @@ -32,16 +34,18 @@ source "qemu" "default" { cd_label = "cidata" cd_content = { "meta-data" = "" - "user-data" = format("%s\n%s", + "user-data" = format("%s\n%s\n%s", templatefile("${path.cwd}/tests/cloud-init/common.yml", { - username = "${var.username}" - password = "${var.password}" - ssh_key = file("${var.ssh_publickey}") - hostname = "${local.name}" + username = var.username + password = var.password + ssh_key = file(var.ssh_publickey) + hostname = regex_replace(local.name, "\\.", "") + group = local.group } ), - file("${path.cwd}/tests/cloud-init/${var.dist}-${var.flavor}.user-data.yml") + file("${path.cwd}/tests/cloud-init/${regex_replace(local.osinfo, "[0-9.]*$", "")}.yml"), + file("${path.cwd}/tests/cloud-init/${local.osinfo}-${var.flavor}.user-data.yml") ) } } @@ -70,10 +74,10 @@ build { "while [ ! -f /var/lib/cloud/instance/boot-finished ]; do echo 'Waiting for Cloud-Init...'; sleep 20; done", # Ensure cloud-init is successful - "cloud-init status", + "cloud-init status || cloud-init collect-logs --tarfile /root/cloud-init.tar.gz", # Remove logs and artifacts so cloud-init can re-run - "cloud-init clean", + "cloud-init clean || true", # Install local files and config "bash /tmp/init.sh", diff --git a/tests/packer/clean.sh b/tests/packer/clean.sh index b7650a1d52..719cbe9011 100644 --- a/tests/packer/clean.sh +++ b/tests/packer/clean.sh @@ -51,18 +51,17 @@ clean_apt() { apt-get -y autoremove --purge apt-get -y autoclean apt-get -y clean + apt-get update } clean_pacman() { _msg "Cleaning pacman cache" - pacman -Syu --noconfirm pacman -Scc --noconfirm } clean_zypper() { _msg "Cleaning zypper cache" - zypper update -y - zypper clean -y + zypper clean --all } # Make the image as impersonal as possible. @@ -71,11 +70,6 @@ impersonalize() { # Remove remaining pkg file, docs and caches dirs=( - /usr/share/doc - /usr/share/man - /var/cache/ - /var/lib/apt - /var/lib/dhcp /var/tmp ) for dir in "${dirs[@]}"; do @@ -92,11 +86,6 @@ impersonalize() { truncate --size=0 /var/lib/dbus/machine-id remove=( - # Remove remaining pkg file, docs and caches - /usr/share/info/ - /usr/share/lintian/ - /usr/share/linda/ - # Remove history & unique ids /etc/adjtime /etc/ansible/ diff --git a/tests/packer/init.sh b/tests/packer/init.sh index 4e4e1ec99f..91fc1c85b0 100644 --- a/tests/packer/init.sh +++ b/tests/packer/init.sh @@ -3,16 +3,11 @@ # Copyright (C) 2023-2024 Alexandre Pujol # SPDX-License-Identifier: GPL-2.0-only -set -eu +set -eux -o pipefail -_lsb_release() { - # shellcheck source=/dev/null - . /etc/os-release - echo "$ID" -} -DISTRIBUTION="$(_lsb_release)" +# shellcheck source=/dev/null +source /etc/os-release || exit 1 readonly SRC=/tmp/ -readonly DISTRIBUTION main() { install -dm0750 -o "$SUDO_USER" -g "$SUDO_USER" "/home/$SUDO_USER/Projects/" "/home/$SUDO_USER/Projects/apparmor.d" "/home/$SUDO_USER/.config/" @@ -24,29 +19,28 @@ main() { install -Dm0755 $SRC/aa-clean /usr/bin/aa-clean chown -R "$SUDO_USER:$SUDO_USER" "/home/$SUDO_USER/.config/" - case "$DISTRIBUTION" in + case "$ID" in arch) - rm -f $SRC/*.sig # Ignore signature files - pacman --noconfirm -U $SRC/*.pkg.tar.zst + rm -f $SRC/*.sig # Ignore signature files + rm -f $SRC/*enforced* # Ignore enforced package + pacman --noconfirm -U $SRC/*.pkg.tar.zst || true ;; debian | ubuntu) - dpkg -i $SRC/*.deb + if dpkg-vendor --is Ubuntu; then + suffix="ubuntu1~$(lsb_release -sr)" + elif dpkg-vendor --is Debian; then + suffix="1+deb$(lsb_release -sr)" + fi + dpkg -i $SRC/*-"${suffix}"*.deb || true ;; opensuse*) mv "/home/$SUDO_USER/.bash_aliases" "/home/$SUDO_USER/.alias" - rpm -i $SRC/*.rpm + rpm -i $SRC/*.rpm || true ;; esac - - verb="start" - rm -rf /var/cache/apparmor/* || true - if systemctl is-active -q apparmor; then - verb="reload" - fi - systemctl "$verb" apparmor.service || journalctl -xeu apparmor.service } main "$@" diff --git a/tests/packer/src/.bash_aliases b/tests/packer/src/.bash_aliases index 27e05bf80c..c18f0f3887 100644 --- a/tests/packer/src/.bash_aliases +++ b/tests/packer/src/.bash_aliases @@ -3,21 +3,27 @@ source /usr/share/bash-completion/bash_completion function up() { -for nb in $(seq "$1"); do - cd ../ -done + for nb in $(seq "$1"); do + cd ../ + done +} + +function _ps() { + LIBPROC_HIDE_KERNEL=1 ps "$@" | sed \ + -e "s/\bunconfined\b/\x1b[1;41;97munconfined\x1b[0m/g" \ + -e "s/\bcomplain\b/\x1b[1;33mcomplain\x1b[0m/g" \ + -e "s/\benforce\b/\x1b[1;32menforce\x1b[0m/g" } -alias sudo='sudo -E' alias aa-log='sudo aa-log' alias aa-status='sudo aa-status' alias c='clear' alias du='du -hs' alias l='ll -h' alias ll='ls -alFh' -alias p="ps auxZ | grep -v '\[.*\]'" -alias pf="ps auxfZ | grep -v '\[.*\]'" -alias pu="ps auxZ | grep -v '\[.*\]' | grep unconfined" +alias p="_ps auxZ" +alias pf="_ps auxfZ" +alias pu="_ps auxZ | grep unconfined" alias u='up 1' alias uu='up 2' alias uuu='up 3' diff --git a/tests/packer/src/aa-update b/tests/packer/src/aa-update index 48267d2f09..bdbd6ed00e 100644 --- a/tests/packer/src/aa-update +++ b/tests/packer/src/aa-update @@ -13,15 +13,15 @@ DISTRIBUTION="$(_lsb_release)" cd "$HOME/Projects/apparmor.d" case "$DISTRIBUTION" in arch) - make pkg + just pkg ;; debian | ubuntu | whonix) sudo rm -rf debian/.debhelper/ - make dpkg + just dpkg sudo rm -rf debian/.debhelper/ ;; opensuse*) - make rpm + just rpm ;; *) ;; esac diff --git a/tests/packer/src/site.local b/tests/packer/src/site.local index e154358625..da823f6588 100644 --- a/tests/packer/src/site.local +++ b/tests/packer/src/site.local @@ -1,3 +1,4 @@ @{user_build_dirs}+=@{user_projects_dirs} @{user_pkg_dirs}+=@{user_projects_dirs} +@{user_sync_dirs}+=@{user_projects_dirs} diff --git a/tests/packer/variables.pkr.hcl b/tests/packer/variables.pkr.hcl index 073544f59a..b56b5406cb 100644 --- a/tests/packer/variables.pkr.hcl +++ b/tests/packer/variables.pkr.hcl @@ -25,7 +25,7 @@ variable "cpus" { variable "ram" { description = "Default RAM of the VM" type = string - default = "4096" + default = "2048" } variable "disk_size" { @@ -61,7 +61,7 @@ variable "output_dir" { variable "firmware" { description = "Path to the UEFI firmware" type = string - default = "/usr/share/edk2/x64/OVMF.4m.fd" + default = "" } variable "prefix" { @@ -73,7 +73,13 @@ variable "prefix" { variable "dist" { description = "Distribution to target" type = string - default = "ubuntu24" + default = "" +} + +variable "release" { + description = "Release to target" + type = string + default = "" } variable "flavor" { @@ -93,25 +99,25 @@ variable "DM" { img_url = "https://geo.mirror.pkgbuild.com/images/latest/Arch-Linux-x86_64-cloudimg.qcow2" img_checksum = "https://geo.mirror.pkgbuild.com/images/latest/Arch-Linux-x86_64-cloudimg.qcow2.SHA256" }, - "debian12" : { - img_url = "https://cdimage.debian.org/images/cloud/bookworm/latest/debian-12-genericcloud-amd64.qcow2" - img_checksum = "https://cdimage.debian.org/images/cloud/bookworm/latest/SHA512SUMS" - } "debian13" : { - img_url = "https://cdimage.debian.org/images/cloud/trixie/daily/latest/debian-13-genericcloud-amd64-daily.qcow2" - img_checksum = "https://cdimage.debian.org/images/cloud/trixie/daily/latest/SHA512SUMS" + img_url = "https://cdimage.debian.org/images/cloud/trixie/latest/debian-13-genericcloud-amd64.qcow2" + img_checksum = "https://cdimage.debian.org/images/cloud/trixie/latest/SHA512SUMS" } - "ubuntu22" : { - img_url = "https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img" - img_checksum = "https://cloud-images.ubuntu.com/jammy/current/SHA256SUMS" - }, - "ubuntu24" : { + "debian14" : { + img_url = "https://cdimage.debian.org/images/cloud/forky/daily/latest/debian-14-genericcloud-amd64-daily.qcow2" + img_checksum = "https://cdimage.debian.org/images/cloud/forky/daily/latest/SHA512SUMS" + } + "ubuntu24.04" : { img_url = "https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img" img_checksum = "https://cloud-images.ubuntu.com/noble/current/SHA256SUMS" }, - "ubuntu25" : { - img_url = "https://cloud-images.ubuntu.com/plucky/current/plucky-server-cloudimg-amd64.img" - img_checksum = "https://cloud-images.ubuntu.com/plucky/current/SHA256SUMS" + "ubuntu25.10" : { + img_url = "https://cloud-images.ubuntu.com/questing/current/questing-server-cloudimg-amd64.img" + img_checksum = "https://cloud-images.ubuntu.com/questing/current/SHA256SUMS" + }, + "ubuntu26.04" : { + img_url = "https://cloud-images.ubuntu.com/resolute/current/resolute-server-cloudimg-amd64.img" + img_checksum = "https://cloud-images.ubuntu.com/resolute/current/SHA256SUMS" }, "opensuse" : { img_url = "https://download.opensuse.org/tumbleweed/appliances/openSUSE-Tumbleweed-Minimal-VM.x86_64-Cloud.qcow2" diff --git a/tests/requirements.sh b/tests/requirements.sh index 52d7cb36bc..087f72df0f 100644 --- a/tests/requirements.sh +++ b/tests/requirements.sh @@ -5,7 +5,7 @@ # Dependencies for the bats integration tests -set -eu +set -eu -o pipefail # shellcheck source=/dev/null _lsb_release() { @@ -16,12 +16,16 @@ DISTRIBUTION="$(_lsb_release)" case "$DISTRIBUTION" in arch) + sudo pacman -Syu --noconfirm \ + bats bats-support \ + pacman-contrib tlp flatpak networkmanager ;; debian | ubuntu | whonix) - sudo apt update -y - sudo apt install -y \ + sudo apt-get update -y + sudo apt-get install -y \ bats bats-support \ - cpuid dfc systemd-userdbd systemd-homed tlp network-manager flatpak + cpuid dfc systemd-boot systemd-userdbd systemd-homed systemd-container tlp \ + network-manager systemd-container flatpak util-linux-extra ;; opensuse*) ;; diff --git a/tests/sbin.list b/tests/sbin.list new file mode 100644 index 0000000000..0345dc023b --- /dev/null +++ b/tests/sbin.list @@ -0,0 +1,903 @@ +a2enmod +a2query +aa-audit +aa-autodep +aa-cleanprof +aa-complain +aa-decode +aa-disable +aa-enforce +aa-genprof +aa-load +aa-logprof +aa-mergeprof +aa-remove-unknown +aa-status +aa-teardown +aa-unconfined +aa-update-browser +accessdb +acpi_genl +acpid +acpidump +add-shell +addgnupghome +addpart +adduser +agetty +alsa +alsa-info +alsa-info.sh +alsa-init +alsabat-test +alsactl +anacron +apache2 +apache2ctl +apparmor_parser +apparmor_status +applygnupgdefaults +aptd +argdist-bpfcc +arp +arpd +aspell-autobuildhash +atd +audisp-af_unix +audisp-filter +audisp-syslog +audit +auditctl +auditd +augenrules +aureport +ausearch +autodep +automount +autrace +avahi-daemon +avahi-dnsconfd +badblocks +bashreadline-bpfcc +bashreadline.bt +bcache-super-show +bindsnoop-bpfcc +biolatency-bpfcc +biolatency-kp.bt +biolatency.bt +biolatpcts-bpfcc +biopattern-bpfcc +biosdecode +biosnoop-bpfcc +biosnoop.bt +biostacks.bt +biotop-bpfcc +bitesize-bpfcc +bitesize.bt +blkdeactivate +blkdiscard +blkid +blkmapd +blkpr +blkzone +blockdev +blogctl +blogd +blogger +bpflist-bpfcc +bpftool +brctl +bridge +brltty-setup +btrfs +btrfs-convert +btrfs-find-root +btrfs-image +btrfsdist-bpfcc +btrfsslower-bpfcc +btrfstune +cachestat-bpfcc +cachetop-bpfcc +capable-bpfcc +capable.bt +capsh +cfdisk +cgdisk +chat +chcpu +check_forensic +check_mail_queue +check-bios-nx +checkproc +chgpasswd +chkstat-polkit +chmem +chpasswd +chronyd +chroot +cifs.idmap +cifs.upcall +cobjnew-bpfcc +coldreboot +compactsnoop-bpfcc +complain +config.postfix +cppw +cpudist-bpfcc +cpuunclaimed-bpfcc +cpuwalk.bt +cracklib-check +cracklib-format +cracklib-packer +cracklib-unpacker +cracklib-update +crda +create-cracklib-dict +criticalstat-bpfcc +criu +criu-ns +cron +cryptdisks_start +cryptdisks_stop +cryptsetup +ctrlaltdel +cups-browsed +cups-genppd.5.3 +cups-genppdupdate +cupsaccept +cupsctl +cupsd +cupsfilter +dbslower-bpfcc +dbstat-bpfcc +dcb +dcsnoop-bpfcc +dcsnoop.bt +dcstat-bpfcc +ddns-confgen +deadlock-bpfcc +debugfs +debugreiserfs +decode +delpart +deluser +devlink +dhcpcd +dirtop-bpfcc +disable +dkms +dmevent_tool +dmeventd +dmfilemapd +dmidecode +dmraid +dmsetup +dnsmasq +dockerd +dosfsck +dosfslabel +dpkg-preconfigure +dpkg-reconfigure +docker-proxy +drsnoop-bpfcc +dump.exfat +dump.f2fs +dumpe2fs +e2freefrag +e2fsck +e2image +e2label +e2mmpstatus +e2scrub +e2scrub_all +e2undo +e4crypt +e4defrag +eapol_test +ebtables-legacy +ebtables-legacy-restore +ec_access +efibootdump +efibootmgr +enforce +ephemeral-disk-warning +escapesrc +ethtool +eventlogadm +execsnoop-bpfcc +execsnoop.bt +exfat2img +exfatlabel +exicyclog +exigrep +exim_checkaccess +exim_convert4r4 +exim_dbmbuild +exim_dumpdb +exim_fixdb +exim_id_update +exim_lock +exim_msgdate +exim_tidydb +exim4 +eximstats +exinext +exipick +exiqgrep +exiqsumm +exitsnoop-bpfcc +exiwhat +ext4dist-bpfcc +ext4slower-bpfcc +f2fs_io +f2fscrypt +f2fsslower-bpfcc +faillock +fanatic +fancontrol +fanctl +fatlabel +fatresize +fbtest +fdformat +fdisk +fibmap.f2fs +filefrag +filegone-bpfcc +filelife-bpfcc +fileslower-bpfcc +filetop-bpfcc +findfs +firewalld +fixparts +flushb +fonts-config +fsadm +fsck +fsck. +fsck.btrfs +fsck.cramfs +fsck.exfat +fsck.ext2 +fsck.ext3 +fsck.ext4 +fsck.f2fs +fsck.fat +fsck.minix +fsck.msdos +fsck.reiserfs +fsck.vfat +fsck.xfs +fsfreeze +fstab-decode +fstrim +funccount-bpfcc +funcinterval-bpfcc +funclatency-bpfcc +funcslower-bpfcc +g13-syshelp +gdisk +gdm +gdm3 +genccode +gencmn +genl +gennorm2 +genprof +gensprep +getcap +gethostlatency-bpfcc +gethostlatency.bt +getpcaps +getsysinfo +getweb +gnome-menus-blacklist +gnuchroot +gpart +gparted +gpartedbin +gpm +groupadd +groupdel +groupmems +groupmod +grpck +grpconv +grpunconv +grub-install +grub-macbless +grub-mkconfig +grub-mkdevicemap +grub-probe +grub-reboot +grub-set-default +grub2-bios-setup +grub2-check-default +grub2-install +grub2-macbless +grub2-mkconfig +grub2-ofpathname +grub2-once +grub2-probe +grub2-reboot +grub2-set-default +grub2-sparc64-setup +grub2-switch-to-blscfg +hardirqs-bpfcc +haveged +hc-ifscan +hdparm +httxt2dbm +hv_fcopy_daemon +hv_get_dhcp_info +hv_get_dns_info +hv_kvp_daemon +hv_set_ifconfig +hv_vss_daemon +hwclock +hwinfo +iconvconfig +icupkg +ifconfig +ifrename +ifstat +import-openSUSE-build-key +inject-bpfcc +inputattach +install_acx100_firmware +install_intersil_firmware +install-sgmlcatalog +installkernel +integritysetup +invoke-rc.d +ip6tables-legacy-batch +ipmaddr +ipp-usb +ippevepcl +ippeveprinter +ippeveps +ipset +iptables-apply +iptables-legacy-batch +iptunnel +irqbalance +irqbalance-ui +isadump +isaset +iscsi_discovery +iscsi-iname +iscsiadm +iscsid +iscsistart +isosize +ispell-autobuildhash +isserial +issue-generator +iucode_tool +iw +iwconfig +iwevent +iwgetid +iwlist +iwpriv +iwspy +javacalls-bpfcc +javaflow-bpfcc +javagc-bpfcc +javaobjnew-bpfcc +javastat-bpfcc +javathreads-bpfcc +kbdrate +kbdsettings +kdump-config +kerneloops +kexec +kexec-bootloader +kexec-load-kernel +key.dns_resolver +killall5 +killproc +killsnoop-bpfcc +killsnoop.bt +klockstat-bpfcc +klogd +kpartx +kvm-ok +kvmexit-bpfcc +ldattach +ldconfig +ldconfig.real +libguestfs-make-fixed-appliance +libgvc6-config-update +libvirt-dbus +libvirtd +llcstat-bpfcc +lnstat +loads.bt +locale-gen +logprof +logrotate +logrotate-all +logsave +losetup +lpadmin +lpc +lpinfo +lpmove +lsvmbus +luksformat +lvm +lvm_import_vdo +lvmconfig +lvmdump +lvmpolld +lwepgen +lxc +lxd +make-bcache +make-ssl-cert +mariadbd +mcelog +mdadm +mdevctl +mdflush-bpfcc +mdflush.bt +mdmon +memleak-bpfcc +mii-tool +mk_isdnhwdb +mkdict +mkdosfs +mke2fs +mkfs +mkfs. +mkfs.bfs +mkfs.btrfs +mkfs.cramfs +mkfs.exfat +mkfs.ext2 +mkfs.ext3 +mkfs.ext4 +mkfs.f2fs +mkfs.fat +mkfs.minix +mkfs.xfs +mkhomedir_helper +mkill +mkinitramfs +mklost+found +mkntfs +mkpostfixcert +mkreiserfs +mksubvolume +mkswap +ModemManager +mount.cifs +mount.ddi +mount.fuse +mount.fuse3 +mount.lowntfs-3g +mount.nfs +mount.nfs4 +mount.ntfs +mount.ntfs-3g +mount.smb3 +mount.veracrypt +mountsnoop-bpfcc +mountstats +mpathpersist +multipath +multipathc +multipathd +mysqld +mysqld_qslower-bpfcc +nameif +naptime.bt +needrestart +netqtop-bpfcc +NetworkManager +newusers +nfnl_osf +nfsconf +nfsdcld +nfsdist-bpfcc +nfsidmap +nfsiostat +nfsslower-bpfcc +nfsstat +nft +nginx +nmbd +nodegc-bpfcc +nodestat-bpfcc +nologin +notify +nss-mdns-config +nstat +ntfsclone +ntfscp +ntfslabel +ntfsresize +ntfsundelete +nvme +offcputime-bpfcc +offwaketime-bpfcc +on_ac_power +oomkill-bpfcc +oomkill.bt +openconnect +opensnoop-bpfcc +opensnoop.bt +openvpn +overlayroot-chroot +ownership +pam_extrausers_chkpwd +pam_extrausers_update +pam_getenv +pam_namespace_helper +pam_timestamp_check +pam-auth-update +pam-config +paperconfig +parse.f2fs +parted +partprobe +partx +pbl +pccardctl +pcscd +pdata_tools +perlcalls-bpfcc +perlflow-bpfcc +perlstat-bpfcc +pg_updatedicts +php-fpm8.3 +phpcalls-bpfcc +phpenmod +phpflow-bpfcc +phpquery +phpstat-bpfcc +pidpersec-bpfcc +pidpersec.bt +pivot_root +plipconfig +pluginviewer +plymouth-set-default-theme +plymouthd +postalias +postcat +postconf +postdrop +postfix +postkick +postlock +postlog +postmap +postmulti +postqueue +postsuper +posttls-finger +ppchcalls-bpfcc +pppd +pppdump +pppoe-discovery +pppstats +pptp +pptpsetup +profile-bpfcc +pwck +pwconv +pwhistory_helper +pwmconfig +pwunconv +pythoncalls-bpfcc +pythonflow-bpfcc +pythongc-bpfcc +pythonstat-bpfcc +qemu-ga +qmqp-source +qshape +rarp +rcfirewalld +rcopenvpn +rcpcscd +rcxdm +rcxvnc +rdma +rdmaucma-bpfcc +rdmsr +readahead-bpfcc +readprofile +realm +regdbdump +reiserfsck +reiserfstune +remove-default-ispell +remove-default-wordlist +remove-shell +request-key +reset-trace-bpfcc +resize_reiserfs +resize2fs +resizepart +resolvconf +rfkill +rmt-tar +rndc +rndc-confgen +rngd +route +routel +rpc.gssd +rpc.idmapd +rpc.statd +rpc.svcgssd +rpcbind +rpcctl +rpcdebug +rpmconfigcheck +rsyncd +rsyslogd +rtacct +rtcwake +rtkitctl +rtmon +rubycalls-bpfcc +rubyflow-bpfcc +rubygc-bpfcc +rubyobjnew-bpfcc +rubystat-bpfcc +runc +runqlat-bpfcc +runqlat.bt +runqlen-bpfcc +runqlen.bt +runqslower-bpfcc +runuser +rvmtab +saned +sasldblistusers2 +saslpasswd2 +save_y2logs +schema2ldif +select-default-ispell +select-default-wordlist +sendmail +sensors-detect +service +set_polkit_default_privs +setcap +setuids.bt +setup-nsssysinit.sh +setvesablank +setvtrgb +sfdisk +sgdisk +shadowconfig +shim-install +shmsnoop-bpfcc +showconsole +showmount +skdump +sktest +slabratetop-bpfcc +slattach +sm-notify +smart_agetty +smartctl +smartd +smbd +smtp-sink +smtp-source +snapperd +snmpd +snmptrapd +sofdsnoop-bpfcc +softirqs-bpfcc +solisten-bpfcc +spice-vdagentd +split-logfile +ss +sshd +sshd-gen-keys-start +sshd.hmac +ssllatency.bt +sslsniff-bpfcc +sslsnoop.bt +sssd +stackcount-bpfcc +start-statd +start-stop-daemon +startproc +statsnoop-bpfcc +statsnoop.bt +status +sudo_logsrvd +sudo_sendlog +sudo_sendlog.ws +sulogin +swapin.bt +swaplabel +swapoff +swapon +switch_root +sync-available +syncsnoop-bpfcc +syncsnoop.bt +sysconf_addword +syscount-bpfcc +syscount.bt +sysctl +syslog2eximlog +sysusers2shadow +tarcat +tc +tclcalls-bpfcc +tclflow-bpfcc +tclobjnew-bpfcc +tclstat-bpfcc +tcpaccept-bpfcc +tcpaccept.bt +tcpcong-bpfcc +tcpconnect-bpfcc +tcpconnect.bt +tcpconnlat-bpfcc +tcpdrop-bpfcc +tcpdrop.bt +tcplife-bpfcc +tcplife.bt +tcpretrans-bpfcc +tcpretrans.bt +tcprtt-bpfcc +tcpstates-bpfcc +tcpsubnet-bpfcc +tcpsynbl-bpfcc +tcpsynbl.bt +tcptop-bpfcc +tcptracer-bpfcc +tcptraceroute.db +thermald +threadsnoop-bpfcc +threadsnoop.bt +tipc +tlp +tplist-bpfcc +trace-bpfcc +tsig-keygen +ttysnoop-bpfcc +tune.exfat +tune2fs +tuned +tuned-adm +tunelp +u-d-c-print-pci-ids +ucalls +uflow +ufw +ugc +umount.nfs +umount.nfs4 +umount.udisks2 +unbound +unconfined +undump.bt +unix_chkpwd +unix_update +unix2_chkpwd +uobjnew +update-ca-certificates +update-catalog +update-cracklib +update-default-ispell +update-default-wordlist +update-dictcommon-aspell +update-dictcommon-hunspell +update-exim4.conf +update-exim4.conf.template +update-fonts-alias +update-fonts-dir +update-fonts-scale +update-grub +update-grub-gfxpayload +update-gsfontmap +update-icon-caches +update-ieee-data +update-inetd +update-info-dir +update-initramfs +update-java-alternatives +update-language +update-locale +update-mime +update-passwd +update-pciids +update-rc.d +update-secureboot-policy +update-shells +update-smart-drivedb +update-texmf +update-texmf-config +update-tl-stacked-conffile +update-xmlcatalog +upgrade-from-grub-legacy +usb_modeswitch +usb_modeswitch_dispatcher +usbmuxd +useradd +userdel +usermod +ustat +uthreads +uuidd +validlocale +vconfig +vcstime +vdpa +veritysetup +vfscount-bpfcc +vfscount.bt +vfsstat-bpfcc +vfsstat.bt +vhangup +vipw +virt-what +virt-what-cvm +virtiostat-bpfcc +virtlockd +virtlogd +visudo +visudo.ws +vmcore-dmesg +vncsession +vpddecode +vpnc +vpnc-disconnect +wakeuptime-bpfcc +wipefs +wiper.sh +wpa_action +wpa_cli +wpa_passphrase +wpa_supplicant +wqlat-bpfcc +writeback.bt +wrmsr +xfs_admin +xfs_bmap +xfs_copy +xfs_db +xfs_estimate +xfs_freeze +xfs_fsr +xfs_growfs +xfs_info +xfs_io +xfs_logprint +xfs_mdrestore +xfs_metadump +xfs_mkfile +xfs_ncheck +xfs_property +xfs_protofile +xfs_quota +xfs_repair +xfs_rtcp +xfs_scrub +xfs_scrub_all +xfs_spaceman +xfsdist-bpfcc +xfsdist.bt +xfsslower-bpfcc +xkbctrl +xtables- +xtables-legacy-multi +xtables-nft-multi +yast2 +zdump +zerofree +zfsdist-bpfcc +zfsslower-bpfcc +zic +zramctl +zypp-refresh +zypper-log diff --git a/tests/testdata/logs/aa-log b/tests/testdata/logs/aa-log new file mode 100644 index 0000000000..c06f373e30 --- /dev/null +++ b/tests/testdata/logs/aa-log @@ -0,0 +1,42 @@ +ALLOWED kmod file_inherit comm=modprobe family=unix sock_type=stream protocol=0 requested_mask="send receive" +ALLOWED mkinitcpio file_inherit comm=modprobe family=unix sock_type=stream protocol=0 requested_mask=receive +ALLOWED pacman file_inherit comm=modprobe family=unix sock_type=stream protocol=0 requested_mask=receive +ALLOWED pacman-hook-mkinitcpio-install file_inherit comm=modprobe family=unix sock_type=stream protocol=0 requested_mask=receive +ALLOWED aa-log open @{sys}/kernel/mm/transparent_hugepage/hpage_pmd_size comm=remove-system.m requested_mask=r denied_mask=r +ALLOWED sysctl open @{PROC}/sys/kernel/panic_on_oops comm=sysctl requested_mask=r denied_mask=r +DENIED dbus-daemon signal comm=at-spi-bus-laun requested_mask=receive denied_mask=receive signal=term peer=at-spi-bus-launcher +DENIED dnsmasq open @{PROC}/sys/kernel/osrelease comm=dnsmasq requested_mask=r denied_mask=r +DENIED dnsmasq open @{PROC}/1/environ comm=dnsmasq requested_mask=r denied_mask=r +DENIED dnsmasq open @{PROC}/cmdline comm=dnsmasq requested_mask=r denied_mask=r +DENIED lsb_release open owner @{HOME}/ comm=find requested_mask=r denied_mask=r +DENIED lsb_release open /etc/ comm=find requested_mask=r denied_mask=r +DENIED chromium-chromium file_inherit owner @{user_share_dirs}/gvfs-metadata/root comm=chromium requested_mask=r denied_mask=r +DENIED chromium-chromium file_inherit owner @{user_share_dirs}/gvfs-metadata/root-aaabbbc0.log comm=chromium requested_mask=r denied_mask=r +ALLOWED fusermount open @{run}/user/@{uid}/doc/ comm=fusermount requested_mask=r denied_mask=r +DENIED chrome-gnome-shell open owner @{HOME}/.netrc comm=chrome-gnome-sh requested_mask=r denied_mask=r +ALLOWED man exec owner @{bin}/preconv -> man_groff info="no new privs" comm=man requested_mask=x denied_mask=x error=-1 +ALLOWED dbus-daemon dbus_method_call @{busname} receive bus=system path=/org/freedesktop/DBus interface=org.freedesktop.DBus member=AddMatch peer_label=power-profiles-daemon addr=? +ALLOWED "foo bar" file_perm @{HOME}/.bash_history comm=bash requested_mask=rw denied_mask=rw parent=16001 +ALLOWED power-profiles-daemon dbus_method_call org.freedesktop.DBus send bus=system path=/org/freedesktop/DBus interface=org.freedesktop.DBus member=AddMatch peer_label=dbus-daemon addr=? +ALLOWED dbus-daemon dbus_method_call @{busname} receive bus=system path=/org/freedesktop/DBus interface=org.freedesktop.DBus member=AddMatch peer_label=unconfined addr=? +ALLOWED gnome-shell bind comm=gnome-shell family=unix sock_type=stream protocol=0 requested_mask=bind denied_mask=bind addr=@/tmp/.X11-unix/X1 +ALLOWED gnome-session-binary file_perm comm=gnome-session-b family=unix sock_type=stream protocol=0 requested_mask="send receive" denied_mask="send receive" peer=gnome-shell peer_addr=none addr=@/tmp/.ICE-unix/1995 +ALLOWED lightdm dbus_method_call org.freedesktop.Accounts send bus=system path=/org/freedesktop/Accounts/User1000 interface=org.freedesktop.DBus.Properties member=GetAll peer_label=accounts-daemon +ALLOWED lightdm dbus_signal @{busname} receive bus=system path=/org/freedesktop/Accounts/User1000 interface=org.freedesktop.Accounts.User member=Changed peer_label=accounts-daemon +ALLOWED akonadi_maildispatcher_agent link owner @{user_config_dirs}/akonadi/agent_config_akonadi_maildispatcher_agent.CmJRGE -> @{user_config_dirs}/akonadi/#@{int6}1 comm=akonadi_maildis requested_mask=k denied_mask=k +ALLOWED xdg-document-portal ptrace comm=pool-/usr/lib/x requested_mask=read denied_mask=read peer=nautilus +DENIED nvidia_modprobe file_inherit comm=nvidia-modprobe family=netlink sock_type=raw protocol=0 requested_mask="send receive" denied_mask="send receive" +ALLOWED gsettings open owner /var/lib/gdm3/greeter-dconf-defaults comm=gsettings requested_mask=r denied_mask=r +ALLOWED gsettings connect comm="dconf worker" family=unix sock_type=stream protocol=0 requested_mask="send receive connect" denied_mask="send receive connect" peer=dbus-daemon addr=none peer_addr=@/tmp/dbus-AaKMpxzC4k +ALLOWED gsettings file_perm comm=dbus-daemon family=unix sock_type=stream protocol=0 requested_mask="send receive" denied_mask="send receive" peer=dbus-daemon addr=none peer_addr=@/tmp/dbus-AaKMpxzC4k +ALLOWED gnome-keyring-daemon mkdir owner /var/lib/gdm3/.local/ comm=gnome-keyring-d requested_mask=c denied_mask=c +ALLOWED gnome-keyring-daemon mkdir owner /var/lib/gdm3/.local/share/ comm=gnome-keyring-d requested_mask=c denied_mask=c +DENIED snap-update-ns.firefox ptrace comm=systemd-journal requested_mask=readby denied_mask=readby peer=systemd-journald +DENIED /snap/snapd/19457@{lib}/snapd/snap-confine capable comm=snap-confine capability=12 capname=net_admin +DENIED /snap/snapd/19457@{lib}/snapd/snap-confine capable comm=snap-confine capability=38 capname=perfmon +ALLOWED firefox-vaapitest file_inherit comm=vaapitest family=netlink sock_type=raw protocol=0 requested_mask="send receive" denied_mask="send receive" +ALLOWED @{lib}/kauth/backlighthelper capable comm=backlighthelper capability=12 capname=net_admin +ALLOWED xorg capable comm=Xorg.bin capability=17 capname=sys_rawio +ALLOWED pacman capable info="optional: no audit" comm=killall capability=19 capname=sys_ptrace error=-1 +ALLOWED signal-desktop open @{sys}/devices/@{pci}/boot_vga comm=signal-desktop requested_mask=r denied_mask=r +ALLOWED startplasma link owner @{user_cache_dirs}/ksycoca5_de_LQ6f0J2qZg4vOKgw2NbXuW7iuVU=.isNSBz -> @{user_cache_dirs}/#@{int} comm=startplasma-way requested_mask=k denied_mask=k diff --git a/tests/testdata/logs/audit.log b/tests/testdata/logs/audit.log index 11b8770d22..abf9d8956f 100644 --- a/tests/testdata/logs/audit.log +++ b/tests/testdata/logs/audit.log @@ -55,4 +55,12 @@ type=AVC msg=audit(1111111111.111:1111): apparmor="ALLOWED" operation="getattr" type=AVC msg=audit(1111111111.111:1111): apparmor="ALLOWED" operation="capable" class="cap" info="optional: no audit" error=-1 profile="pacman" comm="killall" capability=19 capname="sys_ptrace" apparmor="ALLOWED" operation="open" class="file" profile="signal-desktop" name="/sys/devices/pci0000:00/0000:00:02.0/boot_vga" comm="signal-desktop" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0 FSUID="user" OUID="root" apparmor="ALLOWED" operation="link" class="file" profile="startplasma" name="@{user_cache_dirs}/ksycoca5_de_LQ6f0J2qZg4vOKgw2NbXuW7iuVU=.isNSBz" comm="startplasma-way" requested_mask="k" denied_mask="k" fsuid=1000 ouid=1000 target="@{user_cache_dirs}/#@{int}" FSUID="user" OUID="user" +apparmor="ALLOWED" operation="open" class="file" profile="localsearch//gstreamer" name="/sys/devices/pci0000:00/0000:00:08.1/0000:04:00.0/drm/renderD128/uevent" comm="gst-plugin-scan" requested_mask="r" denied_mask="r" fsuid=60578 ouid=0 +type=AVC msg=audit(1690029190.344:2232): apparmor="DENIED" operation="symlink" class="file" profile="nvidia_modprobe" name="/dev/char/195:0" pid=54651 comm="nvidia-modprobe" requested_mask="c" denied_mask="c" fsuid=0 ouid=0FSUID="root" OUID="root" +apparmor="DENIED" operation="mknod" class="file" profile="snap.snapd-desktop-integration.snapd-desktop-integration" name="/home/alex/.local/share/fonts/.uuid.TMP-mX2Vd6" comm="[pango] FcInit" requested_mask="c" denied_mask="c" fsuid=1000 ouid=1000 +apparmor="DENIED" operation="mknod" class="file" profile="snap.snapd-desktop-integration.snapd-desktop-integration" name="/home/alex/.local/share/fonts/.uuid.TMP-3TDhre" comm="[pango] FcInit" requested_mask="c" denied_mask="c" fsuid=1000 ouid=1000 +apparmor="DENIED" operation="mknod" class="file" profile="snap.snapd-desktop-integration.snapd-desktop-integration" name="/home/alex/.local/share/fonts/.uuid.TMP-2fAFcM" comm="[pango] FcInit" requested_mask="c" denied_mask="c" fsuid=1000 ouid=1000 +apparmor="DENIED" operation="mknod" class="file" profile="snap.snapd-desktop-integration.snapd-desktop-integration" name="/home/alex/.local/share/fonts/.uuid.TMP-kTfuWJ" comm="[pango] FcInit" requested_mask="c" denied_mask="c" fsuid=1000 ouid=1000 +apparmor="DENIED" operation="mknod" class="file" profile="snap.snapd-desktop-integration.snapd-desktop-integration" name="/home/alex/.local/share/fonts/.uuid.TMP-ynKAS2" comm="[pango] FcInit" requested_mask="c" denied_mask="c" fsuid=1000 ouid=1000 +apparmor="ALLOWED" operation="link" class="file" profile="startplasma" name="@{user_cache_dirs}/ksycoca5_de_LQ6f0J2qZg4vOKgw2NbXuW7iuVU=.rSxlFV" comm="startplasma-way" requested_mask="k" denied_mask="k" fsuid=1000 ouid=1000 target="@{user_cache_dirs}/#@{int}" FSUID="seeker" OUID="seeker" diff --git a/tests/testdata/parse.aa b/tests/testdata/parse.aa new file mode 100644 index 0000000000..8e3dc54c58 --- /dev/null +++ b/tests/testdata/parse.aa @@ -0,0 +1,45 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only +# TODO: Test rule with only ',' + +abi , + +alias /mnt/usr -> /usr, + +include # optional: A nice message +include if exists "/etc/apparmor.d/global/dummy space" + +@{name} = torbrowser "tor browser" +@{lib_dirs} = @{lib}/@{name} /opt/@{name} # This is a comment + +alias /mnt/{,usr.sbin.}mount.cifs + -> + /sbin/mount.cifs, + +@{exec_path} = @{bin}/@{name} @{lib_dirs}/@{name} +profile foo @{exec_path} xattrs=(security.tagged=allowed) flags=(complain attach_disconnected) { + include + + remount /newroot/{,**}, + + unix (send receive) type=stream addr="@/tmp/.ICE[0-9]-unix/19 5" peer=(label=gnome-shell, addr=none), + + dbus bind bus=session name=org.gnome.*, # wfdwde + dbus receive bus=system path=/org/freedesktop/DBus + interface=org.freedesktop.DBus + member=AddMatch + peer=(name=:1.3, label=power-profiles-daemon), + + # Oh my god, it's a comment! before a paragraph of rules + "/opt/Mullvad VPN/resources/*.so*" mr, # To be able to read the /proc/ files + /usr/share/gnome-shell/extensions/ding@rastersoft.com/{,*/}ding.js rPx, + + @{bin}/zsh rix, + + owner /{var/,}tmp/#@{int} rw, + + owner @{user_config_dirs}/powerdevilrc{,.@{rand6}} rwl -> @{user_config_dirs}/#@{int}, + + include if exists +} diff --git a/tests/testdata/paths/broken_symlink/dir_1/broken_link b/tests/testdata/paths/broken_symlink/dir_1/broken_link new file mode 120000 index 0000000000..86a410dd1d --- /dev/null +++ b/tests/testdata/paths/broken_symlink/dir_1/broken_link @@ -0,0 +1 @@ +broken \ No newline at end of file diff --git a/tests/testdata/paths/broken_symlink/dir_1/file2 b/tests/testdata/paths/broken_symlink/dir_1/file2 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/testdata/paths/broken_symlink/dir_1/linked_dir b/tests/testdata/paths/broken_symlink/dir_1/linked_dir new file mode 120000 index 0000000000..4b019049fd --- /dev/null +++ b/tests/testdata/paths/broken_symlink/dir_1/linked_dir @@ -0,0 +1 @@ +real_dir \ No newline at end of file diff --git a/tests/testdata/paths/broken_symlink/dir_1/linked_file b/tests/testdata/paths/broken_symlink/dir_1/linked_file new file mode 120000 index 0000000000..30d67d4672 --- /dev/null +++ b/tests/testdata/paths/broken_symlink/dir_1/linked_file @@ -0,0 +1 @@ +file2 \ No newline at end of file diff --git a/tests/testdata/paths/broken_symlink/dir_1/real_dir/file1 b/tests/testdata/paths/broken_symlink/dir_1/real_dir/file1 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/testdata/paths/delay/.gitignore b/tests/testdata/paths/delay/.gitignore new file mode 100644 index 0000000000..fd5812a40b --- /dev/null +++ b/tests/testdata/paths/delay/.gitignore @@ -0,0 +1 @@ +delay* diff --git a/tests/testdata/paths/delay/main.go b/tests/testdata/paths/delay/main.go new file mode 100644 index 0000000000..d484f1c2c9 --- /dev/null +++ b/tests/testdata/paths/delay/main.go @@ -0,0 +1,16 @@ +// This file is part of PathsHelper library. +// Copyright (C) 2018-2025 Arduino AG (http://www.arduino.cc/) +// Copyright (C) 2021-2026 Alexandre Pujol +// SPDX-License-Identifier: GPL-2.0-only + +package main + +import ( + "fmt" + "time" +) + +func main() { + time.Sleep(3 * time.Second) + fmt.Println("Elapsed!") +} diff --git a/tests/testdata/paths/fileset/anotherFile b/tests/testdata/paths/fileset/anotherFile new file mode 100644 index 0000000000..27649646ed --- /dev/null +++ b/tests/testdata/paths/fileset/anotherFile @@ -0,0 +1,4 @@ +line 1 +line 2 + +line 3 \ No newline at end of file diff --git a/tests/testdata/paths/fileset/file b/tests/testdata/paths/fileset/file new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/testdata/paths/fileset/folder/.hidden b/tests/testdata/paths/fileset/folder/.hidden new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/testdata/paths/fileset/folder/file2 b/tests/testdata/paths/fileset/folder/file2 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/testdata/paths/fileset/folder/file3 b/tests/testdata/paths/fileset/folder/file3 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/testdata/paths/fileset/folder/subfolder/file4 b/tests/testdata/paths/fileset/folder/subfolder/file4 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/testdata/paths/fileset/symlinktofolder b/tests/testdata/paths/fileset/symlinktofolder new file mode 120000 index 0000000000..01196353b6 --- /dev/null +++ b/tests/testdata/paths/fileset/symlinktofolder @@ -0,0 +1 @@ +folder \ No newline at end of file diff --git a/tests/testdata/paths/loops/loop_1/dir1/loop b/tests/testdata/paths/loops/loop_1/dir1/loop new file mode 120000 index 0000000000..c9f3ab1eac --- /dev/null +++ b/tests/testdata/paths/loops/loop_1/dir1/loop @@ -0,0 +1 @@ +../dir1 \ No newline at end of file diff --git a/tests/testdata/paths/loops/loop_2/dir1/loop2 b/tests/testdata/paths/loops/loop_2/dir1/loop2 new file mode 120000 index 0000000000..d014eb492e --- /dev/null +++ b/tests/testdata/paths/loops/loop_2/dir1/loop2 @@ -0,0 +1 @@ +../dir2 \ No newline at end of file diff --git a/tests/testdata/paths/loops/loop_2/dir2/loop1 b/tests/testdata/paths/loops/loop_2/dir2/loop1 new file mode 120000 index 0000000000..c9f3ab1eac --- /dev/null +++ b/tests/testdata/paths/loops/loop_2/dir2/loop1 @@ -0,0 +1 @@ +../dir1 \ No newline at end of file diff --git a/tests/testdata/paths/loops/loop_3/dir1/loop2 b/tests/testdata/paths/loops/loop_3/dir1/loop2 new file mode 120000 index 0000000000..d014eb492e --- /dev/null +++ b/tests/testdata/paths/loops/loop_3/dir1/loop2 @@ -0,0 +1 @@ +../dir2 \ No newline at end of file diff --git a/tests/testdata/paths/loops/loop_3/dir2/dir3/loop2 b/tests/testdata/paths/loops/loop_3/dir2/dir3/loop2 new file mode 120000 index 0000000000..85babfdb0e --- /dev/null +++ b/tests/testdata/paths/loops/loop_3/dir2/dir3/loop2 @@ -0,0 +1 @@ +../../dir1/ \ No newline at end of file diff --git a/tests/testdata/paths/loops/loop_4/dir1/dir2/loop2 b/tests/testdata/paths/loops/loop_4/dir1/dir2/loop2 new file mode 120000 index 0000000000..3fd50ca463 --- /dev/null +++ b/tests/testdata/paths/loops/loop_4/dir1/dir2/loop2 @@ -0,0 +1 @@ +../dir3 \ No newline at end of file diff --git a/tests/testdata/paths/loops/loop_4/dir1/dir3/dir4/loop1 b/tests/testdata/paths/loops/loop_4/dir1/dir3/dir4/loop1 new file mode 120000 index 0000000000..4f388a6696 --- /dev/null +++ b/tests/testdata/paths/loops/loop_4/dir1/dir3/dir4/loop1 @@ -0,0 +1 @@ +../../../dir1 \ No newline at end of file diff --git a/tests/testdata/paths/loops/regular_1/dir1/file1 b/tests/testdata/paths/loops/regular_1/dir1/file1 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/testdata/paths/loops/regular_1/dir2 b/tests/testdata/paths/loops/regular_1/dir2 new file mode 120000 index 0000000000..df490f837a --- /dev/null +++ b/tests/testdata/paths/loops/regular_1/dir2 @@ -0,0 +1 @@ +dir1 \ No newline at end of file diff --git a/tests/testdata/paths/loops/regular_2/dir1/file1 b/tests/testdata/paths/loops/regular_2/dir1/file1 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/testdata/paths/loops/regular_2/dir2/dir1 b/tests/testdata/paths/loops/regular_2/dir2/dir1 new file mode 120000 index 0000000000..c9f3ab1eac --- /dev/null +++ b/tests/testdata/paths/loops/regular_2/dir2/dir1 @@ -0,0 +1 @@ +../dir1 \ No newline at end of file diff --git a/tests/testdata/paths/loops/regular_2/dir2/file2 b/tests/testdata/paths/loops/regular_2/dir2/file2 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/testdata/paths/loops/regular_3/dir1/file1 b/tests/testdata/paths/loops/regular_3/dir1/file1 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/testdata/paths/loops/regular_3/dir2/dir1 b/tests/testdata/paths/loops/regular_3/dir2/dir1 new file mode 120000 index 0000000000..c9f3ab1eac --- /dev/null +++ b/tests/testdata/paths/loops/regular_3/dir2/dir1 @@ -0,0 +1 @@ +../dir1 \ No newline at end of file diff --git a/tests/testdata/paths/loops/regular_3/dir2/file2 b/tests/testdata/paths/loops/regular_3/dir2/file2 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/testdata/paths/loops/regular_3/link b/tests/testdata/paths/loops/regular_3/link new file mode 120000 index 0000000000..86a410dd1d --- /dev/null +++ b/tests/testdata/paths/loops/regular_3/link @@ -0,0 +1 @@ +broken \ No newline at end of file diff --git a/tests/testdata/paths/loops/regular_4_with_permission_error/dir1/file1 b/tests/testdata/paths/loops/regular_4_with_permission_error/dir1/file1 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/testdata/paths/loops/regular_4_with_permission_error/dir2/dir1 b/tests/testdata/paths/loops/regular_4_with_permission_error/dir2/dir1 new file mode 120000 index 0000000000..c9f3ab1eac --- /dev/null +++ b/tests/testdata/paths/loops/regular_4_with_permission_error/dir2/dir1 @@ -0,0 +1 @@ +../dir1 \ No newline at end of file diff --git a/tests/testdata/paths/loops/regular_4_with_permission_error/dir2/file2 b/tests/testdata/paths/loops/regular_4_with_permission_error/dir2/file2 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/testdata/paths/loops/regular_4_with_permission_error/link b/tests/testdata/paths/loops/regular_4_with_permission_error/link new file mode 120000 index 0000000000..86a410dd1d --- /dev/null +++ b/tests/testdata/paths/loops/regular_4_with_permission_error/link @@ -0,0 +1 @@ +broken \ No newline at end of file diff --git a/tests/testdata/profile0.aa b/tests/testdata/profile0.aa new file mode 100644 index 0000000000..bcca0464eb --- /dev/null +++ b/tests/testdata/profile0.aa @@ -0,0 +1,13 @@ +profile A flags=(attach_disconnected) { + /path/to/A mr, + + profile B { + /path/to/B mr, + } + profile C { + /path/to/C mr, + } + profile D { + /path/to/D mr, + } +} \ No newline at end of file diff --git a/tests/testdata/profile1.aa b/tests/testdata/profile1.aa new file mode 100644 index 0000000000..e85f319154 --- /dev/null +++ b/tests/testdata/profile1.aa @@ -0,0 +1,16 @@ + +profile A flags=(attach_disconnected) { + /path/to/A mr, + + profile B { + /path/to/B mr, + + profile C { + /path/to/C mr, + + profile D { + /path/to/D mr, + } + } + } +} \ No newline at end of file diff --git a/tests/testdata/string.aa b/tests/testdata/string.aa index 25065ce358..2ee487892a 100644 --- a/tests/testdata/string.aa +++ b/tests/testdata/string.aa @@ -27,7 +27,7 @@ profile foo @{exec_path} xattrs=(security.tagged=allowed) flags=(complain attach ptrace read peer=nautilus, - unix (send receive) type=stream addr=@/tmp/.ICE-unix/1995 peer=(label=gnome-shell, addr=none), + unix (send receive) type=stream addr=@/tmp/.ICE-unix/1995 peer=(label=gnome-shell), dbus bind bus=session name=org.gnome.*, dbus receive bus=system path=/org/freedesktop/DBus @@ -41,3 +41,4 @@ profile foo @{exec_path} xattrs=(security.tagged=allowed) flags=(complain attach include if exists } + diff --git a/zensical.toml b/zensical.toml new file mode 100644 index 0000000000..4696364b2d --- /dev/null +++ b/zensical.toml @@ -0,0 +1,243 @@ +# apparmor.d - Full set of apparmor profiles +# Copyright (C) 2021-2024 Alexandre Pujol +# SPDX-License-Identifier: GPL-2.0-only + +# https://zensical.org/docs/setup/basics/ + +[project] + +# Project information +site_name = "AppArmor.d" +site_url = "https://apparmor.pujol.io" +site_description = "Full set of AppArmor profiles" +site_author = "Alexandre Pujol" +copyright = "Copyright © 2021-2026 Alexandre Pujol" + +# Repository +repo_name = "roddhjav/apparmor.d" +repo_url = "https://github.com/roddhjav/apparmor.d" +edit_uri = "edit/main/docs/" + +# Extra stylesheets and scripts +extra_css = ["assets/stylesheets/extra.css"] + +# Navigation structure +nav = [ + { "Home" = [ + { "Home" = [ + "index.md", + ] }, + { "Getting Started" = [ + "overview.md", + "install.md", + "configuration.md", + "usage.md", + "report.md", + ] }, + { "Advanced" = [ + "variables.md", + "enforce.md", + "full-system-policy.md", + ] }, + { "Troubleshooting" = [ + "issues.md", + "recovery.md", + ] }, + ] }, + { "Security" = [ + { "Security" = [ + "security/index.md", + ] }, + { "Security Model" = [ + "security/ecosystem.md", + "security/threat.md", + "security/model.md", + ] }, + { "Implementation" = [ + "security/architecture.md", + "security/hardening.md", + ] }, + ] }, + { "Development" = [ + { "Development" = [ + "development/index.md", + "development/roadmap.md", + ] }, + { "Profiles" = [ + "development/workflow.md", + "development/guidelines.md", + "development/internal.md", + "development/directives.md", + "development/dbus.md", + "development/recommendations.md", + ] }, + { "Packages" = [ + "development/build.md", + ] }, + { "Tests" = [ + "development/tests.md", + "development/vm.md", + "development/integration.md", + "development/autopkgtest.md", + ] }, + ] }, + { "Abstractions" = [ + { "Abstractions" = [ + "abstractions/index.md", + ] }, + { "Layers" = [ + "abstractions/core.md", + "abstractions/generic.md", + "abstractions/common.md", + "abstractions/app.md", + ] }, + { "System" = [ + "abstractions/dbus.md", + "abstractions/sys.md", + "abstractions/udev.md", + "abstractions/dev.md", + ] }, + { "Specialized" = [ + "abstractions/flatpak.md", + "abstractions/attached.md", + "abstractions/mapping.md", + ] }, + ] }, + { "Linter" = [ + { "Linter" = [ + "linter/index.md", + ] }, + { "Security Checks" = [ + "linter/checks/abstractions.md", + "linter/checks/too-wide.md", + "linter/checks/transition.md", + "linter/checks/tunables.md", + ] }, + { "Compatibility Checks" = [ + "linter/checks/abi.md", + "linter/checks/bin.md", + "linter/checks/directory-mark.md", + "linter/checks/equivalent.md", + ] }, + { "Style Checks" = [ + "linter/checks/header.md", + "linter/checks/include.md", + "linter/checks/profile.md", + "linter/checks/tabs.md", + "linter/checks/trailing.md", + "linter/checks/useless.md", + "linter/checks/vim.md", + ] }, + ] }, +] + +# Navigation structure +# Theme configuration +[project.theme] +logo = "assets/favicon.png" +favicon = "assets/favicon.png" +features = [ + "content.action.edit", + "content.action.view", + "content.code.annotate", + "content.code.copy", + "content.code.select", + "content.footnote.tooltips", + "content.tabs.link", + "content.tooltips", + "navigation.indexes", + "navigation.instant.prefetch", + "navigation.instant", + "navigation.sections", + "navigation.tabs", + "navigation.top", + "navigation.tracking", + "search.highlight", +] + +# Extensions +[project.markdown_extensions.abbr] +[project.markdown_extensions.admonition] +[project.markdown_extensions.attr_list] +[project.markdown_extensions.def_list] +[project.markdown_extensions.footnotes] +[project.markdown_extensions.md_in_html] +[project.markdown_extensions.toc] +permalink = true +toc_depth = 4 +[project.markdown_extensions.pymdownx.arithmatex] +generic = true +[project.markdown_extensions.pymdownx.betterem] +smart_enable = "all" +[project.markdown_extensions.pymdownx.caret] +[project.markdown_extensions.pymdownx.details] +[project.markdown_extensions.pymdownx.emoji] +emoji_generator = "zensical.extensions.emoji.to_svg" +emoji_index = "zensical.extensions.emoji.twemoji" +[project.markdown_extensions.pymdownx.highlight] +anchor_linenums = true +[project.markdown_extensions.pymdownx.inlinehilite] +[project.markdown_extensions.pymdownx.keys] +[project.markdown_extensions.pymdownx.magiclink] +repo_url_shorthand = true +user = "squidfunk" +repo = "mkdocs-material" +[project.markdown_extensions.pymdownx.mark] +[project.markdown_extensions.pymdownx.smartsymbols] +[project.markdown_extensions.pymdownx.superfences] +custom_fences = [ + { name = "mermaid", class = "mermaid", format = "pymdownx.superfences.fence_code_format" }, +] +[project.markdown_extensions.pymdownx.tabbed] +alternate_style = true +[project.markdown_extensions.pymdownx.tabbed.slugify] +kwds = { case = "lower" } +object = "pymdownx.slugs.slugify" +[project.markdown_extensions.pymdownx.tasklist] +custom_checkbox = true +[project.markdown_extensions.pymdownx.tilde] + +# Plugins +[project.plugins.offline] +enabled = false + +# Palette toggle for automatic mode +[[project.theme.palette]] +media = "(prefers-color-scheme)" +toggle.icon = "lucide/sun-moon" +toggle.name = "Switch to light mode" + +# Palette toggle for light mode +[[project.theme.palette]] +media = "(prefers-color-scheme: light)" +scheme = "default" +primary = "brown" +accent = "deep orange" +toggle.icon = "lucide/sun" +toggle.name = "Switch to dark mode" + +# Palette toggle for dark mode +[[project.theme.palette]] +media = "(prefers-color-scheme: dark)" +scheme = "slate" +primary = "brown" +accent = "deep orange" +toggle.icon = "lucide/moon" +toggle.name = "Switch to system preference" + +# Customization +[[project.extra.social]] +icon = "fontawesome/brands/mastodon" +link = "https://mamot.fr/@roddhjav" + +[[project.extra.social]] +icon = "fontawesome/brands/github" +link = "https://github.com/roddhjav/apparmor.d" + +[[project.extra.social]] +icon = "fontawesome/brands/gitlab" +link = "https://gitlab.com/roddhjav/apparmor.d" + +[[project.extra.social]] +icon = "fontawesome/solid/up-right-from-square" +link = "https://pujol.io"