diff --git a/Makefile b/Makefile index 1caed67f..85a4a719 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ P = $(filter-out dpkg,$(notdir $(wildcard ${BUILD}/apparmor.d/*))) .PHONY: all build enforce full install local $(P) pkg dpkg rpm tests lint clean all: build - @./${BUILD}/prebuild --complain + @./${BUILD}/prebuild --complain build: @go build -o ${BUILD}/ ./cmd/aa-log @@ -26,6 +26,7 @@ full: build ROOT = $(shell find "${BUILD}/root" -type f -printf "%P\n") PROFILES = $(shell find "${BUILD}/apparmor.d" -type f -printf "%P\n") +DISABLES = $(shell find "${BUILD}/apparmor.d" -type l -printf "%P\n") install: @install -Dm0755 ${BUILD}/aa-log ${DESTDIR}/usr/bin/aa-log @for file in ${ROOT}; do \ @@ -34,6 +35,10 @@ install: @for file in ${PROFILES}; do \ install -Dm0644 "${BUILD}/apparmor.d/$${file}" "${DESTDIR}/etc/apparmor.d/$${file}"; \ done; + @for file in ${DISABLES}; 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"; \ diff --git a/pkg/prebuild/cfg/directories.go b/pkg/prebuild/cfg/directories.go index 4032249b..497a67df 100644 --- a/pkg/prebuild/cfg/directories.go +++ b/pkg/prebuild/cfg/directories.go @@ -28,8 +28,11 @@ var ( // DebianDir is the directory where the debian specific files are stored DebianDir *paths.Path = paths.New("debian") - // Either or not overwrite some upstreamed profile - Overwrite = Overwriter{Enabled: false} + // AppArmor 4.0 contains several profiles that allow userns and are otherwise + // unconfined. Overwriter disables upstream profile in favor of (better) apparmor.d + // counterpart + Overwrite Overwriter = false + Ignore = Ignorer{} Flags = Flagger{} diff --git a/pkg/prebuild/cfg/files.go b/pkg/prebuild/cfg/files.go index 6d635d65..7fb3a2fa 100644 --- a/pkg/prebuild/cfg/files.go +++ b/pkg/prebuild/cfg/files.go @@ -50,42 +50,35 @@ func (i Ignorer) Read(name string) []string { return util.MustReadFileAsLines(path) } -type Overwriter struct { - Enabled bool -} +type Overwriter bool + +// Overwrite upstream profile: disable upstream & rename ours +func (o Overwriter) Apply() error { + const ext = ".apparmor.d" + disableDir := RootApparmord.Join("disable") + if err := disableDir.Mkdir(); err != nil { + return err + } -// Get the list of upstream profiles to overwrite from dist/overwrite -func (o Overwriter) Get() []string { path := DistDir.Join("overwrite") if !path.Exist() { - return []string{} + return fmt.Errorf("%s not found", path) } - return util.MustReadFileAsLines(path) -} - -// Overwrite upstream profile for APT: rename our profile & hide upstream -func (o Overwriter) Apt(files []string) { - const ext = ".apparmor.d" - file, err := DebianDir.Join("apparmor.d.hide").Append() - if err != nil { - panic(err) - } - for _, name := range files { + for _, name := range util.MustReadFileAsLines(path) { origin := RootApparmord.Join(name) dest := RootApparmord.Join(name + ext) if err := origin.Rename(dest); err != nil { - panic(err) + return err } - if _, err := file.WriteString("/etc/apparmor.d/" + name + "\n"); err != nil { - panic(err) + originRel, err := origin.RelFrom(dest) + if err != nil { + return err + } + if err := os.Symlink(originRel.String(), disableDir.Join(name).String()); err != nil { + return err } } + return nil } -// Clean the debian/apparmor.d.hide file -func (o Overwriter) AptClean() { - path := DebianDir.Join("apparmor.d.hide") - if err := path.WriteFile([]byte(Hide)); err != nil { - panic(err) - } } diff --git a/pkg/prebuild/cfg/files_test.go b/pkg/prebuild/cfg/files_test.go index c3d89dd2..b4ce13a1 100644 --- a/pkg/prebuild/cfg/files_test.go +++ b/pkg/prebuild/cfg/files_test.go @@ -102,64 +102,3 @@ code }) } } - -func TestOverwriter_Get(t *testing.T) { - tests := []struct { - name string - content string - want []string - }{ - { - name: "empty", - content: ` - -`, - want: []string{}, - }, - { - name: "main", - content: ` -# This is managed globally -brave # not so brave -chrome -firefox -`, - want: []string{ - "brave", - "chrome", - "firefox", - }, - }, - } - DistDir = paths.New("/tmp/") - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - err := DistDir.Join("overwrite").WriteFile([]byte(tt.content)) - if err != nil { - return - } - if got := Overwrite.Get(); !reflect.DeepEqual(got, tt.want) { - t.Errorf("Overwriter.Get() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestOverwriter_Apt(t *testing.T) { - tests := []struct { - name string - files []string - }{ - { - name: "empty", - files: []string{}, - }, - } - DebianDir = paths.New("/tmp/") - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - Overwrite.Apt(tt.files) - Overwrite.AptClean() - }) - } -} diff --git a/pkg/prebuild/prebuild.go b/pkg/prebuild/prebuild.go index a0e8117d..fc327fff 100644 --- a/pkg/prebuild/prebuild.go +++ b/pkg/prebuild/prebuild.go @@ -32,11 +32,16 @@ func init() { builder.Register("dev") switch cfg.Distribution { + case "opensuse": + builder.Register("abi3") + cfg.Overwrite = true + case "ubuntu": if cfg.Release["VERSION_CODENAME"] == "noble" { builder.Register("abi3") - cfg.Overwrite.Enabled = true + cfg.Overwrite = true } + case "whonix": cfg.Hide += `/etc/apparmor.d/abstractions/base.d/kicksecure /etc/apparmor.d/home.tor-browser.firefox diff --git a/pkg/prebuild/prepare/configure.go b/pkg/prebuild/prepare/configure.go index ba0c700c..abca3d54 100644 --- a/pkg/prebuild/prepare/configure.go +++ b/pkg/prebuild/prepare/configure.go @@ -28,12 +28,17 @@ func (p Configure) Apply() ([]string, error) { res := []string{} switch cfg.Distribution { case "arch", "opensuse": + if cfg.Overwrite { + if err := cfg.Overwrite.Apply(); err != nil { + return res, err + } + } case "ubuntu": - cfg.Overwrite.AptClean() - if cfg.Overwrite.Enabled { - profiles := cfg.Overwrite.Get() - cfg.Overwrite.Apt(profiles) + if cfg.Overwrite { + if err := cfg.Overwrite.Apply(); err != nil { + return res, err + } } else { if err := util.CopyTo(cfg.DistDir.Join("ubuntu"), cfg.RootApparmord); err != nil { return res, err