Compare commits

...

11 Commits

Author SHA1 Message Date
Alex
76105e699c
Merge 78ae93ff70 into 026fbf7552 2024-11-04 19:18:22 +08:00
Besanon
026fbf7552
Add lxqt-panel (#594)
Some checks failed
Ubuntu / build (default, ubuntu-22.04) (push) Has been cancelled
Ubuntu / build (default, ubuntu-24.04) (push) Has been cancelled
Ubuntu / build (full-system-policy, ubuntu-22.04) (push) Has been cancelled
Ubuntu / build (full-system-policy, ubuntu-24.04) (push) Has been cancelled
Ubuntu / tests (push) Has been cancelled
2024-11-04 10:21:08 +00:00
Roman Beslik
1eb7be5447 /boot/EFI 2 2024-11-04 10:18:06 +00:00
Alexandre Pujol
a9a41ef810
feat(profile): pacman can restart any updated program.
Some checks failed
Ubuntu / build (default, ubuntu-22.04) (push) Has been cancelled
Ubuntu / build (default, ubuntu-24.04) (push) Has been cancelled
Ubuntu / build (full-system-policy, ubuntu-22.04) (push) Has been cancelled
Ubuntu / build (full-system-policy, ubuntu-24.04) (push) Has been cancelled
Ubuntu / tests (push) Has been cancelled
See #596
2024-11-01 11:59:30 +01:00
odomingao
3144c30c0c
Update nvtop (#595)
Some checks failed
Ubuntu / build (default, ubuntu-22.04) (push) Has been cancelled
Ubuntu / build (default, ubuntu-24.04) (push) Has been cancelled
Ubuntu / build (full-system-policy, ubuntu-22.04) (push) Has been cancelled
Ubuntu / build (full-system-policy, ubuntu-24.04) (push) Has been cancelled
Ubuntu / tests (push) Has been cancelled
2024-10-29 10:43:39 +00:00
Alexandre Pujol
78ae93ff70
fix(build): remove empty suse group. 2024-10-23 15:52:02 +01:00
Alexandre Pujol
b614bdda36
build: update directive and prepare tasks to new structure. 2024-10-23 15:47:49 +01:00
Alexandre Pujol
17cee26dc0
build: update the PKGBUILD to support sub packages.
Note: It also keep full compatibility with the unified package.
2024-10-23 14:58:09 +01:00
Alexandre Pujol
3020de1ba2
build: makefile: add support for sub packages. 2024-10-23 14:52:53 +01:00
Alexandre Pujol
a1c8260305
build: add initial build structure for sub packages. 2024-10-23 14:48:47 +01:00
Alexandre Pujol
467b24ccee
build: add initial pkg definition for the base pkg.
Note: we are purposelly not using yaml to not add externak build dependencies.
2024-10-23 14:10:52 +01:00
23 changed files with 643 additions and 95 deletions

View File

@ -7,7 +7,8 @@ DESTDIR ?= /
BUILD ?= .build
PKGDEST ?= ${PWD}/.pkg
PKGNAME := apparmor.d
PROFILES = $(filter-out dpkg,$(notdir $(wildcard ${BUILD}/apparmor.d/*)))
PROFILE = $(filter-out dpkg,$(notdir $(wildcard ${BUILD}/apparmor.d/*)))
PROFILES = profiles-apparmor.d profiles-other $(patsubst dists/packages/%,profiles-%,$(basename $(wildcard dists/packages/*.conf)))
.PHONY: all
all: build
@ -26,32 +27,53 @@ enforce: build
full: build
@./${BUILD}/prebuild --complain --full
.PHONY: packages
packages: clean build
@./${BUILD}/prebuild --complain --packages
# Install apparmor.d
.PHONY: install
install:
install: install-bin install-share install-systemd profiles-apparmor.d
# Install apparmor.d.base
.PHONY: install-base
install-base: install-bin install-share install-systemd profiles-base
.PHONY: install-bin
install-bin:
@install -Dm0755 ${BUILD}/aa-log ${DESTDIR}/usr/bin/aa-log
.PHONY: install-share
install-share:
@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;
.PHONY: install-systemd
install-systemd:
@for file in ${BUILD}/systemd/system/*; do \
service="$$(basename "$$file")"; \
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")"; \
service="$$(basename "$${file}")"; \
install -Dm0644 "$${file}" "${DESTDIR}/usr/lib/systemd/user/$${service}.d/apparmor.conf"; \
done
# Install all profiles for a given (sub)package
.PHONY: $(PROFILES)
$(PROFILES):
@install -Dm0755 ${BUILD}/aa-log ${DESTDIR}/usr/bin/aa-log
@for file in $(shell find "${BUILD}/$(patsubst profiles-%,%,$@)" -type f -printf "%P\n"); do \
install -Dm0644 "${BUILD}/$(patsubst profiles-%,%,$@)/$${file}" "${DESTDIR}/etc/apparmor.d/$${file}"; \
done;
@for file in $(shell find "${BUILD}/$(patsubst profiles-%,%,$@)" -type l -printf "%P\n"); do \
mkdir -p "${DESTDIR}/etc/apparmor.d/disable"; \
cp -d "${BUILD}/$(patsubst profiles-%,%,$@)/$${file}" "${DESTDIR}/etc/apparmor.d/$${file}"; \
done;
# Partial install (not recommended)
.PHONY: $(PROFILE)
$(PROFILE): install-bin
@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;

View File

@ -3,19 +3,23 @@
# 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.other
)
pkgver=0.0001
pkgrel=1
pkgdesc="Full set of apparmor profiles"
arch=("x86_64")
url="https://github.com/roddhjav/$pkgname"
pkgdesc="Full set of apparmor profiles (base)"
arch=("any")
url="https://github.com/roddhjav/apparmor.d"
license=('GPL2')
depends=('apparmor')
makedepends=('go' 'git' 'rsync')
conflicts=("$pkgname-git")
conflicts=("$pkgbase-git" "$pkgbase")
pkgver() {
cd "$srcdir/$pkgname"
cd "$srcdir/$pkgbase"
echo "0.$(git rev-list --count HEAD)"
}
@ -24,16 +28,33 @@ prepare() {
}
build() {
cd "$srcdir/$pkgname"
cd "$srcdir/$pkgbase"
export CGO_CPPFLAGS="${CPPFLAGS}"
export CGO_CFLAGS="${CFLAGS}"
export CGO_CXXFLAGS="${CXXFLAGS}"
export CGO_LDFLAGS="${LDFLAGS}"
export GOFLAGS="-buildmode=pie -trimpath -ldflags=-linkmode=external -mod=readonly -modcacherw"
make DISTRIBUTION=arch
make BUILD=.buid.all DISTRIBUTION=arch
make packages DISTRIBUTION=arch
}
package() {
cd "$srcdir/$pkgname"
make install DESTDIR="$pkgdir"
package_apparmor.d() {
pkgdesc="Full set of apparmor profiles"
arch=("$CARCH")
conflicts=("${pkgname[@]:1}")
cd "$srcdir/$pkgbase"
make install BUILD=.buid.all DESTDIR="$pkgdir"
}
package_apparmor.d.base() {
arch=("$CARCH")
cd "$srcdir/$pkgbase"
make install-base DESTDIR="$pkgdir"
}
package_apparmor.d.other() {
pkgdesc="Full set of apparmor profiles (other)"
depends=(apparmor.d.base)
cd "$srcdir/$pkgbase"
make profiles-other DESTDIR="$pkgdir"
}

View File

@ -0,0 +1,92 @@
# apparmor.d - Full set of apparmor profiles
# Copyright (C) 2024 Alexandre Pujol <alexandre@pujol.io>
# Copyright (C) 2024 Besanon <m231009ts@mailfence.com>
# SPDX-License-Identifier: GPL-2.0-only
abi <abi/4.0>,
include <tunables/global>
@{exec_path} = @{bin}/lxqt-panel
profile lxqt-panel @{exec_path} {
include <abstractions/base>
include <abstractions/audio-client>
include <abstractions/dconf-write>
include <abstractions/lxqt>
include <abstractions/nameservice-strict>
network inet dgram,
network inet6 dgram,
network inet stream,
network inet6 stream,
network netlink raw,
network packet dgram,
@{exec_path} mr,
@{bin}/exo-open rix,
@{lib}/gio-launch-desktop rix,
@{bin}/nm-applet rPx,
@{bin}/nm-connection-editor rPx,
@{bin}/ControlPanel rPx,
@{bin}/sudo rCx -> root,
@{lib}/lxqt-panel/*.so mr, # LXQT-Plugins
@{lib}/lxqt-config/*.so mr, # LXQT-Plugins
/usr/share/desktop-directories/{,**} r,
/usr/share/lxqt/{,**} r,
/etc/fstab r,
/etc/udev/udev.conf r,
/etc/machine-id r,
/etc/xdg/lxqt-qtxdg.conf r,
/etc/xdg/menus/**.menu r,
/etc/xdg/menus/applications-merged/ r,
/etc/xdg/ui/uistandards.rc r,
/var/lib/dbus/machine-id r,
owner @{HOME}/Desktop/*.desktop rw,
owner @{HOME}/Desktop/#@{int} rw,
owner @{HOME}/Desktop/*.desktop l -> @{HOME}/Desktop/#@{int},
owner @{user_config_dirs}/menus/*.menu rw,
owner @{user_config_dirs}/menus/applications-merged/ r,
owner @{user_config_dirs}/share/desktop-directories/*.directory r,
owner @{user_config_dirs}/share/gvfs-metadata/{,*} r,
owner @{user_config_dirs}/lxqt/#@{int} rw,
owner @{user_config_dirs}/lxqt/panel.conf rw,
owner @{user_config_dirs}/lxqt/panel.conf.lock rwk,
owner @{user_config_dirs}/lxqt/panel.conf.@{rand6} rw,
owner @{user_config_dirs}/lxqt/panel.conf.@{rand6} l -> @{user_config_dirs}/lxqt/#@{int},
owner @{user_config_dirs}/pulse/{,**} rwk,
@{run}/udev/data/* r,
@{sys}/class/i2c-adapter/ r,
@{sys}/devices/system/cpu/cpufreq/policy@{int}/scaling_{cur,min,max}_freq r,
@{PROC}/@{pid}/fd/ r,
@{PROC}/@{pid}/net/dev r,
owner @{PROC}/@{pid}/mounts r,
/dev/tty rw,
/dev/tty@{int} rw,
/dev/pts/@{int} rw,
/dev/snd/controlC@{int} rw,
profile root {
include <abstractions/base>
include <abstractions/app/sudo>
@{bin}/lsblk rPx,
include if exists <local/lxqt-panel_root>
}
include if exists <local/lxqt-panel>
}
# vim:syntax=apparmor

View File

@ -83,10 +83,10 @@ profile mkinitcpio @{exec_path} flags=(attach_disconnected) {
# Manage /boot
/ r,
/{boot,efi}/ r,
/boot/ r,
/{boot,efi}/EFI/{,**} rw,
/{boot,efi}/initramfs-*.img* rw,
/{boot,efi}/vmlinuz-* r,
/boot/initramfs-*.img* rw,
/boot/vmlinuz-* r,
/usr/share/systemd/bootctl/** r,

View File

@ -39,7 +39,7 @@ profile pacman @{exec_path} flags=(attach_disconnected) {
ptrace read,
signal send set=usr1 peer=gvfsd,
signal send,
signal receive set=winch peer=makepkg//sudo,
@{exec_path} mrix,

View File

@ -37,7 +37,7 @@ profile pacman-hook-mkinitcpio @{exec_path} flags=(attach_disconnected) {
/ r,
/boot/ r,
/boot/efi/boot/boot*.efi rw,
/{boot,efi}/EFI/boot/boot*.efi rw,
/boot/initramfs-*-fallback.img rw,
/boot/initramfs-*.img rw,
/boot/vmlinuz-* rw,

View File

@ -31,7 +31,16 @@ profile nvtop @{exec_path} flags=(attach_disconnected) {
@{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/system/node/node@{int}/cpumap r,
@{PROC}/ r,

View File

@ -37,8 +37,6 @@ func init() {
// Compatibility with AppArmor 3
switch prebuild.Distribution {
case "arch":
case "ubuntu":
if !slices.Contains([]string{"noble"}, prebuild.Release["VERSION_CODENAME"]) {
prebuild.ABI = 3

View File

@ -4,9 +4,6 @@ apparmor.d/groups/apt
# Ubuntu specific definition
apparmor.d/groups/ubuntu
# OpenSUSE specific definition
apparmor.d/groups/suse
# Whonix specific definition
apparmor.d/groups/whonix
apparmor.d/tunables/home.d/whonix

View File

@ -5,9 +5,6 @@ share/libalpm
# Ubuntu specific definition
apparmor.d/groups/ubuntu
# OpenSUSE specific definition
apparmor.d/groups/suse
# Whonix specific definition
apparmor.d/groups/whonix
apparmor.d/abstractions/base.anondist

View File

@ -2,9 +2,6 @@
apparmor.d/groups/pacman
share/libalpm
# OpenSUSE specific definition
apparmor.d/groups/suse
# Whonix specific definition
apparmor.d/groups/whonix
apparmor.d/tunables/home.d/whonix

View File

@ -2,9 +2,6 @@
apparmor.d/groups/pacman
share/libalpm
# OpenSUSE specific definition
apparmor.d/groups/suse
# Whonix does not have them
apparmor.d/groups/pacman
apparmor.d/groups/ubuntu

22
dists/packages/base.conf Normal file
View File

@ -0,0 +1,22 @@
# apparmor.d - Full set of apparmor profiles
# Copyright (C) 2024 Alexandre Pujol <alexandre@pujol.io>
# SPDX-License-Identifier: GPL-2.0-only
# Minimal core with tunables, abstractions, and dependencies of other profiles
mode=enforce
tunables
abstractions
!abstractions/app/chromium
!abstractions/app/firefox
groups/children
!groups/children/user_confined
!groups/children/user_default
!groups/children/user_unconfined
groups/bus
profiles-s-z/unix-chkpwd
profiles-m-r/pam-tmpdir-helper

View File

@ -6,6 +6,8 @@ package builder
import (
"fmt"
"slices"
"strings"
"github.com/roddhjav/apparmor.d/pkg/paths"
"github.com/roddhjav/apparmor.d/pkg/prebuild"
@ -33,7 +35,7 @@ type Option struct {
func NewOption(file *paths.Path) *Option {
return &Option{
Name: file.Base(),
Name: strings.TrimSuffix(file.Base(), ".apparmor.d"),
File: file,
}
}
@ -41,13 +43,26 @@ func NewOption(file *paths.Path) *Option {
func Register(names ...string) {
for _, name := range names {
if b, present := Builders[name]; present {
Builds = append(Builds, b)
if !slices.Contains(Builds, b) {
Builds = append(Builds, b)
}
} else {
panic(fmt.Sprintf("Unknown builder: %s", name))
}
}
}
func Unregister(names ...string) {
for _, name := range names {
for i, b := range Builds {
if b.Name() == name {
Builds = slices.Delete(Builds, i, i+1)
break
}
}
}
}
func RegisterBuilder(d Builder) {
Builders[d.Name()] = d
}

View File

@ -15,21 +15,24 @@ import (
"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/util"
)
const (
nilABI uint = 0
usage = `aa-prebuild [-h] [--complain | --enforce] [--full] [--abi 3|4]
usage = `aa-prebuild [-h] [-s] [--complain|--enforce] [--packages] [--full] [--abi 3|4]
Prebuild apparmor.d profiles for a given distribution and apply
internal built-in directives.
Prebuild apparmor.d profiles for a given distribution, apply
internal built-in directives and build sub-packages structure.
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.
-e, --enforce Set enforce flag on ALL profiles.
-a, --abi ABI Target apparmor ABI.
-f, --full Set AppArmor for full system policy.
-p, --packages Build all split packages.
-s, --status Show build configuration.
-F, --file Only prebuild a given file.
`
)
@ -39,6 +42,7 @@ var (
complain bool
enforce bool
full bool
packages bool
abi uint
file string
)
@ -54,6 +58,8 @@ func init() {
flag.BoolVar(&enforce, "enforce", false, "Set enforce flag on all profiles.")
flag.UintVar(&abi, "a", nilABI, "Target apparmor ABI.")
flag.UintVar(&abi, "abi", nilABI, "Target apparmor ABI.")
flag.BoolVar(&packages, "p", false, "Build all split packages.")
flag.BoolVar(&packages, "packages", false, "Build all split packages.")
flag.StringVar(&file, "F", "", "Only prebuild a given file.")
flag.StringVar(&file, "file", "", "Only prebuild a given file.")
}
@ -79,12 +85,6 @@ func Prebuild() {
prepare.Register("systemd-early")
}
if complain {
builder.Register("complain")
} else if enforce {
builder.Register("enforce")
}
if abi != nilABI {
prebuild.ABI = abi
}
@ -104,13 +104,32 @@ func Prebuild() {
overwrite.OneFile = true
}
logging.Step("Building apparmor.d profiles for %s on ABI%d.", prebuild.Distribution, prebuild.ABI)
// Prepare the build directories
logging.Step("Building apparmor.d profiles for %s (abi%d).", prebuild.Distribution, prebuild.ABI)
prebuild.RootApparmord = prebuild.Root.Join(prebuild.Src)
if err := Prepare(); err != nil {
logging.Fatal("%s", err.Error())
}
// Generate the packages
if packages {
if err := Packages(); err != nil {
logging.Fatal("%s", err.Error())
}
}
// Build the apparmor.d profiles
if err := Build(); err != nil {
logging.Fatal("%s", err.Error())
}
if packages {
// Move all other profiles to apparmor.d.other
prebuild.RootApparmord = prebuild.Root.Join(prebuild.Src)
if err := prebuild.RootApparmord.Rename(prebuild.Root.Join("other")); err != nil {
logging.Fatal("%s", err.Error())
}
}
}
func Prepare() error {
@ -136,26 +155,64 @@ func Prepare() error {
return nil
}
func Packages() error {
logging.Success("Building apparmor.d.* packages structure:")
for _, name := range prebuild.Packages {
pkg := prebuild.NewPackage(name)
msg, err := pkg.Generate()
if err != nil {
return err
}
if err = pkg.Validate(); err != nil {
return err
}
logging.Indent = " "
logging.Bullet("apparmor.d.%s", name)
logging.Indent += " "
for _, line := range util.RemoveDuplicate(msg) {
logging.Warning("%s", line)
}
logging.Indent = ""
}
return nil
}
func Build() error {
files, _ := prebuild.RootApparmord.ReadDirRecursiveFiltered(nil, paths.FilterOutDirectories())
for _, file := range files {
if !file.Exist() {
continue
sources := []string{prebuild.Src}
if packages {
sources = append(sources, prebuild.Packages...)
}
for _, src := range sources {
prebuild.RootApparmord = prebuild.Root.Join(src)
if src == prebuild.Src {
setMode("")
} else {
pkg := prebuild.NewPackage(src)
setMode(pkg.Mode)
}
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
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
}
}
}
@ -173,3 +230,20 @@ func Build() error {
logging.Indent = ""
return nil
}
func setMode(mode string) {
if mode == "" {
if complain {
mode = "complain"
} else if enforce {
mode = "enforce"
}
}
switch mode {
case "complain":
builder.Register("complain")
builder.Unregister("enforce")
case "enforce":
builder.Unregister("complain")
}
}

View File

@ -8,10 +8,12 @@ package directive
import (
"fmt"
"path/filepath"
"slices"
"strings"
"github.com/roddhjav/apparmor.d/pkg/aa"
"github.com/roddhjav/apparmor.d/pkg/paths"
"github.com/roddhjav/apparmor.d/pkg/prebuild"
)
@ -43,7 +45,14 @@ func (d Exec) Apply(opt *Option, profileRaw string) (string, error) {
rules := aa.Rules{}
for name := range opt.ArgMap {
profiletoTransition := prebuild.RootApparmord.Join(name).MustReadFileAsString()
match, err := filepath.Glob(prebuild.Root.String() + "/*/" + name)
if err != nil {
return "", err
}
if len(match) != 1 {
return "", fmt.Errorf("No profile found for %s", name)
}
profiletoTransition := paths.New(match[0]).MustReadFileAsString()
dstProfile := aa.DefaultTunables()
if _, err := dstProfile.Parse(profiletoTransition); err != nil {
return "", err

View File

@ -6,10 +6,12 @@ package directive
import (
"fmt"
"path/filepath"
"regexp"
"slices"
"strings"
"github.com/roddhjav/apparmor.d/pkg/paths"
"github.com/roddhjav/apparmor.d/pkg/prebuild"
"github.com/roddhjav/apparmor.d/pkg/util"
)
@ -55,7 +57,14 @@ func (s Stack) Apply(opt *Option, profile string) (string, error) {
res := ""
for name := range opt.ArgMap {
stackedProfile := prebuild.RootApparmord.Join(name).MustReadFileAsString()
match, err := filepath.Glob(prebuild.Root.String() + "/*/" + name)
if err != nil {
return "", err
}
if len(match) != 1 {
return "", fmt.Errorf("No profile found for %s", name)
}
stackedProfile := paths.New(match[0]).MustReadFileAsString()
m := regRules.FindStringSubmatch(stackedProfile)
if len(m) < 2 {
return "", fmt.Errorf("No profile found in %s", name)

View File

@ -4,17 +4,28 @@
package prebuild
import "github.com/roddhjav/apparmor.d/pkg/paths"
import (
"os"
"strings"
"github.com/roddhjav/apparmor.d/pkg/paths"
)
var (
// AppArmor ABI version
ABI uint = 0
// Root is the root directory for the build (default: .build)
Root *paths.Path = paths.New(".build")
// Root is the root directory for the build (default: ./.build)
Root *paths.Path = getRootBuild()
// RootApparmord is the final built apparmor.d directory (default: .build/apparmor.d)
RootApparmord *paths.Path = Root.Join("apparmor.d")
RootApparmord *paths.Path = Root.Join(Src)
// src is the basename of the source directory (default: apparmor.d)
Src = "apparmor.d"
// SrcApparmord is the source apparmor.d directory (default: ./apparmor.d)
SrcApparmord *paths.Path = paths.New(Src)
// DistDir is the directory where the distribution specific files are stored
DistDir *paths.Path = paths.New("dists")
@ -25,6 +36,9 @@ var (
// IgnoreDir is the directory where the ignore files are stored
IgnoreDir *paths.Path = DistDir.Join("ignore")
// PkgDir is the directory where the packages files are stored
PkgDir *paths.Path = DistDir.Join("packages")
// SystemdDir is the directory where the systemd drop-in files are stored
SystemdDir *paths.Path = paths.New("systemd")
@ -34,6 +48,29 @@ var (
// DebianHide is the path to the debian/apparmor.d.hide file
DebianHide = DebianHider{path: DebianDir.Join("apparmor.d.hide")}
// Packages are the packages to build
Packages = getPackages()
Ignore = Ignorer{}
Flags = Flagger{}
)
func getRootBuild() *paths.Path {
root, present := os.LookupEnv("BUILD")
if !present {
root = ".build"
}
return paths.New(root)
}
func getPackages() []string {
files, err := PkgDir.ReadDirRecursiveFiltered(nil, paths.FilterOutDirectories())
if err != nil {
return []string{}
}
packages := make([]string, 0, len(files))
for _, file := range files {
packages = append(packages, strings.TrimSuffix(file.Base(), ".conf"))
}
return packages
}

231
pkg/prebuild/packages.go Normal file
View File

@ -0,0 +1,231 @@
// apparmor.d - Full set of apparmor profiles
// Copyright (C) 2021-2024 Alexandre Pujol <alexandre@pujol.io>
// SPDX-License-Identifier: GPL-2.0-only
package prebuild
import (
"fmt"
"slices"
"strings"
"github.com/roddhjav/apparmor.d/pkg/paths"
)
type Package struct {
Name string
Mode string
Required []string
Profiles []string
Ignores []string
Ignored []string
builddir *paths.Path
}
func NewPackage(name string) *Package {
path := PkgDir.Join(name + ".conf")
if !path.Exist() {
panic(fmt.Sprintf("Unknown package: %s", name))
}
lines := path.MustReadFilteredFileAsLines()
mode := ""
profiles := make([]string, 0, len(lines))
ignores := []string{}
dependencies := []string{}
ignored := getFilesIgnoredByDistribution()
for _, line := range lines {
switch {
case strings.HasPrefix(line, "mode="):
mode = strings.TrimPrefix(line, "mode=")
case strings.HasPrefix(line, "require="):
dependencies = strings.Split(strings.TrimPrefix(line, "require="), ",")
case strings.HasPrefix(line, "!"):
ignores = append(ignores, strings.TrimPrefix(line, "!"))
default:
profiles = append(profiles, line)
}
}
return &Package{
Name: name,
Mode: mode,
Required: dependencies,
Profiles: profiles,
Ignores: ignores,
Ignored: ignored,
builddir: Root.Join(name),
}
}
func getFilesIgnoredByDistribution() []string {
res := []string{}
for _, iname := range []string{"main", Distribution} {
for _, ignore := range Ignore.Read(iname) {
if !strings.HasPrefix(ignore, Src) {
continue
}
profile := strings.TrimPrefix(ignore, Src+"/")
path := SrcApparmord.Join(profile)
if path.IsDir() {
files, err := path.ReadDirRecursiveFiltered(nil, paths.FilterOutDirectories())
if err != nil {
panic(err)
}
for _, file := range files {
res = append(res, file.Base())
}
} else if path.Exist() {
res = append(res, path.Base())
} else {
panic(fmt.Errorf("%s.ignore: no files found for '%s'", iname, profile))
}
}
}
return res
}
func (p *Package) Generate() ([]string, error) {
var res []string
if err := p.builddir.RemoveAll(); err != nil {
return res, err
}
if err := p.builddir.MkdirAll(); err != nil {
return res, err
}
explode := paths.PathList{
paths.New("groups"), paths.New("profiles-a-f"),
paths.New("profiles-m-r"), paths.New("profiles-s-z"),
}
for _, name := range p.Profiles {
originalPath := SrcApparmord.Join(name)
if originalPath.IsDir() {
originFiles, err := originalPath.ReadDirRecursiveFiltered(nil, paths.FilterOutDirectories())
if err != nil {
return res, err
}
for _, originFile := range originFiles {
file, err := originFile.RelFrom(SrcApparmord)
if err != nil {
return res, err
}
if slices.Contains(p.Ignores, file.String()) {
continue
}
done := false
for _, e := range explode {
if ok, _ := file.IsInsideDir(e); ok {
base := file.Base()
msg, err := p.move(base)
if err != nil {
return res, err
}
res = append(res, msg)
done = true
break
}
}
if !done {
msg, err := p.move(file)
if err != nil {
return res, err
}
res = append(res, msg)
}
}
} else if originalPath.Exist() {
base := originalPath.Base()
if slices.Contains(p.Ignores, base) {
continue
}
msg, err := p.move(base)
if err != nil {
return res, err
}
res = append(res, msg)
} else {
return res, fmt.Errorf("No %s", originalPath)
}
}
return res, nil
}
func (p *Package) move(origin any) (string, error) {
var src *paths.Path
var dst *paths.Path
var srcOverridden *paths.Path
var dstOverridden *paths.Path
var srcSymlink *paths.Path
var dstSymlink *paths.Path
const ext = ".apparmor.d"
switch value := any(origin).(type) {
case string:
src = RootApparmord.Join(value)
dst = p.builddir.Join(value)
srcOverridden = RootApparmord.Join(value + ext)
dstOverridden = p.builddir.Join(value + ext)
srcSymlink = RootApparmord.Join("disable", value)
dstSymlink = p.builddir.Join("disable", value)
case *paths.Path:
src = RootApparmord.JoinPath(value)
dst = p.builddir.JoinPath(value)
srcOverridden = RootApparmord.JoinPath(value.Parent()).Join(value.Base() + ext)
dstOverridden = p.builddir.JoinPath(value.Parent()).Join(value.Base() + ext)
srcSymlink = RootApparmord.Join("disable").JoinPath(value)
dstSymlink = p.builddir.Join("disable").JoinPath(value)
default:
panic("Package.move: unsupported type")
}
if src.Exist() {
if err := dst.Parent().MkdirAll(); err != nil {
return "", nil
}
if err := src.Rename(dst); err != nil {
return "", nil
}
// fmt.Printf("%s -> %s\n", src, dst)
} else if srcOverridden.Exist() {
if err := dstOverridden.Parent().MkdirAll(); err != nil {
return "", nil
}
if err := dstSymlink.Parent().MkdirAll(); err != nil {
return "", nil
}
if err := srcOverridden.Rename(dstOverridden); err != nil {
return "", nil
}
if err := srcSymlink.Rename(dstSymlink); err != nil {
return "", nil
}
// fmt.Printf("%s -> %s\n", srcOverridden, dstOverridden)
} else {
srcRltv, err := src.RelFrom(RootApparmord)
if err != nil {
return "", nil
}
if !slices.Contains(p.Ignored, srcRltv.String()) {
fmt.Printf("Warning: No %s\n", src)
// return "", fmt.Errorf("No %s", src)
}
}
return "", nil
}
// Validate ensures a package has its required dependencies
func (p *Package) Validate() error {
return nil
}

View File

@ -5,6 +5,9 @@
package prepare
import (
"fmt"
"strings"
"github.com/roddhjav/apparmor.d/pkg/paths"
"github.com/roddhjav/apparmor.d/pkg/prebuild"
)
@ -26,21 +29,39 @@ func (p Ignore) Apply() ([]string, error) {
res := []string{}
for _, name := range []string{"main", prebuild.Distribution} {
for _, ignore := range prebuild.Ignore.Read(name) {
profile := prebuild.Root.Join(ignore)
if profile.NotExist() {
files, err := prebuild.RootApparmord.ReadDirRecursiveFiltered(nil, paths.FilterNames(ignore))
// Ignore file from share/
path := prebuild.Root.Join(ignore)
if path.Exist() {
if err := path.RemoveAll(); err != nil {
return res, err
}
continue
}
// Ignore file from apparmor.d/
profile := strings.TrimPrefix(ignore, prebuild.Src+"/")
if strings.HasPrefix(ignore, prebuild.Src) {
path = prebuild.RootApparmord.Join(profile)
}
if path.Exist() {
if err := path.RemoveAll(); err != nil {
return res, err
}
} else {
files, err := prebuild.RootApparmord.ReadDirRecursiveFiltered(nil, paths.FilterNames(profile))
if err != nil {
return res, err
}
if len(files) == 0 {
return res, fmt.Errorf("%s.ignore: no files found for '%s'", name, profile)
}
for _, path := range files {
if err := path.RemoveAll(); err != nil {
return res, err
}
}
} else {
if err := profile.RemoveAll(); err != nil {
return res, err
}
}
}
res = append(res, prebuild.IgnoreDir.Join(name+".ignore").String())

View File

@ -48,7 +48,7 @@ func (p Merge) Apply() ([]string, error) {
files, err = filepath.Glob(prebuild.RootApparmord.Join(dirRemoved).String())
if err != nil {
return []string{}, err
return res, err
}
for _, file := range files {
if err := paths.New(file).RemoveAll(); err != nil {

View File

@ -50,7 +50,6 @@ func (p Overwrite) Apply() ([]string, error) {
continue
}
if err := origin.Rename(dest); err != nil {
return res, err
}
originRel, err := origin.RelFrom(dest)

View File

@ -33,14 +33,15 @@ func (p Synchronise) Apply() ([]string, error) {
}
}
if p.Path == "" {
for _, name := range []string{"apparmor.d", "share"} {
if err := paths.CopyTo(paths.New(name), prebuild.Root.Join(name)); err != nil {
return res, err
}
if err := paths.CopyTo(paths.New("share"), prebuild.Root.Join("share")); err != nil {
return res, err
}
if err := paths.CopyTo(prebuild.SrcApparmord, prebuild.RootApparmord); err != nil {
return res, err
}
} else {
file := paths.New(p.Path)
destination, err := file.RelFrom(paths.New("apparmor.d"))
destination, err := file.RelFrom(prebuild.SrcApparmord)
if err != nil {
return res, err
}