mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-09-01 14:55:10 +00:00
Compare commits
99 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
f9e9954f12 | ||
|
3ec3fc47a1 | ||
|
86d193e183 | ||
|
ca7f79174e | ||
|
515d93ab1a | ||
|
ad6833bb34 | ||
|
3c5d40e84a | ||
|
eac7202808 | ||
|
3b61d42f79 | ||
|
f34d60b1e8 | ||
|
29b21b09d4 | ||
|
96395d9b82 | ||
|
9980ae76d8 | ||
|
dd136f4dd9 | ||
|
e5a3c03357 | ||
|
6831a8f440 | ||
|
ea5b52d3b2 | ||
|
3cdeb140a1 | ||
|
8c49449e46 | ||
|
a3685436eb | ||
|
2610fe4e80 | ||
|
c7f761b710 | ||
|
f00f296201 | ||
|
83772acf00 | ||
|
1d35eedef8 | ||
|
a597a612a7 | ||
|
64463c8686 | ||
|
7bd1c4d8ef | ||
|
c7bd872071 | ||
|
3d33fd440b | ||
|
e37cbd43c9 | ||
|
f91f33f2c6 | ||
|
51751aa687 | ||
|
89f1a84dfe | ||
|
d984b3edb6 | ||
|
2a7ddbc773 | ||
|
54bb7dccf0 | ||
|
aff29ef0ee | ||
|
26e85c17bd | ||
|
bdcd76a8ea | ||
|
e69cb50479 | ||
|
5a25bc6240 | ||
|
06e15a7789 | ||
|
d0e086e93a | ||
|
0e6b48cc78 | ||
|
c8eefe440c | ||
|
df3b9601de | ||
|
a9fa20a456 | ||
|
089064439d | ||
|
1759c1bd24 | ||
|
68de30cf76 | ||
|
925ccfe482 | ||
|
dc4b38acf0 | ||
|
9f25b5f6ff | ||
|
6e2eabd424 | ||
|
c8ce78e00c | ||
|
7526ba4b0a | ||
|
0eaf6d3649 | ||
|
e44e9187ae | ||
|
677051bd02 | ||
|
21ca572de6 | ||
|
6c240a473b | ||
|
eec9086ecf | ||
|
81d8af7c13 | ||
|
a9bea8a377 | ||
|
3aa895073a | ||
|
dcf7e9a0d5 | ||
|
57fec9624d | ||
|
aee9bf56c0 | ||
|
0295fadab3 | ||
|
5bc35342ed | ||
|
6cc9160246 | ||
|
5452053f5b | ||
|
da906cda8c | ||
|
a19754f52f | ||
|
379a486b87 | ||
|
5ad91d482d | ||
|
19bbc5dfc3 | ||
|
66cb0ed739 | ||
|
d179a704e7 | ||
|
4244737f65 | ||
|
e617f04681 | ||
|
9d826aae65 | ||
|
465c861b02 | ||
|
dc85d04805 | ||
|
a40923006c | ||
|
1fe80c0f85 | ||
|
8043dda3f6 | ||
|
e95080e140 | ||
|
45125cedd3 | ||
|
969a8f7618 | ||
|
770b8f1e88 | ||
|
3345250f72 | ||
|
51cf0848c7 | ||
|
e0c0a6a6a5 | ||
|
ea127f13cd | ||
|
480cb56553 | ||
|
075c69a4eb | ||
|
f9dbaa38ec |
86
.gitignore
vendored
86
.gitignore
vendored
@@ -1,4 +1,4 @@
|
|||||||
apparmor-
|
apparmor-*
|
||||||
cscope.*
|
cscope.*
|
||||||
binutils/aa-enabled
|
binutils/aa-enabled
|
||||||
binutils/aa-enabled.1
|
binutils/aa-enabled.1
|
||||||
@@ -6,29 +6,15 @@ binutils/aa-exec
|
|||||||
binutils/aa-exec.1
|
binutils/aa-exec.1
|
||||||
binutils/aa-features-abi
|
binutils/aa-features-abi
|
||||||
binutils/aa-features-abi.1
|
binutils/aa-features-abi.1
|
||||||
binutils/aa-load
|
|
||||||
binutils/aa-load.8
|
|
||||||
binutils/aa-status
|
binutils/aa-status
|
||||||
binutils/aa-status.8
|
binutils/aa-status.8
|
||||||
binutils/cJSON.o
|
binutils/cJSON.o
|
||||||
binutils/po/*.mo
|
binutils/po/*.mo
|
||||||
changehat/mod_apparmor/.libs
|
|
||||||
changehat/mod_apparmor/mod_apparmor.8
|
|
||||||
changehat/mod_apparmor/mod_apparmor.8.html
|
|
||||||
changehat/mod_apparmor/mod_apparmor.la
|
|
||||||
changehat/mod_apparmor/mod_apparmor.lo
|
|
||||||
changehat/mod_apparmor/mod_apparmor.slo
|
|
||||||
changehat/mod_apparmor/mod_apparmor.so
|
|
||||||
changehat/mod_apparmor/pod2htmd.tmp
|
|
||||||
changehat/pam_apparmor/get_options.o
|
|
||||||
changehat/pam_apparmor/pam_apparmor.o
|
|
||||||
changehat/pam_apparmor/pam_apparmor.so
|
|
||||||
parser/po/*.mo
|
parser/po/*.mo
|
||||||
parser/af_names.h
|
parser/af_names.h
|
||||||
parser/cap_names.h
|
parser/cap_names.h
|
||||||
parser/generated_cap_names.h
|
parser/generated_cap_names.h
|
||||||
parser/generated_af_names.h
|
parser/generated_af_names.h
|
||||||
parser/errnos.h
|
|
||||||
parser/tst_lib
|
parser/tst_lib
|
||||||
parser/tst_misc
|
parser/tst_misc
|
||||||
parser/tst_regex
|
parser/tst_regex
|
||||||
@@ -40,9 +26,38 @@ parser/parser_version.h
|
|||||||
parser/parser_yacc.c
|
parser/parser_yacc.c
|
||||||
parser/parser_yacc.h
|
parser/parser_yacc.h
|
||||||
parser/pod2htm*.tmp
|
parser/pod2htm*.tmp
|
||||||
parser/libapparmor_re/*.o
|
parser/af_rule.o
|
||||||
|
parser/af_unix.o
|
||||||
|
parser/common_optarg.o
|
||||||
|
parser/dbus.o
|
||||||
|
parser/default_features.o
|
||||||
|
parser/lib.o
|
||||||
|
parser/libapparmor_re/aare_rules.o
|
||||||
|
parser/libapparmor_re/chfa.o
|
||||||
|
parser/libapparmor_re/expr-tree.o
|
||||||
|
parser/libapparmor_re/hfa.o
|
||||||
parser/libapparmor_re/libapparmor_re.a
|
parser/libapparmor_re/libapparmor_re.a
|
||||||
parser/*.o
|
parser/libapparmor_re/parse.o
|
||||||
|
parser/mount.o
|
||||||
|
parser/network.o
|
||||||
|
parser/parser_alias.o
|
||||||
|
parser/parser_common.o
|
||||||
|
parser/parser_include.o
|
||||||
|
parser/parser_interface.o
|
||||||
|
parser/parser_lex.o
|
||||||
|
parser/parser_main.o
|
||||||
|
parser/parser_merge.o
|
||||||
|
parser/parser_misc.o
|
||||||
|
parser/parser_policy.o
|
||||||
|
parser/parser_regex.o
|
||||||
|
parser/parser_symtab.o
|
||||||
|
parser/parser_variable.o
|
||||||
|
parser/parser_yacc.o
|
||||||
|
parser/policy_cache.o
|
||||||
|
parser/profile.o
|
||||||
|
parser/ptrace.o
|
||||||
|
parser/rule.o
|
||||||
|
parser/signal.o
|
||||||
parser/*.7
|
parser/*.7
|
||||||
parser/*.5
|
parser/*.5
|
||||||
parser/*.8
|
parser/*.8
|
||||||
@@ -121,18 +136,6 @@ libraries/libapparmor/src/tst_aalogmisc
|
|||||||
libraries/libapparmor/src/tst_aalogmisc.log
|
libraries/libapparmor/src/tst_aalogmisc.log
|
||||||
libraries/libapparmor/src/tst_aalogmisc.o
|
libraries/libapparmor/src/tst_aalogmisc.o
|
||||||
libraries/libapparmor/src/tst_aalogmisc.trs
|
libraries/libapparmor/src/tst_aalogmisc.trs
|
||||||
libraries/libapparmor/src/tst_aalogparse_cpp
|
|
||||||
libraries/libapparmor/src/tst_aalogparse_cpp.log
|
|
||||||
libraries/libapparmor/src/tst_aalogparse_cpp.o
|
|
||||||
libraries/libapparmor/src/tst_aalogparse_cpp.trs
|
|
||||||
libraries/libapparmor/src/tst_aalogparse_reentrancy
|
|
||||||
libraries/libapparmor/src/tst_aalogparse_reentrancy.log
|
|
||||||
libraries/libapparmor/src/tst_aalogparse_reentrancy.o
|
|
||||||
libraries/libapparmor/src/tst_aalogparse_reentrancy.trs
|
|
||||||
libraries/libapparmor/src/tst_aalogparse_oldname
|
|
||||||
libraries/libapparmor/src/tst_aalogparse_oldname.log
|
|
||||||
libraries/libapparmor/src/tst_aalogparse_oldname.o
|
|
||||||
libraries/libapparmor/src/tst_aalogparse_oldname.trs
|
|
||||||
libraries/libapparmor/src/tst_features
|
libraries/libapparmor/src/tst_features
|
||||||
libraries/libapparmor/src/tst_features.log
|
libraries/libapparmor/src/tst_features.log
|
||||||
libraries/libapparmor/src/tst_features.o
|
libraries/libapparmor/src/tst_features.o
|
||||||
@@ -193,6 +196,7 @@ libraries/libapparmor/testsuite/libaalogparse.test/Makefile
|
|||||||
libraries/libapparmor/testsuite/libaalogparse.test/Makefile.in
|
libraries/libapparmor/testsuite/libaalogparse.test/Makefile.in
|
||||||
libraries/libapparmor/testsuite/test_multi/out
|
libraries/libapparmor/testsuite/test_multi/out
|
||||||
libraries/libapparmor/testsuite/test_multi_multi-test_multi.o
|
libraries/libapparmor/testsuite/test_multi_multi-test_multi.o
|
||||||
|
changehat/mod_apparmor/.libs
|
||||||
utils/*.8
|
utils/*.8
|
||||||
utils/*.8.html
|
utils/*.8.html
|
||||||
utils/*.5
|
utils/*.5
|
||||||
@@ -203,7 +207,6 @@ utils/apparmor/*.pyc
|
|||||||
utils/apparmor/rule/*.pyc
|
utils/apparmor/rule/*.pyc
|
||||||
utils/apparmor.egg-info/
|
utils/apparmor.egg-info/
|
||||||
utils/build/
|
utils/build/
|
||||||
!utils/emacs/apparmor-mode.el
|
|
||||||
utils/htmlcov/
|
utils/htmlcov/
|
||||||
utils/test/common_test.pyc
|
utils/test/common_test.pyc
|
||||||
utils/test/.coverage
|
utils/test/.coverage
|
||||||
@@ -232,7 +235,6 @@ tests/regression/apparmor/chgrp
|
|||||||
tests/regression/apparmor/chmod
|
tests/regression/apparmor/chmod
|
||||||
tests/regression/apparmor/chown
|
tests/regression/apparmor/chown
|
||||||
tests/regression/apparmor/clone
|
tests/regression/apparmor/clone
|
||||||
tests/regression/apparmor/complain
|
|
||||||
tests/regression/apparmor/dbus_eavesdrop
|
tests/regression/apparmor/dbus_eavesdrop
|
||||||
tests/regression/apparmor/dbus_message
|
tests/regression/apparmor/dbus_message
|
||||||
tests/regression/apparmor/dbus_service
|
tests/regression/apparmor/dbus_service
|
||||||
@@ -251,23 +253,17 @@ tests/regression/apparmor/fd_inheritance
|
|||||||
tests/regression/apparmor/fd_inheritor
|
tests/regression/apparmor/fd_inheritor
|
||||||
tests/regression/apparmor/fork
|
tests/regression/apparmor/fork
|
||||||
tests/regression/apparmor/introspect
|
tests/regression/apparmor/introspect
|
||||||
tests/regression/apparmor/io_uring
|
|
||||||
tests/regression/apparmor/link
|
tests/regression/apparmor/link
|
||||||
tests/regression/apparmor/link_subset
|
tests/regression/apparmor/link_subset
|
||||||
tests/regression/apparmor/mkdir
|
tests/regression/apparmor/mkdir
|
||||||
tests/regression/apparmor/mmap
|
tests/regression/apparmor/mmap
|
||||||
tests/regression/apparmor/mount
|
tests/regression/apparmor/mount
|
||||||
tests/regression/apparmor/move_mount
|
|
||||||
tests/regression/apparmor/named_pipe
|
tests/regression/apparmor/named_pipe
|
||||||
tests/regression/apparmor/net_inet_rcv
|
|
||||||
tests/regression/apparmor/net_inet_snd
|
|
||||||
tests/regression/apparmor/net_raw
|
tests/regression/apparmor/net_raw
|
||||||
tests/regression/apparmor/open
|
tests/regression/apparmor/open
|
||||||
tests/regression/apparmor/openat
|
tests/regression/apparmor/openat
|
||||||
tests/regression/apparmor/pipe
|
tests/regression/apparmor/pipe
|
||||||
tests/regression/apparmor/pivot_root
|
tests/regression/apparmor/pivot_root
|
||||||
tests/regression/apparmor/posix_mq_rcv
|
|
||||||
tests/regression/apparmor/posix_mq_snd
|
|
||||||
tests/regression/apparmor/ptrace
|
tests/regression/apparmor/ptrace
|
||||||
tests/regression/apparmor/ptrace_helper
|
tests/regression/apparmor/ptrace_helper
|
||||||
tests/regression/apparmor/pwrite
|
tests/regression/apparmor/pwrite
|
||||||
@@ -291,8 +287,6 @@ tests/regression/apparmor/syscall_setpriority
|
|||||||
tests/regression/apparmor/syscall_setscheduler
|
tests/regression/apparmor/syscall_setscheduler
|
||||||
tests/regression/apparmor/syscall_sysctl
|
tests/regression/apparmor/syscall_sysctl
|
||||||
tests/regression/apparmor/sysctl_proc
|
tests/regression/apparmor/sysctl_proc
|
||||||
tests/regression/apparmor/sysv_mq_rcv
|
|
||||||
tests/regression/apparmor/sysv_mq_snd
|
|
||||||
tests/regression/apparmor/tcp
|
tests/regression/apparmor/tcp
|
||||||
tests/regression/apparmor/transition
|
tests/regression/apparmor/transition
|
||||||
tests/regression/apparmor/unix_fd_client
|
tests/regression/apparmor/unix_fd_client
|
||||||
@@ -300,23 +294,9 @@ tests/regression/apparmor/unix_fd_server
|
|||||||
tests/regression/apparmor/unix_socket
|
tests/regression/apparmor/unix_socket
|
||||||
tests/regression/apparmor/unix_socket_client
|
tests/regression/apparmor/unix_socket_client
|
||||||
tests/regression/apparmor/unlink
|
tests/regression/apparmor/unlink
|
||||||
tests/regression/apparmor/userns
|
|
||||||
tests/regression/apparmor/userns_setns
|
|
||||||
tests/regression/apparmor/uservars.inc
|
tests/regression/apparmor/uservars.inc
|
||||||
tests/regression/apparmor/xattrs
|
tests/regression/apparmor/xattrs
|
||||||
tests/regression/apparmor/xattrs_profile
|
tests/regression/apparmor/xattrs_profile
|
||||||
tests/regression/apparmor/coredump
|
tests/regression/apparmor/coredump
|
||||||
**/__pycache__/
|
**/__pycache__/
|
||||||
*.orig
|
*.orig
|
||||||
|
|
||||||
# Patterns related to spread integration tests
|
|
||||||
*.img
|
|
||||||
*.iso
|
|
||||||
*.lock
|
|
||||||
*.log
|
|
||||||
*.qcow2
|
|
||||||
*.run
|
|
||||||
.spread-reuse.yaml
|
|
||||||
.spread-reuse.*.yaml
|
|
||||||
spread-artifacts/
|
|
||||||
spread-logs/
|
|
||||||
|
262
.gitlab-ci.yml
262
.gitlab-ci.yml
@@ -1,51 +1,28 @@
|
|||||||
spec:
|
|
||||||
inputs:
|
|
||||||
build-test-images:
|
|
||||||
default: false
|
|
||||||
type: boolean
|
|
||||||
description: Explicitly build virtual machine images used by integration tests.
|
|
||||||
---
|
---
|
||||||
image: ubuntu:latest
|
image: ubuntu:latest
|
||||||
|
|
||||||
# XXX - add a deploy stage to publish man pages, docs, and coverage
|
# XXX - add a deploy stage to publish man pages, docs, and coverage
|
||||||
# reports
|
# reports
|
||||||
|
|
||||||
workflow:
|
|
||||||
rules:
|
|
||||||
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
|
|
||||||
- if: $CI_COMMIT_TAG
|
|
||||||
- if: $CI_COMMIT_BRANCH
|
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- build
|
- build
|
||||||
- test
|
- test
|
||||||
- spread
|
|
||||||
|
|
||||||
.ubuntu-common:
|
.ubuntu-before_script:
|
||||||
interruptible: true
|
|
||||||
before_script:
|
before_script:
|
||||||
# Install build-dependencies by loading the package list from the ubuntu/debian cloud-init profile.
|
- export DEBIAN_FRONTEND=noninteractive
|
||||||
- printf '\e[0K%s:%s:%s[collapsed=true]\r\e[0K%s\n' section_start "$(date +%s)" install_deps "Installing dependencies..."
|
|
||||||
- apt-get update -qq
|
- apt-get update -qq
|
||||||
- apt-get install --yes yq make lsb-release
|
- apt-get install --no-install-recommends -y gcc perl liblocale-gettext-perl linux-libc-dev lsb-release make
|
||||||
- |
|
|
||||||
printf 'include .image-garden.mk\n$(info $(UBUNTU_CLOUD_INIT_USER_DATA_TEMPLATE))\n.PHONY: nothing\nnothing:\n' \
|
|
||||||
| make -f - nothing \
|
|
||||||
| yq '.packages | .[]' \
|
|
||||||
| xargs apt-get install --yes --no-install-recommends
|
|
||||||
- printf '\e[0K%s:%s:%s\r\e[0K\n' section_end "$(date +%s)" install_deps
|
|
||||||
after_script:
|
|
||||||
# Inspect the kernel and lsb-release.
|
|
||||||
- lsb_release -a
|
- lsb_release -a
|
||||||
- uname -a
|
- uname -a
|
||||||
|
|
||||||
|
.install-c-build-deps: &install-c-build-deps
|
||||||
|
- apt-get install --no-install-recommends -y build-essential apache2-dev autoconf automake bison dejagnu flex libpam-dev libtool pkg-config python3-all-dev python3-setuptools ruby-dev swig zlib1g-dev
|
||||||
|
|
||||||
build-all:
|
build-all:
|
||||||
stage: build
|
stage: build
|
||||||
extends:
|
extends:
|
||||||
- .ubuntu-common
|
- .ubuntu-before_script
|
||||||
script:
|
|
||||||
# Run the spread prepare section to build everything.
|
|
||||||
- yq -r '.prepare' <spread.yaml | SPREAD_PATH=. bash -xeu
|
|
||||||
artifacts:
|
artifacts:
|
||||||
name: ${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA}
|
name: ${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA}
|
||||||
expire_in: 30 days
|
expire_in: 30 days
|
||||||
@@ -58,33 +35,39 @@ build-all:
|
|||||||
- changehat/mod_apparmor/
|
- changehat/mod_apparmor/
|
||||||
- changehat/pam_apparmor/
|
- changehat/pam_apparmor/
|
||||||
- profiles/
|
- profiles/
|
||||||
|
script:
|
||||||
|
- *install-c-build-deps
|
||||||
|
- cd libraries/libapparmor && ./autogen.sh && ./configure --with-perl --with-python --prefix=/usr && make && cd ../.. || { cat config.log ; exit 1 ; }
|
||||||
|
- make -C parser
|
||||||
|
- make -C binutils
|
||||||
|
- make -C utils
|
||||||
|
- make -C changehat/mod_apparmor
|
||||||
|
- make -C changehat/pam_apparmor
|
||||||
|
- make -C profiles
|
||||||
|
|
||||||
test-libapparmor:
|
test-libapparmor:
|
||||||
stage: test
|
stage: test
|
||||||
needs: ["build-all"]
|
needs: ["build-all"]
|
||||||
extends:
|
extends:
|
||||||
- .ubuntu-common
|
- .ubuntu-before_script
|
||||||
script:
|
script:
|
||||||
# This is to touch the built files in the test stage to avoid needless rebuilding
|
- *install-c-build-deps
|
||||||
- make -C libraries/libapparmor --touch
|
|
||||||
- make -C libraries/libapparmor check
|
- make -C libraries/libapparmor check
|
||||||
|
|
||||||
test-parser:
|
test-parser:
|
||||||
stage: test
|
stage: test
|
||||||
needs: ["build-all"]
|
needs: ["build-all"]
|
||||||
extends:
|
extends:
|
||||||
- .ubuntu-common
|
- .ubuntu-before_script
|
||||||
script:
|
script:
|
||||||
# This is to touch the built files in the test stage to avoid needless rebuilding
|
- *install-c-build-deps
|
||||||
- make -C parser --touch
|
|
||||||
- make -C parser -j $(nproc) tst_binaries
|
|
||||||
- make -C parser check
|
- make -C parser check
|
||||||
|
|
||||||
test-binutils:
|
test-binutils:
|
||||||
stage: test
|
stage: test
|
||||||
needs: ["build-all"]
|
needs: ["build-all"]
|
||||||
extends:
|
extends:
|
||||||
- .ubuntu-common
|
- .ubuntu-before_script
|
||||||
script:
|
script:
|
||||||
- make -C binutils check
|
- make -C binutils check
|
||||||
|
|
||||||
@@ -92,16 +75,9 @@ test-utils:
|
|||||||
stage: test
|
stage: test
|
||||||
needs: ["build-all"]
|
needs: ["build-all"]
|
||||||
extends:
|
extends:
|
||||||
- .ubuntu-common
|
- .ubuntu-before_script
|
||||||
script:
|
script:
|
||||||
# This is to touch the built files in the test stage to avoid needless rebuilding
|
- apt-get install --no-install-recommends -y libc6-dev libjs-jquery libjs-jquery-throttle-debounce libjs-jquery-isonscreen libjs-jquery-tablesorter pyflakes3 python3-coverage python3-notify2 python3-psutil python3-setuptools
|
||||||
- make -C utils --touch
|
|
||||||
|
|
||||||
# TODO: move those to cloud-init list?
|
|
||||||
- printf '\e[0K%s:%s:%s[collapsed=true]\r\e[0K%s\n' section_start "$(date +%s)" install_extra_deps "Installing additional dependencies..."
|
|
||||||
- apt-get install --no-install-recommends -y libc6-dev libjs-jquery libjs-jquery-throttle-debounce libjs-jquery-isonscreen libjs-jquery-tablesorter flake8 python3-coverage python3-notify2 python3-psutil python3-setuptools python3-tk python3-ttkthemes python3-gi
|
|
||||||
- printf '\e[0K%s:%s:%s\r\e[0K\n' section_end "$(date +%s)" install_extra_deps
|
|
||||||
|
|
||||||
# See apparmor/apparmor#221
|
# See apparmor/apparmor#221
|
||||||
- make -C parser/tst gen_dbus
|
- make -C parser/tst gen_dbus
|
||||||
- make -C parser/tst gen_xtrans
|
- make -C parser/tst gen_xtrans
|
||||||
@@ -116,37 +92,31 @@ test-mod-apparmor:
|
|||||||
stage: test
|
stage: test
|
||||||
needs: ["build-all"]
|
needs: ["build-all"]
|
||||||
extends:
|
extends:
|
||||||
- .ubuntu-common
|
- .ubuntu-before_script
|
||||||
script:
|
script:
|
||||||
# This is to touch the built files in the test stage to avoid needless rebuilding
|
|
||||||
- make -C changehat/mod_apparmor --touch
|
|
||||||
- make -C changehat/mod_apparmor check
|
- make -C changehat/mod_apparmor check
|
||||||
|
|
||||||
test-profiles:
|
test-profiles:
|
||||||
stage: test
|
stage: test
|
||||||
needs: ["build-all"]
|
needs: ["build-all"]
|
||||||
extends:
|
extends:
|
||||||
- .ubuntu-common
|
- .ubuntu-before_script
|
||||||
script:
|
script:
|
||||||
# This is to touch the built files in the test stage to avoid needless rebuilding
|
|
||||||
- make -C profiles --touch
|
|
||||||
- make -C profiles check-parser
|
- make -C profiles check-parser
|
||||||
- make -C profiles check-abstractions.d
|
- make -C profiles check-abstractions.d
|
||||||
- make -C profiles check-local
|
- make -C profiles check-extras
|
||||||
|
|
||||||
shellcheck:
|
shellcheck:
|
||||||
stage: test
|
stage: test
|
||||||
needs: []
|
needs: []
|
||||||
extends:
|
extends:
|
||||||
- .ubuntu-common
|
- .ubuntu-before_script
|
||||||
script:
|
script:
|
||||||
- printf '\e[0K%s:%s:%s[collapsed=true]\r\e[0K%s\n' section_start "$(date +%s)" install_extra_deps "Installing additional dependencies..."
|
- apt-get install --no-install-recommends -y file shellcheck xmlstarlet
|
||||||
- apt-get install --no-install-recommends -y python3-minimal file shellcheck xmlstarlet
|
- shellcheck --version
|
||||||
- printf '\e[0K%s:%s:%s\r\e[0K\n' section_end "$(date +%s)" install_extra_deps
|
- './tests/bin/shellcheck-tree --format=checkstyle
|
||||||
- shellcheck --version
|
| xmlstarlet tr tests/checkstyle2junit.xslt
|
||||||
- "./tests/bin/shellcheck-tree --format=checkstyle
|
> shellcheck.xml'
|
||||||
| xmlstarlet tr tests/checkstyle2junit.xslt
|
|
||||||
> shellcheck.xml"
|
|
||||||
artifacts:
|
artifacts:
|
||||||
when: always
|
when: always
|
||||||
reports:
|
reports:
|
||||||
@@ -167,171 +137,3 @@ include:
|
|||||||
variables:
|
variables:
|
||||||
SAST_EXCLUDED_ANALYZERS: "eslint,flawfinder,semgrep,spotbugs"
|
SAST_EXCLUDED_ANALYZERS: "eslint,flawfinder,semgrep,spotbugs"
|
||||||
SAST_BANDIT_EXCLUDED_PATHS: "*/tst/*, */test/*"
|
SAST_BANDIT_EXCLUDED_PATHS: "*/tst/*, */test/*"
|
||||||
|
|
||||||
coverity:
|
|
||||||
stage: .post
|
|
||||||
interruptible: true
|
|
||||||
extends:
|
|
||||||
- .ubuntu-common
|
|
||||||
script:
|
|
||||||
- printf '\e[0K%s:%s:%s[collapsed=true]\r\e[0K%s\n' section_start "$(date +%s)" install_extra_deps "Installing additional dependencies..."
|
|
||||||
- apt-get install --no-install-recommends -y curl git texlive-latex-recommended
|
|
||||||
- printf '\e[0K%s:%s:%s\r\e[0K\n' section_end "$(date +%s)" install_extra_deps
|
|
||||||
- curl -o /tmp/cov-analysis-linux64.tgz https://scan.coverity.com/download/linux64
|
|
||||||
--form project=$COVERITY_SCAN_PROJECT_NAME --form token=$COVERITY_SCAN_TOKEN
|
|
||||||
- tar xfz /tmp/cov-analysis-linux64.tgz
|
|
||||||
- COV_VERSION=$(ls -dt cov-analysis-linux64-* | head -1)
|
|
||||||
- PATH=$PATH:$(pwd)/$COV_VERSION/bin
|
|
||||||
- make coverity
|
|
||||||
- curl https://scan.coverity.com/builds?project=$COVERITY_SCAN_PROJECT_NAME
|
|
||||||
--form token=$COVERITY_SCAN_TOKEN --form email=$GITLAB_USER_EMAIL
|
|
||||||
--form file=@$(ls apparmor-*-cov-int.tar.gz) --form version="$(git describe --tags)"
|
|
||||||
--form description="$(git describe --tags) / $CI_COMMIT_TITLE / $CI_COMMIT_REF_NAME:$CI_PIPELINE_ID"
|
|
||||||
artifacts:
|
|
||||||
paths:
|
|
||||||
- "apparmor-*.tar.gz"
|
|
||||||
rules:
|
|
||||||
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PROJECT_PATH == "apparmor/apparmor"
|
|
||||||
|
|
||||||
.image-garden-x86_64:
|
|
||||||
stage: spread
|
|
||||||
interruptible: true
|
|
||||||
# TODO: use tagged release once container tagging is improved upstream.
|
|
||||||
image: registry.gitlab.com/zygoon/image-garden:latest
|
|
||||||
tags:
|
|
||||||
- linux
|
|
||||||
- x86_64
|
|
||||||
- kvm
|
|
||||||
variables:
|
|
||||||
ARCH: x86_64
|
|
||||||
GARDEN_DL_DIR: dl
|
|
||||||
CACHE_POLICY: pull-push
|
|
||||||
CACHE_COMPRESSION_LEVEL: fastest
|
|
||||||
before_script:
|
|
||||||
# Restore the mtime of the .image-garden.mk file. This helps make determine
|
|
||||||
# if there's actually something to do correctly. Git does not preserve the
|
|
||||||
# mtime of files during checkout.
|
|
||||||
- git restore-mtime .image-garden.mk
|
|
||||||
# Prepare the image in dry-run mode. This helps in debugging cache misses
|
|
||||||
# when files are not cached correctly by the runner, causing the build section
|
|
||||||
# below to always do hevy-duty work.
|
|
||||||
- printf '\e[0K%s:%s:%s[collapsed=true]\r\e[0K%s\n' section_start "$(date +%s)" prepare_image_dry_run "Prepare image (dry run)"
|
|
||||||
- image-garden make --dry-run --debug "$GARDEN_SYSTEM.$ARCH.run" "$GARDEN_SYSTEM.$ARCH.qcow2" "$GARDEN_SYSTEM.seed.iso" "$GARDEN_SYSTEM.user-data" "$GARDEN_SYSTEM.meta-data"
|
|
||||||
- printf '\e[0K%s:%s:%s\r\e[0K\n' section_end "$(date +%s)" prepare_image_dry_run
|
|
||||||
script:
|
|
||||||
# Prepare the image, for real.
|
|
||||||
- printf '\e[0K%s:%s:%s[collapsed=true]\r\e[0K%s\n' section_start "$(date +%s)" prepare_image "Prepare image"
|
|
||||||
# If there's nothing to do then remove all the files that we would normally
|
|
||||||
# cache so that GitLab skips the cache upload step. This saves significant
|
|
||||||
# time required to re-compress and upload unchanged content.
|
|
||||||
# The idea for how to do is is documented at
|
|
||||||
# https://olex.biz/2025/04/gitlab-ci-prevent-cache-reupload-without-changes/
|
|
||||||
# The GitLab issue requesting a proper feature is
|
|
||||||
# https://gitlab.com/gitlab-org/gitlab/-/issues/226068
|
|
||||||
- |
|
|
||||||
if image-garden make --question "$GARDEN_SYSTEM.$ARCH.run" "$GARDEN_SYSTEM.$ARCH.qcow2" "$GARDEN_SYSTEM.seed.iso" "$GARDEN_SYSTEM.user-data" "$GARDEN_SYSTEM.meta-data"; then
|
|
||||||
rm -f "$GARDEN_SYSTEM".* efi-code.*.img efi-vars.*.img
|
|
||||||
rm -rf "$GARDEN_DL_DIR"
|
|
||||||
else
|
|
||||||
image-garden make "$GARDEN_SYSTEM.$ARCH.run" "$GARDEN_SYSTEM.$ARCH.qcow2" "$GARDEN_SYSTEM.seed.iso" "$GARDEN_SYSTEM.user-data" "$GARDEN_SYSTEM.meta-data"
|
|
||||||
fi
|
|
||||||
- printf '\e[0K%s:%s:%s\r\e[0K\n' section_end "$(date +%s)" prepare_image
|
|
||||||
cache:
|
|
||||||
# Cache the base image (pre-customization).
|
|
||||||
- key: image-garden-base-${GARDEN_SYSTEM}.${ARCH}
|
|
||||||
policy: $CACHE_POLICY
|
|
||||||
when: always
|
|
||||||
paths:
|
|
||||||
- $GARDEN_DL_DIR
|
|
||||||
# Those are never mutated so they are safe to share.
|
|
||||||
- efi-code.*.img
|
|
||||||
- efi-vars.*.img
|
|
||||||
# Cache the customized system. This cache depends on .image-garden.mk file
|
|
||||||
# so that any customization updates are immediately acted upon.
|
|
||||||
- key:
|
|
||||||
prefix: image-garden-custom-${GARDEN_SYSTEM}.${ARCH}-
|
|
||||||
files:
|
|
||||||
- .image-garden.mk
|
|
||||||
policy: $CACHE_POLICY
|
|
||||||
when: always
|
|
||||||
paths:
|
|
||||||
- $GARDEN_SYSTEM.*
|
|
||||||
- $GARDEN_SYSTEM.seed.iso
|
|
||||||
- $GARDEN_SYSTEM.meta-data
|
|
||||||
- $GARDEN_SYSTEM.user-data
|
|
||||||
|
|
||||||
# This job builds and caches the image that the job below looks at.
|
|
||||||
image-ubuntu-cloud-24.04-x86_64:
|
|
||||||
extends: .image-garden-x86_64
|
|
||||||
variables:
|
|
||||||
GARDEN_SYSTEM: ubuntu-cloud-24.04
|
|
||||||
needs: []
|
|
||||||
dependencies: []
|
|
||||||
rules:
|
|
||||||
- if: $CI_COMMIT_TAG
|
|
||||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
|
||||||
changes:
|
|
||||||
paths:
|
|
||||||
- .image-garden.mk
|
|
||||||
- .gitlab-ci.yml
|
|
||||||
compare_to: "refs/heads/master"
|
|
||||||
- if: $CI_COMMIT_BRANCH && "$[[ inputs.build-test-images ]]" == "true"
|
|
||||||
|
|
||||||
.spread-x86_64:
|
|
||||||
extends: .image-garden-x86_64
|
|
||||||
variables:
|
|
||||||
# GitLab project identifier of zygoon/spread-dist can be seen on
|
|
||||||
# https://gitlab.com/zygoon/spread-dist, under the three-dot menu on
|
|
||||||
# top-right.
|
|
||||||
SPREAD_GITLAB_PROJECT_ID: "65375371"
|
|
||||||
# Git revision of spread to install.
|
|
||||||
# This must have been built via spread-dist.
|
|
||||||
# TODO: switch to upstream 1.0 release when available.
|
|
||||||
SPREAD_REV: 413817eda7bec07a3885e0717c178b965f8924e1
|
|
||||||
# Run all the tasks for a given system.
|
|
||||||
SPREAD_ARGS: "garden:$GARDEN_SYSTEM:"
|
|
||||||
SPREAD_GOARCH: amd64
|
|
||||||
before_script:
|
|
||||||
# Restore the mtime of the .image-garden.mk file. This helps make determine
|
|
||||||
# if there's actually something to do correctly. Git does not preserve the
|
|
||||||
# mtime of files during checkout.
|
|
||||||
- git restore-mtime .image-garden.mk
|
|
||||||
# Prepare the image in dry-run mode. This helps in debugging cache misses
|
|
||||||
# when files are not cached correctly by the runner, causing the build section
|
|
||||||
# below to always do hevy-duty work.
|
|
||||||
- printf '\e[0K%s:%s:%s[collapsed=true]\r\e[0K%s\n' section_start "$(date +%s)" prepare_image_dry_run "Prepare image (dry run)"
|
|
||||||
- image-garden make --dry-run --debug "$GARDEN_SYSTEM.$ARCH.run" "$GARDEN_SYSTEM.$ARCH.qcow2" "$GARDEN_SYSTEM.seed.iso" "$GARDEN_SYSTEM.user-data" "$GARDEN_SYSTEM.meta-data"
|
|
||||||
- stat .image-garden.mk "$GARDEN_SYSTEM".* || true
|
|
||||||
- printf '\e[0K%s:%s:%s\r\e[0K\n' section_end "$(date +%s)" prepare_image_dry_run
|
|
||||||
# Install the selected revision of spread.
|
|
||||||
- printf '\e[0K%s:%s:%s[collapsed=true]\r\e[0K%s\n' section_start "$(date +%s)" install_spread "Installing spread..."
|
|
||||||
# Install pre-built spread from https://gitlab.com/zygoon/spread-dist generic package repository.
|
|
||||||
- |
|
|
||||||
curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --location --output spread "${CI_API_V4_URL}/projects/${SPREAD_GITLAB_PROJECT_ID}/packages/generic/spread/${SPREAD_REV}/spread.${SPREAD_GOARCH}"
|
|
||||||
- chmod +x spread
|
|
||||||
- printf '\e[0K%s:%s:%s\r\e[0K\n' section_end "$(date +%s)" install_spread
|
|
||||||
script:
|
|
||||||
- printf '\e[0K%s:%s:%s\r\e[0K%s\n' section_start "$(date +%s)" run_spread "Running spread for $GARDEN_SYSTEM..."
|
|
||||||
# TODO: transform to inject ^...$ to properly select jobs to run.
|
|
||||||
- mkdir -p spread-logs spread-artifacts
|
|
||||||
- ./spread -list $SPREAD_ARGS |
|
|
||||||
split --number=l/"${CI_NODE_INDEX:-1}"/"${CI_NODE_TOTAL:-1}" |
|
|
||||||
xargs --verbose ./spread -v -artifacts ./spread-artifacts -v | tee spread-logs/"$GARDEN_SYSTEM".log
|
|
||||||
- printf '\e[0K%s:%s:%s\r\e[0K\n' section_end "$(date +%s)" run_spread
|
|
||||||
artifacts:
|
|
||||||
paths:
|
|
||||||
- spread-logs
|
|
||||||
- spread-artifacts
|
|
||||||
when: always
|
|
||||||
|
|
||||||
spread-ubuntu-cloud-24.04-x86_64:
|
|
||||||
extends: .spread-x86_64
|
|
||||||
variables:
|
|
||||||
GARDEN_SYSTEM: ubuntu-cloud-24.04
|
|
||||||
SPREAD_ARGS: garden:$GARDEN_SYSTEM:tests/regression/ garden:$GARDEN_SYSTEM:tests/profiles/
|
|
||||||
CACHE_POLICY: pull
|
|
||||||
dependencies: []
|
|
||||||
needs:
|
|
||||||
- job: image-ubuntu-cloud-24.04-x86_64
|
|
||||||
optional: true
|
|
||||||
parallel: 4
|
|
||||||
|
128
.image-garden.mk
128
.image-garden.mk
@@ -1,128 +0,0 @@
|
|||||||
# This file is read by image-garden when spread is allocating test machines.
|
|
||||||
# All the package installation happens through cloud-init profiles defined
|
|
||||||
# below.
|
|
||||||
|
|
||||||
# NOTE: Should the kernel be out of date, just increment this value. Make will
|
|
||||||
# re-create the image whenever the .image-garden.mk file is more recent than
|
|
||||||
# the image itself. In reality all you need is touch(1), but this is more apt.
|
|
||||||
unused=1
|
|
||||||
|
|
||||||
# This is the cloud-init user-data profile for all Debian systems. Note that it
|
|
||||||
# is an extension of the default profile necessary for operation of
|
|
||||||
# image-garden.
|
|
||||||
define DEBIAN_CLOUD_INIT_USER_DATA_TEMPLATE
|
|
||||||
$(CLOUD_INIT_USER_DATA_TEMPLATE)
|
|
||||||
packages:
|
|
||||||
- apache2-dev
|
|
||||||
- attr
|
|
||||||
- autoconf
|
|
||||||
- autoconf-archive
|
|
||||||
- automake
|
|
||||||
- bison
|
|
||||||
- build-essential
|
|
||||||
- dejagnu
|
|
||||||
- dosfstools
|
|
||||||
- flake8
|
|
||||||
- flex
|
|
||||||
- fuse-overlayfs
|
|
||||||
- gdb
|
|
||||||
- gettext
|
|
||||||
- libdbus-1-dev
|
|
||||||
- libpam0g-dev
|
|
||||||
- libtool
|
|
||||||
- liburing-dev
|
|
||||||
- pkg-config
|
|
||||||
- python3-all-dev
|
|
||||||
- python3-gi
|
|
||||||
- python3-notify2
|
|
||||||
- python3-psutil
|
|
||||||
- python3-setuptools
|
|
||||||
- python3-tk
|
|
||||||
- python3-ttkthemes
|
|
||||||
- swig
|
|
||||||
- toybox
|
|
||||||
# Update all the packages. This allows us to be on the up-to-date kernel
|
|
||||||
# version that we cannot otherwise easily select with cloud init alone. Note
|
|
||||||
# that we do not need to reboot the system as image garden shuts down the image
|
|
||||||
# after first boot. On subsequent boot we will be running the latest kernel.
|
|
||||||
package_upgrade: true
|
|
||||||
package_update: true
|
|
||||||
endef
|
|
||||||
|
|
||||||
# Ubuntu shares cloud-init profile with Debian.
|
|
||||||
UBUNTU_CLOUD_INIT_USER_DATA_TEMPLATE=$(DEBIAN_CLOUD_INIT_USER_DATA_TEMPLATE)
|
|
||||||
|
|
||||||
# This is the cloud-init user-data profile for openSUSE Tumbleweed.
|
|
||||||
define OPENSUSE_tumbleweed_CLOUD_INIT_USER_DATA_TEMPLATE
|
|
||||||
$(CLOUD_INIT_USER_DATA_TEMPLATE)
|
|
||||||
- sed -i -e 's/security=selinux/security=apparmor/g' /etc/default/grub
|
|
||||||
- update-bootloader
|
|
||||||
packages:
|
|
||||||
- apache2-devel
|
|
||||||
- attr
|
|
||||||
- autoconf
|
|
||||||
- autoconf-archive
|
|
||||||
- automake
|
|
||||||
- bison
|
|
||||||
- dbus-1-devel
|
|
||||||
- dejagnu
|
|
||||||
- dosfstools
|
|
||||||
- flex
|
|
||||||
- fuse-overlayfs
|
|
||||||
- gcc
|
|
||||||
- gcc-c++
|
|
||||||
- gdb
|
|
||||||
- gettext
|
|
||||||
- gobject-introspection
|
|
||||||
- libtool
|
|
||||||
- liburing2-devel
|
|
||||||
- make
|
|
||||||
- pam-devel
|
|
||||||
- pkg-config
|
|
||||||
- python3-devel
|
|
||||||
- python3-flake8
|
|
||||||
- python3-notify2
|
|
||||||
- python3-psutil
|
|
||||||
- python3-setuptools
|
|
||||||
- python3-setuptools
|
|
||||||
- python3-tk
|
|
||||||
- python311
|
|
||||||
- python311-devel
|
|
||||||
- swig
|
|
||||||
- which
|
|
||||||
# See above for rationale.
|
|
||||||
package_upgrade: true
|
|
||||||
package_update: true
|
|
||||||
endef
|
|
||||||
|
|
||||||
define FEDORA_CLOUD_INIT_USER_DATA_TEMPLATE
|
|
||||||
$(CLOUD_INIT_USER_DATA_TEMPLATE)
|
|
||||||
packages:
|
|
||||||
- attr
|
|
||||||
- autoconf
|
|
||||||
- autoconf-archive
|
|
||||||
- automake
|
|
||||||
- bison
|
|
||||||
- dbus-devel
|
|
||||||
- dejagnu
|
|
||||||
- dosfstools
|
|
||||||
- flex
|
|
||||||
- gdb
|
|
||||||
- gettext
|
|
||||||
- httpd-devel
|
|
||||||
- libstdc++-static
|
|
||||||
- libtool
|
|
||||||
- liburing-devel
|
|
||||||
- pam-devel
|
|
||||||
- perl
|
|
||||||
- pkg-config
|
|
||||||
- python3-devel
|
|
||||||
- python3-flake8
|
|
||||||
- python3-gobject-base
|
|
||||||
- python3-notify2
|
|
||||||
- python3-tkinter
|
|
||||||
- swig
|
|
||||||
# See above for rationale.
|
|
||||||
package_upgrade: true
|
|
||||||
package_update: true
|
|
||||||
endef
|
|
2
Makefile
2
Makefile
@@ -59,7 +59,7 @@ coverity: snapshot
|
|||||||
mv $(COVERITY_DIR)/build-log.txt $(COVERITY_DIR)/build-log-python-$(subst /,.,$(dir)).txt ;)
|
mv $(COVERITY_DIR)/build-log.txt $(COVERITY_DIR)/build-log-python-$(subst /,.,$(dir)).txt ;)
|
||||||
cov-build --dir $(COVERITY_DIR) -- sh -c \
|
cov-build --dir $(COVERITY_DIR) -- sh -c \
|
||||||
"$(foreach dir, $(filter-out utils profiles tests, $(DIRS)), \
|
"$(foreach dir, $(filter-out utils profiles tests, $(DIRS)), \
|
||||||
$(MAKE) -j $$(nproc) -C $(SNAPSHOT_NAME)/$(dir);) "
|
$(MAKE) -C $(SNAPSHOT_NAME)/$(dir);) "
|
||||||
tar -cvzf $(SNAPSHOT_NAME)-$(COVERITY_DIR).tar.gz $(COVERITY_DIR)
|
tar -cvzf $(SNAPSHOT_NAME)-$(COVERITY_DIR).tar.gz $(COVERITY_DIR)
|
||||||
|
|
||||||
.PHONY: export_dir
|
.PHONY: export_dir
|
||||||
|
47
README.md
47
README.md
@@ -181,9 +181,6 @@ $ make check # depends on the parser having been built first
|
|||||||
$ make install
|
$ make install
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that the empty local/* profile sniplets no longer get created by default.
|
|
||||||
If you want them, run `make local` before running `make check`.
|
|
||||||
|
|
||||||
[Note that for the parser, binutils, and utils, if you only wish to build/use
|
[Note that for the parser, binutils, and utils, if you only wish to build/use
|
||||||
some of the locale languages, you can override the default by passing
|
some of the locale languages, you can override the default by passing
|
||||||
the LANGS arguments to make; e.g. make all install "LANGS=en_US fr".]
|
the LANGS arguments to make; e.g. make all install "LANGS=en_US fr".]
|
||||||
@@ -197,46 +194,6 @@ usage and how to update and add tests. Below is a quick overview of their
|
|||||||
location and how to run them.
|
location and how to run them.
|
||||||
|
|
||||||
|
|
||||||
Using spread with local virtual machines
|
|
||||||
----------------------------------------
|
|
||||||
|
|
||||||
It may be convenient to use the spread tool to provision and run the test suite
|
|
||||||
in an ephemeral virtual machine. This allows testing in isolation from the
|
|
||||||
host, as well as testing across different commonly used distributions and their
|
|
||||||
real kernels.
|
|
||||||
|
|
||||||
Image Garden is available as a snap. If you wish to use it this way then snap
|
|
||||||
then install the snap with:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
sudo snap install image-garden
|
|
||||||
```
|
|
||||||
|
|
||||||
If you need to install snapd first, see https://snapcraft.io/docs/installing-snapd
|
|
||||||
|
|
||||||
Alternatively you may build image-garden and spread from source, and install
|
|
||||||
dependencies manually.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
sudo apt install git golang whois ovmf genisoimage qemu-utils qemu-system
|
|
||||||
go install github.com/snapcore/spread/cmd/spread@latest
|
|
||||||
git clone https://gitlab.com/zygoon/image-garden
|
|
||||||
make -C image-garden
|
|
||||||
sudo make -C image-garden install
|
|
||||||
image-garden make ubuntu-cloud-24.10.x86_64.run
|
|
||||||
cd $APPARMOR_PATH
|
|
||||||
git clean -xdf
|
|
||||||
~/go/bin/spread -artifacts ./spread-artifacts -v ubuntu-cloud-24.10
|
|
||||||
# or ~/go/bin/spread -v garden:ubuntu-cloud-24.04:tests/regression/apparmor:at_secure
|
|
||||||
```
|
|
||||||
|
|
||||||
Running the `run_spread.sh` script, with `image-garden` snap installed or with
|
|
||||||
`spread` on `PATH` will run all the tests across several supported systems
|
|
||||||
(Debian, Ubuntu and openSUSE).
|
|
||||||
|
|
||||||
If you include a `bzImage` file in the root of the repository then that kernel
|
|
||||||
will be used in the integration test. Please look at `spread.yaml` for details.
|
|
||||||
|
|
||||||
Regression tests
|
Regression tests
|
||||||
----------------
|
----------------
|
||||||
For details on structure and adding tests, see
|
For details on structure and adding tests, see
|
||||||
@@ -394,10 +351,6 @@ The aa-notify tool's Python dependencies can be satisfied by installing the
|
|||||||
following packages (Debian package names, other distros may vary):
|
following packages (Debian package names, other distros may vary):
|
||||||
* python3-notify2
|
* python3-notify2
|
||||||
* python3-psutil
|
* python3-psutil
|
||||||
* python3-sqlite (part of the python3.NN-stdlib package)
|
|
||||||
* python3-tk
|
|
||||||
* python3-ttkthemes
|
|
||||||
* python3-gi
|
|
||||||
|
|
||||||
Perl is no longer needed since none of the utilities shipped to end users depend
|
Perl is no longer needed since none of the utilities shipped to end users depend
|
||||||
on it anymore.
|
on it anymore.
|
||||||
|
@@ -21,7 +21,7 @@ DESTDIR=/
|
|||||||
BINDIR=${DESTDIR}/usr/bin
|
BINDIR=${DESTDIR}/usr/bin
|
||||||
SBINDIR=${DESTDIR}/usr/sbin
|
SBINDIR=${DESTDIR}/usr/sbin
|
||||||
LOCALEDIR=/usr/share/locale
|
LOCALEDIR=/usr/share/locale
|
||||||
MANPAGES=aa-enabled.1 aa-exec.1 aa-features-abi.1 aa-load.8 aa-status.8
|
MANPAGES=aa-enabled.1 aa-exec.1 aa-features-abi.1 aa-status.8
|
||||||
|
|
||||||
WARNINGS = -Wall
|
WARNINGS = -Wall
|
||||||
CPP_WARNINGS =
|
CPP_WARNINGS =
|
||||||
@@ -48,10 +48,10 @@ endif
|
|||||||
# Internationalization support. Define a package and a LOCALEDIR
|
# Internationalization support. Define a package and a LOCALEDIR
|
||||||
EXTRA_CFLAGS+=-DPACKAGE=\"${NAME}\" -DLOCALEDIR=\"${LOCALEDIR}\"
|
EXTRA_CFLAGS+=-DPACKAGE=\"${NAME}\" -DLOCALEDIR=\"${LOCALEDIR}\"
|
||||||
|
|
||||||
SRCS = aa_enabled.c aa_load.c
|
SRCS = aa_enabled.c
|
||||||
HDRS =
|
HDRS =
|
||||||
BINTOOLS = aa-enabled aa-exec aa-features-abi
|
BINTOOLS = aa-enabled aa-exec aa-features-abi
|
||||||
SBINTOOLS = aa-status aa-load
|
SBINTOOLS = aa-status
|
||||||
|
|
||||||
AALIB = -Wl,-Bstatic -lapparmor -Wl,-Bdynamic -lpthread
|
AALIB = -Wl,-Bstatic -lapparmor -Wl,-Bdynamic -lpthread
|
||||||
|
|
||||||
@@ -126,9 +126,6 @@ endif
|
|||||||
aa-features-abi: aa_features_abi.c $(LIBAPPARMOR_A)
|
aa-features-abi: aa_features_abi.c $(LIBAPPARMOR_A)
|
||||||
$(CC) $(LDFLAGS) $(EXTRA_CFLAGS) -o $@ $< $(LIBS) $(AALIB)
|
$(CC) $(LDFLAGS) $(EXTRA_CFLAGS) -o $@ $< $(LIBS) $(AALIB)
|
||||||
|
|
||||||
aa-load: aa_load.c $(LIBAPPARMOR_A)
|
|
||||||
$(CC) $(LDFLAGS) $(EXTRA_CFLAGS) -o $@ $< $(LIBS) $(AALIB)
|
|
||||||
|
|
||||||
aa-enabled: aa_enabled.c $(LIBAPPARMOR_A)
|
aa-enabled: aa_enabled.c $(LIBAPPARMOR_A)
|
||||||
$(CC) $(LDFLAGS) $(EXTRA_CFLAGS) -o $@ $< $(LIBS) $(AALIB)
|
$(CC) $(LDFLAGS) $(EXTRA_CFLAGS) -o $@ $< $(LIBS) $(AALIB)
|
||||||
|
|
||||||
|
@@ -80,109 +80,6 @@ aa-exec.
|
|||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
=head1 RESTRICTIONS
|
|
||||||
|
|
||||||
aa-exec uses I<aa_change_profile(3)> to change application confinement.
|
|
||||||
The use of I<aa_change_profile(3)> may be restricted by policy in ways
|
|
||||||
that will cause failure or results different than expected.
|
|
||||||
|
|
||||||
Even when using I<aa-exec> from unconfined restrictions in policy can
|
|
||||||
causes failure or the confinement entered to be different than requested
|
|
||||||
|
|
||||||
See the unpriviled unconfined restriction documentation for more detail.
|
|
||||||
https://gitlab.com/apparmor/apparmor/-/wikis/unprivileged_unconfined_restriction
|
|
||||||
|
|
||||||
=head1 STACKING
|
|
||||||
|
|
||||||
aa-exec can be used to setup a stack of profiles as confinement. When an
|
|
||||||
application is confined by a stack, all profiles in the stack are checked
|
|
||||||
as if they were the profile confining the application. The resulting
|
|
||||||
mediation is the intersection of what is allowed by each profile in the
|
|
||||||
stack.
|
|
||||||
|
|
||||||
The profiles in a stack are treated independently. Each profile can have
|
|
||||||
its own flags and profile transitions. During an exec each profile gets
|
|
||||||
to specify its transition and the results brought together to form a
|
|
||||||
new canonicalized stack.
|
|
||||||
|
|
||||||
The profile separator indicating a stack is the character sequence I<//&>.
|
|
||||||
Thus a stack can be expressed using
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
$ aa-exec -p "unconfined//&firefox" -- bash
|
|
||||||
$ ps -Z
|
|
||||||
LABEL PID TTY TIME CMD
|
|
||||||
unconfined 30714 pts/12 00:00:00 bash
|
|
||||||
firefox//&unconfined (unconfined) 31160 pts/12 00:00:00 bash
|
|
||||||
firefox//&unconfined (unconfined) 31171 pts/12 00:00:00 ps
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
=head1 NAMESPACES
|
|
||||||
|
|
||||||
aa-exec can be used to enter confinement in another policy namespace
|
|
||||||
if the policy namespaces exists, is visible, and the profile exists in
|
|
||||||
the namespace. Note applications launched within the namespace will
|
|
||||||
not be able to exit the namespace, and may be restricted by additional
|
|
||||||
confinement around namespacing. Files and resources visible to the
|
|
||||||
parent that launches the application may not be visible in the policy
|
|
||||||
namespace resulting in access denials.
|
|
||||||
|
|
||||||
To enter a policy namespace the profile is prefixed with the namespace's
|
|
||||||
name, using a I<:> prefix and suffix.
|
|
||||||
|
|
||||||
Eg.
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
$ aa-exec -p :ex1:unconfined -- bash
|
|
||||||
$ ps -Z
|
|
||||||
LABEL PID TTY TIME CMD
|
|
||||||
- 30714 pts/12 00:00:00 bash
|
|
||||||
unconfined 34372 pts/12 00:00:00 bash
|
|
||||||
unconfined 34379 pts/12 00:00:00 ps
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
Confinement of processes outside of the namespace may not be visible
|
|
||||||
in which case the confinement will be represented with a -. If policy
|
|
||||||
is stacked only part of the confinement might be visible. However
|
|
||||||
confinement is usually fully visible from the parent policy namespace.
|
|
||||||
|
|
||||||
Eg. the confinement of the child can be queried in the parent to see
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
$ ps -Z 34372
|
|
||||||
LABEL PID TTY STAT TIME COMMAND
|
|
||||||
:ex1:unconfined 34372 pts/12 S+ 0:00 bash
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
And in the case of stacking with namespaces
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
$ aa-exec -p "unconfined//&:ex1:unconfined" -- bash
|
|
||||||
$ ps -Z
|
|
||||||
LABEL PID TTY TIME CMD
|
|
||||||
- 30714 pts/12 00:00:00 bash
|
|
||||||
unconfined 36298 pts/12 00:00:00 bash
|
|
||||||
unconfined 36305 pts/12 00:00:00 ps
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
while from the parent namespace the full confinement can be seen
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
$ ps -Z 36298
|
|
||||||
LABEL PID TTY STAT TIME COMMAND
|
|
||||||
unconfined//&:ex1:unconfined 36298 pts/12 S+ 0:00 bash
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
=head1 BUGS
|
=head1 BUGS
|
||||||
|
|
||||||
If you find any bugs, please report them at
|
If you find any bugs, please report them at
|
||||||
@@ -190,7 +87,7 @@ L<https://gitlab.com/apparmor/apparmor/-/issues>
|
|||||||
|
|
||||||
=head1 SEE ALSO
|
=head1 SEE ALSO
|
||||||
|
|
||||||
apparmor(7), apparmor.d(5), aa_change_profile(3),
|
aa-stack(8), aa-namespace(8), apparmor(7), apparmor.d(5), aa_change_profile(3),
|
||||||
aa_change_onexec(3) and L<https://wiki.apparmor.net>.
|
aa_change_onexec(3) and L<https://wiki.apparmor.net>.
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
|
@@ -1,77 +0,0 @@
|
|||||||
# This publication is intellectual property of Canonical Ltd. Its contents
|
|
||||||
# can be duplicated, either in part or in whole, provided that a copyright
|
|
||||||
# label is visibly located on each copy.
|
|
||||||
#
|
|
||||||
# All information found in this book has been compiled with utmost
|
|
||||||
# attention to detail. However, this does not guarantee complete accuracy.
|
|
||||||
# Neither Canonical Ltd, the authors, nor the translators shall be held
|
|
||||||
# liable for possible errors or the consequences thereof.
|
|
||||||
#
|
|
||||||
# Many of the software and hardware descriptions cited in this book
|
|
||||||
# are registered trademarks. All trade names are subject to copyright
|
|
||||||
# restrictions and may be registered trade marks. Canonical Ltd
|
|
||||||
# essentially adheres to the manufacturer's spelling.
|
|
||||||
#
|
|
||||||
# Names of products and trademarks appearing in this book (with or without
|
|
||||||
# specific notation) are likewise subject to trademark and trade protection
|
|
||||||
# laws and may thus fall under copyright restrictions.
|
|
||||||
#
|
|
||||||
|
|
||||||
|
|
||||||
=pod
|
|
||||||
|
|
||||||
=head1 NAME
|
|
||||||
|
|
||||||
aa-load - load precompiled AppArmor policy from cache location(s)
|
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
|
||||||
|
|
||||||
B<aa-load> [options] (cache file|cache dir|cache base dir)+
|
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
|
||||||
|
|
||||||
B<aa-load> loads precompiled AppArmor policy from the specified locations.
|
|
||||||
|
|
||||||
=head1 OPTIONS
|
|
||||||
|
|
||||||
B<aa-load> accepts the following arguments:
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item -f, --force
|
|
||||||
|
|
||||||
Force B<aa-load> to load a policy even if its abi does not match the kernel abi.
|
|
||||||
|
|
||||||
=item -d, --debug
|
|
||||||
|
|
||||||
Display debug messages.
|
|
||||||
|
|
||||||
=item -v, --verbose
|
|
||||||
|
|
||||||
Display progress and error messages.
|
|
||||||
|
|
||||||
=item -n, --dry-run
|
|
||||||
|
|
||||||
Do not actually load the specified policy/policies into the kernel.
|
|
||||||
|
|
||||||
=item -h, --help
|
|
||||||
|
|
||||||
Display a brief usage guide.
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
=head1 EXIT STATUS
|
|
||||||
|
|
||||||
Upon exiting, B<aa-load> returns 0 upon success and 1 upon an error loading
|
|
||||||
the precompiled policy.
|
|
||||||
|
|
||||||
=head1 BUGS
|
|
||||||
|
|
||||||
If you find any bugs, please report them at
|
|
||||||
L<https://gitlab.com/apparmor/apparmor/-/issues>.
|
|
||||||
|
|
||||||
=head1 SEE ALSO
|
|
||||||
|
|
||||||
apparmor(7), apparmor.d(5), apparmor_parser(8), and L<https://wiki.apparmor.net>.
|
|
||||||
|
|
||||||
=cut
|
|
@@ -72,18 +72,11 @@ displays the number of loaded non-enforcing AppArmor policies.
|
|||||||
|
|
||||||
=item --kill
|
=item --kill
|
||||||
|
|
||||||
displays the number of loaded enforcing AppArmor policies that will
|
displays the number of loaded enforcing AppArmor policies that will kill tasks on policy violations.
|
||||||
kill tasks on policy violations.
|
|
||||||
|
|
||||||
=item --prompt
|
|
||||||
|
|
||||||
displays the number of loaded enforcing AppArmor policies, with
|
|
||||||
fallback to userspace mediation.
|
|
||||||
|
|
||||||
=item --special-unconfined
|
=item --special-unconfined
|
||||||
|
|
||||||
displays the number of loaded non-enforcing AppArmor policies that are
|
displays the number of loaded non-enforcing AppArmor policies that are in the special unconfined mode.
|
||||||
in the special unconfined mode.
|
|
||||||
|
|
||||||
=item --process-mixed
|
=item --process-mixed
|
||||||
displays the number of processes confined by profile stacks with
|
displays the number of processes confined by profile stacks with
|
||||||
@@ -104,40 +97,6 @@ set in a JSON format, fit for machine consumption.
|
|||||||
same as --json, formatted to be readable by humans as well
|
same as --json, formatted to be readable by humans as well
|
||||||
as by machines.
|
as by machines.
|
||||||
|
|
||||||
=item --show
|
|
||||||
|
|
||||||
what data sets to show information about. Currently I<processes>,
|
|
||||||
I<profiles>, I<all> for both processes and profiles. The default is
|
|
||||||
I<all>.
|
|
||||||
|
|
||||||
=item --count
|
|
||||||
|
|
||||||
display only counts for selected information.
|
|
||||||
|
|
||||||
=item --filter.mode=filter
|
|
||||||
|
|
||||||
Allows specifying a posix regular expression filter that will be
|
|
||||||
applied against the displayed processes and profiles apparmor profile
|
|
||||||
mode, reducing the output.
|
|
||||||
|
|
||||||
=item --filter.profiles=filter
|
|
||||||
|
|
||||||
Allows specifying a posix regular expression filter that will be
|
|
||||||
applied against the displayed processes and profiles confining
|
|
||||||
profile, reducing the output.
|
|
||||||
|
|
||||||
=item --filter.pid=filter
|
|
||||||
|
|
||||||
Allows specifying a posix regular expression filter that will be
|
|
||||||
applied against the displayed processes, so that only processes pids
|
|
||||||
matching the expression will be displayed.
|
|
||||||
|
|
||||||
=item --filter.exe=filter
|
|
||||||
|
|
||||||
Allows specifying a posix regular expression filter that will be
|
|
||||||
applied against the displayed processes, so that only processes
|
|
||||||
executable name matching the expression will be displayed.
|
|
||||||
|
|
||||||
=item --help
|
=item --help
|
||||||
|
|
||||||
displays a short usage statement.
|
displays a short usage statement.
|
||||||
@@ -165,8 +124,7 @@ if apparmor is enabled but no policy is loaded.
|
|||||||
|
|
||||||
=item B<3>
|
=item B<3>
|
||||||
|
|
||||||
if the apparmor control files aren't available under
|
if the apparmor control files aren't available under /sys/kernel/security/.
|
||||||
/sys/kernel/security/.
|
|
||||||
|
|
||||||
=item B<4>
|
=item B<4>
|
||||||
|
|
||||||
@@ -182,9 +140,8 @@ if an internal error occurred.
|
|||||||
=head1 BUGS
|
=head1 BUGS
|
||||||
|
|
||||||
B<aa-status> must be run as root to read the state of the loaded
|
B<aa-status> must be run as root to read the state of the loaded
|
||||||
policy from the apparmor module. It uses the /proc filesystem to
|
policy from the apparmor module. It uses the /proc filesystem to determine
|
||||||
determine which processes are confined and so is susceptible to race
|
which processes are confined and so is susceptible to race conditions.
|
||||||
conditions.
|
|
||||||
|
|
||||||
If you find any additional bugs, please report them at
|
If you find any additional bugs, please report them at
|
||||||
L<https://gitlab.com/apparmor/apparmor/-/issues>.
|
L<https://gitlab.com/apparmor/apparmor/-/issues>.
|
||||||
|
@@ -1,409 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2020 Canonical Ltd.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of version 2 of the GNU General Public
|
|
||||||
* License published by the Free Software Foundation.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define _GNU_SOURCE /* for asprintf() */
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
#include <sys/apparmor.h>
|
|
||||||
|
|
||||||
#include <libintl.h>
|
|
||||||
#define _(s) gettext(s)
|
|
||||||
|
|
||||||
/* TODO: implement config locations - value can change */
|
|
||||||
#define DEFAULT_CONFIG_LOCATIONS "/etc/apparmor/parser.conf"
|
|
||||||
#define DEFAULT_POLICY_LOCATIONS "/var/cache/apparmor:/etc/apparmor.d/cache.d:/etc/apparmor.d/cache"
|
|
||||||
#define CACHE_FEATURES_FILE ".features"
|
|
||||||
|
|
||||||
bool opt_debug = false;
|
|
||||||
bool opt_verbose = false;
|
|
||||||
bool opt_dryrun = false;
|
|
||||||
bool opt_force = false;
|
|
||||||
bool opt_config = false;
|
|
||||||
|
|
||||||
#define warning(fmt, args...) _error(_("aa-load: WARN: " fmt "\n"), ## args)
|
|
||||||
#define error(fmt, args...) _error(_("aa-load: ERROR: " fmt "\n"), ## args)
|
|
||||||
static void _error(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
|
|
||||||
va_start(args, fmt);
|
|
||||||
vfprintf(stderr, fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define verbose(fmt, args...) _debug(opt_verbose, _(fmt "\n"), ## args)
|
|
||||||
#define debug(fmt, args...) _debug(opt_debug, _("aa-load: DEBUG: " fmt "\n"), ## args)
|
|
||||||
static void _debug(bool opt_displayit, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
|
|
||||||
if (!opt_displayit)
|
|
||||||
return;
|
|
||||||
|
|
||||||
va_start(args, fmt);
|
|
||||||
vfprintf(stderr, fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int have_enough_privilege(const char *command)
|
|
||||||
{
|
|
||||||
uid_t uid, euid;
|
|
||||||
|
|
||||||
uid = getuid();
|
|
||||||
euid = geteuid();
|
|
||||||
|
|
||||||
if (uid != 0 && euid != 0) {
|
|
||||||
error("%s: Sorry. You need root privileges to run this program.\n",
|
|
||||||
command);
|
|
||||||
return EPERM;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uid != 0 && euid == 0) {
|
|
||||||
error("%s: Aborting! You've set this program setuid root.\n"
|
|
||||||
"Anybody who can run this program can update "
|
|
||||||
"your AppArmor profiles.\n", command);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int load_config(const char *file)
|
|
||||||
{
|
|
||||||
/* TODO */
|
|
||||||
return ENOENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* load a single policy cache file to the kernel
|
|
||||||
*/
|
|
||||||
static int load_policy_file(const char *file)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
struct aa_kernel_interface *kernel_interface;
|
|
||||||
|
|
||||||
if (aa_kernel_interface_new(&kernel_interface, NULL, NULL)) {
|
|
||||||
rc = -errno;
|
|
||||||
error("Failed to open kernel interface '%s': %m", file);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
if (!opt_dryrun &&
|
|
||||||
aa_kernel_interface_replace_policy_from_file(kernel_interface,
|
|
||||||
AT_FDCWD, file)) {
|
|
||||||
rc = -errno;
|
|
||||||
error("Failed to load policy into kernel '%s': %m", file);
|
|
||||||
}
|
|
||||||
aa_kernel_interface_unref(kernel_interface);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void validate_features(const char *dir_path)
|
|
||||||
{
|
|
||||||
aa_features *kernel_features;
|
|
||||||
|
|
||||||
if (aa_features_new_from_kernel(&kernel_features) == -1) {
|
|
||||||
error("Failed to obtain features: %m");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aa_features_check(AT_FDCWD, dir_path, kernel_features) == -1) {
|
|
||||||
if (errno == ENOENT) {
|
|
||||||
/* features file does not exist
|
|
||||||
* not an issue when loading cache policies from dir
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
else if (errno == EEXIST) {
|
|
||||||
warning("Overlay features do not match kernel features");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
aa_features_unref(kernel_features);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* load a directory of policy cache files to the kernel
|
|
||||||
* This does not do a subdir search to find the kernel match but
|
|
||||||
* tries to load the dir regardless of whether its features match
|
|
||||||
*
|
|
||||||
* The hierarchy looks like
|
|
||||||
*
|
|
||||||
* dir/
|
|
||||||
* .features
|
|
||||||
* profile1
|
|
||||||
* ...
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int load_policy_dir(const char *dir_path)
|
|
||||||
{
|
|
||||||
DIR *d;
|
|
||||||
struct dirent *dir;
|
|
||||||
int rc = 0;
|
|
||||||
char *file;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
validate_features(dir_path);
|
|
||||||
|
|
||||||
d = opendir(dir_path);
|
|
||||||
if (!d) {
|
|
||||||
rc = -errno;
|
|
||||||
error("Failed to open directory '%s': %m", dir_path);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((dir = readdir(d)) != NULL) {
|
|
||||||
/* Only check regular files for now */
|
|
||||||
if (dir->d_type == DT_REG) {
|
|
||||||
/* As per POSIX dir->d_name has at most NAME_MAX characters */
|
|
||||||
len = strnlen(dir->d_name, NAME_MAX);
|
|
||||||
/* Ignores .features */
|
|
||||||
if (strncmp(dir->d_name, CACHE_FEATURES_FILE, len) == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (asprintf(&file, "%s/%s", dir_path, dir->d_name) == -1) {
|
|
||||||
error("Failure allocating memory");
|
|
||||||
closedir(d);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
load_policy_file(file);
|
|
||||||
free(file);
|
|
||||||
file = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closedir(d);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* load_hashed_policy - find policy hashed dir and load it
|
|
||||||
*
|
|
||||||
* load/replace all policy from a policy hierarchy directory
|
|
||||||
*
|
|
||||||
* Returns: 0 on success < -errno
|
|
||||||
*
|
|
||||||
* It will find the subdir that matches the kernel and load all
|
|
||||||
* precompiled policy files from it.
|
|
||||||
*
|
|
||||||
* The hierarchy looks something like
|
|
||||||
*
|
|
||||||
* location/
|
|
||||||
* kernel_hash1.0/
|
|
||||||
* .features
|
|
||||||
* profile1
|
|
||||||
* ...
|
|
||||||
* kernel_hash2.0/
|
|
||||||
* .features
|
|
||||||
* profile1
|
|
||||||
* ...
|
|
||||||
*/
|
|
||||||
static int load_policy_by_hash(const char *location)
|
|
||||||
{
|
|
||||||
aa_policy_cache *policy_cache = NULL;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
if ((rc = aa_policy_cache_new(&policy_cache, NULL, AT_FDCWD, location, 0))) {
|
|
||||||
rc = -errno;
|
|
||||||
error("Failed to open policy cache '%s': %m", location);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opt_debug) {
|
|
||||||
/* show hash directory under location that matches the
|
|
||||||
* current kernel
|
|
||||||
*/
|
|
||||||
char *cache_loc = aa_policy_cache_dir_path_preview(NULL, AT_FDCWD, location);
|
|
||||||
if (!cache_loc) {
|
|
||||||
rc = -errno;
|
|
||||||
error("Failed to find cache location '%s': %m", location);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
debug("Loading cache from '%s'\n", cache_loc);
|
|
||||||
free(cache_loc);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!opt_dryrun) {
|
|
||||||
if ((rc = aa_policy_cache_replace_all(policy_cache, NULL)) < 0) {
|
|
||||||
error("Failed to load policy cache '%s': %m", location);
|
|
||||||
} else {
|
|
||||||
verbose("Success - Loaded policy cache '%s'", location);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
aa_policy_cache_unref(policy_cache);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* load_arg - calls specific load functions for files and directories
|
|
||||||
*
|
|
||||||
* load/replace all policy files/dir in arg
|
|
||||||
*
|
|
||||||
* Returns: 0 on success, 1 on failure.
|
|
||||||
*
|
|
||||||
* It will load by hash subtree first, and fallback to a cache dir
|
|
||||||
* If not a directory, it will try to load it as a cache file
|
|
||||||
*/
|
|
||||||
static int load_arg(char *arg)
|
|
||||||
{
|
|
||||||
char **location = NULL;
|
|
||||||
int i, n, rc = 0;
|
|
||||||
|
|
||||||
|
|
||||||
/* arg can specify an overlay of multiple cache locations */
|
|
||||||
if ((n = aa_split_overlay_str(arg, &location, 0, true)) == -1) {
|
|
||||||
error("Failed to parse overlay locations: %m");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
|
||||||
struct stat st;
|
|
||||||
debug("Trying to open %s", location[i]);
|
|
||||||
if (stat(location[i], &st) == -1) {
|
|
||||||
error("Failed stat of '%s': %m", location[i]);
|
|
||||||
rc = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (S_ISDIR(st.st_mode)) {
|
|
||||||
/* try hash dir subtree first */
|
|
||||||
if (load_policy_by_hash(location[i]) < 0) {
|
|
||||||
error("Failed load policy by hash '%s': %m", location[i]);
|
|
||||||
rc = 1;
|
|
||||||
}
|
|
||||||
/* fall back to cache dir */
|
|
||||||
if (load_policy_dir(location[i]) < 0) {
|
|
||||||
error("Failed load policy by directory '%s': %m", location[i]);
|
|
||||||
rc = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (load_policy_file(location[i]) < 0) {
|
|
||||||
rc = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < n; i++)
|
|
||||||
free(location[i]);
|
|
||||||
free(location);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void print_usage(const char *command)
|
|
||||||
{
|
|
||||||
printf("Usage: %s [OPTIONS] (cache file|cache dir|cache base dir)+\n"
|
|
||||||
"Load precompiled AppArmor policy from cache location(s)\n\n"
|
|
||||||
"Options:\n"
|
|
||||||
" -f, --force load policy even if abi does not match the kernel\n"
|
|
||||||
" -d, --debug display debug messages\n"
|
|
||||||
" -v, --verbose display progress and error messages\n"
|
|
||||||
" -n, --dry-run do everything except actual load\n"
|
|
||||||
" -h, --help this message\n",
|
|
||||||
command);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *short_options = "c:dfvnh";
|
|
||||||
struct option long_options[] = {
|
|
||||||
{"config", 1, 0, 'c'},
|
|
||||||
{"debug", 0, 0, 'd'},
|
|
||||||
{"force", 0, 0, 'f'},
|
|
||||||
{"verbose", 0, 0, 'v'},
|
|
||||||
{"dry-run", 0, 0, 'n'},
|
|
||||||
{"help", 0, 0, 'h'},
|
|
||||||
{NULL, 0, 0, 0},
|
|
||||||
};
|
|
||||||
|
|
||||||
static int process_args(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int c, o;
|
|
||||||
|
|
||||||
opterr = 1;
|
|
||||||
while ((c = getopt_long(argc, argv, short_options, long_options, &o)) != -1) {
|
|
||||||
switch(c) {
|
|
||||||
case 0:
|
|
||||||
error("error in argument processing\n");
|
|
||||||
exit(1);
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
opt_debug = true;
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
opt_force = true;
|
|
||||||
break;
|
|
||||||
case 'v':
|
|
||||||
opt_verbose = true;
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
opt_dryrun = true;
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
print_usage(argv[0]);
|
|
||||||
exit(0);
|
|
||||||
break;
|
|
||||||
case 'c':
|
|
||||||
/* TODO: reserved config location,
|
|
||||||
* act as a bad arg for now, when added update usage
|
|
||||||
*/
|
|
||||||
//opt_config = true; uncomment when implemented
|
|
||||||
/* Fall through */
|
|
||||||
default:
|
|
||||||
error("unknown argument: '%s'\n\n", optarg);
|
|
||||||
print_usage(argv[1]);
|
|
||||||
exit(1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return optind;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int i, rc = 0;
|
|
||||||
|
|
||||||
optind = process_args(argc, argv);
|
|
||||||
|
|
||||||
if (!opt_dryrun && have_enough_privilege(argv[0]))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/* if no location use the default one */
|
|
||||||
if (optind == argc) {
|
|
||||||
if (!opt_config && load_config(DEFAULT_CONFIG_LOCATIONS) == 0) {
|
|
||||||
verbose("Loaded policy config");
|
|
||||||
}
|
|
||||||
if ((rc = load_arg(DEFAULT_POLICY_LOCATIONS)))
|
|
||||||
verbose("Loading policy from default location '%s'", DEFAULT_POLICY_LOCATIONS);
|
|
||||||
else
|
|
||||||
debug("No policy specified, and no policy config or policy in default locations");
|
|
||||||
}
|
|
||||||
for (i = optind; i < argc; i++) {
|
|
||||||
/* Try to load all policy locations even if one fails
|
|
||||||
* but always return an error if any fail
|
|
||||||
*/
|
|
||||||
|
|
||||||
int tmp = load_arg(argv[i]);
|
|
||||||
if (!rc)
|
|
||||||
rc = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@@ -1,34 +0,0 @@
|
|||||||
# SOME DESCRIPTIVE TITLE.
|
|
||||||
# Copyright (C) YEAR Canonical Ltd
|
|
||||||
# This file is distributed under the same license as the PACKAGE package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
||||||
#
|
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
|
||||||
"Report-Msgid-Bugs-To: apparmor@lists.ubuntu.com\n"
|
|
||||||
"POT-Creation-Date: 2025-02-18 07:37-0800\n"
|
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
|
||||||
"Language: \n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=CHARSET\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
|
|
||||||
#: ../aa_load.c:40
|
|
||||||
msgid "aa-load: WARN: "
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_load.c:41
|
|
||||||
msgid "aa-load: ERROR: "
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_load.c:51
|
|
||||||
msgid "\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_load.c:52
|
|
||||||
msgid "aa-load: DEBUG: "
|
|
||||||
msgstr ""
|
|
@@ -1,67 +0,0 @@
|
|||||||
# Belarusian translation for apparmor
|
|
||||||
# Copyright (c) 2020 Rosetta Contributors and Canonical Ltd 2020
|
|
||||||
# This file is distributed under the same license as the apparmor package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: apparmor\n"
|
|
||||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
|
||||||
"PO-Revision-Date: 2020-05-05 21:55+0000\n"
|
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"Language-Team: Belarusian <be@li.org>\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Launchpad-Export-Date: 2020-05-06 05:41+0000\n"
|
|
||||||
"X-Generator: Launchpad (build fbdff7602bd10fb883bf7e2ddcc7fd5a16f60398)\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:26
|
|
||||||
#, c-format
|
|
||||||
msgid ""
|
|
||||||
"%s: [options]\n"
|
|
||||||
" options:\n"
|
|
||||||
" -q | --quiet Don't print out any messages\n"
|
|
||||||
" -h | --help Print help\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:45
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown or incompatible options\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:55
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown option '%s'\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:64
|
|
||||||
#, c-format
|
|
||||||
msgid "Yes\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:71
|
|
||||||
#, c-format
|
|
||||||
msgid "No - not available on this system.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:74
|
|
||||||
#, c-format
|
|
||||||
msgid "No - disabled at boot.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:77
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - policy interface not available.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:81
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - insufficient permissions to determine availability.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:84
|
|
||||||
#, c-format
|
|
||||||
msgid "Error - '%s'\n"
|
|
||||||
msgstr ""
|
|
@@ -1,71 +0,0 @@
|
|||||||
# Catalan translation for apparmor
|
|
||||||
# Copyright (c) 2024 Rosetta Contributors and Canonical Ltd 2024
|
|
||||||
# This file is distributed under the same license as the apparmor package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2024.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: apparmor\n"
|
|
||||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
|
||||||
"PO-Revision-Date: 2024-09-14 10:17+0000\n"
|
|
||||||
"Last-Translator: Walter Garcia-Fontes <walter.garcia@upf.edu>\n"
|
|
||||||
"Language-Team: Catalan <ca@li.org>\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Launchpad-Export-Date: 2024-09-15 07:16+0000\n"
|
|
||||||
"X-Generator: Launchpad (build 1b1ed1ad2dbfc71ee62b5c5491c975135a771bf0)\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:26
|
|
||||||
#, c-format
|
|
||||||
msgid ""
|
|
||||||
"%s: [options]\n"
|
|
||||||
" options:\n"
|
|
||||||
" -q | --quiet Don't print out any messages\n"
|
|
||||||
" -h | --help Print help\n"
|
|
||||||
msgstr ""
|
|
||||||
"%s: [opcions]\n"
|
|
||||||
" opcions:\n"
|
|
||||||
" -q | --quiet No imprimeixis cap missatge\n"
|
|
||||||
" -h | --help Imprimeix l'ajuda\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:45
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown or incompatible options\n"
|
|
||||||
msgstr "opcions desconegudes o incompatibles\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:55
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown option '%s'\n"
|
|
||||||
msgstr "opció desconeguda «%s»\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:64
|
|
||||||
#, c-format
|
|
||||||
msgid "Yes\n"
|
|
||||||
msgstr "Sí\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:71
|
|
||||||
#, c-format
|
|
||||||
msgid "No - not available on this system.\n"
|
|
||||||
msgstr "No - no esta disponible a aquest sistema\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:74
|
|
||||||
#, c-format
|
|
||||||
msgid "No - disabled at boot.\n"
|
|
||||||
msgstr "No - desactivat a l'inici.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:77
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - policy interface not available.\n"
|
|
||||||
msgstr "Potser - la interfície de política no està disponible.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:81
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - insufficient permissions to determine availability.\n"
|
|
||||||
msgstr "Potser - permisos insuficient per determinar la disponibilitat.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:84
|
|
||||||
#, c-format
|
|
||||||
msgid "Error - '%s'\n"
|
|
||||||
msgstr "Error - '%s'\n"
|
|
@@ -1,67 +0,0 @@
|
|||||||
# Czech translation for apparmor
|
|
||||||
# Copyright (c) 2022 Rosetta Contributors and Canonical Ltd 2022
|
|
||||||
# This file is distributed under the same license as the apparmor package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: apparmor\n"
|
|
||||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
|
||||||
"PO-Revision-Date: 2022-01-09 11:59+0000\n"
|
|
||||||
"Last-Translator: Marek Hladík <mhladik@seznam.cz>\n"
|
|
||||||
"Language-Team: Czech <cs@li.org>\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Launchpad-Export-Date: 2022-01-10 06:32+0000\n"
|
|
||||||
"X-Generator: Launchpad (build 1682fd44eec4f62371f0bed122a83482daf08e23)\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:26
|
|
||||||
#, c-format
|
|
||||||
msgid ""
|
|
||||||
"%s: [options]\n"
|
|
||||||
" options:\n"
|
|
||||||
" -q | --quiet Don't print out any messages\n"
|
|
||||||
" -h | --help Print help\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:45
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown or incompatible options\n"
|
|
||||||
msgstr "neznámé nebo nekompatibilní volby\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:55
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown option '%s'\n"
|
|
||||||
msgstr "neznámá volba '%s'\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:64
|
|
||||||
#, c-format
|
|
||||||
msgid "Yes\n"
|
|
||||||
msgstr "Ano\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:71
|
|
||||||
#, c-format
|
|
||||||
msgid "No - not available on this system.\n"
|
|
||||||
msgstr "Ne - není v tomto systému k dispozici.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:74
|
|
||||||
#, c-format
|
|
||||||
msgid "No - disabled at boot.\n"
|
|
||||||
msgstr "Ne - zakázáno při startu.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:77
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - policy interface not available.\n"
|
|
||||||
msgstr "Možná - rozhraní zásad není k dispozici.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:81
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - insufficient permissions to determine availability.\n"
|
|
||||||
msgstr "Možná - nedostatečná oprávnění k určení dostupnosti.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:84
|
|
||||||
#, c-format
|
|
||||||
msgid "Error - '%s'\n"
|
|
||||||
msgstr "Chyba - '%s'\n"
|
|
@@ -1,67 +0,0 @@
|
|||||||
# English (Australia) translation for apparmor
|
|
||||||
# Copyright (c) 2020 Rosetta Contributors and Canonical Ltd 2020
|
|
||||||
# This file is distributed under the same license as the apparmor package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: apparmor\n"
|
|
||||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
|
||||||
"PO-Revision-Date: 2020-11-28 04:45+0000\n"
|
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"Language-Team: English (Australia) <en_AU@li.org>\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Launchpad-Export-Date: 2020-11-29 06:26+0000\n"
|
|
||||||
"X-Generator: Launchpad (build 12d09381f8e8eee3115395875b132e165fa96574)\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:26
|
|
||||||
#, c-format
|
|
||||||
msgid ""
|
|
||||||
"%s: [options]\n"
|
|
||||||
" options:\n"
|
|
||||||
" -q | --quiet Don't print out any messages\n"
|
|
||||||
" -h | --help Print help\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:45
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown or incompatible options\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:55
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown option '%s'\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:64
|
|
||||||
#, c-format
|
|
||||||
msgid "Yes\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:71
|
|
||||||
#, c-format
|
|
||||||
msgid "No - not available on this system.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:74
|
|
||||||
#, c-format
|
|
||||||
msgid "No - disabled at boot.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:77
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - policy interface not available.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:81
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - insufficient permissions to determine availability.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:84
|
|
||||||
#, c-format
|
|
||||||
msgid "Error - '%s'\n"
|
|
||||||
msgstr ""
|
|
@@ -1,67 +0,0 @@
|
|||||||
# English (Canada) translation for apparmor
|
|
||||||
# Copyright (c) 2021 Rosetta Contributors and Canonical Ltd 2021
|
|
||||||
# This file is distributed under the same license as the apparmor package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2021.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: apparmor\n"
|
|
||||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
|
||||||
"PO-Revision-Date: 2021-10-01 04:55+0000\n"
|
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"Language-Team: English (Canada) <en_CA@li.org>\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Launchpad-Export-Date: 2021-10-02 06:17+0000\n"
|
|
||||||
"X-Generator: Launchpad (build 1ce78163f6a09ed42b4201fe7d3f0e3a2eba7d02)\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:26
|
|
||||||
#, c-format
|
|
||||||
msgid ""
|
|
||||||
"%s: [options]\n"
|
|
||||||
" options:\n"
|
|
||||||
" -q | --quiet Don't print out any messages\n"
|
|
||||||
" -h | --help Print help\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:45
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown or incompatible options\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:55
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown option '%s'\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:64
|
|
||||||
#, c-format
|
|
||||||
msgid "Yes\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:71
|
|
||||||
#, c-format
|
|
||||||
msgid "No - not available on this system.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:74
|
|
||||||
#, c-format
|
|
||||||
msgid "No - disabled at boot.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:77
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - policy interface not available.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:81
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - insufficient permissions to determine availability.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:84
|
|
||||||
#, c-format
|
|
||||||
msgid "Error - '%s'\n"
|
|
||||||
msgstr ""
|
|
@@ -1,71 +0,0 @@
|
|||||||
# Estonian translation for apparmor
|
|
||||||
# Copyright (c) 2023 Rosetta Contributors and Canonical Ltd 2023
|
|
||||||
# This file is distributed under the same license as the apparmor package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2023.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: apparmor\n"
|
|
||||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
|
||||||
"PO-Revision-Date: 2023-07-04 08:52+0000\n"
|
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"Language-Team: Estonian <et@li.org>\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Launchpad-Export-Date: 2023-07-05 04:31+0000\n"
|
|
||||||
"X-Generator: Launchpad (build beda0e9dd2b131780db60fe479d4b43618b27243)\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:26
|
|
||||||
#, c-format
|
|
||||||
msgid ""
|
|
||||||
"%s: [options]\n"
|
|
||||||
" options:\n"
|
|
||||||
" -q | --quiet Don't print out any messages\n"
|
|
||||||
" -h | --help Print help\n"
|
|
||||||
msgstr ""
|
|
||||||
"%s: [valikud]\n"
|
|
||||||
" valikud:\n"
|
|
||||||
" -q | --quiet Ärge printige sõnumeid välja\n"
|
|
||||||
" -h | --help Prindi abiinfo\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:45
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown or incompatible options\n"
|
|
||||||
msgstr "tundmatud või ühildumatud valikud\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:55
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown option '%s'\n"
|
|
||||||
msgstr "tundmatu valik '%s'\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:64
|
|
||||||
#, c-format
|
|
||||||
msgid "Yes\n"
|
|
||||||
msgstr "Jah\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:71
|
|
||||||
#, c-format
|
|
||||||
msgid "No - not available on this system.\n"
|
|
||||||
msgstr "Ei – pole selles süsteemis saadaval.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:74
|
|
||||||
#, c-format
|
|
||||||
msgid "No - disabled at boot.\n"
|
|
||||||
msgstr "Ei – käivitamisel keelatud.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:77
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - policy interface not available.\n"
|
|
||||||
msgstr "Võib-olla – poliisiliides pole saadaval.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:81
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - insufficient permissions to determine availability.\n"
|
|
||||||
msgstr "Võib-olla - kättesaadavuse määramiseks pole piisavalt õigusi.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:84
|
|
||||||
#, c-format
|
|
||||||
msgid "Error - '%s'\n"
|
|
||||||
msgstr "Viga – '%s'\n"
|
|
@@ -1,67 +0,0 @@
|
|||||||
# Galician translation for apparmor
|
|
||||||
# Copyright (c) 2020 Rosetta Contributors and Canonical Ltd 2020
|
|
||||||
# This file is distributed under the same license as the apparmor package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: apparmor\n"
|
|
||||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
|
||||||
"PO-Revision-Date: 2020-04-21 14:59+0000\n"
|
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"Language-Team: Galician <gl@li.org>\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Launchpad-Export-Date: 2020-04-22 06:10+0000\n"
|
|
||||||
"X-Generator: Launchpad (build aad6b57d58e2f621954298e262c1cc904860f5d2)\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:26
|
|
||||||
#, c-format
|
|
||||||
msgid ""
|
|
||||||
"%s: [options]\n"
|
|
||||||
" options:\n"
|
|
||||||
" -q | --quiet Don't print out any messages\n"
|
|
||||||
" -h | --help Print help\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:45
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown or incompatible options\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:55
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown option '%s'\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:64
|
|
||||||
#, c-format
|
|
||||||
msgid "Yes\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:71
|
|
||||||
#, c-format
|
|
||||||
msgid "No - not available on this system.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:74
|
|
||||||
#, c-format
|
|
||||||
msgid "No - disabled at boot.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:77
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - policy interface not available.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:81
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - insufficient permissions to determine availability.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:84
|
|
||||||
#, c-format
|
|
||||||
msgid "Error - '%s'\n"
|
|
||||||
msgstr ""
|
|
@@ -1,71 +0,0 @@
|
|||||||
# Hebrew translation for apparmor
|
|
||||||
# Copyright (c) 2023 Rosetta Contributors and Canonical Ltd 2023
|
|
||||||
# This file is distributed under the same license as the apparmor package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2023.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: apparmor\n"
|
|
||||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
|
||||||
"PO-Revision-Date: 2023-10-05 05:12+0000\n"
|
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"Language-Team: Hebrew <he@li.org>\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Launchpad-Export-Date: 2023-10-06 08:32+0000\n"
|
|
||||||
"X-Generator: Launchpad (build bd6cfd0cfc024dbe1dcd7d5d91165fb4f6a6c596)\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:26
|
|
||||||
#, c-format
|
|
||||||
msgid ""
|
|
||||||
"%s: [options]\n"
|
|
||||||
" options:\n"
|
|
||||||
" -q | --quiet Don't print out any messages\n"
|
|
||||||
" -h | --help Print help\n"
|
|
||||||
msgstr ""
|
|
||||||
"%s: [אפשרויות]\n"
|
|
||||||
" אפשרויות:\n"
|
|
||||||
" -q | --quiet לא להציג הודעות\n"
|
|
||||||
" -h | --help הצגת עזרה\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:45
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown or incompatible options\n"
|
|
||||||
msgstr "אפשרויות לא ידועות או לא נתמכות\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:55
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown option '%s'\n"
|
|
||||||
msgstr "האפשרות ‚%s’ לא מוכרת\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:64
|
|
||||||
#, c-format
|
|
||||||
msgid "Yes\n"
|
|
||||||
msgstr "כן\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:71
|
|
||||||
#, c-format
|
|
||||||
msgid "No - not available on this system.\n"
|
|
||||||
msgstr "לא - לא זמין במערכת הזאת.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:74
|
|
||||||
#, c-format
|
|
||||||
msgid "No - disabled at boot.\n"
|
|
||||||
msgstr "לא - מושבת בעלייה.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:77
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - policy interface not available.\n"
|
|
||||||
msgstr "אולי - מנשק המדיניות לא זמין.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:81
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - insufficient permissions to determine availability.\n"
|
|
||||||
msgstr "אולי - אין מספיק הרשאות לקבוע זמינות.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:84
|
|
||||||
#, c-format
|
|
||||||
msgid "Error - '%s'\n"
|
|
||||||
msgstr "שגיאה - ‚%s’\n"
|
|
@@ -1,67 +0,0 @@
|
|||||||
# Hindi translation for apparmor
|
|
||||||
# Copyright (c) 2023 Rosetta Contributors and Canonical Ltd 2023
|
|
||||||
# This file is distributed under the same license as the apparmor package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2023.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: apparmor\n"
|
|
||||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
|
||||||
"PO-Revision-Date: 2023-01-09 07:39+0000\n"
|
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"Language-Team: Hindi <hi@li.org>\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Launchpad-Export-Date: 2023-01-10 06:22+0000\n"
|
|
||||||
"X-Generator: Launchpad (build 87bfee1fd14ea3245297d63eeec1e4c8a1d203a8)\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:26
|
|
||||||
#, c-format
|
|
||||||
msgid ""
|
|
||||||
"%s: [options]\n"
|
|
||||||
" options:\n"
|
|
||||||
" -q | --quiet Don't print out any messages\n"
|
|
||||||
" -h | --help Print help\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:45
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown or incompatible options\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:55
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown option '%s'\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:64
|
|
||||||
#, c-format
|
|
||||||
msgid "Yes\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:71
|
|
||||||
#, c-format
|
|
||||||
msgid "No - not available on this system.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:74
|
|
||||||
#, c-format
|
|
||||||
msgid "No - disabled at boot.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:77
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - policy interface not available.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:81
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - insufficient permissions to determine availability.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:84
|
|
||||||
#, c-format
|
|
||||||
msgid "Error - '%s'\n"
|
|
||||||
msgstr ""
|
|
@@ -1,71 +0,0 @@
|
|||||||
# Croatian translation for apparmor
|
|
||||||
# Copyright (c) 2020 Rosetta Contributors and Canonical Ltd 2020
|
|
||||||
# This file is distributed under the same license as the apparmor package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: apparmor\n"
|
|
||||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
|
||||||
"PO-Revision-Date: 2021-10-03 10:17+0000\n"
|
|
||||||
"Last-Translator: gogo <trebelnik2@gmail.com>\n"
|
|
||||||
"Language-Team: Croatian <hr@li.org>\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Launchpad-Export-Date: 2021-10-04 06:23+0000\n"
|
|
||||||
"X-Generator: Launchpad (build 1ce78163f6a09ed42b4201fe7d3f0e3a2eba7d02)\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:26
|
|
||||||
#, c-format
|
|
||||||
msgid ""
|
|
||||||
"%s: [options]\n"
|
|
||||||
" options:\n"
|
|
||||||
" -q | --quiet Don't print out any messages\n"
|
|
||||||
" -h | --help Print help\n"
|
|
||||||
msgstr ""
|
|
||||||
"%s: [mogućnosti]\n"
|
|
||||||
" options:\n"
|
|
||||||
" -q | --quiet Ne prikazuj poruke\n"
|
|
||||||
" -h | --help Prikaži pomoć\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:45
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown or incompatible options\n"
|
|
||||||
msgstr "nepoznata ili nepotpuna mogućnost\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:55
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown option '%s'\n"
|
|
||||||
msgstr "nepoznata mogućnost '%s'\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:64
|
|
||||||
#, c-format
|
|
||||||
msgid "Yes\n"
|
|
||||||
msgstr "Da\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:71
|
|
||||||
#, c-format
|
|
||||||
msgid "No - not available on this system.\n"
|
|
||||||
msgstr "Ne - nedostupno na ovom sustavu.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:74
|
|
||||||
#, c-format
|
|
||||||
msgid "No - disabled at boot.\n"
|
|
||||||
msgstr "Ne - onemogućeno pri pokretanju.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:77
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - policy interface not available.\n"
|
|
||||||
msgstr "Možda - pravilo sučelja nedostupno.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:81
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - insufficient permissions to determine availability.\n"
|
|
||||||
msgstr "Možda - nedovoljna dozvola za određivanje dostupnosti.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:84
|
|
||||||
#, c-format
|
|
||||||
msgid "Error - '%s'\n"
|
|
||||||
msgstr "Greška - '%s'\n"
|
|
@@ -1,72 +0,0 @@
|
|||||||
# Italian translation for apparmor
|
|
||||||
# Copyright (c) 2022 Rosetta Contributors and Canonical Ltd 2022
|
|
||||||
# This file is distributed under the same license as the apparmor package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: apparmor\n"
|
|
||||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
|
||||||
"PO-Revision-Date: 2022-06-30 17:54+0000\n"
|
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"Language-Team: Italian <it@li.org>\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Launchpad-Export-Date: 2022-07-01 04:30+0000\n"
|
|
||||||
"X-Generator: Launchpad (build f48158886a49da429840bcd298f0c7ed60f9ad7b)\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:26
|
|
||||||
#, c-format
|
|
||||||
msgid ""
|
|
||||||
"%s: [options]\n"
|
|
||||||
" options:\n"
|
|
||||||
" -q | --quiet Don't print out any messages\n"
|
|
||||||
" -h | --help Print help\n"
|
|
||||||
msgstr ""
|
|
||||||
"%s: [opzioni]\n"
|
|
||||||
" opzioni:\n"
|
|
||||||
" -q | --quiet Non stampa nessun messaggio\n"
|
|
||||||
" -h | --help Stampa la guida\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:45
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown or incompatible options\n"
|
|
||||||
msgstr "opzioni sconosciute o incompatibili\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:55
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown option '%s'\n"
|
|
||||||
msgstr "opzione sconosciuta '%s'\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:64
|
|
||||||
#, c-format
|
|
||||||
msgid "Yes\n"
|
|
||||||
msgstr "Si\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:71
|
|
||||||
#, c-format
|
|
||||||
msgid "No - not available on this system.\n"
|
|
||||||
msgstr "No - non disponibile su questo sistema.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:74
|
|
||||||
#, c-format
|
|
||||||
msgid "No - disabled at boot.\n"
|
|
||||||
msgstr "No - disabilitato all'avvio.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:77
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - policy interface not available.\n"
|
|
||||||
msgstr "Forse - interfaccia dei criteri non disponibile.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:81
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - insufficient permissions to determine availability.\n"
|
|
||||||
msgstr ""
|
|
||||||
"Forse - autorizzazioni insufficienti per determinare la disponibilità.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:84
|
|
||||||
#, c-format
|
|
||||||
msgid "Error - '%s'\n"
|
|
||||||
msgstr "Errore - '%s'\n"
|
|
@@ -1,72 +0,0 @@
|
|||||||
# Georgian translation for apparmor
|
|
||||||
# Copyright (c) 2023 Rosetta Contributors and Canonical Ltd 2023
|
|
||||||
# This file is distributed under the same license as the apparmor package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2023.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: apparmor\n"
|
|
||||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
|
||||||
"PO-Revision-Date: 2023-06-26 15:06+0000\n"
|
|
||||||
"Last-Translator: NorwayFun <temuri.doghonadze@gmail.com>\n"
|
|
||||||
"Language-Team: Georgian <ka@li.org>\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Launchpad-Export-Date: 2023-06-27 04:31+0000\n"
|
|
||||||
"X-Generator: Launchpad (build aedf8597c50c1abc5fb7f9e871e686dfcb381fde)\n"
|
|
||||||
"Language: aa\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:26
|
|
||||||
#, c-format
|
|
||||||
msgid ""
|
|
||||||
"%s: [options]\n"
|
|
||||||
" options:\n"
|
|
||||||
" -q | --quiet Don't print out any messages\n"
|
|
||||||
" -h | --help Print help\n"
|
|
||||||
msgstr ""
|
|
||||||
"%s: [პარამეტრები]\n"
|
|
||||||
" პარამეტრები:\n"
|
|
||||||
" -q | --quiet შეტყობინებები გამოტანილი არ იქნება\n"
|
|
||||||
" -h | --help დახმარების გამოტანა\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:45
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown or incompatible options\n"
|
|
||||||
msgstr "უცნობი ან შეუთავსებელი პარამეტრები\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:55
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown option '%s'\n"
|
|
||||||
msgstr "უცნობი პარამეტრი \"%s\"-სთვის\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:64
|
|
||||||
#, c-format
|
|
||||||
msgid "Yes\n"
|
|
||||||
msgstr "დიახ\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:71
|
|
||||||
#, c-format
|
|
||||||
msgid "No - not available on this system.\n"
|
|
||||||
msgstr "არა - მიუწვდომელია ამ სისტემაზე\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:74
|
|
||||||
#, c-format
|
|
||||||
msgid "No - disabled at boot.\n"
|
|
||||||
msgstr "არა - გამორთულია ჩატვირთვისას\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:77
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - policy interface not available.\n"
|
|
||||||
msgstr "შეიძლება - პოლიტიკის ინტერფეისი ხელმისაწვდომი არაა.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:81
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - insufficient permissions to determine availability.\n"
|
|
||||||
msgstr "შეიძლება - არასაკმარისი წვდომები ხელმისაწვდომობის დასადგენად.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:84
|
|
||||||
#, c-format
|
|
||||||
msgid "Error - '%s'\n"
|
|
||||||
msgstr "შეცდომა - \"%s\"\n"
|
|
@@ -1,67 +0,0 @@
|
|||||||
# Kabyle translation for apparmor
|
|
||||||
# Copyright (c) 2020 Rosetta Contributors and Canonical Ltd 2020
|
|
||||||
# This file is distributed under the same license as the apparmor package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: apparmor\n"
|
|
||||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
|
||||||
"PO-Revision-Date: 2020-04-29 14:31+0000\n"
|
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"Language-Team: Kabyle <kab@li.org>\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Launchpad-Export-Date: 2020-04-30 05:44+0000\n"
|
|
||||||
"X-Generator: Launchpad (build fbdff7602bd10fb883bf7e2ddcc7fd5a16f60398)\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:26
|
|
||||||
#, c-format
|
|
||||||
msgid ""
|
|
||||||
"%s: [options]\n"
|
|
||||||
" options:\n"
|
|
||||||
" -q | --quiet Don't print out any messages\n"
|
|
||||||
" -h | --help Print help\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:45
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown or incompatible options\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:55
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown option '%s'\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:64
|
|
||||||
#, c-format
|
|
||||||
msgid "Yes\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:71
|
|
||||||
#, c-format
|
|
||||||
msgid "No - not available on this system.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:74
|
|
||||||
#, c-format
|
|
||||||
msgid "No - disabled at boot.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:77
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - policy interface not available.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:81
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - insufficient permissions to determine availability.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:84
|
|
||||||
#, c-format
|
|
||||||
msgid "Error - '%s'\n"
|
|
||||||
msgstr ""
|
|
@@ -1,73 +0,0 @@
|
|||||||
# Burmese translation for apparmor
|
|
||||||
# Copyright (c) 2022 Rosetta Contributors and Canonical Ltd 2022
|
|
||||||
# This file is distributed under the same license as the apparmor package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: apparmor\n"
|
|
||||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
|
||||||
"PO-Revision-Date: 2022-06-26 11:50+0000\n"
|
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"Language-Team: Burmese <my@li.org>\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Launchpad-Export-Date: 2022-06-27 04:30+0000\n"
|
|
||||||
"X-Generator: Launchpad (build 51a2e4fa2e9b8e45f00904ad7f53546f45ac48a5)\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:26
|
|
||||||
#, c-format
|
|
||||||
msgid ""
|
|
||||||
"%s: [options]\n"
|
|
||||||
" options:\n"
|
|
||||||
" -q | --quiet Don't print out any messages\n"
|
|
||||||
" -h | --help Print help\n"
|
|
||||||
msgstr ""
|
|
||||||
"%s- [options]\n"
|
|
||||||
" ရွေးချယ်စရာများ-\n"
|
|
||||||
" -q | --quiet မည်သည့်စာတိုကိုမှ ပရင့်မထုတ်ပါနှင့်။\n"
|
|
||||||
" -h | --help ပရင့်အကူအညီ\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:45
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown or incompatible options\n"
|
|
||||||
msgstr "အမည်မသိ သို့မဟုတ် သဟဇာတမဖြစ်သော ရွေးချယ်စရာများ\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:55
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown option '%s'\n"
|
|
||||||
msgstr "အမည်မသိရွေးချယ်မှု '%s'\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:64
|
|
||||||
#, c-format
|
|
||||||
msgid "Yes\n"
|
|
||||||
msgstr "ဟုတ်\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:71
|
|
||||||
#, c-format
|
|
||||||
msgid "No - not available on this system.\n"
|
|
||||||
msgstr "မဟုတ်ပါ - ဤစနစ်တွင် မရနိုင်ပါ။\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:74
|
|
||||||
#, c-format
|
|
||||||
msgid "No - disabled at boot.\n"
|
|
||||||
msgstr "မဟုတ်ပါ - boot တွင် ပိတ်ထားပါသည်။\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:77
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - policy interface not available.\n"
|
|
||||||
msgstr "ဖြစ်နိုင်ပါသည် - မူဝါဒ interface ကို မရနိုင်ပါ။\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:81
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - insufficient permissions to determine availability.\n"
|
|
||||||
msgstr ""
|
|
||||||
"ဖြစ်နိုင်ပါသည် - ရရှိနိုင်မှုကို ဆုံးဖြတ်ရန်အတွက် ခွင့်ပြုချက်များမှာ "
|
|
||||||
"လုံလောက်မှုမရှိပါ။\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:84
|
|
||||||
#, c-format
|
|
||||||
msgid "Error - '%s'\n"
|
|
||||||
msgstr "အမှား- '%s'\n"
|
|
@@ -1,67 +0,0 @@
|
|||||||
# Occitan (post 1500) translation for apparmor
|
|
||||||
# Copyright (c) 2021 Rosetta Contributors and Canonical Ltd 2021
|
|
||||||
# This file is distributed under the same license as the apparmor package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2021.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: apparmor\n"
|
|
||||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
|
||||||
"PO-Revision-Date: 2021-01-14 18:26+0000\n"
|
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"Language-Team: Occitan (post 1500) <oc@li.org>\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Launchpad-Export-Date: 2021-01-15 07:59+0000\n"
|
|
||||||
"X-Generator: Launchpad (build 511b4a3b6512aa3d421c5f7d74f3527e78bff26e)\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:26
|
|
||||||
#, c-format
|
|
||||||
msgid ""
|
|
||||||
"%s: [options]\n"
|
|
||||||
" options:\n"
|
|
||||||
" -q | --quiet Don't print out any messages\n"
|
|
||||||
" -h | --help Print help\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:45
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown or incompatible options\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:55
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown option '%s'\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:64
|
|
||||||
#, c-format
|
|
||||||
msgid "Yes\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:71
|
|
||||||
#, c-format
|
|
||||||
msgid "No - not available on this system.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:74
|
|
||||||
#, c-format
|
|
||||||
msgid "No - disabled at boot.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:77
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - policy interface not available.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:81
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - insufficient permissions to determine availability.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:84
|
|
||||||
#, c-format
|
|
||||||
msgid "Error - '%s'\n"
|
|
||||||
msgstr ""
|
|
@@ -1,71 +0,0 @@
|
|||||||
# Polish translation for apparmor
|
|
||||||
# Copyright (c) 2021 Rosetta Contributors and Canonical Ltd 2021
|
|
||||||
# This file is distributed under the same license as the apparmor package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2021.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: apparmor\n"
|
|
||||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
|
||||||
"PO-Revision-Date: 2021-07-22 20:10+0000\n"
|
|
||||||
"Last-Translator: Marek Adamski <Unknown>\n"
|
|
||||||
"Language-Team: Polish <pl@li.org>\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Launchpad-Export-Date: 2021-07-23 06:03+0000\n"
|
|
||||||
"X-Generator: Launchpad (build 7edebbcd0516593cf020aaa3c59299732a7c73cc)\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:26
|
|
||||||
#, c-format
|
|
||||||
msgid ""
|
|
||||||
"%s: [options]\n"
|
|
||||||
" options:\n"
|
|
||||||
" -q | --quiet Don't print out any messages\n"
|
|
||||||
" -h | --help Print help\n"
|
|
||||||
msgstr ""
|
|
||||||
"%s: [opcje]\n"
|
|
||||||
" opcje:\n"
|
|
||||||
" -q | --quiet Nie wyświetlaj żadnych komunikatów\n"
|
|
||||||
" -h | --help Wyświetl pomoc\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:45
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown or incompatible options\n"
|
|
||||||
msgstr "nieznane lub niekompatybilne opcje\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:55
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown option '%s'\n"
|
|
||||||
msgstr "nieznana opcja '%s'\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:64
|
|
||||||
#, c-format
|
|
||||||
msgid "Yes\n"
|
|
||||||
msgstr "Tak\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:71
|
|
||||||
#, c-format
|
|
||||||
msgid "No - not available on this system.\n"
|
|
||||||
msgstr "Nie - nie jest dostępne w tym systemie.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:74
|
|
||||||
#, c-format
|
|
||||||
msgid "No - disabled at boot.\n"
|
|
||||||
msgstr "Nie - wyłączone podczas rozruchu.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:77
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - policy interface not available.\n"
|
|
||||||
msgstr "Może - interfejs zasad nie jest dostępny.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:81
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - insufficient permissions to determine availability.\n"
|
|
||||||
msgstr "Może - brak wystarczających uprawnień do określenia dostępności.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:84
|
|
||||||
#, c-format
|
|
||||||
msgid "Error - '%s'\n"
|
|
||||||
msgstr "Błąd - '%s'\n"
|
|
@@ -1,71 +0,0 @@
|
|||||||
# Brazilian Portuguese translation for apparmor
|
|
||||||
# Copyright (c) 2020 Rosetta Contributors and Canonical Ltd 2020
|
|
||||||
# This file is distributed under the same license as the apparmor package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: apparmor\n"
|
|
||||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
|
||||||
"PO-Revision-Date: 2020-04-27 20:32+0000\n"
|
|
||||||
"Last-Translator: Rodrigo Farias <Unknown>\n"
|
|
||||||
"Language-Team: Brazilian Portuguese <pt_BR@li.org>\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Launchpad-Export-Date: 2020-04-28 05:52+0000\n"
|
|
||||||
"X-Generator: Launchpad (build d1105341713c5be348effe2a5142c4a210ce4cde)\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:26
|
|
||||||
#, c-format
|
|
||||||
msgid ""
|
|
||||||
"%s: [options]\n"
|
|
||||||
" options:\n"
|
|
||||||
" -q | --quiet Don't print out any messages\n"
|
|
||||||
" -h | --help Print help\n"
|
|
||||||
msgstr ""
|
|
||||||
"%s: [options]\n"
|
|
||||||
" opções:\n"
|
|
||||||
" -q | --quiet Não imprimir nenhum mensagem\n"
|
|
||||||
" -h | --help Assistente de impressão\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:45
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown or incompatible options\n"
|
|
||||||
msgstr "opções incompatíveis ou desconhecidas\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:55
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown option '%s'\n"
|
|
||||||
msgstr "opção desconhecida '%s'\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:64
|
|
||||||
#, c-format
|
|
||||||
msgid "Yes\n"
|
|
||||||
msgstr "Sim\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:71
|
|
||||||
#, c-format
|
|
||||||
msgid "No - not available on this system.\n"
|
|
||||||
msgstr "Não - não disponível neste sistema.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:74
|
|
||||||
#, c-format
|
|
||||||
msgid "No - disabled at boot.\n"
|
|
||||||
msgstr "Não - desabilitado na inicialização.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:77
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - policy interface not available.\n"
|
|
||||||
msgstr "Talvez - interface de política não disponível.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:81
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - insufficient permissions to determine availability.\n"
|
|
||||||
msgstr "Talvez - permissões insuficientes para determinar disponibilidade.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:84
|
|
||||||
#, c-format
|
|
||||||
msgid "Error - '%s'\n"
|
|
||||||
msgstr "Erro - '%s'\n"
|
|
@@ -1,26 +1,21 @@
|
|||||||
# Romanian translation for apparmor, "apparmor-binutils" component.
|
# Romanian translation for apparmor
|
||||||
# Mesajele în limba română pentru pachetul „apparmor”, componenta „apparmor-binutils”.
|
# Copyright (c) 2020 Rosetta Contributors and Canonical Ltd 2020
|
||||||
# Copyright © 2020 Rosetta Contributors and Canonical Ltd.
|
|
||||||
# Copyright © 2024 Canonical Ltd.
|
|
||||||
# This file is distributed under the same license as the apparmor package.
|
# This file is distributed under the same license as the apparmor package.
|
||||||
#
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
|
||||||
# Daniel Slavu <Unknown>, feb-2020.
|
|
||||||
# Remus-Gabriel Chelu <remusgabriel.chelu@disroot.org>, sep-2024.
|
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: apparmor-binutils\n"
|
"Project-Id-Version: apparmor\n"
|
||||||
"Report-Msgid-Bugs-To: <apparmor@lists.ubuntu.com>\n"
|
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
||||||
"PO-Revision-Date: 2024-09-23 22:45+0000\n"
|
"PO-Revision-Date: 2020-02-20 21:47+0000\n"
|
||||||
"Last-Translator: Remus-Gabriel Chelu <Unknown>\n"
|
"Last-Translator: Daniel Slavu <Unknown>\n"
|
||||||
"Language-Team: Romanian <debian-l10n-romanian@lists.debian.org>\n"
|
"Language-Team: Romanian <ro@li.org>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2024-09-25 04:33+0000\n"
|
"X-Launchpad-Export-Date: 2020-02-21 05:39+0000\n"
|
||||||
"X-Generator: Launchpad (build 1b1ed1ad2dbfc71ee62b5c5491c975135a771bf0)\n"
|
"X-Generator: Launchpad (build 19413b719a8df7423ab1390528edadce9e0e4aca)\n"
|
||||||
"Language: ro\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:26
|
#: ../aa_enabled.c:26
|
||||||
#, c-format
|
#, c-format
|
||||||
@@ -32,8 +27,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"%s: [opțiuni]\n"
|
"%s: [opțiuni]\n"
|
||||||
" opțiuni:\n"
|
" opțiuni:\n"
|
||||||
" -q | --quiet nu afișează niciun mesaj\n"
|
" -q | --calm Nu imprima niciun mesaj\n"
|
||||||
" -h | --help imprimă ajutorul\n"
|
" -h | - ajutor Imprimare ajutor\n"
|
||||||
|
|
||||||
#: ../aa_enabled.c:45
|
#: ../aa_enabled.c:45
|
||||||
#, c-format
|
#, c-format
|
||||||
@@ -43,7 +38,7 @@ msgstr "opțiuni necunoscute sau incompatibile\n"
|
|||||||
#: ../aa_enabled.c:55
|
#: ../aa_enabled.c:55
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "unknown option '%s'\n"
|
msgid "unknown option '%s'\n"
|
||||||
msgstr "opțiune necunoscută „%s”\n"
|
msgstr "opțiune necunoscută '%s'\n"
|
||||||
|
|
||||||
#: ../aa_enabled.c:64
|
#: ../aa_enabled.c:64
|
||||||
#, c-format
|
#, c-format
|
||||||
@@ -63,8 +58,7 @@ msgstr "Nu - dezactivat la pornire.\n"
|
|||||||
#: ../aa_enabled.c:77
|
#: ../aa_enabled.c:77
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Maybe - policy interface not available.\n"
|
msgid "Maybe - policy interface not available.\n"
|
||||||
msgstr ""
|
msgstr "Poate - interfața politică nu este disponibilă.\n"
|
||||||
"Poate - interfața politică (de directive politice) nu este disponibilă.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:81
|
#: ../aa_enabled.c:81
|
||||||
#, c-format
|
#, c-format
|
||||||
@@ -75,4 +69,4 @@ msgstr ""
|
|||||||
#: ../aa_enabled.c:84
|
#: ../aa_enabled.c:84
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Error - '%s'\n"
|
msgid "Error - '%s'\n"
|
||||||
msgstr "Eroare - „%s”\n"
|
msgstr "Eroare - '%s'\n"
|
||||||
|
@@ -1,67 +0,0 @@
|
|||||||
# Serbian translation for apparmor
|
|
||||||
# Copyright (c) 2020 Rosetta Contributors and Canonical Ltd 2020
|
|
||||||
# This file is distributed under the same license as the apparmor package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: apparmor\n"
|
|
||||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
|
||||||
"PO-Revision-Date: 2020-11-23 18:06+0000\n"
|
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"Language-Team: Serbian <sr@li.org>\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Launchpad-Export-Date: 2020-11-24 05:55+0000\n"
|
|
||||||
"X-Generator: Launchpad (build c35ff22711d15549e2303ae18ae521fd91f6bf00)\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:26
|
|
||||||
#, c-format
|
|
||||||
msgid ""
|
|
||||||
"%s: [options]\n"
|
|
||||||
" options:\n"
|
|
||||||
" -q | --quiet Don't print out any messages\n"
|
|
||||||
" -h | --help Print help\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:45
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown or incompatible options\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:55
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown option '%s'\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:64
|
|
||||||
#, c-format
|
|
||||||
msgid "Yes\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:71
|
|
||||||
#, c-format
|
|
||||||
msgid "No - not available on this system.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:74
|
|
||||||
#, c-format
|
|
||||||
msgid "No - disabled at boot.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:77
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - policy interface not available.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:81
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - insufficient permissions to determine availability.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:84
|
|
||||||
#, c-format
|
|
||||||
msgid "Error - '%s'\n"
|
|
||||||
msgstr ""
|
|
@@ -1,71 +0,0 @@
|
|||||||
# Ukrainian translation for apparmor
|
|
||||||
# Copyright (c) 2020 Rosetta Contributors and Canonical Ltd 2020
|
|
||||||
# This file is distributed under the same license as the apparmor package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: apparmor\n"
|
|
||||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
|
||||||
"PO-Revision-Date: 2020-05-19 21:48+0000\n"
|
|
||||||
"Last-Translator: Nazarii Ritter <nazariy.ritter@gmail.com>\n"
|
|
||||||
"Language-Team: Ukrainian <uk@li.org>\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Launchpad-Export-Date: 2020-05-20 05:42+0000\n"
|
|
||||||
"X-Generator: Launchpad (build 0385b538081bc4718df6fb844a3afc89729c94ce)\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:26
|
|
||||||
#, c-format
|
|
||||||
msgid ""
|
|
||||||
"%s: [options]\n"
|
|
||||||
" options:\n"
|
|
||||||
" -q | --quiet Don't print out any messages\n"
|
|
||||||
" -h | --help Print help\n"
|
|
||||||
msgstr ""
|
|
||||||
"%s: [опції]\n"
|
|
||||||
" опції:\n"
|
|
||||||
" -q | --quiet Не виводити жодних повідомлень\n"
|
|
||||||
" -h | --help Вивести довідку\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:45
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown or incompatible options\n"
|
|
||||||
msgstr "невідомі або несумісні опції\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:55
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown option '%s'\n"
|
|
||||||
msgstr "невідомий параметр «%s»\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:64
|
|
||||||
#, c-format
|
|
||||||
msgid "Yes\n"
|
|
||||||
msgstr "Так\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:71
|
|
||||||
#, c-format
|
|
||||||
msgid "No - not available on this system.\n"
|
|
||||||
msgstr "Ні – недоступно на цій системі.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:74
|
|
||||||
#, c-format
|
|
||||||
msgid "No - disabled at boot.\n"
|
|
||||||
msgstr "Ні – вимкнено під час завантаження.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:77
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - policy interface not available.\n"
|
|
||||||
msgstr "Можливо – інтерфейс політики недоступний.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:81
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - insufficient permissions to determine availability.\n"
|
|
||||||
msgstr "Можливо – недостатньо дозволів для визначення наявності.\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:84
|
|
||||||
#, c-format
|
|
||||||
msgid "Error - '%s'\n"
|
|
||||||
msgstr "Помилка - '%s'\n"
|
|
@@ -1,71 +0,0 @@
|
|||||||
# Chinese (Simplified) translation for apparmor
|
|
||||||
# Copyright (c) 2020 Rosetta Contributors and Canonical Ltd 2020
|
|
||||||
# This file is distributed under the same license as the apparmor package.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: apparmor\n"
|
|
||||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
|
||||||
"PO-Revision-Date: 2020-05-14 09:16+0000\n"
|
|
||||||
"Last-Translator: 玉堂白鹤 <yjwork@qq.com>\n"
|
|
||||||
"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Launchpad-Export-Date: 2020-05-15 05:51+0000\n"
|
|
||||||
"X-Generator: Launchpad (build 0385b538081bc4718df6fb844a3afc89729c94ce)\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:26
|
|
||||||
#, c-format
|
|
||||||
msgid ""
|
|
||||||
"%s: [options]\n"
|
|
||||||
" options:\n"
|
|
||||||
" -q | --quiet Don't print out any messages\n"
|
|
||||||
" -h | --help Print help\n"
|
|
||||||
msgstr ""
|
|
||||||
"%s: [选项]\n"
|
|
||||||
" 选项:\n"
|
|
||||||
" -q | --quiet 不要打印任何消息\n"
|
|
||||||
" -h | --help 打印帮助\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:45
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown or incompatible options\n"
|
|
||||||
msgstr "未知或不兼容的选项\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:55
|
|
||||||
#, c-format
|
|
||||||
msgid "unknown option '%s'\n"
|
|
||||||
msgstr "未知选项 '%s'\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:64
|
|
||||||
#, c-format
|
|
||||||
msgid "Yes\n"
|
|
||||||
msgstr "是\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:71
|
|
||||||
#, c-format
|
|
||||||
msgid "No - not available on this system.\n"
|
|
||||||
msgstr "否 - 在此系统上不可用。\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:74
|
|
||||||
#, c-format
|
|
||||||
msgid "No - disabled at boot.\n"
|
|
||||||
msgstr "否 - 引导时被禁用。\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:77
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - policy interface not available.\n"
|
|
||||||
msgstr "也许 - 策略界面不可用\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:81
|
|
||||||
#, c-format
|
|
||||||
msgid "Maybe - insufficient permissions to determine availability.\n"
|
|
||||||
msgstr "也许 - 没有足够的权限确定可用性。\n"
|
|
||||||
|
|
||||||
#: ../aa_enabled.c:84
|
|
||||||
#, c-format
|
|
||||||
msgid "Error - '%s'\n"
|
|
||||||
msgstr "错误 - '%s'\n"
|
|
@@ -67,10 +67,10 @@ to syslog.
|
|||||||
References
|
References
|
||||||
----------
|
----------
|
||||||
Project webpage:
|
Project webpage:
|
||||||
https://apparmor.net/
|
http://developer.novell.com/wiki/index.php/Novell_AppArmor
|
||||||
|
|
||||||
To provide feedback or ask questions please contact the
|
To provide feedback or ask questions please contact the
|
||||||
apparmor@lists.ubuntu.com mail list. This is the development list
|
apparmor-dev@forge.novell.com mail list. This is the development list
|
||||||
for the AppArmor team.
|
for the AppArmor team.
|
||||||
|
|
||||||
See also: change_hat(3), and the Linux-PAM online documentation at
|
See also: change_hat(3), and the Linux-PAM online documentation at
|
||||||
|
@@ -188,9 +188,10 @@ parent context.
|
|||||||
8. Feedback/Resources
|
8. Feedback/Resources
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
Project webpage:
|
To provide feedback or ask questions please contact the
|
||||||
https://apparmor.net/
|
apparmor-dev@forge.novell.com mail list. This is the development list for the
|
||||||
|
AppArmor team.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
To provide feedback or ask questions please contact the
|
|
||||||
apparmor@lists.ubuntu.com mail list. This is the development list
|
|
||||||
for the AppArmor team.
|
|
||||||
|
@@ -188,9 +188,10 @@ parent context.
|
|||||||
8. Feedback/Resources
|
8. Feedback/Resources
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
Project webpage:
|
To provide feedback or ask questions please contact the
|
||||||
https://apparmor.net/
|
apparmor-dev@forge.novell.com mail list. This is the development list for the
|
||||||
|
AppArmor team.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
To provide feedback or ask questions please contact the
|
|
||||||
apparmor@lists.ubuntu.com mail list. This is the development list
|
|
||||||
for the AppArmor team.
|
|
||||||
|
@@ -35,14 +35,16 @@ VERSION=$(shell cat $(COMMONDIR)/Version)
|
|||||||
pathsearch = $(firstword $(wildcard $(addsuffix /$(1),$(subst :, ,$(PATH)))))
|
pathsearch = $(firstword $(wildcard $(addsuffix /$(1),$(subst :, ,$(PATH)))))
|
||||||
map = $(foreach a,$(2),$(call $(1),$(a)))
|
map = $(foreach a,$(2),$(call $(1),$(a)))
|
||||||
|
|
||||||
AWK?=$(or $(shell which awk),$(error awk utility required for build but not available))
|
AWK:=$(shell which awk)
|
||||||
|
ifndef AWK
|
||||||
|
$(error awk utility required for build but not available)
|
||||||
|
endif
|
||||||
|
|
||||||
define nl
|
define nl
|
||||||
|
|
||||||
|
|
||||||
endef
|
endef
|
||||||
|
|
||||||
REPO_VERSION_CMD=[ -x /usr/bin/git ] && /usr/bin/git describe --tags --long --abbrev=16 --match 'v*' 2> /dev/null || $(AWK) '{ print $2 }' common/.stamp_rev
|
REPO_VERSION_CMD=[ -x /usr/bin/git ] && /usr/bin/git describe --tags --long --abbrev=16 --match 'v*' 2> /dev/null || awk '{ print $2 }' common/.stamp_rev
|
||||||
|
|
||||||
ifndef PYTHON_VERSIONS
|
ifndef PYTHON_VERSIONS
|
||||||
PYTHON_VERSIONS = $(call map, pathsearch, python3)
|
PYTHON_VERSIONS = $(call map, pathsearch, python3)
|
||||||
|
@@ -1 +1 @@
|
|||||||
4.1.1
|
3.1.6
|
||||||
|
Binary file not shown.
@@ -92,17 +92,6 @@ if test "$ac_cv_prog_cc_c99" = "no"; then
|
|||||||
AC_MSG_ERROR([C99 mode is required to build libapparmor])
|
AC_MSG_ERROR([C99 mode is required to build libapparmor])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_PROG_CXX
|
|
||||||
|
|
||||||
m4_ifndef([AX_CHECK_COMPILE_FLAG], [AC_MSG_ERROR(['autoconf-archive' missing])])
|
|
||||||
EXTRA_CFLAGS="-Wall $EXTRA_WARNINGS -fPIC"
|
|
||||||
AX_CHECK_COMPILE_FLAG([-flto-partition=none], , , [-Werror])
|
|
||||||
AS_VAR_IF([ax_cv_check_cflags__Werror__flto_partition_none], [yes],
|
|
||||||
[EXTRA_CFLAGS="$EXTRA_CFLAGS -flto-partition=none"]
|
|
||||||
,)
|
|
||||||
AC_SUBST([AM_CFLAGS], ["$EXTRA_CFLAGS"])
|
|
||||||
AC_SUBST([AM_CXXFLAGS], ["$EXTRA_CFLAGS"])
|
|
||||||
|
|
||||||
AC_OUTPUT(
|
AC_OUTPUT(
|
||||||
Makefile
|
Makefile
|
||||||
doc/Makefile
|
doc/Makefile
|
||||||
|
@@ -116,14 +116,6 @@ The specified I<file/task> does not exist or is not visible.
|
|||||||
|
|
||||||
The confinement data is too large to fit in the supplied buffer.
|
The confinement data is too large to fit in the supplied buffer.
|
||||||
|
|
||||||
=item B<ENOPROTOOPT>
|
|
||||||
|
|
||||||
The kernel doesn't support the SO_PEERLABEL option in sockets. This happens
|
|
||||||
mainly when the kernel lacks 'fine grained unix mediation' support. It also
|
|
||||||
can happen on LSM stacking kernels where another LSM has claimed this
|
|
||||||
interface and decides to return this error, although this is really a
|
|
||||||
corner case.
|
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
=head1 NOTES
|
=head1 NOTES
|
||||||
|
@@ -109,12 +109,12 @@ To immediately stack a profile named "profile_a", as performed with
|
|||||||
aa_stack_profile("profile_a"), the equivalent of this shell command can be
|
aa_stack_profile("profile_a"), the equivalent of this shell command can be
|
||||||
used:
|
used:
|
||||||
|
|
||||||
$ echo -n "stack profile_a" > /proc/self/attr/current
|
$ echo -n "stackprofile profile_a" > /proc/self/attr/current
|
||||||
|
|
||||||
To stack a profile named "profile_a" at the next exec, as performed with
|
To stack a profile named "profile_a" at the next exec, as performed with
|
||||||
aa_stack_onexec("profile_a"), the equivalent of this shell command can be used:
|
aa_stack_onexec("profile_a"), the equivalent of this shell command can be used:
|
||||||
|
|
||||||
$ echo -n "stack profile_a" > /proc/self/attr/exec
|
$ echo -n "stackexec profile_a" > /proc/self/attr/exec
|
||||||
|
|
||||||
These raw AppArmor filesystem operations must only be used when using
|
These raw AppArmor filesystem operations must only be used when using
|
||||||
libapparmor is not a viable option.
|
libapparmor is not a viable option.
|
||||||
@@ -184,7 +184,6 @@ with apparmor_parser(8):
|
|||||||
/etc/passwd r,
|
/etc/passwd r,
|
||||||
|
|
||||||
# Needed for aa_stack_profile()
|
# Needed for aa_stack_profile()
|
||||||
change-profile -> &i_cant_be_trusted_anymore,
|
|
||||||
/usr/lib/libapparmor*.so* mr,
|
/usr/lib/libapparmor*.so* mr,
|
||||||
/proc/[0-9]*/attr/current w,
|
/proc/[0-9]*/attr/current w,
|
||||||
}
|
}
|
||||||
|
@@ -19,10 +19,6 @@
|
|||||||
#ifndef __LIBAALOGPARSE_H_
|
#ifndef __LIBAALOGPARSE_H_
|
||||||
#define __LIBAALOGPARSE_H_
|
#define __LIBAALOGPARSE_H_
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define AA_RECORD_EXEC_MMAP 1
|
#define AA_RECORD_EXEC_MMAP 1
|
||||||
#define AA_RECORD_READ 2
|
#define AA_RECORD_READ 2
|
||||||
#define AA_RECORD_WRITE 4
|
#define AA_RECORD_WRITE 4
|
||||||
@@ -30,10 +26,10 @@ extern "C" {
|
|||||||
#define AA_RECORD_LINK 16
|
#define AA_RECORD_LINK 16
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enum representing which syntax version the log entry used.
|
* This is just for convenience now that we have two
|
||||||
* Support for V1 parsing was completely removed in 2011 and that enum entry
|
* wildly different grammars.
|
||||||
* is only still there for API compatibility reasons.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
AA_RECORD_SYNTAX_V1,
|
AA_RECORD_SYNTAX_V1,
|
||||||
@@ -52,23 +48,70 @@ typedef enum
|
|||||||
AA_RECORD_STATUS /* Configuration change */
|
AA_RECORD_STATUS /* Configuration change */
|
||||||
} aa_record_event_type;
|
} aa_record_event_type;
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Use this preprocessor dance to maintain backcompat for field names
|
* With the sole exception of active_hat, this is a 1:1
|
||||||
* This will break C code that used the C++ reserved keywords "namespace"
|
* mapping from the keys that the new syntax uses.
|
||||||
* and "class" as identifiers, but this is bad practice anyways, and we
|
|
||||||
* hope that we are the only ones in a given C file that messed up this way
|
|
||||||
*
|
*
|
||||||
* TODO: document this in a man page for aalogparse?
|
* Some examples of the old syntax and how they're mapped with the aa_log_record struct:
|
||||||
*/
|
*
|
||||||
#if defined(SWIG) && defined(__cplusplus)
|
* "PERMITTING r access to /path (program_name(12345) profile /profile active hat)"
|
||||||
#error "SWIG and __cplusplus are defined together"
|
* - operation: access
|
||||||
#elif !defined(SWIG) && !defined(__cplusplus)
|
* - requested_mask: r
|
||||||
/* Use SWIG's %rename feature to preserve backcompat */
|
* - pid: 12345
|
||||||
#define class rule_class
|
* - profile: /profile
|
||||||
#define namespace aa_namespace
|
* - name: /path
|
||||||
#endif
|
* - info: program_name
|
||||||
|
* - active_hat: hat
|
||||||
|
*
|
||||||
|
* "REJECTING mkdir on /path/to/something (bash(23415) profile /bin/freak-aa-out active /bin/freak-aa-out"
|
||||||
|
* - operation: mkdir
|
||||||
|
* - name: /path/to/something
|
||||||
|
* - info: bash
|
||||||
|
* - pid: 23415
|
||||||
|
* - profile: /bin/freak-aa-out
|
||||||
|
* - active_hat: /bin/freak-aa-out
|
||||||
|
*
|
||||||
|
* "REJECTING xattr set on /path/to/something (bash(23415) profile /bin/freak-aa-out active /bin/freak-aa-out)"
|
||||||
|
* - operation: xattr
|
||||||
|
* - attribute: set
|
||||||
|
* - name: /path/to/something
|
||||||
|
* - info: bash
|
||||||
|
* - pid: 23415
|
||||||
|
* - profile: /bin/freak-aa-out
|
||||||
|
* - active_hat: /bin/freak-aa-out
|
||||||
|
*
|
||||||
|
* "PERMITTING attribute (something) change to /else (bash(23415) profile /bin/freak-aa-out active /bin/freak-aa-out)"
|
||||||
|
* - operation: setattr
|
||||||
|
* - attribute: something
|
||||||
|
* - name: /else
|
||||||
|
* - info: bash
|
||||||
|
* - pid: 23415
|
||||||
|
* - profile: /bin/freak-aa-out
|
||||||
|
* - active_hat: /bin/freak-aa-out
|
||||||
|
*
|
||||||
|
* "PERMITTING access to capability 'cap' (bash(23415) profile /bin/freak-aa-out active /bin/freak-aa-out)"
|
||||||
|
* - operation: capability
|
||||||
|
* - name: cap
|
||||||
|
* - info: bash
|
||||||
|
* - pid: 23415
|
||||||
|
* - profile: /bin/freak-aa-out
|
||||||
|
* - active_hat: /bin/freak-aa-out
|
||||||
|
*
|
||||||
|
* "LOGPROF-HINT unknown_hat TESTHAT pid=27764 profile=/change_hat_test/test_hat active=/change_hat_test/test_hat"
|
||||||
|
* - operation: change_hat
|
||||||
|
* - name: TESTHAT
|
||||||
|
* - info: unknown_hat
|
||||||
|
* - pid: 27764
|
||||||
|
* - profile: /change_hat_test/test_hat
|
||||||
|
* - active_hat: /change_hat_test/test_hat
|
||||||
|
*
|
||||||
|
* "LOGPROF-HINT fork pid=27764 child=38229"
|
||||||
|
* - operation: clone
|
||||||
|
* - task: 38229
|
||||||
|
* - pid: 27764
|
||||||
|
**/
|
||||||
|
|
||||||
typedef struct aa_log_record
|
typedef struct
|
||||||
{
|
{
|
||||||
aa_record_syntax_version version;
|
aa_record_syntax_version version;
|
||||||
aa_record_event_type event; /* Event type */
|
aa_record_event_type event; /* Event type */
|
||||||
@@ -91,7 +134,7 @@ typedef struct aa_log_record
|
|||||||
char *comm; /* Command that triggered msg */
|
char *comm; /* Command that triggered msg */
|
||||||
char *name;
|
char *name;
|
||||||
char *name2;
|
char *name2;
|
||||||
char *aa_namespace;
|
char *namespace;
|
||||||
char *attribute;
|
char *attribute;
|
||||||
unsigned long parent;
|
unsigned long parent;
|
||||||
char *info;
|
char *info;
|
||||||
@@ -105,7 +148,6 @@ typedef struct aa_log_record
|
|||||||
unsigned long net_local_port;
|
unsigned long net_local_port;
|
||||||
char *net_foreign_addr;
|
char *net_foreign_addr;
|
||||||
unsigned long net_foreign_port;
|
unsigned long net_foreign_port;
|
||||||
|
|
||||||
char *dbus_bus;
|
char *dbus_bus;
|
||||||
char *dbus_path;
|
char *dbus_path;
|
||||||
char *dbus_interface;
|
char *dbus_interface;
|
||||||
@@ -118,11 +160,7 @@ typedef struct aa_log_record
|
|||||||
char *flags;
|
char *flags;
|
||||||
char *src_name;
|
char *src_name;
|
||||||
|
|
||||||
char *rule_class;
|
char *class;
|
||||||
|
|
||||||
char *net_addr;
|
|
||||||
char *peer_addr;
|
|
||||||
char *execpath;
|
|
||||||
} aa_log_record;
|
} aa_log_record;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -133,7 +171,7 @@ typedef struct aa_log_record
|
|||||||
* @return Parsed data.
|
* @return Parsed data.
|
||||||
*/
|
*/
|
||||||
aa_log_record *
|
aa_log_record *
|
||||||
parse_record(const char *str);
|
parse_record(char *str);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Frees all struct data.
|
* Frees all struct data.
|
||||||
@@ -142,9 +180,5 @@ parse_record(const char *str);
|
|||||||
void
|
void
|
||||||
free_record(aa_log_record *record);
|
free_record(aa_log_record *record);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -105,8 +105,8 @@ extern int aa_getpeercon(int fd, char **label, char **mode);
|
|||||||
#define AA_QUERY_CMD_LABEL "label"
|
#define AA_QUERY_CMD_LABEL "label"
|
||||||
#define AA_QUERY_CMD_LABEL_SIZE sizeof(AA_QUERY_CMD_LABEL)
|
#define AA_QUERY_CMD_LABEL_SIZE sizeof(AA_QUERY_CMD_LABEL)
|
||||||
|
|
||||||
extern int aa_query_label(uint32_t mask, char *query, size_t size, int *allowed,
|
extern int aa_query_label(uint32_t mask, char *query, size_t size, int *allow,
|
||||||
int *audited);
|
int *audit);
|
||||||
extern int aa_query_file_path_len(uint32_t mask, const char *label,
|
extern int aa_query_file_path_len(uint32_t mask, const char *label,
|
||||||
size_t label_len, const char *path,
|
size_t label_len, const char *path,
|
||||||
size_t path_len, int *allowed, int *audited);
|
size_t path_len, int *allowed, int *audited);
|
||||||
@@ -157,8 +157,6 @@ extern int aa_features_write_to_file(aa_features *features,
|
|||||||
int dirfd, const char *path);
|
int dirfd, const char *path);
|
||||||
extern bool aa_features_is_equal(aa_features *features1,
|
extern bool aa_features_is_equal(aa_features *features1,
|
||||||
aa_features *features2);
|
aa_features *features2);
|
||||||
extern int aa_features_check(int dirfd, const char *path,
|
|
||||||
aa_features *features);
|
|
||||||
extern bool aa_features_supports(aa_features *features, const char *str);
|
extern bool aa_features_supports(aa_features *features, const char *str);
|
||||||
extern char *aa_features_id(aa_features *features);
|
extern char *aa_features_id(aa_features *features);
|
||||||
extern char *aa_features_value(aa_features *features, const char *str, size_t *len);
|
extern char *aa_features_value(aa_features *features, const char *str, size_t *len);
|
||||||
@@ -211,8 +209,6 @@ extern char *aa_policy_cache_filename(aa_policy_cache *policy_cache, const char
|
|||||||
extern char *aa_policy_cache_dir_path_preview(aa_features *kernel_features,
|
extern char *aa_policy_cache_dir_path_preview(aa_features *kernel_features,
|
||||||
int dirfd, const char *path);
|
int dirfd, const char *path);
|
||||||
|
|
||||||
extern int aa_split_overlay_str(char *str, char ***vec, size_t max_size, bool immutable);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -32,10 +32,10 @@ INCLUDES = $(all_includes)
|
|||||||
#
|
#
|
||||||
# After changing the AA_LIB_* variables, also update EXPECTED_SO_NAME.
|
# After changing the AA_LIB_* variables, also update EXPECTED_SO_NAME.
|
||||||
|
|
||||||
AA_LIB_CURRENT = 25
|
AA_LIB_CURRENT = 13
|
||||||
AA_LIB_REVISION = 2
|
AA_LIB_REVISION = 3
|
||||||
AA_LIB_AGE = 24
|
AA_LIB_AGE = 12
|
||||||
EXPECTED_SO_NAME = libapparmor.so.1.24.2
|
EXPECTED_SO_NAME = libapparmor.so.1.12.3
|
||||||
|
|
||||||
SUFFIXES = .pc.in .pc
|
SUFFIXES = .pc.in .pc
|
||||||
|
|
||||||
@@ -44,7 +44,8 @@ include $(COMMONDIR)/Make.rules
|
|||||||
|
|
||||||
BUILT_SOURCES = grammar.h scanner.h af_protos.h
|
BUILT_SOURCES = grammar.h scanner.h af_protos.h
|
||||||
AM_LFLAGS = -v
|
AM_LFLAGS = -v
|
||||||
AM_YFLAGS = -Wno-yacc -d -p aalogparse_
|
AM_YFLAGS = -d -p aalogparse_
|
||||||
|
AM_CFLAGS = -Wall $(EXTRA_WARNINGS) -fPIC -flto-partition=none
|
||||||
AM_CPPFLAGS = -D_GNU_SOURCE -I$(top_srcdir)/include/
|
AM_CPPFLAGS = -D_GNU_SOURCE -I$(top_srcdir)/include/
|
||||||
scanner.h: scanner.l
|
scanner.h: scanner.l
|
||||||
$(LEX) -v $<
|
$(LEX) -v $<
|
||||||
@@ -52,13 +53,13 @@ scanner.h: scanner.l
|
|||||||
scanner.c: scanner.l
|
scanner.c: scanner.l
|
||||||
|
|
||||||
af_protos.h:
|
af_protos.h:
|
||||||
echo '#include <netinet/in.h>' | $(CC) $(CPPFLAGS) -E -dD - | LC_ALL=C sed -n -e "/IPPROTO_MAX/d" -e "s/^\#define[ \\t]\\+IPPROTO_\\([A-Z0-9_]\\+\\)\\(.*\\)$$/AA_GEN_PROTO_ENT(\\UIPPROTO_\\1, \"\\L\\1\")/p" > $@
|
echo '#include <netinet/in.h>' | $(CC) $(CPPFLAGS) -E -dM - | LC_ALL=C sed -n -e "/IPPROTO_MAX/d" -e "s/^\#define[ \\t]\\+IPPROTO_\\([A-Z0-9_]\\+\\)\\(.*\\)$$/AA_GEN_PROTO_ENT(\\UIPPROTO_\\1, \"\\L\\1\")/p" > $@
|
||||||
|
|
||||||
lib_LTLIBRARIES = libapparmor.la
|
lib_LTLIBRARIES = libapparmor.la
|
||||||
noinst_HEADERS = grammar.h parser.h scanner.h af_protos.h private.h PMurHash.h
|
noinst_HEADERS = grammar.h parser.h scanner.h af_protos.h private.h PMurHash.h
|
||||||
|
|
||||||
libapparmor_la_SOURCES = grammar.y libaalogparse.c kernel.c scanner.c private.c features.c kernel_interface.c policy_cache.c PMurHash.c
|
libapparmor_la_SOURCES = grammar.y libaalogparse.c kernel.c scanner.c private.c features.c kernel_interface.c policy_cache.c PMurHash.c
|
||||||
libapparmor_la_LDFLAGS = -version-info $(AA_LIB_CURRENT):$(AA_LIB_REVISION):$(AA_LIB_AGE) -XCClinker -Bdynamic -pthread \
|
libapparmor_la_LDFLAGS = -version-info $(AA_LIB_CURRENT):$(AA_LIB_REVISION):$(AA_LIB_AGE) -XCClinker -dynamic -pthread \
|
||||||
-Wl,--version-script=$(top_srcdir)/src/libapparmor.map
|
-Wl,--version-script=$(top_srcdir)/src/libapparmor.map
|
||||||
|
|
||||||
pkgconfigdir = $(libdir)/pkgconfig
|
pkgconfigdir = $(libdir)/pkgconfig
|
||||||
@@ -73,16 +74,6 @@ CLEANFILES = libapparmor.pc
|
|||||||
tst_aalogmisc_SOURCES = tst_aalogmisc.c
|
tst_aalogmisc_SOURCES = tst_aalogmisc.c
|
||||||
tst_aalogmisc_LDADD = .libs/libapparmor.a
|
tst_aalogmisc_LDADD = .libs/libapparmor.a
|
||||||
|
|
||||||
tst_aalogparse_cpp_SOURCES = tst_aalogparse_cpp.cpp
|
|
||||||
tst_aalogparse_cpp_LDADD = .libs/libapparmor.a
|
|
||||||
|
|
||||||
tst_aalogparse_oldname_SOURCES = tst_aalogparse_oldname.c
|
|
||||||
tst_aalogparse_oldname_LDADD = .libs/libapparmor.a
|
|
||||||
|
|
||||||
tst_aalogparse_reentrancy_SOURCES = tst_aalogparse_reentrancy.c
|
|
||||||
tst_aalogparse_reentrancy_LDADD = .libs/libapparmor.a
|
|
||||||
tst_aalogparse_reentrancy_LDFLAGS = -pthread
|
|
||||||
|
|
||||||
tst_features_SOURCES = tst_features.c
|
tst_features_SOURCES = tst_features.c
|
||||||
tst_features_LDADD = .libs/libapparmor.a
|
tst_features_LDADD = .libs/libapparmor.a
|
||||||
|
|
||||||
@@ -90,7 +81,7 @@ tst_kernel_SOURCES = tst_kernel.c
|
|||||||
tst_kernel_LDADD = .libs/libapparmor.a
|
tst_kernel_LDADD = .libs/libapparmor.a
|
||||||
tst_kernel_LDFLAGS = -pthread
|
tst_kernel_LDFLAGS = -pthread
|
||||||
|
|
||||||
check_PROGRAMS = tst_aalogmisc tst_aalogparse_cpp tst_aalogparse_reentrancy tst_aalogparse_oldname tst_features tst_kernel
|
check_PROGRAMS = tst_aalogmisc tst_features tst_kernel
|
||||||
TESTS = $(check_PROGRAMS)
|
TESTS = $(check_PROGRAMS)
|
||||||
|
|
||||||
.PHONY: check-local
|
.PHONY: check-local
|
||||||
|
@@ -35,7 +35,6 @@
|
|||||||
#include "PMurHash.h"
|
#include "PMurHash.h"
|
||||||
|
|
||||||
#define FEATURES_FILE "/sys/kernel/security/apparmor/features"
|
#define FEATURES_FILE "/sys/kernel/security/apparmor/features"
|
||||||
#define CACHE_FEATURES_FILE ".features"
|
|
||||||
|
|
||||||
#define HASH_SIZE (8 + 1) /* 32 bits binary to hex + NUL terminator */
|
#define HASH_SIZE (8 + 1) /* 32 bits binary to hex + NUL terminator */
|
||||||
#define STRING_SIZE 8192
|
#define STRING_SIZE 8192
|
||||||
@@ -399,10 +398,6 @@ static bool walk_one(const char **str, const struct component *component,
|
|||||||
i = 0;
|
i = 0;
|
||||||
|
|
||||||
cur++;
|
cur++;
|
||||||
|
|
||||||
/* Partial match, continue to search */
|
|
||||||
if (i == component->len && !isbrace_space_or_nul(*cur))
|
|
||||||
i = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return false if a full match was not found */
|
/* Return false if a full match was not found */
|
||||||
@@ -663,44 +658,6 @@ bool aa_features_is_equal(aa_features *features1, aa_features *features2)
|
|||||||
strcmp(features1->string, features2->string) == 0;
|
strcmp(features1->string, features2->string) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* aa_features_check - check if features from a directory matches an aa_features object
|
|
||||||
* @dirfd: a directory file descriptory or AT_FDCWD (see openat(2))
|
|
||||||
* @path: the path containing the features
|
|
||||||
* @features: features to be matched against
|
|
||||||
*
|
|
||||||
* Returns: 0 on success, -1 on failure. errno is set to EEXIST when there's not a match
|
|
||||||
*/
|
|
||||||
int aa_features_check(int dirfd, const char *path,
|
|
||||||
aa_features *features)
|
|
||||||
{
|
|
||||||
aa_features *local_features = NULL;
|
|
||||||
autofree char *name = NULL;
|
|
||||||
bool rc;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
len = asprintf(&name, "%s/%s", path, CACHE_FEATURES_FILE);
|
|
||||||
if (len == -1) {
|
|
||||||
errno = ENOMEM;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* verify that path dir .features matches */
|
|
||||||
if (aa_features_new(&local_features, dirfd, name)) {
|
|
||||||
PDEBUG("could not setup new features object for dirfd '%d' '%s'\n", dirfd, name);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = aa_features_is_equal(local_features, features);
|
|
||||||
aa_features_unref(local_features);
|
|
||||||
if (!rc) {
|
|
||||||
errno = EEXIST;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *features_lookup(aa_features *features, const char *str)
|
static const char *features_lookup(aa_features *features, const char *str)
|
||||||
{
|
{
|
||||||
const char *features_string = features->string;
|
const char *features_string = features->string;
|
||||||
|
@@ -15,15 +15,17 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* aalogparse_error now requires visibility of the aa_log_record type
|
|
||||||
* Also include in a %code requires block to add it to the header
|
|
||||||
*/
|
|
||||||
%code requires{
|
|
||||||
#include <aalogparse.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
%{
|
%{
|
||||||
|
|
||||||
|
/* set the following to non-zero to get bison to emit debugging
|
||||||
|
* information about tokens given and rules matched.
|
||||||
|
* Also:
|
||||||
|
* Uncomment the %defines
|
||||||
|
* parse.error
|
||||||
|
* parse.trace
|
||||||
|
*/
|
||||||
|
#define YYDEBUG 0
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <aalogparse.h>
|
#include <aalogparse.h>
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
@@ -39,10 +41,12 @@
|
|||||||
#define debug_unused_ unused_
|
#define debug_unused_ unused_
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
aa_log_record *ret_record;
|
||||||
|
|
||||||
/* Since we're a library, on any errors we don't want to print out any
|
/* Since we're a library, on any errors we don't want to print out any
|
||||||
* error messages. We should probably add a debug interface that does
|
* error messages. We should probably add a debug interface that does
|
||||||
* emit messages when asked for. */
|
* emit messages when asked for. */
|
||||||
void aalogparse_error(unused_ void *scanner, aa_log_record *ret_record, debug_unused_ char const *s)
|
void aalogparse_error(unused_ void *scanner, debug_unused_ char const *s)
|
||||||
{
|
{
|
||||||
#if (YYDEBUG != 0)
|
#if (YYDEBUG != 0)
|
||||||
printf("ERROR: %s\n", s);
|
printf("ERROR: %s\n", s);
|
||||||
@@ -85,10 +89,9 @@ aa_record_event_type lookup_aa_event(unsigned int type)
|
|||||||
%define parse.trace
|
%define parse.trace
|
||||||
*/
|
*/
|
||||||
|
|
||||||
%define api.pure full
|
%define api.pure
|
||||||
%lex-param{void *scanner}
|
%lex-param{void *scanner}
|
||||||
%parse-param{void *scanner}
|
%parse-param{void *scanner}
|
||||||
%parse-param{aa_log_record *ret_record}
|
|
||||||
|
|
||||||
%union
|
%union
|
||||||
{
|
{
|
||||||
@@ -111,7 +114,6 @@ aa_record_event_type lookup_aa_event(unsigned int type)
|
|||||||
%token TOK_PERIOD
|
%token TOK_PERIOD
|
||||||
%token TOK_QUESTION_MARK
|
%token TOK_QUESTION_MARK
|
||||||
%token TOK_SINGLE_QUOTE
|
%token TOK_SINGLE_QUOTE
|
||||||
%token TOK_NONE
|
|
||||||
|
|
||||||
%token TOK_TYPE_REJECT
|
%token TOK_TYPE_REJECT
|
||||||
%token TOK_TYPE_AUDIT
|
%token TOK_TYPE_AUDIT
|
||||||
@@ -185,8 +187,6 @@ aa_record_event_type lookup_aa_event(unsigned int type)
|
|||||||
%token TOK_KEY_FSTYPE
|
%token TOK_KEY_FSTYPE
|
||||||
%token TOK_KEY_FLAGS
|
%token TOK_KEY_FLAGS
|
||||||
%token TOK_KEY_SRCNAME
|
%token TOK_KEY_SRCNAME
|
||||||
%token TOK_KEY_UNIX_PEER_ADDR
|
|
||||||
%token TOK_KEY_EXECPATH
|
|
||||||
%token TOK_KEY_CLASS
|
%token TOK_KEY_CLASS
|
||||||
|
|
||||||
%token TOK_SOCKLOGD_KERNEL
|
%token TOK_SOCKLOGD_KERNEL
|
||||||
@@ -249,7 +249,7 @@ syslog_type:
|
|||||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($3); }
|
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($3); }
|
||||||
| syslog_date syslog_id TOK_DMESG_STAMP key_type audit_id key_list
|
| syslog_date syslog_id TOK_DMESG_STAMP key_type audit_id key_list
|
||||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($3); }
|
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($3); }
|
||||||
/* needs update: hard newline in handling multiline log messages */
|
/* needs update: hard newline in handling mutiline log messages */
|
||||||
| syslog_date syslog_id TOK_DMESG_STAMP TOK_AUDIT TOK_COLON key_type audit_id audit_user_msg_partial_tail
|
| syslog_date syslog_id TOK_DMESG_STAMP TOK_AUDIT TOK_COLON key_type audit_id audit_user_msg_partial_tail
|
||||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($3); }
|
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($3); }
|
||||||
| syslog_date syslog_id TOK_DMESG_STAMP TOK_AUDIT TOK_COLON key_type audit_id audit_user_msg_tail
|
| syslog_date syslog_id TOK_DMESG_STAMP TOK_AUDIT TOK_COLON key_type audit_id audit_user_msg_tail
|
||||||
@@ -281,9 +281,8 @@ audit_user_msg: TOK_KEY_MSG TOK_EQUALS audit_id audit_user_msg_tail
|
|||||||
|
|
||||||
audit_id: TOK_AUDIT TOK_OPEN_PAREN TOK_AUDIT_DIGITS TOK_PERIOD TOK_AUDIT_DIGITS TOK_COLON TOK_AUDIT_DIGITS TOK_CLOSE_PAREN TOK_COLON
|
audit_id: TOK_AUDIT TOK_OPEN_PAREN TOK_AUDIT_DIGITS TOK_PERIOD TOK_AUDIT_DIGITS TOK_COLON TOK_AUDIT_DIGITS TOK_CLOSE_PAREN TOK_COLON
|
||||||
{
|
{
|
||||||
if (!asprintf(&ret_record->audit_id, "%s.%s:%s", $3, $5, $7)) {
|
if (!asprintf(&ret_record->audit_id, "%s.%s:%s", $3, $5, $7))
|
||||||
yyerror(scanner, ret_record, YY_("Out of memory"));
|
yyerror(scanner, YY_("Out of memory"));
|
||||||
}
|
|
||||||
ret_record->epoch = atol($3);
|
ret_record->epoch = atol($3);
|
||||||
ret_record->audit_sub_id = atoi($7);
|
ret_record->audit_sub_id = atoi($7);
|
||||||
free($3);
|
free($3);
|
||||||
@@ -306,7 +305,7 @@ key: TOK_KEY_OPERATION TOK_EQUALS TOK_QUOTED_STRING
|
|||||||
| TOK_KEY_NAME TOK_EQUALS safe_string
|
| TOK_KEY_NAME TOK_EQUALS safe_string
|
||||||
{ ret_record->name = $3;}
|
{ ret_record->name = $3;}
|
||||||
| TOK_KEY_NAMESPACE TOK_EQUALS safe_string
|
| TOK_KEY_NAMESPACE TOK_EQUALS safe_string
|
||||||
{ ret_record->aa_namespace = $3;}
|
{ ret_record->namespace = $3;}
|
||||||
| TOK_KEY_NAME2 TOK_EQUALS safe_string
|
| TOK_KEY_NAME2 TOK_EQUALS safe_string
|
||||||
{ ret_record->name2 = $3;}
|
{ ret_record->name2 = $3;}
|
||||||
| TOK_KEY_MASK TOK_EQUALS TOK_QUOTED_STRING
|
| TOK_KEY_MASK TOK_EQUALS TOK_QUOTED_STRING
|
||||||
@@ -355,13 +354,6 @@ key: TOK_KEY_OPERATION TOK_EQUALS TOK_QUOTED_STRING
|
|||||||
{ ret_record->fsuid = $3;}
|
{ ret_record->fsuid = $3;}
|
||||||
| TOK_KEY_OUID TOK_EQUALS TOK_DIGITS
|
| TOK_KEY_OUID TOK_EQUALS TOK_DIGITS
|
||||||
{ ret_record->ouid = $3;}
|
{ ret_record->ouid = $3;}
|
||||||
| TOK_KEY_ADDR TOK_EQUALS TOK_QUESTION_MARK
|
|
||||||
| TOK_KEY_ADDR TOK_EQUALS TOK_NONE
|
|
||||||
| TOK_KEY_ADDR TOK_EQUALS safe_string
|
|
||||||
{ ret_record->net_addr = $3; }
|
|
||||||
| TOK_KEY_UNIX_PEER_ADDR TOK_EQUALS TOK_NONE
|
|
||||||
| TOK_KEY_UNIX_PEER_ADDR TOK_EQUALS safe_string
|
|
||||||
{ ret_record->peer_addr = $3; }
|
|
||||||
| TOK_KEY_FSUID_UPPER TOK_EQUALS TOK_QUOTED_STRING
|
| TOK_KEY_FSUID_UPPER TOK_EQUALS TOK_QUOTED_STRING
|
||||||
{ free($3);} /* Ignore - fsuid username */
|
{ free($3);} /* Ignore - fsuid username */
|
||||||
| TOK_KEY_OUID_UPPER TOK_EQUALS TOK_QUOTED_STRING
|
| TOK_KEY_OUID_UPPER TOK_EQUALS TOK_QUOTED_STRING
|
||||||
@@ -371,7 +363,10 @@ key: TOK_KEY_OPERATION TOK_EQUALS TOK_QUOTED_STRING
|
|||||||
| TOK_KEY_HOSTNAME TOK_EQUALS safe_string
|
| TOK_KEY_HOSTNAME TOK_EQUALS safe_string
|
||||||
{ free($3); /* Ignore - hostname from user AVC messages */ }
|
{ free($3); /* Ignore - hostname from user AVC messages */ }
|
||||||
| TOK_KEY_HOSTNAME TOK_EQUALS TOK_QUESTION_MARK
|
| TOK_KEY_HOSTNAME TOK_EQUALS TOK_QUESTION_MARK
|
||||||
|
| TOK_KEY_ADDR TOK_EQUALS TOK_QUESTION_MARK
|
||||||
| TOK_KEY_TERMINAL TOK_EQUALS TOK_QUESTION_MARK
|
| TOK_KEY_TERMINAL TOK_EQUALS TOK_QUESTION_MARK
|
||||||
|
| TOK_KEY_ADDR TOK_EQUALS safe_string
|
||||||
|
{ free($3); /* Ignore - IP address from user AVC messages */ }
|
||||||
| TOK_KEY_TERMINAL TOK_EQUALS safe_string
|
| TOK_KEY_TERMINAL TOK_EQUALS safe_string
|
||||||
{ free($3); /* Ignore - TTY from user AVC messages */ }
|
{ free($3); /* Ignore - TTY from user AVC messages */ }
|
||||||
| TOK_KEY_EXE TOK_EQUALS safe_string
|
| TOK_KEY_EXE TOK_EQUALS safe_string
|
||||||
@@ -424,21 +419,21 @@ key: TOK_KEY_OPERATION TOK_EQUALS TOK_QUOTED_STRING
|
|||||||
{ ret_record->dbus_member = $3; }
|
{ ret_record->dbus_member = $3; }
|
||||||
| TOK_KEY_SIGNAL TOK_EQUALS TOK_ID
|
| TOK_KEY_SIGNAL TOK_EQUALS TOK_ID
|
||||||
{ ret_record->signal = $3; }
|
{ ret_record->signal = $3; }
|
||||||
|
|
||||||
| TOK_KEY_FSTYPE TOK_EQUALS TOK_QUOTED_STRING
|
| TOK_KEY_FSTYPE TOK_EQUALS TOK_QUOTED_STRING
|
||||||
{ ret_record->fs_type = $3; }
|
{ ret_record->fs_type = $3; }
|
||||||
| TOK_KEY_FLAGS TOK_EQUALS TOK_QUOTED_STRING
|
| TOK_KEY_FLAGS TOK_EQUALS TOK_QUOTED_STRING
|
||||||
{ ret_record->flags = $3; }
|
{ ret_record->flags = $3; }
|
||||||
| TOK_KEY_SRCNAME TOK_EQUALS TOK_QUOTED_STRING
|
| TOK_KEY_SRCNAME TOK_EQUALS TOK_QUOTED_STRING
|
||||||
{ ret_record->src_name = $3; }
|
{ ret_record->src_name = $3; }
|
||||||
| TOK_KEY_EXECPATH TOK_EQUALS TOK_QUOTED_STRING
|
|
||||||
{ ret_record->execpath = $3; }
|
|
||||||
| TOK_MSG_REST
|
| TOK_MSG_REST
|
||||||
{
|
{
|
||||||
ret_record->event = AA_RECORD_INVALID;
|
ret_record->event = AA_RECORD_INVALID;
|
||||||
ret_record->info = $1;
|
ret_record->info = $1;
|
||||||
}
|
}
|
||||||
| TOK_KEY_CLASS TOK_EQUALS TOK_QUOTED_STRING
|
| TOK_KEY_CLASS TOK_EQUALS TOK_QUOTED_STRING
|
||||||
{ ret_record->rule_class = $3; }
|
{ ret_record->class = $3; }
|
||||||
;
|
;
|
||||||
|
|
||||||
apparmor_event:
|
apparmor_event:
|
||||||
@@ -475,3 +470,31 @@ protocol: TOK_QUOTED_STRING
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
%%
|
%%
|
||||||
|
|
||||||
|
aa_log_record *
|
||||||
|
_parse_yacc(char *str)
|
||||||
|
{
|
||||||
|
/* yydebug = 1; */
|
||||||
|
YY_BUFFER_STATE lex_buf;
|
||||||
|
yyscan_t scanner;
|
||||||
|
|
||||||
|
ret_record = NULL;
|
||||||
|
ret_record = malloc(sizeof(aa_log_record));
|
||||||
|
|
||||||
|
_init_log_record(ret_record);
|
||||||
|
|
||||||
|
if (ret_record == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
#if (YYDEBUG != 0)
|
||||||
|
yydebug = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
aalogparse_lex_init(&scanner);
|
||||||
|
lex_buf = aalogparse__scan_string(str, scanner);
|
||||||
|
/* Ignore return value to return an AA_RECORD_INVALID event */
|
||||||
|
(void)aalogparse_parse(scanner);
|
||||||
|
aalogparse__delete_buffer(lex_buf, scanner);
|
||||||
|
aalogparse_lex_destroy(scanner);
|
||||||
|
return ret_record;
|
||||||
|
}
|
||||||
|
@@ -463,7 +463,7 @@ static char *procattr_path(pid_t pid, const char *attr)
|
|||||||
|
|
||||||
static int procattr_open(pid_t tid, const char *attr, int flags)
|
static int procattr_open(pid_t tid, const char *attr, int flags)
|
||||||
{
|
{
|
||||||
autofree char *tmp = NULL;
|
char *tmp;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
tmp = procattr_path(tid, attr);
|
tmp = procattr_path(tid, attr);
|
||||||
@@ -471,7 +471,7 @@ static int procattr_open(pid_t tid, const char *attr, int flags)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
fd = open(tmp, flags);
|
fd = open(tmp, flags);
|
||||||
|
free(tmp);
|
||||||
/* Test is we can fallback to the old interface (this is ugly).
|
/* Test is we can fallback to the old interface (this is ugly).
|
||||||
* If we haven't tried the old interface already
|
* If we haven't tried the old interface already
|
||||||
* proc_attr_base == proc_attr_base_old - no fallback
|
* proc_attr_base == proc_attr_base_old - no fallback
|
||||||
@@ -483,14 +483,11 @@ static int procattr_open(pid_t tid, const char *attr, int flags)
|
|||||||
* old interface where is_enabled() is only successful if
|
* old interface where is_enabled() is only successful if
|
||||||
* the old interface is available to apparmor.
|
* the old interface is available to apparmor.
|
||||||
*/
|
*/
|
||||||
if (fd == -1 && param_check_enabled() != 0 && strncmp(tmp, proc_attr_base_old, strlen(proc_attr_base_old)) != 0) {
|
if (fd == -1 && tmp != proc_attr_base_old && param_check_enabled() != 0) {
|
||||||
free(tmp);
|
if (asprintf(&tmp, proc_attr_base_old, tid, attr) < 0)
|
||||||
if (asprintf(&tmp, proc_attr_base_old, tid, attr) < 0) {
|
|
||||||
/* tmp is undefined, make sure it is null for autofree*/
|
|
||||||
tmp = NULL;
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
fd = open(tmp, flags);
|
fd = open(tmp, flags);
|
||||||
|
free(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
@@ -1358,121 +1355,3 @@ int aa_query_link_path(const char *label, const char *target, const char *link,
|
|||||||
strlen(target), link, strlen(link),
|
strlen(target), link, strlen(link),
|
||||||
allowed, audited);
|
allowed, audited);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int alloc_substring(char ***v, char *s, char *p,
|
|
||||||
size_t max_size, size_t n, bool immutable)
|
|
||||||
{
|
|
||||||
if (max_size) {
|
|
||||||
if (n >= max_size) {
|
|
||||||
errno = E2BIG;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
char ** tmpv;
|
|
||||||
tmpv = (char **) realloc(*v, (n + 1) * sizeof(char *));
|
|
||||||
if (tmpv == NULL) {
|
|
||||||
errno = ENOMEM;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*v = tmpv;
|
|
||||||
}
|
|
||||||
if (immutable) {
|
|
||||||
char *tmp;
|
|
||||||
tmp = (char *) malloc(p - s + 1);
|
|
||||||
if (tmp == NULL) {
|
|
||||||
errno = ENOMEM;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
memcpy(tmp, s, p - s);
|
|
||||||
tmp[p - s] = 0;
|
|
||||||
(*v)[n] = tmp;
|
|
||||||
} else {
|
|
||||||
(*v)[n] = s;
|
|
||||||
if (*p)
|
|
||||||
*p = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* aa_split_overlay_str - split a string into potentially multiple strings
|
|
||||||
* @str: the string to split
|
|
||||||
* @vec: vector to put string pointers into, IF null will be allocated
|
|
||||||
* @max_size: maximum number of ents to put in @vec, IF 0 dynamic
|
|
||||||
* @immutable: true if @str should not be modified.
|
|
||||||
*
|
|
||||||
* Returns: the number of entries in vec on success. -1 on error and errno set.
|
|
||||||
*
|
|
||||||
* Split a comma or colon separated string into substrings.
|
|
||||||
*
|
|
||||||
* IF @vec == NULL
|
|
||||||
* the vec will be dynamically allocated
|
|
||||||
* ELSE
|
|
||||||
* passed in @vec will be used, and NOT updated/extended
|
|
||||||
*
|
|
||||||
* IF @max_size == 0 && @vec == NULL
|
|
||||||
* @vec will be dynamically resized
|
|
||||||
* ELSE
|
|
||||||
* @vec will be fixed at @max_size
|
|
||||||
*
|
|
||||||
* IF @immutable is true
|
|
||||||
* the substrings placed in @vec will be allocated copies.
|
|
||||||
* ELSE
|
|
||||||
* @str will be updated in place and @vec[x] will point into @str
|
|
||||||
*/
|
|
||||||
int aa_split_overlay_str(char *str, char ***vec, size_t max_size, bool immutable)
|
|
||||||
{
|
|
||||||
char *s = str;
|
|
||||||
char *p = str;
|
|
||||||
int rc, n = 0;
|
|
||||||
char **v = *vec;
|
|
||||||
|
|
||||||
if (!*vec) {
|
|
||||||
if (max_size) {
|
|
||||||
v = (char **) malloc(max_size * sizeof(char *));
|
|
||||||
if (v == NULL) {
|
|
||||||
rc = ENOMEM;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (*p) {
|
|
||||||
if (*p == '\\') {
|
|
||||||
if (*(p + 1) != 0)
|
|
||||||
p++;
|
|
||||||
} else if (*p == ',' || *p == ':') {
|
|
||||||
if (p != s) {
|
|
||||||
if (alloc_substring(&v, s, p, max_size, n, immutable) == -1) {
|
|
||||||
rc = errno;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
s = p;
|
|
||||||
} else
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
if (p != s) {
|
|
||||||
if (alloc_substring(&v, s, p, max_size, n, immutable) == -1) {
|
|
||||||
rc = errno;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
|
|
||||||
*vec = v;
|
|
||||||
return n;
|
|
||||||
err:
|
|
||||||
if (immutable) {
|
|
||||||
for (int i = 0; i < n; i++) {
|
|
||||||
free(v[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!*vec)
|
|
||||||
free(v);
|
|
||||||
errno = rc;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
@@ -34,42 +34,13 @@
|
|||||||
#include <aalogparse.h>
|
#include <aalogparse.h>
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
|
||||||
#include "grammar.h"
|
|
||||||
#include "scanner.h"
|
|
||||||
|
|
||||||
/* This is mostly just a wrapper around the code in grammar.y */
|
/* This is mostly just a wrapper around the code in grammar.y */
|
||||||
aa_log_record *parse_record(const char *str)
|
aa_log_record *parse_record(char *str)
|
||||||
{
|
{
|
||||||
YY_BUFFER_STATE lex_buf;
|
|
||||||
yyscan_t scanner;
|
|
||||||
aa_log_record *ret_record;
|
|
||||||
|
|
||||||
if (str == NULL)
|
if (str == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ret_record = malloc(sizeof(aa_log_record));
|
return _parse_yacc(str);
|
||||||
|
|
||||||
_init_log_record(ret_record);
|
|
||||||
|
|
||||||
if (ret_record == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
struct string_buf string_buf = {.buf = NULL, .buf_len = 0, .buf_alloc = 0};
|
|
||||||
|
|
||||||
#if (YYDEBUG != 0)
|
|
||||||
/* Warning: this is still a global even in reentrant parsers */
|
|
||||||
aalogparse_debug = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
aalogparse_lex_init_extra(&string_buf, &scanner);
|
|
||||||
lex_buf = aalogparse__scan_string(str, scanner);
|
|
||||||
/* Ignore return value to return an AA_RECORD_INVALID event */
|
|
||||||
(void)aalogparse_parse(scanner, ret_record);
|
|
||||||
aalogparse__delete_buffer(lex_buf, scanner);
|
|
||||||
aalogparse_lex_destroy(scanner);
|
|
||||||
/* free(NULL) is a no-op */
|
|
||||||
free(string_buf.buf);
|
|
||||||
return ret_record;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_record(aa_log_record *record)
|
void free_record(aa_log_record *record)
|
||||||
@@ -92,8 +63,8 @@ void free_record(aa_log_record *record)
|
|||||||
free(record->name);
|
free(record->name);
|
||||||
if (record->name2 != NULL)
|
if (record->name2 != NULL)
|
||||||
free(record->name2);
|
free(record->name2);
|
||||||
if (record->aa_namespace != NULL)
|
if (record->namespace != NULL)
|
||||||
free(record->aa_namespace);
|
free(record->namespace);
|
||||||
if (record->attribute != NULL)
|
if (record->attribute != NULL)
|
||||||
free(record->attribute);
|
free(record->attribute);
|
||||||
if (record->info != NULL)
|
if (record->info != NULL)
|
||||||
@@ -132,15 +103,8 @@ void free_record(aa_log_record *record)
|
|||||||
free(record->flags);
|
free(record->flags);
|
||||||
if (record->src_name != NULL)
|
if (record->src_name != NULL)
|
||||||
free(record->src_name);
|
free(record->src_name);
|
||||||
if (record->net_addr != NULL)
|
if (record->class != NULL)
|
||||||
free(record->net_addr);
|
free(record->class);
|
||||||
if (record->peer_addr != NULL)
|
|
||||||
free(record->peer_addr);
|
|
||||||
if (record->execpath != NULL)
|
|
||||||
free(record->execpath);
|
|
||||||
|
|
||||||
if (record->rule_class != NULL)
|
|
||||||
free(record->rule_class);
|
|
||||||
|
|
||||||
free(record);
|
free(record);
|
||||||
}
|
}
|
||||||
|
@@ -124,14 +124,6 @@ APPARMOR_3.0 {
|
|||||||
*;
|
*;
|
||||||
} APPARMOR_2.13.1;
|
} APPARMOR_2.13.1;
|
||||||
|
|
||||||
APPARMOR_3.1 {
|
|
||||||
global:
|
|
||||||
aa_features_check;
|
|
||||||
aa_split_overlay_str;
|
|
||||||
local:
|
|
||||||
*;
|
|
||||||
} APPARMOR_3.0;
|
|
||||||
|
|
||||||
PRIVATE {
|
PRIVATE {
|
||||||
global:
|
global:
|
||||||
_aa_is_blacklisted;
|
_aa_is_blacklisted;
|
||||||
|
@@ -19,14 +19,8 @@
|
|||||||
#ifndef __AA_LOG_PARSER_H__
|
#ifndef __AA_LOG_PARSER_H__
|
||||||
#define __AA_LOG_PARSER_H__
|
#define __AA_LOG_PARSER_H__
|
||||||
|
|
||||||
// Internal-only type
|
|
||||||
struct string_buf {
|
|
||||||
char *buf;
|
|
||||||
unsigned int buf_len;
|
|
||||||
unsigned int buf_alloc;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern void _init_log_record(aa_log_record *record);
|
extern void _init_log_record(aa_log_record *record);
|
||||||
|
extern aa_log_record *_parse_yacc(char *str);
|
||||||
extern char *hex_to_string(char *str);
|
extern char *hex_to_string(char *str);
|
||||||
extern char *ipproto_to_string(unsigned int proto);
|
extern char *ipproto_to_string(unsigned int proto);
|
||||||
|
|
||||||
|
@@ -147,6 +147,36 @@ repeat:
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cache_check_features(int dirfd, const char *cache_name,
|
||||||
|
aa_features *features)
|
||||||
|
{
|
||||||
|
aa_features *local_features = NULL;
|
||||||
|
autofree char *name = NULL;
|
||||||
|
bool rc;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
len = asprintf(&name, "%s/%s", cache_name, CACHE_FEATURES_FILE);
|
||||||
|
if (len == -1) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* verify that cache dir .features matches */
|
||||||
|
if (aa_features_new(&local_features, dirfd, name)) {
|
||||||
|
PDEBUG("could not setup new features object for dirfd '%d' '%s'\n", dirfd, name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = aa_features_is_equal(local_features, features);
|
||||||
|
aa_features_unref(local_features);
|
||||||
|
if (!rc) {
|
||||||
|
errno = EEXIST;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int create_cache(aa_policy_cache *policy_cache, aa_features *features)
|
static int create_cache(aa_policy_cache *policy_cache, aa_features *features)
|
||||||
{
|
{
|
||||||
if (aa_policy_cache_remove(policy_cache->dirfd[0], "."))
|
if (aa_policy_cache_remove(policy_cache->dirfd[0], "."))
|
||||||
@@ -164,8 +194,8 @@ static int create_cache(aa_policy_cache *policy_cache, aa_features *features)
|
|||||||
static int init_cache_features(aa_policy_cache *policy_cache,
|
static int init_cache_features(aa_policy_cache *policy_cache,
|
||||||
aa_features *kernel_features, bool create)
|
aa_features *kernel_features, bool create)
|
||||||
{
|
{
|
||||||
if (aa_features_check(policy_cache->dirfd[0], ".",
|
if (cache_check_features(policy_cache->dirfd[0], ".",
|
||||||
kernel_features)) {
|
kernel_features)) {
|
||||||
/* EEXIST must come before ENOENT for short circuit eval */
|
/* EEXIST must come before ENOENT for short circuit eval */
|
||||||
if (!create || errno == EEXIST || errno != ENOENT)
|
if (!create || errno == EEXIST || errno != ENOENT)
|
||||||
return -1;
|
return -1;
|
||||||
@@ -201,13 +231,13 @@ static int cache_miss_cb(int dirfd, const struct dirent *ent, void *arg)
|
|||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (!aa_features_check(dirfd, cache_name, data->features) || errno == ENOENT) {
|
if (!cache_check_features(dirfd, cache_name, data->features) || errno == ENOENT) {
|
||||||
/* found cache dir matching pattern */
|
/* found cache dir matching pattern */
|
||||||
data->cache_name = cache_name;
|
data->cache_name = cache_name;
|
||||||
/* return 1 to stop iteration and signal dir found */
|
/* return 1 to stop iteration and signal dir found */
|
||||||
return 1;
|
return 1;
|
||||||
} else if (errno != EEXIST) {
|
} else if (errno != EEXIST) {
|
||||||
PDEBUG("aa_features_check() failed for dirfd '%d' '%s'\n", dirfd, cache_name);
|
PDEBUG("cache_check_features() failed for dirfd '%d' '%s'\n", dirfd, cache_name);
|
||||||
free(cache_name);
|
free(cache_name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -243,12 +273,12 @@ static int cache_dir_from_path_and_features(char **cache_path,
|
|||||||
if (len == -1)
|
if (len == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (!aa_features_check(dirfd, cache_dir, features) || errno == ENOENT) {
|
if (!cache_check_features(dirfd, cache_dir, features) || errno == ENOENT) {
|
||||||
PDEBUG("cache_dir_from_path_and_features() found '%s'\n", cache_dir);
|
PDEBUG("cache_dir_from_path_and_features() found '%s'\n", cache_dir);
|
||||||
*cache_path = cache_dir;
|
*cache_path = cache_dir;
|
||||||
return 0;
|
return 0;
|
||||||
} else if (errno != EEXIST) {
|
} else if (errno != EEXIST) {
|
||||||
PDEBUG("aa_features_check() failed for dirfd '%d' %s\n", dirfd, cache_dir);
|
PDEBUG("cache_check_features() failed for dirfd '%d' %s\n", dirfd, cache_dir);
|
||||||
free(cache_dir);
|
free(cache_dir);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@@ -19,7 +19,6 @@
|
|||||||
%option nounput
|
%option nounput
|
||||||
%option noyy_top_state
|
%option noyy_top_state
|
||||||
%option reentrant
|
%option reentrant
|
||||||
%option extra-type="struct string_buf*"
|
|
||||||
%option prefix="aalogparse_"
|
%option prefix="aalogparse_"
|
||||||
%option bison-bridge
|
%option bison-bridge
|
||||||
%option header-file="scanner.h"
|
%option header-file="scanner.h"
|
||||||
@@ -35,37 +34,40 @@
|
|||||||
|
|
||||||
#define YY_NO_INPUT
|
#define YY_NO_INPUT
|
||||||
|
|
||||||
void string_buf_reset(struct string_buf* char_buf)
|
unsigned int string_buf_alloc = 0;
|
||||||
|
unsigned int string_buf_len = 0;
|
||||||
|
char *string_buf = NULL;
|
||||||
|
|
||||||
|
void string_buf_reset()
|
||||||
{
|
{
|
||||||
/* rewind buffer to zero, possibly doing initial allocation too */
|
/* rewind buffer to zero, possibly doing initial allocation too */
|
||||||
char_buf->buf_len = 0;
|
string_buf_len = 0;
|
||||||
if (char_buf->buf == NULL) {
|
if (string_buf == NULL) {
|
||||||
char_buf->buf_alloc = 128;
|
string_buf_alloc = 128;
|
||||||
char_buf->buf = malloc(char_buf->buf_alloc);
|
string_buf = malloc(string_buf_alloc);
|
||||||
assert(char_buf->buf != NULL);
|
assert(string_buf != NULL);
|
||||||
}
|
}
|
||||||
/* always start with a valid but empty string */
|
/* always start with a valid but empty string */
|
||||||
char_buf->buf[0] = '\0';
|
string_buf[0] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
void string_buf_append(struct string_buf* char_buf, unsigned int length, char *text)
|
void string_buf_append(unsigned int length, char *text)
|
||||||
{
|
{
|
||||||
unsigned int current_length = char_buf->buf_len;
|
unsigned int current_length = string_buf_len;
|
||||||
|
|
||||||
/* handle calling ..._append before ..._reset */
|
/* handle calling ..._append before ..._reset */
|
||||||
if (char_buf->buf == NULL) string_buf_reset(char_buf);
|
if (string_buf == NULL) string_buf_reset();
|
||||||
|
|
||||||
char_buf->buf_len += length;
|
string_buf_len += length;
|
||||||
/* expand allocation if this append would exceed the allocation */
|
/* expand allocation if this append would exceed the allocation */
|
||||||
while (char_buf->buf_len >= char_buf->buf_alloc) {
|
while (string_buf_len >= string_buf_alloc) {
|
||||||
// TODO: overflow?
|
string_buf_alloc *= 2;
|
||||||
char_buf->buf_alloc *= 2;
|
string_buf = realloc(string_buf, string_buf_alloc);
|
||||||
char_buf->buf = realloc(char_buf->buf, char_buf->buf_alloc);
|
assert(string_buf != NULL);
|
||||||
assert(char_buf->buf != NULL);
|
|
||||||
}
|
}
|
||||||
/* copy and unconditionally terminate */
|
/* copy and unconditionally terminate */
|
||||||
memcpy(char_buf->buf+current_length, text, length);
|
memcpy(string_buf+current_length, text, length);
|
||||||
char_buf->buf[char_buf->buf_len] = '\0';
|
string_buf[string_buf_len] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
%}
|
%}
|
||||||
@@ -88,7 +90,6 @@ question_mark "?"
|
|||||||
single_quote "'"
|
single_quote "'"
|
||||||
mode_chars ([RrWwaLlMmkXx])|([Pp][Xx])|([Uu][Xx])|([Ii][Xx])|([Pp][Ii][Xx])
|
mode_chars ([RrWwaLlMmkXx])|([Pp][Xx])|([Uu][Xx])|([Ii][Xx])|([Pp][Ii][Xx])
|
||||||
modes ({mode_chars}+)|({mode_chars}+::{mode_chars}*)|(::{mode_chars}*)
|
modes ({mode_chars}+)|({mode_chars}+::{mode_chars}*)|(::{mode_chars}*)
|
||||||
none "none"
|
|
||||||
/* New message types */
|
/* New message types */
|
||||||
|
|
||||||
aa_reject_type "APPARMOR_DENIED"
|
aa_reject_type "APPARMOR_DENIED"
|
||||||
@@ -156,13 +157,9 @@ key_capname "capname"
|
|||||||
key_offset "offset"
|
key_offset "offset"
|
||||||
key_target "target"
|
key_target "target"
|
||||||
key_laddr "laddr"
|
key_laddr "laddr"
|
||||||
key_saddr "saddr"
|
|
||||||
key_faddr "faddr"
|
key_faddr "faddr"
|
||||||
key_daddr "daddr"
|
|
||||||
key_lport "lport"
|
key_lport "lport"
|
||||||
key_srcport "src"
|
|
||||||
key_fport "fport"
|
key_fport "fport"
|
||||||
key_destport "dest"
|
|
||||||
key_bus "bus"
|
key_bus "bus"
|
||||||
key_dest "dest"
|
key_dest "dest"
|
||||||
key_path "path"
|
key_path "path"
|
||||||
@@ -175,9 +172,6 @@ key_fstype "fstype"
|
|||||||
key_flags "flags"
|
key_flags "flags"
|
||||||
key_srcname "srcname"
|
key_srcname "srcname"
|
||||||
key_class "class"
|
key_class "class"
|
||||||
key_tcontext "tcontext"
|
|
||||||
key_unix_peer_addr "peer_addr"
|
|
||||||
key_execpath "execpath"
|
|
||||||
audit "audit"
|
audit "audit"
|
||||||
|
|
||||||
/* network addrs */
|
/* network addrs */
|
||||||
@@ -230,7 +224,7 @@ yy_flex_debug = 0;
|
|||||||
{open_paren} { return(TOK_OPEN_PAREN); }
|
{open_paren} { return(TOK_OPEN_PAREN); }
|
||||||
{close_paren} { BEGIN(INITIAL); return(TOK_CLOSE_PAREN); }
|
{close_paren} { BEGIN(INITIAL); return(TOK_CLOSE_PAREN); }
|
||||||
{ws} { }
|
{ws} { }
|
||||||
\" { string_buf_reset(yyextra); BEGIN(quoted_string); }
|
\" { string_buf_reset(); BEGIN(quoted_string); }
|
||||||
{ID}+ {
|
{ID}+ {
|
||||||
yylval->t_str = strdup(yytext);
|
yylval->t_str = strdup(yytext);
|
||||||
BEGIN(INITIAL);
|
BEGIN(INITIAL);
|
||||||
@@ -239,20 +233,20 @@ yy_flex_debug = 0;
|
|||||||
{equals} { return(TOK_EQUALS); }
|
{equals} { return(TOK_EQUALS); }
|
||||||
}
|
}
|
||||||
|
|
||||||
\" { string_buf_reset(yyextra); BEGIN(quoted_string); }
|
\" { string_buf_reset(); BEGIN(quoted_string); }
|
||||||
<quoted_string>\" { /* End of the quoted string */
|
<quoted_string>\" { /* End of the quoted string */
|
||||||
BEGIN(INITIAL);
|
BEGIN(INITIAL);
|
||||||
yylval->t_str = strdup(yyextra->buf);
|
yylval->t_str = strdup(string_buf);
|
||||||
return(TOK_QUOTED_STRING);
|
return(TOK_QUOTED_STRING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
<quoted_string>\\(.|\n) { string_buf_append(yyextra, 1, &yytext[1]); }
|
<quoted_string>\\(.|\n) { string_buf_append(1, &yytext[1]); }
|
||||||
|
|
||||||
<quoted_string>[^\\\n\"]+ { string_buf_append(yyextra, yyleng, yytext); }
|
<quoted_string>[^\\\n\"]+ { string_buf_append(yyleng, yytext); }
|
||||||
|
|
||||||
<safe_string>{
|
<safe_string>{
|
||||||
\" { string_buf_reset(yyextra); BEGIN(quoted_string); }
|
\" { string_buf_reset(); BEGIN(quoted_string); }
|
||||||
{hexstring} { yylval->t_str = hex_to_string(yytext); BEGIN(INITIAL); return(TOK_HEXSTRING);}
|
{hexstring} { yylval->t_str = hex_to_string(yytext); BEGIN(INITIAL); return(TOK_HEXSTRING);}
|
||||||
{equals} { return(TOK_EQUALS); }
|
{equals} { return(TOK_EQUALS); }
|
||||||
. { /* eek, error! try another state */ BEGIN(INITIAL); yyless(0); }
|
. { /* eek, error! try another state */ BEGIN(INITIAL); yyless(0); }
|
||||||
@@ -308,8 +302,6 @@ yy_flex_debug = 0;
|
|||||||
{period} { return(TOK_PERIOD); }
|
{period} { return(TOK_PERIOD); }
|
||||||
{question_mark} { return(TOK_QUESTION_MARK); }
|
{question_mark} { return(TOK_QUESTION_MARK); }
|
||||||
{single_quote} { return(TOK_SINGLE_QUOTE); }
|
{single_quote} { return(TOK_SINGLE_QUOTE); }
|
||||||
{none} { return(TOK_NONE); }
|
|
||||||
|
|
||||||
|
|
||||||
{key_apparmor} { BEGIN(audit_types); return(TOK_KEY_APPARMOR); }
|
{key_apparmor} { BEGIN(audit_types); return(TOK_KEY_APPARMOR); }
|
||||||
{key_type} { BEGIN(audit_types); return(TOK_KEY_TYPE); }
|
{key_type} { BEGIN(audit_types); return(TOK_KEY_TYPE); }
|
||||||
@@ -335,7 +327,6 @@ yy_flex_debug = 0;
|
|||||||
{key_peer_profile} { BEGIN(safe_string); return(TOK_KEY_PEER_PROFILE); }
|
{key_peer_profile} { BEGIN(safe_string); return(TOK_KEY_PEER_PROFILE); }
|
||||||
{key_label} { BEGIN(safe_string); return(TOK_KEY_LABEL); }
|
{key_label} { BEGIN(safe_string); return(TOK_KEY_LABEL); }
|
||||||
{key_peer_label} { BEGIN(safe_string); return(TOK_KEY_PEER_LABEL); }
|
{key_peer_label} { BEGIN(safe_string); return(TOK_KEY_PEER_LABEL); }
|
||||||
{key_tcontext} { BEGIN(safe_string); return(TOK_KEY_PEER_LABEL); }
|
|
||||||
{key_family} { return(TOK_KEY_FAMILY); }
|
{key_family} { return(TOK_KEY_FAMILY); }
|
||||||
{key_sock_type} { return(TOK_KEY_SOCK_TYPE); }
|
{key_sock_type} { return(TOK_KEY_SOCK_TYPE); }
|
||||||
{key_protocol} { return(TOK_KEY_PROTOCOL); }
|
{key_protocol} { return(TOK_KEY_PROTOCOL); }
|
||||||
@@ -349,7 +340,7 @@ yy_flex_debug = 0;
|
|||||||
{key_sauid} { return(TOK_KEY_SAUID); }
|
{key_sauid} { return(TOK_KEY_SAUID); }
|
||||||
{key_ses} { return(TOK_KEY_SES); }
|
{key_ses} { return(TOK_KEY_SES); }
|
||||||
{key_hostname} { return(TOK_KEY_HOSTNAME); }
|
{key_hostname} { return(TOK_KEY_HOSTNAME); }
|
||||||
{key_addr} { BEGIN(safe_string); return(TOK_KEY_ADDR); }
|
{key_addr} { return(TOK_KEY_ADDR); }
|
||||||
{key_terminal} { return(TOK_KEY_TERMINAL); }
|
{key_terminal} { return(TOK_KEY_TERMINAL); }
|
||||||
{key_exe} { BEGIN(safe_string); return(TOK_KEY_EXE); }
|
{key_exe} { BEGIN(safe_string); return(TOK_KEY_EXE); }
|
||||||
{key_comm} { BEGIN(safe_string); return(TOK_KEY_COMM); }
|
{key_comm} { BEGIN(safe_string); return(TOK_KEY_COMM); }
|
||||||
@@ -358,13 +349,9 @@ yy_flex_debug = 0;
|
|||||||
{key_offset} { return(TOK_KEY_OFFSET); }
|
{key_offset} { return(TOK_KEY_OFFSET); }
|
||||||
{key_target} { return(TOK_KEY_TARGET); }
|
{key_target} { return(TOK_KEY_TARGET); }
|
||||||
{key_laddr} { yy_push_state(ip_addr, yyscanner); return(TOK_KEY_LADDR); }
|
{key_laddr} { yy_push_state(ip_addr, yyscanner); return(TOK_KEY_LADDR); }
|
||||||
{key_saddr} { yy_push_state(ip_addr, yyscanner); return(TOK_KEY_LADDR); }
|
|
||||||
{key_faddr} { yy_push_state(ip_addr, yyscanner); return(TOK_KEY_FADDR); }
|
{key_faddr} { yy_push_state(ip_addr, yyscanner); return(TOK_KEY_FADDR); }
|
||||||
{key_daddr} { yy_push_state(ip_addr, yyscanner); return(TOK_KEY_FADDR); }
|
|
||||||
{key_lport} { return(TOK_KEY_LPORT); }
|
{key_lport} { return(TOK_KEY_LPORT); }
|
||||||
{key_srcport} { return(TOK_KEY_LPORT); }
|
|
||||||
{key_fport} { return(TOK_KEY_FPORT); }
|
{key_fport} { return(TOK_KEY_FPORT); }
|
||||||
{key_destport} { return(TOK_KEY_FPORT); }
|
|
||||||
{key_bus} { return(TOK_KEY_BUS); }
|
{key_bus} { return(TOK_KEY_BUS); }
|
||||||
{key_path} { return(TOK_KEY_PATH); }
|
{key_path} { return(TOK_KEY_PATH); }
|
||||||
{key_interface} { return(TOK_KEY_INTERFACE); }
|
{key_interface} { return(TOK_KEY_INTERFACE); }
|
||||||
@@ -375,8 +362,6 @@ yy_flex_debug = 0;
|
|||||||
{key_fstype} { return(TOK_KEY_FSTYPE); }
|
{key_fstype} { return(TOK_KEY_FSTYPE); }
|
||||||
{key_flags} { BEGIN(safe_string); return(TOK_KEY_FLAGS); }
|
{key_flags} { BEGIN(safe_string); return(TOK_KEY_FLAGS); }
|
||||||
{key_srcname} { BEGIN(safe_string); return(TOK_KEY_SRCNAME); }
|
{key_srcname} { BEGIN(safe_string); return(TOK_KEY_SRCNAME); }
|
||||||
{key_unix_peer_addr} { BEGIN(safe_string); return(TOK_KEY_UNIX_PEER_ADDR); }
|
|
||||||
{key_execpath} { BEGIN(safe_string); return(TOK_KEY_EXECPATH); }
|
|
||||||
{key_class} { BEGIN(safe_string); return(TOK_KEY_CLASS); }
|
{key_class} { BEGIN(safe_string); return(TOK_KEY_CLASS); }
|
||||||
|
|
||||||
{socklogd_kernel} { BEGIN(dmesg_timestamp); return(TOK_SOCKLOGD_KERNEL); }
|
{socklogd_kernel} { BEGIN(dmesg_timestamp); return(TOK_SOCKLOGD_KERNEL); }
|
||||||
|
@@ -1,20 +0,0 @@
|
|||||||
#include <aalogparse.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "private.h"
|
|
||||||
|
|
||||||
const char* log_line = "[23342.075380] audit: type=1400 audit(1725487203.971:1831): apparmor=\"DENIED\" operation=\"open\" class=\"file\" profile=\"snap-update-ns.firmware-updater\" name=\"/proc/202964/maps\" pid=202964 comm=\"5\" requested_mask=\"r\" denied_mask=\"r\" fsuid=1000 ouid=0";
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
/* Very basic test to ensure we can do aalogparse stuff in C++ */
|
|
||||||
aa_log_record *record = parse_record(log_line);
|
|
||||||
MY_TEST(record != NULL, "Log failed to parse");
|
|
||||||
MY_TEST(record->version == AA_RECORD_SYNTAX_V2, "Log should have parsed as v2 form");
|
|
||||||
MY_TEST(record->aa_namespace == NULL, "Log should have NULL namespace");
|
|
||||||
MY_TEST((record->rule_class != NULL) && (strcmp(record->rule_class, "file") == 0), "Log should have file class");
|
|
||||||
free_record(record);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
@@ -1,20 +0,0 @@
|
|||||||
#include <aalogparse.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "private.h"
|
|
||||||
|
|
||||||
const char* log_line = "[23342.075380] audit: type=1400 audit(1725487203.971:1831): apparmor=\"DENIED\" operation=\"open\" class=\"file\" profile=\"snap-update-ns.firmware-updater\" name=\"/proc/202964/maps\" pid=202964 comm=\"5\" requested_mask=\"r\" denied_mask=\"r\" fsuid=1000 ouid=0";
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
/* Very basic test to ensure we can use the C++-incompatible field names */
|
|
||||||
aa_log_record *record = parse_record(log_line);
|
|
||||||
MY_TEST(record != NULL, "Log failed to parse");
|
|
||||||
MY_TEST(record->version == AA_RECORD_SYNTAX_V2, "Log should have parsed as v2 form");
|
|
||||||
MY_TEST(record->namespace == NULL, "Log should have NULL namespace");
|
|
||||||
MY_TEST((record->class != NULL) && (strcmp(record->class, "file") == 0), "Log should have file class");
|
|
||||||
free_record(record);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
@@ -1,154 +0,0 @@
|
|||||||
#include <pthread.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <aalogparse.h>
|
|
||||||
|
|
||||||
#include "private.h"
|
|
||||||
|
|
||||||
const char* log_line = "[23342.075380] audit: type=1400 audit(1725487203.971:1831): apparmor=\"DENIED\" operation=\"open\" class=\"file\" profile=\"snap-update-ns.firmware-updater\" name=\"/proc/202964/maps\" pid=202964 comm=\"5\" requested_mask=\"r\" denied_mask=\"r\" fsuid=1000 ouid=0";
|
|
||||||
const char* log_line_2 = "[ 4074.372559] audit: type=1400 audit(1725553393.143:793): apparmor=\"DENIED\" operation=\"capable\" class=\"cap\" profile=\"/usr/lib/snapd/snap-confine\" pid=19034 comm=\"snap-confine\" capability=12 capname=\"net_admin\"";
|
|
||||||
|
|
||||||
static int pthread_barrier_ok(int barrier_result) {
|
|
||||||
return barrier_result == 0 || barrier_result == PTHREAD_BARRIER_SERIAL_THREAD;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int nullcmp_and_strcmp(const void *s1, const void *s2)
|
|
||||||
{
|
|
||||||
/* Return 0 if both pointers are NULL & non-zero if only one is NULL */
|
|
||||||
if (!s1 || !s2)
|
|
||||||
return s1 != s2;
|
|
||||||
|
|
||||||
return strcmp(s1, s2);
|
|
||||||
}
|
|
||||||
|
|
||||||
int aa_log_record_eq(aa_log_record *record1, aa_log_record *record2) {
|
|
||||||
int are_eq = 1;
|
|
||||||
|
|
||||||
are_eq &= (record1->version == record2->version);
|
|
||||||
are_eq &= (record1->event == record2->event);
|
|
||||||
are_eq &= (record1->pid == record2->pid);
|
|
||||||
are_eq &= (record1->peer_pid == record2->peer_pid);
|
|
||||||
are_eq &= (record1->task == record2->task);
|
|
||||||
are_eq &= (record1->magic_token == record2->magic_token);
|
|
||||||
are_eq &= (record1->epoch == record2->epoch);
|
|
||||||
are_eq &= (record1->audit_sub_id == record2->audit_sub_id);
|
|
||||||
|
|
||||||
are_eq &= (record1->bitmask == record2->bitmask);
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->audit_id, record2->audit_id) == 0);
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->operation, record2->operation) == 0);
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->denied_mask, record2->denied_mask) == 0);
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->requested_mask, record2->requested_mask) == 0);
|
|
||||||
are_eq &= (record1->fsuid == record2->fsuid);
|
|
||||||
are_eq &= (record1->ouid == record2->ouid);
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->profile, record2->profile) == 0);
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->peer_profile, record2->peer_profile) == 0);
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->comm, record2->comm) == 0);
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->name, record2->name) == 0);
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->name2, record2->name2) == 0);
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->namespace, record2->namespace) == 0);
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->attribute, record2->attribute) == 0);
|
|
||||||
are_eq &= (record1->parent == record2->parent);
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->info, record2->info) == 0);
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->peer_info, record2->peer_info) == 0);
|
|
||||||
are_eq &= (record1->error_code == record2->error_code);
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->active_hat, record2->active_hat) == 0);
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->net_family, record2->net_family) == 0);
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->net_protocol, record2->net_protocol) == 0);
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->net_sock_type, record2->net_sock_type) == 0);
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->net_local_addr, record2->net_local_addr) == 0);
|
|
||||||
are_eq &= (record1->net_local_port == record2->net_local_port);
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->net_foreign_addr, record2->net_foreign_addr) == 0);
|
|
||||||
are_eq &= (record1->net_foreign_port == record2->net_foreign_port);
|
|
||||||
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->execpath, record2->execpath) == 0);
|
|
||||||
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->dbus_bus, record2->dbus_bus) == 0);
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->dbus_path, record2->dbus_path) == 0);
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->dbus_interface, record2->dbus_interface) == 0);
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->dbus_member, record2->dbus_member) == 0);
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->signal, record2->signal) == 0);
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->peer, record2->peer) == 0);
|
|
||||||
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->fs_type, record2->fs_type) == 0);
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->flags, record2->flags) == 0);
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->src_name, record2->src_name) == 0);
|
|
||||||
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->class, record2->class) == 0);
|
|
||||||
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->net_addr, record2->net_addr) == 0);
|
|
||||||
are_eq &= (nullcmp_and_strcmp(record1->peer_addr, record2->peer_addr) == 0);
|
|
||||||
return are_eq;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const char* log;
|
|
||||||
pthread_barrier_t *barrier;
|
|
||||||
} pthread_parse_args;
|
|
||||||
|
|
||||||
void* pthread_parse_log(void* args) {
|
|
||||||
pthread_parse_args *args_real = (pthread_parse_args *) args;
|
|
||||||
int barrier_wait_result = pthread_barrier_wait(args_real->barrier);
|
|
||||||
/* Return NULL and fail test if barrier wait fails */
|
|
||||||
if (!pthread_barrier_ok(barrier_wait_result)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
aa_log_record *record = parse_record(args_real->log);
|
|
||||||
return (void*) record;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define NUM_THREADS 16
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
pthread_t thread_ids[NUM_THREADS];
|
|
||||||
pthread_barrier_t barrier;
|
|
||||||
int barrier_wait_result;
|
|
||||||
aa_log_record* parsed_logs[NUM_THREADS];
|
|
||||||
int rc = 0;
|
|
||||||
/* Set up arguments to be passed to threads */
|
|
||||||
pthread_parse_args args = {.log=log_line, .barrier=&barrier};
|
|
||||||
pthread_parse_args args2 = {.log=log_line_2, .barrier=&barrier};
|
|
||||||
|
|
||||||
MY_TEST(NUM_THREADS > 2, "Test requires more than 2 threads");
|
|
||||||
|
|
||||||
/* Use barrier to synchronize the start of log parsing among all the threads
|
|
||||||
* This increases the likelihood of tickling race conditions, if there are any
|
|
||||||
*/
|
|
||||||
MY_TEST(pthread_barrier_init(&barrier, NULL, NUM_THREADS+1) == 0,
|
|
||||||
"Could not init pthread barrier");
|
|
||||||
for (int i=0; i<NUM_THREADS; i++) {
|
|
||||||
if (i%2 == 0) {
|
|
||||||
pthread_create(&thread_ids[i], NULL, pthread_parse_log, (void *) &args);
|
|
||||||
} else {
|
|
||||||
pthread_create(&thread_ids[i], NULL, pthread_parse_log, (void *) &args2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Final barrier_wait to set off the thread race */
|
|
||||||
barrier_wait_result = pthread_barrier_wait(&barrier);
|
|
||||||
MY_TEST(pthread_barrier_ok(barrier_wait_result), "Could not wait on pthread barrier");
|
|
||||||
|
|
||||||
/* Wait for threads to finish parsing the logs */
|
|
||||||
for (int i=0; i<NUM_THREADS; i++) {
|
|
||||||
MY_TEST(pthread_join(thread_ids[i], (void*) &parsed_logs[i]) == 0, "Could not join thread");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check that all logs parsed and are equal */
|
|
||||||
for (int i=0; i<NUM_THREADS; i++) {
|
|
||||||
MY_TEST(parsed_logs[i] != NULL, "Log failed to parse");
|
|
||||||
MY_TEST(parsed_logs[i]->version == AA_RECORD_SYNTAX_V2, "Log should have parsed as v2 form");
|
|
||||||
MY_TEST(parsed_logs[i]->event == AA_RECORD_DENIED, "Log should have parsed as denied");
|
|
||||||
|
|
||||||
/* Also check i==0 and i==1 as a sanity check for aa_log_record_eq */
|
|
||||||
if (i%2 == 0) {
|
|
||||||
MY_TEST(aa_log_record_eq(parsed_logs[0], parsed_logs[i]), "Log 0 != Log even");
|
|
||||||
} else {
|
|
||||||
MY_TEST(aa_log_record_eq(parsed_logs[1], parsed_logs[i]), "Log 1 != Log odd");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MY_TEST(!aa_log_record_eq(parsed_logs[0], parsed_logs[1]), "Log 0 and log 1 shouldn't be equal");
|
|
||||||
/* Clean up */
|
|
||||||
MY_TEST(pthread_barrier_destroy(&barrier) == 0, "Could not destroy pthread barrier");
|
|
||||||
for (int i=0; i<NUM_THREADS; i++) {
|
|
||||||
free_record(parsed_logs[i]);
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
@@ -135,7 +135,7 @@ static int do_test_walk_one(const char **str, const struct component *component,
|
|||||||
|
|
||||||
static int test_walk_one(void)
|
static int test_walk_one(void)
|
||||||
{
|
{
|
||||||
struct component c = (struct component) { NULL, 0 };
|
struct component c;
|
||||||
const char *str;
|
const char *str;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
|
@@ -5,98 +5,9 @@
|
|||||||
#include <sys/apparmor.h>
|
#include <sys/apparmor.h>
|
||||||
#include <sys/apparmor_private.h>
|
#include <sys/apparmor_private.h>
|
||||||
|
|
||||||
// Include static_assert if the C compiler supports it
|
|
||||||
// static_assert standardized since C11, assert.h not needed since C23
|
|
||||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && __STDC_VERSION__ < 202311L
|
|
||||||
#include <assert.h>
|
|
||||||
#endif
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%include "typemaps.i"
|
%include "typemaps.i"
|
||||||
%include <cstring.i>
|
|
||||||
%include <stdint.i>
|
|
||||||
%include <exception.i>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* SWIG 4.3 included https://github.com/swig/swig/pull/2907 to distinguish
|
|
||||||
* between Py_None being returned as a default void and Py_None being returned
|
|
||||||
* as the equivalent of C NULL. Unfortunately, this turns into an API breaking
|
|
||||||
* change with our use of %append_output when we want the Python function to
|
|
||||||
* return something even when the C function has a void return type. Thus, we
|
|
||||||
* need an additional macro to smooth over the differences. Include all affected
|
|
||||||
* languages, even ones we don't build bindings for, for completeness.
|
|
||||||
*/
|
|
||||||
#if SWIG_VERSION >= 0x040300
|
|
||||||
#ifdef SWIGPYTHON
|
|
||||||
#define ISVOID_APPEND_OUTPUT(value) {$result = SWIG_Python_AppendOutput($result, value, 1);}
|
|
||||||
#elif defined(SWIGRUBY)
|
|
||||||
#define ISVOID_APPEND_OUTPUT(value) {$result = SWIG_Ruby_AppendOutput($result, value, 1);}
|
|
||||||
#elif defined(SWIGPHP)
|
|
||||||
#define ISVOID_APPEND_OUTPUT(value) {$result = SWIG_Php_AppendOutput($result, value, 1);}
|
|
||||||
#else
|
|
||||||
#define ISVOID_APPEND_OUTPUT(value) %append_output(value)
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#define ISVOID_APPEND_OUTPUT(value) %append_output(value)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
%newobject parse_record;
|
|
||||||
%delobject free_record;
|
|
||||||
/*
|
|
||||||
* Despite its name, %delobject does not hook up destructors to language
|
|
||||||
* deletion mechanisms. Instead, it sets flags so that manually calling the
|
|
||||||
* free function and then deleting by language mechanisms doesn't cause a
|
|
||||||
* double-free.
|
|
||||||
*
|
|
||||||
* Additionally, we can manually extend the struct with a C++-like
|
|
||||||
* destructor. This ensures that the record struct is freed
|
|
||||||
* automatically when the high-level object goes out of scope.
|
|
||||||
*/
|
|
||||||
%extend aa_log_record {
|
|
||||||
~aa_log_record() {
|
|
||||||
free_record($self);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Generate a no-op free_record wrapper to avoid making a double-free footgun.
|
|
||||||
* Use rename directive to avoid colliding with the actual free_record, which
|
|
||||||
* we use above to clean up when the higher-level language deletes the object.
|
|
||||||
*
|
|
||||||
* Ideally we would not expose a free_record at all, but we need to maintain
|
|
||||||
* backwards compatibility with the existing high-level code that uses it.
|
|
||||||
*/
|
|
||||||
%rename(free_record) noop_free_record;
|
|
||||||
#ifdef SWIGPYTHON
|
|
||||||
%pythonprepend noop_free_record %{
|
|
||||||
import warnings
|
|
||||||
warnings.warn("free_record is now a no-op as the record's memory is handled automatically", DeprecationWarning)
|
|
||||||
%}
|
|
||||||
#endif
|
|
||||||
%feature("autodoc",
|
|
||||||
"This function used to free aa_log_record objects. Freeing is now handled "
|
|
||||||
"automatically, so this no-op function remains for backwards compatibility.") noop_free_record;
|
|
||||||
%inline %{
|
|
||||||
void noop_free_record(aa_log_record *record) {(void) record;}
|
|
||||||
%}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Do not autogenerate a wrapper around free_record. This does not prevent us
|
|
||||||
* from calling it ourselves in %extend C code.
|
|
||||||
*/
|
|
||||||
%ignore free_record;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Map names to preserve backwards compatibility
|
|
||||||
*/
|
|
||||||
#ifdef SWIGPYTHON
|
|
||||||
%rename("_class") aa_log_record::rule_class;
|
|
||||||
#else
|
|
||||||
%rename("class") aa_log_record::rule_class;
|
|
||||||
#endif
|
|
||||||
%rename("namespace") aa_log_record::aa_namespace;
|
|
||||||
|
|
||||||
%include <aalogparse.h>
|
%include <aalogparse.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -110,75 +21,18 @@ warnings.warn("free_record is now a no-op as the record's memory is handled auto
|
|||||||
|
|
||||||
/* apparmor.h */
|
/* apparmor.h */
|
||||||
|
|
||||||
/*
|
|
||||||
* label is a heap-allocated pointer, but when label and mode occur together,
|
|
||||||
* the freeing of label must be deferred because mode points into label.
|
|
||||||
*
|
|
||||||
* %cstring_output_allocate((char **label, char **mode), free(*$1))
|
|
||||||
* does not handle multi-argument typemaps correctly, so we write our own
|
|
||||||
* typemap based on it instead.
|
|
||||||
*/
|
|
||||||
%typemap(in,noblock=1,numinputs=0) (char **label, char **mode) ($*1_ltype temp_label = 0, $*2_ltype temp_mode = 0) {
|
|
||||||
$1 = &temp_label;
|
|
||||||
$2 = &temp_mode;
|
|
||||||
}
|
|
||||||
%typemap(freearg,match="in") (char **label, char **mode) ""
|
|
||||||
%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") (char **label, char **mode) {
|
|
||||||
ISVOID_APPEND_OUTPUT(SWIG_FromCharPtr(*$1));
|
|
||||||
ISVOID_APPEND_OUTPUT(SWIG_FromCharPtr(*$2));
|
|
||||||
free(*$1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* mode also occurs in combination with con in aa_splitcon
|
|
||||||
* typemap based on %cstring_mutable but with substantial modifications
|
|
||||||
*/
|
|
||||||
%typemap(in,numinputs=1,fragment="SWIG_AsCharPtrAndSize") (char *con, char **mode) ($*2_ltype temp_mode = 0) {
|
|
||||||
int alloc_status = 0;
|
|
||||||
$1_ltype con_ptr = NULL;
|
|
||||||
size_t con_len = 0;
|
|
||||||
int char_ptr_res = SWIG_AsCharPtrAndSize($input, &con_ptr, &con_len, &alloc_status);
|
|
||||||
if (!SWIG_IsOK(char_ptr_res)) {
|
|
||||||
%argument_fail(char_ptr_res, "char *con", $symname, $argnum);
|
|
||||||
}
|
|
||||||
if (alloc_status != SWIG_NEWOBJ) {
|
|
||||||
// Unconditionally copy because the C function modifies the string in place
|
|
||||||
$1 = %new_copy_array(con_ptr, con_len+1, char);
|
|
||||||
} else {
|
|
||||||
$1 = con_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
$2 = &temp_mode;
|
|
||||||
}
|
|
||||||
%typemap(freearg,noblock=1,match="in") (char *con, char **mode) {
|
|
||||||
%delete_array($1);
|
|
||||||
}
|
|
||||||
%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") (char *con, char **mode) {
|
|
||||||
/*
|
|
||||||
* aa_splitcon returns either con or NULL so we don't need to explicitly
|
|
||||||
* append it to the output, and we don't need the ISVOID helper here
|
|
||||||
*
|
|
||||||
* SWIG_FromCharPtr does NULL checks for us
|
|
||||||
*/
|
|
||||||
%append_output(SWIG_FromCharPtr(*$2));
|
|
||||||
}
|
|
||||||
|
|
||||||
%exception aa_splitcon {
|
|
||||||
$action
|
|
||||||
if (result == NULL) {
|
|
||||||
SWIG_exception_fail(SWIG_ValueError, "received invalid confinement context");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extern char *aa_splitcon(char *con, char **mode);
|
extern char *aa_splitcon(char *con, char **mode);
|
||||||
|
|
||||||
|
/* apparmor_private.h */
|
||||||
|
|
||||||
|
extern int _aa_is_blacklisted(const char *name);
|
||||||
|
|
||||||
#ifdef SWIGPYTHON
|
#ifdef SWIGPYTHON
|
||||||
%exception {
|
%exception {
|
||||||
$action
|
$action
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
// Unfortunately SWIG_exception does not support OSError
|
|
||||||
PyErr_SetFromErrno(PyExc_OSError);
|
PyErr_SetFromErrno(PyExc_OSError);
|
||||||
SWIG_fail;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -187,248 +41,33 @@ extern char *aa_splitcon(char *con, char **mode);
|
|||||||
|
|
||||||
/* apparmor.h */
|
/* apparmor.h */
|
||||||
|
|
||||||
/*
|
|
||||||
* aa_is_enabled returns a boolean as an int with failure reason in errno
|
|
||||||
* Therefore, aa_is_enabled either returns True or throws an exception
|
|
||||||
*
|
|
||||||
* Keep that behavior for backwards compatibilty but return a boolean on Python
|
|
||||||
* where it makes more sense, which isn't a breaking change because a boolean is
|
|
||||||
* a subclass of int
|
|
||||||
*/
|
|
||||||
#ifdef SWIGPYTHON
|
|
||||||
%typemap(out) int {
|
|
||||||
$result = PyBool_FromLong($1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
extern int aa_is_enabled(void);
|
extern int aa_is_enabled(void);
|
||||||
|
extern int aa_find_mountpoint(char **mnt);
|
||||||
#ifdef SWIGPYTHON
|
|
||||||
// Based on SWIG's argcargv.i but we don't have an argc
|
|
||||||
%typemap(in,fragment="SWIG_AsCharPtr") const char *subprofiles[] (Py_ssize_t seq_len=0, int* alloc_tracking = NULL) {
|
|
||||||
void* arg_as_ptr = NULL;
|
|
||||||
int res_convertptr = SWIG_ConvertPtr($input, &arg_as_ptr, $descriptor(char*[]), 0);
|
|
||||||
if (SWIG_IsOK(res_convertptr)) {
|
|
||||||
$1 = %static_cast(arg_as_ptr, $1_ltype);
|
|
||||||
} else {
|
|
||||||
// Clear error that would be set if ptr conversion failed
|
|
||||||
PyErr_Clear();
|
|
||||||
|
|
||||||
int is_list = PyList_Check($input);
|
|
||||||
if (is_list || PyTuple_Check($input)) {
|
|
||||||
seq_len = PySequence_Length($input);
|
|
||||||
/*
|
|
||||||
* %new_array zero-inits for cleaner error handling and memory cleanup
|
|
||||||
* %delete_array(NULL) is no-op (either free or delete), and
|
|
||||||
* alloc_tracking of 0 is uninit
|
|
||||||
*
|
|
||||||
* Further note: SWIG_exception_fail jumps to the freearg typemap
|
|
||||||
*/
|
|
||||||
$1 = %new_array(seq_len+1, char *);
|
|
||||||
if ($1 == NULL) {
|
|
||||||
SWIG_exception_fail(SWIG_MemoryError, "could not allocate C subprofiles");
|
|
||||||
}
|
|
||||||
|
|
||||||
alloc_tracking = %new_array(seq_len, int);
|
|
||||||
if (alloc_tracking == NULL) {
|
|
||||||
SWIG_exception_fail(SWIG_MemoryError, "could not allocate C alloc track arr");
|
|
||||||
}
|
|
||||||
for (Py_ssize_t i=0; i<seq_len; i++) {
|
|
||||||
PyObject *o = is_list ? PyList_GetItem($input, i) : PyTuple_GetItem($input, i);
|
|
||||||
if (o == NULL) {
|
|
||||||
// Failed to get item-Python already set exception info
|
|
||||||
SWIG_fail;
|
|
||||||
} else if (o == Py_None) {
|
|
||||||
// SWIG_AsCharPtr(Py_None, ...) succeeds with ptr output being NULL
|
|
||||||
SWIG_exception_fail(SWIG_ValueError, "sequence contains a None object");
|
|
||||||
}
|
|
||||||
int res = SWIG_AsCharPtr(o, &$1[i], &alloc_tracking[i]);
|
|
||||||
if (!SWIG_IsOK(res)) {
|
|
||||||
// Could emit idx of error here, maybe?
|
|
||||||
SWIG_exception_fail(SWIG_ArgError(res), "sequence does not contain all strings");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
SWIG_exception_fail(SWIG_TypeError, "subprofiles is not a list or tuple");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
%typemap(freearg,noblock=1) const char *subprofiles[] {
|
|
||||||
/*
|
|
||||||
* If static_assert is present, use it to verify the assumption that
|
|
||||||
* allocation uninitialized (0) != SWIG_NEWOBJ
|
|
||||||
*/
|
|
||||||
%#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
|
|
||||||
/*
|
|
||||||
* Some older versions of SWIG place this right after a goto label
|
|
||||||
* This would then be a label followed by a declaration, a C23 extension (!)
|
|
||||||
* To ensure this works for older SWIG versions and older compilers,
|
|
||||||
* make this a block element with curly braces.
|
|
||||||
*/
|
|
||||||
{static_assert(SWIG_NEWOBJ != 0, "SWIG_NEWOBJ is 0");}
|
|
||||||
%#endif
|
|
||||||
if ($1 != NULL && alloc_tracking$argnum != NULL) {
|
|
||||||
for (Py_ssize_t i=0; i<seq_len$argnum; i++) {
|
|
||||||
if (alloc_tracking$argnum[i] == SWIG_NEWOBJ) {
|
|
||||||
%delete_array($1[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
%delete_array(alloc_tracking$argnum);
|
|
||||||
%delete_array($1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef SWIGPERL
|
|
||||||
// Copied from perl's argcargv.i, which should be good enough for us
|
|
||||||
%typemap(in) (const char *subprofiles[]) {
|
|
||||||
int i;
|
|
||||||
SSize_t len;
|
|
||||||
AV *av = (AV *)SvRV($input);
|
|
||||||
if (SvTYPE(av) != SVt_PVAV) {
|
|
||||||
SWIG_croak("in method '$symname', Expecting reference to argv array");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
len = av_len(av) + 1;
|
|
||||||
$1 = (char **) malloc((len+1)*sizeof(char *));
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
SV **tv = av_fetch(av, i, 0);
|
|
||||||
$1[i] = SvPV_nolen(*tv);
|
|
||||||
}
|
|
||||||
$1[i] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
%typemap(typecheck, precedence=SWIG_TYPECHECK_STRING_ARRAY) (const char *subprofiles[]) {
|
|
||||||
AV *av = (AV *)SvRV($input);
|
|
||||||
$1 = SvTYPE(av) == SVt_PVAV;
|
|
||||||
}
|
|
||||||
|
|
||||||
%typemap(freearg) (const char *subprofiles[]) {
|
|
||||||
free((void *)$1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* These should not receive the VOID_Object typemap */
|
|
||||||
extern int aa_change_hat(const char *subprofile, unsigned long magic_token);
|
extern int aa_change_hat(const char *subprofile, unsigned long magic_token);
|
||||||
extern int aa_change_profile(const char *profile);
|
extern int aa_change_profile(const char *profile);
|
||||||
extern int aa_change_onexec(const char *profile);
|
extern int aa_change_onexec(const char *profile);
|
||||||
extern int aa_change_hatv(const char *subprofiles[], unsigned long token);
|
extern int aa_change_hatv(const char *subprofiles[], unsigned long token);
|
||||||
|
extern int aa_change_hat_vargs(unsigned long token, int count, ...);
|
||||||
extern int aa_stack_profile(const char *profile);
|
extern int aa_stack_profile(const char *profile);
|
||||||
extern int aa_stack_onexec(const char *profile);
|
extern int aa_stack_onexec(const char *profile);
|
||||||
|
extern int aa_getprocattr_raw(pid_t tid, const char *attr, char *buf, int len,
|
||||||
/*
|
char **mode);
|
||||||
* aa_find_mountpoint mnt is an output pointer to a heap-allocated string
|
extern int aa_getprocattr(pid_t tid, const char *attr, char **buf, char **mode);
|
||||||
*
|
|
||||||
* This is a replica of %cstring_output_allocate(char **mnt, free(*$1))
|
|
||||||
* that uses the ISVOID helper to work correctly on SWIG 4.3 or later.
|
|
||||||
*/
|
|
||||||
%typemap(in,noblock=1,numinputs=0) (char **mnt) ($*1_ltype temp_mnt = 0) {
|
|
||||||
$1 = &temp_mnt;
|
|
||||||
}
|
|
||||||
%typemap(freearg,match="in") (char **mnt) ""
|
|
||||||
%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") (char **mnt) {
|
|
||||||
ISVOID_APPEND_OUTPUT(SWIG_FromCharPtr(*$1));
|
|
||||||
free(*$1);
|
|
||||||
}
|
|
||||||
/* The other errno-based functions should not always be returning the int value:
|
|
||||||
* - Python exceptions signal success/failure status instead via the %exception
|
|
||||||
* handler above.
|
|
||||||
* - Perl (the other binding) has $! for accessing errno but would check the int
|
|
||||||
* return status first.
|
|
||||||
*
|
|
||||||
* The generated C code for (out) resets the return value to None
|
|
||||||
* before appending the returned data (argout generated by %cstring stuff)
|
|
||||||
*/
|
|
||||||
#ifdef SWIGPYTHON
|
|
||||||
%typemap(out,noblock=1) int {
|
|
||||||
#if defined(VOID_Object)
|
|
||||||
$result = VOID_Object;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We can't use "typedef int pid_t" because we still support systems
|
|
||||||
* with 16-bit PIDs and SWIG can't find sys/types.h
|
|
||||||
*
|
|
||||||
* Capture the passed-in value as a long because pid_t is guaranteed
|
|
||||||
* to be a signed integer and because the aalogparse struct uses
|
|
||||||
* (unsigned) longs to store pid values. While intmax_t would be more
|
|
||||||
* technically correct, if sizeof(pid_t) > sizeof(long) then aalogparse
|
|
||||||
* itself would also need fixing.
|
|
||||||
*/
|
|
||||||
%typemap(in,noblock=1,fragment="SWIG_AsVal_long") pid_t (int conv_pid, long pid_large) {
|
|
||||||
%#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
|
|
||||||
static_assert(sizeof(pid_t) <= sizeof(long),
|
|
||||||
"pid_t type is too large to be stored in a long");
|
|
||||||
%#endif
|
|
||||||
conv_pid = SWIG_AsVal_long($input, &pid_large);
|
|
||||||
if (!SWIG_IsOK(conv_pid)) {
|
|
||||||
%argument_fail(conv_pid, "pid_t", $symname, $argnum);
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Cast the long to a pid_t and then cast back to check for overflow
|
|
||||||
* Technically this is implementation-defined behaviour but we should be fine
|
|
||||||
*/
|
|
||||||
$1 = (pid_t) pid_large;
|
|
||||||
if ((long) $1 != pid_large) {
|
|
||||||
SWIG_exception_fail(SWIG_OverflowError, "pid_t is too large");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extern int aa_find_mountpoint(char **mnt);
|
|
||||||
extern int aa_getprocattr(pid_t tid, const char *attr, char **label, char **mode);
|
|
||||||
extern int aa_gettaskcon(pid_t target, char **label, char **mode);
|
extern int aa_gettaskcon(pid_t target, char **label, char **mode);
|
||||||
extern int aa_getcon(char **label, char **mode);
|
extern int aa_getcon(char **label, char **mode);
|
||||||
|
extern int aa_getpeercon_raw(int fd, char *buf, int *len, char **mode);
|
||||||
extern int aa_getpeercon(int fd, char **label, char **mode);
|
extern int aa_getpeercon(int fd, char **label, char **mode);
|
||||||
|
extern int aa_query_label(uint32_t mask, char *query, size_t size, int *allow,
|
||||||
/*
|
int *audit);
|
||||||
* Typemaps for the boolean outputs of the query functions
|
extern int aa_query_file_path_len(uint32_t mask, const char *label,
|
||||||
* Use boolean types for Python and int types elsewhere
|
size_t label_len, const char *path,
|
||||||
*/
|
size_t path_len, int *allowed, int *audited);
|
||||||
#ifdef SWIGPYTHON
|
|
||||||
// TODO: find a way to deduplicate these
|
|
||||||
%typemap(in, numinputs=0) int *allowed (int temp) {
|
|
||||||
$1 = &temp;
|
|
||||||
}
|
|
||||||
%typemap(argout) int *allowed {
|
|
||||||
ISVOID_APPEND_OUTPUT(PyBool_FromLong(*$1));
|
|
||||||
}
|
|
||||||
|
|
||||||
%typemap(in, numinputs=0) int *audited (int temp) {
|
|
||||||
$1 = &temp;
|
|
||||||
}
|
|
||||||
%typemap(argout) int *audited {
|
|
||||||
ISVOID_APPEND_OUTPUT(PyBool_FromLong(*$1));
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
%apply int *OUTPUT { int *allowed };
|
|
||||||
%apply int *OUTPUT { int *audited };
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Sync this with the apparmor.h */
|
|
||||||
/* Permission flags for the AA_CLASS_FILE mediation class */
|
|
||||||
#define AA_MAY_EXEC (1 << 0)
|
|
||||||
#define AA_MAY_WRITE (1 << 1)
|
|
||||||
#define AA_MAY_READ (1 << 2)
|
|
||||||
#define AA_MAY_APPEND (1 << 3)
|
|
||||||
#define AA_MAY_CREATE (1 << 4)
|
|
||||||
#define AA_MAY_DELETE (1 << 5)
|
|
||||||
#define AA_MAY_OPEN (1 << 6)
|
|
||||||
#define AA_MAY_RENAME (1 << 7)
|
|
||||||
#define AA_MAY_SETATTR (1 << 8)
|
|
||||||
#define AA_MAY_GETATTR (1 << 9)
|
|
||||||
#define AA_MAY_SETCRED (1 << 10)
|
|
||||||
#define AA_MAY_GETCRED (1 << 11)
|
|
||||||
#define AA_MAY_CHMOD (1 << 12)
|
|
||||||
#define AA_MAY_CHOWN (1 << 13)
|
|
||||||
#define AA_MAY_LOCK 0x8000
|
|
||||||
#define AA_EXEC_MMAP 0x10000
|
|
||||||
#define AA_MAY_LINK 0x40000
|
|
||||||
#define AA_MAY_ONEXEC 0x20000000
|
|
||||||
#define AA_MAY_CHANGE_PROFILE 0x40000000
|
|
||||||
|
|
||||||
extern int aa_query_file_path(uint32_t mask, const char *label,
|
extern int aa_query_file_path(uint32_t mask, const char *label,
|
||||||
const char *path, int *allowed, int *audited);
|
const char *path, int *allowed, int *audited);
|
||||||
|
extern int aa_query_link_path_len(const char *label, size_t label_len,
|
||||||
|
const char *target, size_t target_len,
|
||||||
|
const char *link, size_t link_len,
|
||||||
|
int *allowed, int *audited);
|
||||||
extern int aa_query_link_path(const char *label, const char *target,
|
extern int aa_query_link_path(const char *label, const char *target,
|
||||||
const char *link, int *allowed, int *audited);
|
const char *link, int *allowed, int *audited);
|
||||||
|
|
||||||
|
@@ -14,7 +14,7 @@ MOSTLYCLEANFILES=libapparmor_wrap.c LibAppArmor.py
|
|||||||
|
|
||||||
all-local: libapparmor_wrap.c setup.py
|
all-local: libapparmor_wrap.c setup.py
|
||||||
if test ! -f libapparmor_wrap.c; then cp $(srcdir)/libapparmor_wrap.c . ; fi
|
if test ! -f libapparmor_wrap.c; then cp $(srcdir)/libapparmor_wrap.c . ; fi
|
||||||
CC="$(CC)" CFLAGS="$(PYTHON_CPPFLAGS) $(CFLAGS) $(EXTRA_WARNINGS)" LDSHARED="$(CC) -shared" LDFLAGS="$(PYTHON_LDFLAGS) $(LDFLAGS)" $(PYTHON) setup.py build
|
CC="$(CC)" CFLAGS="$(PYTHON_CPPFLAGS) $(EXTRA_WARNINGS)" LDSHARED="$(CC) -shared" LDFLAGS="$(PYTHON_LDFLAGS) $(LDFLAGS)" $(PYTHON) setup.py build
|
||||||
|
|
||||||
install-exec-local:
|
install-exec-local:
|
||||||
$(PYTHON) setup.py install --root="/$(DESTDIR)" --prefix="$(prefix)"
|
$(PYTHON) setup.py install --root="/$(DESTDIR)" --prefix="$(prefix)"
|
||||||
|
@@ -2,7 +2,7 @@ from setuptools import setup, Extension
|
|||||||
import string
|
import string
|
||||||
|
|
||||||
setup(name = 'LibAppArmor',
|
setup(name = 'LibAppArmor',
|
||||||
version = '@VERSION@'.replace('~', '-'),
|
version = '@VERSION@',
|
||||||
author = 'AppArmor Dev Team',
|
author = 'AppArmor Dev Team',
|
||||||
author_email = 'apparmor@lists.ubuntu.com',
|
author_email = 'apparmor@lists.ubuntu.com',
|
||||||
url = 'https://wiki.apparmor.net',
|
url = 'https://wiki.apparmor.net',
|
||||||
|
@@ -15,7 +15,6 @@ PYTHON_DIST_BUILD_PATH = '$(builddir)/../build/$$($(PYTHON) buildpath.py)'
|
|||||||
TESTS = test_python.py
|
TESTS = test_python.py
|
||||||
TESTS_ENVIRONMENT = \
|
TESTS_ENVIRONMENT = \
|
||||||
LD_LIBRARY_PATH='$(top_builddir)/src/.libs:$(PYTHON_DIST_BUILD_PATH)' \
|
LD_LIBRARY_PATH='$(top_builddir)/src/.libs:$(PYTHON_DIST_BUILD_PATH)' \
|
||||||
PYTHONPATH='$(PYTHON_DIST_BUILD_PATH)' \
|
PYTHONPATH='$(PYTHON_DIST_BUILD_PATH)'
|
||||||
PYTHONDONTWRITEBYTECODE='1'
|
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
@@ -7,8 +7,8 @@ import sysconfig
|
|||||||
import setuptools
|
import setuptools
|
||||||
|
|
||||||
|
|
||||||
if tuple(map(int, setuptools.__version__.split(".")[:2])) >= (62, 1):
|
if tuple(map(int, setuptools.__version__.split("."))) >= (62, 1):
|
||||||
identifier = sys.implementation.cache_tag
|
identifier = sys.implementation.cache_tag
|
||||||
else:
|
else:
|
||||||
identifier = "%d.%d" % sys.version_info[:2]
|
identifier = "%d.%d" % sys.version_info[:2]
|
||||||
print("lib.{}-{}".format(sysconfig.get_platform(), identifier))
|
print("lib.%s-%s" % (sysconfig.get_platform(), identifier))
|
||||||
|
@@ -55,107 +55,17 @@ NO_VALUE_MAP = {
|
|||||||
'fsuid': int(ctypes.c_ulong(-1).value),
|
'fsuid': int(ctypes.c_ulong(-1).value),
|
||||||
'ouid': int(ctypes.c_ulong(-1).value),
|
'ouid': int(ctypes.c_ulong(-1).value),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class AAPythonBindingsTests(unittest.TestCase):
|
class AAPythonBindingsTests(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
# REPORT ALL THE OUTPUT
|
|
||||||
self.maxDiff = None
|
|
||||||
|
|
||||||
def test_aa_splitcon(self):
|
|
||||||
AA_SPLITCON_EXPECT = [
|
|
||||||
("unconfined", "unconfined", None),
|
|
||||||
("unconfined\n", "unconfined", None),
|
|
||||||
("/bin/ping (enforce)", "/bin/ping", "enforce"),
|
|
||||||
("/bin/ping (enforce)\n", "/bin/ping", "enforce"),
|
|
||||||
("/usr/sbin/rsyslog (complain)", "/usr/sbin/rsyslog", "complain"),
|
|
||||||
]
|
|
||||||
for context, expected_label, expected_mode in AA_SPLITCON_EXPECT:
|
|
||||||
actual_label, actual_mode = libapparmor.aa_splitcon(context)
|
|
||||||
if expected_label is None:
|
|
||||||
self.assertIsNone(actual_label)
|
|
||||||
else:
|
|
||||||
self.assertIsInstance(actual_label, str)
|
|
||||||
self.assertEqual(expected_label, actual_label)
|
|
||||||
|
|
||||||
if expected_mode is None:
|
|
||||||
self.assertIsNone(actual_mode)
|
|
||||||
else:
|
|
||||||
self.assertIsInstance(actual_mode, str)
|
|
||||||
self.assertEqual(expected_mode, actual_mode)
|
|
||||||
|
|
||||||
with self.assertRaises(ValueError):
|
|
||||||
libapparmor.aa_splitcon("")
|
|
||||||
|
|
||||||
def test_aa_is_enabled(self):
|
|
||||||
aa_enabled = libapparmor.aa_is_enabled()
|
|
||||||
self.assertIsInstance(aa_enabled, bool)
|
|
||||||
|
|
||||||
@unittest.skipUnless(libapparmor.aa_is_enabled(), "AppArmor is not enabled")
|
|
||||||
def test_aa_find_mountpoint(self):
|
|
||||||
mount_point = libapparmor.aa_find_mountpoint()
|
|
||||||
self.assertIsInstance(mount_point, str)
|
|
||||||
self.assertGreater(len(mount_point), 0, "mount point should not be empty")
|
|
||||||
self.assertTrue(os.path.isdir(mount_point))
|
|
||||||
|
|
||||||
# TODO: test commented out functions (or at least their prototypes)
|
|
||||||
# extern int aa_change_profile(const char *profile);
|
|
||||||
# extern int aa_change_onexec(const char *profile);
|
|
||||||
@unittest.skipUnless(libapparmor.aa_is_enabled(), "AppArmor is not enabled")
|
|
||||||
def test_change_hats(self):
|
|
||||||
# Changing hats will fail because we have no valid hats to change to
|
|
||||||
# However, we still verify that we get an OSError instead of a TypeError
|
|
||||||
with self.assertRaises(OSError):
|
|
||||||
libapparmor.aa_change_hat("nonexistent_profile", 12345678)
|
|
||||||
|
|
||||||
with self.assertRaises(OSError):
|
|
||||||
libapparmor.aa_change_hatv(["nonexistent_1", "nonexistent_2"], 0xabcdef)
|
|
||||||
libapparmor.aa_change_hatv(("nonexistent_1", "nonexistent_2"), 0xabcdef)
|
|
||||||
|
|
||||||
# extern int aa_stack_profile(const char *profile);
|
|
||||||
# extern int aa_stack_onexec(const char *profile);
|
|
||||||
# extern int aa_getprocattr(pid_t tid, const char *attr, char **label, char **mode);
|
|
||||||
# extern int aa_gettaskcon(pid_t target, char **label, char **mode);
|
|
||||||
|
|
||||||
@unittest.skipUnless(libapparmor.aa_is_enabled(), "AppArmor is not enabled")
|
|
||||||
def test_aa_gettaskcon(self):
|
|
||||||
# Our test harness should be running us as unconfined
|
|
||||||
# Get our own pid and this should be equivalent to aa_getcon
|
|
||||||
pid = os.getpid()
|
|
||||||
|
|
||||||
label, mode = libapparmor.aa_gettaskcon(pid)
|
|
||||||
self.assertEqual(label, "unconfined", "aa_gettaskcon label should be unconfined")
|
|
||||||
self.assertIsNone(mode, "aa_gettaskcon mode should be unconfined")
|
|
||||||
|
|
||||||
@unittest.skipUnless(libapparmor.aa_is_enabled(), "AppArmor is not enabled")
|
|
||||||
def test_aa_getcon(self):
|
|
||||||
# Our test harness should be running us as unconfined
|
|
||||||
label, mode = libapparmor.aa_getcon()
|
|
||||||
self.assertEqual(label, "unconfined", "aa_getcon label should be unconfined")
|
|
||||||
self.assertIsNone(mode, "aa_getcon mode should be unconfined")
|
|
||||||
|
|
||||||
# extern int aa_getpeercon(int fd, char **label, char **mode);
|
|
||||||
|
|
||||||
# extern int aa_query_file_path(uint32_t mask, const char *label,
|
|
||||||
# const char *path, int *allowed, int *audited);
|
|
||||||
@unittest.skipUnless(libapparmor.aa_is_enabled(), "AppArmor is not enabled")
|
|
||||||
def test_aa_query_file_path(self):
|
|
||||||
aa_query_mask = libapparmor.AA_MAY_EXEC | libapparmor.AA_MAY_READ | libapparmor.AA_MAY_WRITE
|
|
||||||
allowed, audited = libapparmor.aa_query_file_path(aa_query_mask, "unconfined", "/tmp/hello")
|
|
||||||
self.assertTrue(allowed)
|
|
||||||
self.assertFalse(audited)
|
|
||||||
# extern int aa_query_link_path(const char *label, const char *target,
|
|
||||||
# const char *link, int *allowed, int *audited);
|
|
||||||
|
|
||||||
|
|
||||||
class AALogParsePythonBindingsTests(unittest.TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
# REPORT ALL THE OUTPUT
|
# REPORT ALL THE OUTPUT
|
||||||
self.maxDiff = None
|
self.maxDiff = None
|
||||||
|
|
||||||
def _runtest(self, testname):
|
def _runtest(self, testname):
|
||||||
infile = testname + ".in"
|
infile = "%s.in" % (testname)
|
||||||
outfile = testname + ".out"
|
outfile = "%s.out" % (testname)
|
||||||
# infile *should* only contain one line
|
# infile *should* only contain one line
|
||||||
with open(os.path.join(TESTDIR, infile), 'r') as f:
|
with open(os.path.join(TESTDIR, infile), 'r') as f:
|
||||||
line = f.read()
|
line = f.read()
|
||||||
@@ -168,7 +78,7 @@ class AALogParsePythonBindingsTests(unittest.TestCase):
|
|||||||
expected = self.parse_output_file(outfile)
|
expected = self.parse_output_file(outfile)
|
||||||
self.assertEqual(expected, record,
|
self.assertEqual(expected, record,
|
||||||
"expected records did not match\n"
|
"expected records did not match\n"
|
||||||
"expected = {}\nactual = {}".format(expected, record))
|
"expected = %s\nactual = %s" % (expected, record))
|
||||||
|
|
||||||
def parse_output_file(self, outfile):
|
def parse_output_file(self, outfile):
|
||||||
"""parse testcase .out file and return dict"""
|
"""parse testcase .out file and return dict"""
|
||||||
@@ -183,7 +93,7 @@ class AALogParsePythonBindingsTests(unittest.TestCase):
|
|||||||
count += 1
|
count += 1
|
||||||
if line == "START":
|
if line == "START":
|
||||||
self.assertEqual(count, 1,
|
self.assertEqual(count, 1,
|
||||||
"Unexpected output format in " + outfile)
|
"Unexpected output format in %s" % (outfile))
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
key, value = line.split(": ", 1)
|
key, value = line.split(": ", 1)
|
||||||
@@ -208,9 +118,6 @@ class AALogParsePythonBindingsTests(unittest.TestCase):
|
|||||||
# FIXME: out files should report log version?
|
# FIXME: out files should report log version?
|
||||||
# FIXME: or can we just deprecate v1 logs?
|
# FIXME: or can we just deprecate v1 logs?
|
||||||
continue
|
continue
|
||||||
elif key == "thisown":
|
|
||||||
# SWIG generates this key to track memory allocation
|
|
||||||
continue
|
|
||||||
elif key in NO_VALUE_MAP:
|
elif key in NO_VALUE_MAP:
|
||||||
if NO_VALUE_MAP[key] == value:
|
if NO_VALUE_MAP[key] == value:
|
||||||
continue
|
continue
|
||||||
@@ -234,8 +141,8 @@ def main():
|
|||||||
for f in find_testcases(TESTDIR):
|
for f in find_testcases(TESTDIR):
|
||||||
def stub_test(self, testname=f):
|
def stub_test(self, testname=f):
|
||||||
self._runtest(testname)
|
self._runtest(testname)
|
||||||
stub_test.__doc__ = "test " + f
|
stub_test.__doc__ = "test %s" % (f)
|
||||||
setattr(AALogParsePythonBindingsTests, 'test_' + f, stub_test)
|
setattr(AAPythonBindingsTests, 'test_%s' % (f), stub_test)
|
||||||
return unittest.main(verbosity=2)
|
return unittest.main(verbosity=2)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
#define _GNU_SOURCE /* for glibc's basename version */
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -5,12 +7,6 @@
|
|||||||
|
|
||||||
#include <aalogparse.h>
|
#include <aalogparse.h>
|
||||||
|
|
||||||
static const char *basename(const char *path)
|
|
||||||
{
|
|
||||||
const char *p = strrchr(path, '/');
|
|
||||||
return p ? p + 1 : path;
|
|
||||||
}
|
|
||||||
|
|
||||||
int print_results(aa_log_record *record);
|
int print_results(aa_log_record *record);
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
@@ -107,7 +103,7 @@ int print_results(aa_log_record *record)
|
|||||||
print_string("Name", record->name);
|
print_string("Name", record->name);
|
||||||
print_string("Command", record->comm);
|
print_string("Command", record->comm);
|
||||||
print_string("Name2", record->name2);
|
print_string("Name2", record->name2);
|
||||||
print_string("Namespace", record->aa_namespace);
|
print_string("Namespace", record->namespace);
|
||||||
print_string("Attribute", record->attribute);
|
print_string("Attribute", record->attribute);
|
||||||
print_long("Task", record->task, 0);
|
print_long("Task", record->task, 0);
|
||||||
print_long("Parent", record->parent, 0);
|
print_long("Parent", record->parent, 0);
|
||||||
@@ -119,8 +115,6 @@ int print_results(aa_log_record *record)
|
|||||||
print_long("Peer PID", record->peer_pid, 0);
|
print_long("Peer PID", record->peer_pid, 0);
|
||||||
print_string("Active hat", record->active_hat);
|
print_string("Active hat", record->active_hat);
|
||||||
|
|
||||||
print_string("Net Addr", record->net_addr);
|
|
||||||
print_string("Peer Addr", record->peer_addr);
|
|
||||||
print_string("Network family", record->net_family);
|
print_string("Network family", record->net_family);
|
||||||
print_string("Socket type", record->net_sock_type);
|
print_string("Socket type", record->net_sock_type);
|
||||||
print_string("Protocol", record->net_protocol);
|
print_string("Protocol", record->net_protocol);
|
||||||
@@ -140,9 +134,7 @@ int print_results(aa_log_record *record)
|
|||||||
print_string("Flags", record->flags);
|
print_string("Flags", record->flags);
|
||||||
print_string("Src name", record->src_name);
|
print_string("Src name", record->src_name);
|
||||||
|
|
||||||
print_string("Execpath", record->execpath);
|
print_string("Class", record->class);
|
||||||
|
|
||||||
print_string("Class", record->rule_class);
|
|
||||||
|
|
||||||
print_long("Epoch", record->epoch, 0);
|
print_long("Epoch", record->epoch, 0);
|
||||||
print_long("Audit subid", (long) record->audit_sub_id, 0);
|
print_long("Audit subid", (long) record->audit_sub_id, 0);
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
/usr/lib/NetworkManager/nm-dhcp-client.action {
|
/usr/lib/NetworkManager/nm-dhcp-client.action {
|
||||||
network inet6 dgram port=10580,
|
network inet6 dgram,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
/usr/sbin/apache2 {
|
/usr/sbin/apache2 {
|
||||||
network inet6 stream ip=::ffff:192.168.236.159 port=80 peer=(ip=::ffff:192.168.103.80 port=61985),
|
network inet6 stream,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
/usr/sbin/apache2 {
|
/usr/sbin/apache2 {
|
||||||
|
|
||||||
^www.xxxxxxxxxx.co.uk {
|
^www.xxxxxxxxxx.co.uk {
|
||||||
network (send) inet6 stream ip=::ffff:192.168.1.100 port=80 peer=(ip=::ffff:192.168.1.100 port=45658),
|
network inet6 stream,
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
/usr/local/apache-tomcat-8.0.33/bin/catalina.sh {
|
/usr/local/apache-tomcat-8.0.33/bin/catalina.sh {
|
||||||
|
|
||||||
^/usr/local/jdk1.8.0_92/bin/java {
|
^/usr/local/jdk1.8.0_92/bin/java {
|
||||||
network (receive) inet6 stream ip=::ffff:127.0.0.1 port=8080 peer=(ip=::ffff:127.0.0.1 port=52308),
|
network inet6 stream,
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1 +0,0 @@
|
|||||||
2025-01-27T13:01:36.226987+05:30 sec-plucky-amd64 kernel: audit: type=1400 audit(1737963096.225:3240): apparmor="AUDIT" operation="getattr" class="file" profile="/usr/sbin/mosquitto" name="/etc/mosquitto/pwfile" pid=8119 comm="mosquitto" requested_mask="r" fsuid=122 ouid=122
|
|
@@ -1,15 +0,0 @@
|
|||||||
START
|
|
||||||
File: testcase36.in
|
|
||||||
Event type: AA_RECORD_AUDIT
|
|
||||||
Audit ID: 1737963096.225:3240
|
|
||||||
Operation: getattr
|
|
||||||
Mask: r
|
|
||||||
fsuid: 122
|
|
||||||
ouid: 122
|
|
||||||
Profile: /usr/sbin/mosquitto
|
|
||||||
Name: /etc/mosquitto/pwfile
|
|
||||||
Command: mosquitto
|
|
||||||
PID: 8119
|
|
||||||
Class: file
|
|
||||||
Epoch: 1737963096
|
|
||||||
Audit subid: 3240
|
|
@@ -1,4 +0,0 @@
|
|||||||
/usr/sbin/mosquitto {
|
|
||||||
/etc/mosquitto/pwfile r,
|
|
||||||
|
|
||||||
}
|
|
@@ -1 +0,0 @@
|
|||||||
[ 4584.703379] audit: type=1400 audit(1680266735.359:69): apparmor="DENIED" operation="uring_sqpoll" class="io_uring" profile="/root/apparmor/tests/regression/apparmor/io_uring" pid=1320 comm="io_uring" requested="sqpoll" denied="sqpoll"
|
|
@@ -1,13 +0,0 @@
|
|||||||
START
|
|
||||||
File: testcase_io_uring_01.in
|
|
||||||
Event type: AA_RECORD_DENIED
|
|
||||||
Audit ID: 1680266735.359:69
|
|
||||||
Operation: uring_sqpoll
|
|
||||||
Mask: sqpoll
|
|
||||||
Denied Mask: sqpoll
|
|
||||||
Profile: /root/apparmor/tests/regression/apparmor/io_uring
|
|
||||||
Command: io_uring
|
|
||||||
PID: 1320
|
|
||||||
Class: io_uring
|
|
||||||
Epoch: 1680266735
|
|
||||||
Audit subid: 69
|
|
@@ -1,4 +0,0 @@
|
|||||||
/root/apparmor/tests/regression/apparmor/io_uring {
|
|
||||||
io_uring sqpoll,
|
|
||||||
|
|
||||||
}
|
|
@@ -1 +0,0 @@
|
|||||||
[ 4584.491076] audit: type=1400 audit(1680266735.147:63): apparmor="DENIED" operation="uring_override" class="io_uring" profile="/root/apparmor/tests/regression/apparmor/io_uring" pid=1193 comm="io_uring" requested="override_creds" denied="override_creds" tcontext="/root/apparmor/tests/regression/apparmor/io_uring"
|
|
@@ -1,14 +0,0 @@
|
|||||||
START
|
|
||||||
File: testcase_io_uring_02.in
|
|
||||||
Event type: AA_RECORD_DENIED
|
|
||||||
Audit ID: 1680266735.147:63
|
|
||||||
Operation: uring_override
|
|
||||||
Mask: override_creds
|
|
||||||
Denied Mask: override_creds
|
|
||||||
Profile: /root/apparmor/tests/regression/apparmor/io_uring
|
|
||||||
Peer profile: /root/apparmor/tests/regression/apparmor/io_uring
|
|
||||||
Command: io_uring
|
|
||||||
PID: 1193
|
|
||||||
Class: io_uring
|
|
||||||
Epoch: 1680266735
|
|
||||||
Audit subid: 63
|
|
@@ -1,4 +0,0 @@
|
|||||||
/root/apparmor/tests/regression/apparmor/io_uring {
|
|
||||||
io_uring override_creds label=/root/apparmor/tests/regression/apparmor/io_uring,
|
|
||||||
|
|
||||||
}
|
|
@@ -1,4 +1,4 @@
|
|||||||
/home/ubuntu/bzr/apparmor/tests/regression/apparmor/mount {
|
/home/ubuntu/bzr/apparmor/tests/regression/apparmor/mount {
|
||||||
mount fstype=(ext2) options=(mand, rw) /dev/loop0/ -> /tmp/sdtest.19033-29001-MPfz98/mountpoint/,
|
mount fstype=ext2 options="rw, mand" /dev/loop0/ -> /tmp/sdtest.19033-29001-MPfz98/mountpoint/,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1 +0,0 @@
|
|||||||
type=AVC msg=audit(1715045678.914:344186): apparmor="ALLOWED" operation="mount" info="failed flags match" error=-13 profile="steam" name="/newroot/dev/" pid=26487 comm="srt-bwrap" flags="rw, nosuid, nodev, remount, bind, silent, relatime"
|
|
@@ -1,14 +0,0 @@
|
|||||||
START
|
|
||||||
File: testcase_mount_02.in
|
|
||||||
Event type: AA_RECORD_ALLOWED
|
|
||||||
Audit ID: 1715045678.914:344186
|
|
||||||
Operation: mount
|
|
||||||
Profile: steam
|
|
||||||
Name: /newroot/dev/
|
|
||||||
Command: srt-bwrap
|
|
||||||
Info: failed flags match
|
|
||||||
ErrorCode: 13
|
|
||||||
PID: 26487
|
|
||||||
Flags: rw, nosuid, nodev, remount, bind, silent, relatime
|
|
||||||
Epoch: 1715045678
|
|
||||||
Audit subid: 344186
|
|
@@ -1,4 +0,0 @@
|
|||||||
profile steam {
|
|
||||||
mount options=(bind, nodev, nosuid, relatime, remount, rw, silent) -> /newroot/dev/,
|
|
||||||
|
|
||||||
}
|
|
@@ -1 +0,0 @@
|
|||||||
Apr 05 19:36:19 ubuntu kernel: audit: type=1400 audit(1649187379.660:255): apparmor="DENIED" operation="create" profile="/root/apparmor/tests/regression/apparmor/posix_mq_rcv" name="/queuename" pid=791 comm="posix_mq_rcv" requested="create" denied="create" class="posix_mqueue" fsuid=0 ouid=0
|
|
@@ -1,16 +0,0 @@
|
|||||||
START
|
|
||||||
File: testcase_mqueue_01.in
|
|
||||||
Event type: AA_RECORD_DENIED
|
|
||||||
Audit ID: 1649187379.660:255
|
|
||||||
Operation: create
|
|
||||||
Mask: create
|
|
||||||
Denied Mask: create
|
|
||||||
fsuid: 0
|
|
||||||
ouid: 0
|
|
||||||
Profile: /root/apparmor/tests/regression/apparmor/posix_mq_rcv
|
|
||||||
Name: /queuename
|
|
||||||
Command: posix_mq_rcv
|
|
||||||
PID: 791
|
|
||||||
Class: posix_mqueue
|
|
||||||
Epoch: 1649187379
|
|
||||||
Audit subid: 255
|
|
@@ -1,4 +0,0 @@
|
|||||||
/root/apparmor/tests/regression/apparmor/posix_mq_rcv {
|
|
||||||
mqueue create type=posix /queuename,
|
|
||||||
|
|
||||||
}
|
|
@@ -1,2 +0,0 @@
|
|||||||
Apr 05 19:36:29 ubuntu kernel: audit: type=1400 audit(1649187389.828:262): apparmor="DENIED" operation="open" profile="/root/apparmor/tests/regression/apparmor/posix_mq_rcv" name="/queuename" pid=848 comm="posix_mq_rcv" requested="read create" denied="read" class="posix_mqueue" fsuid=0 ouid=0
|
|
||||||
|
|
@@ -1,16 +0,0 @@
|
|||||||
START
|
|
||||||
File: testcase_mqueue_02.in
|
|
||||||
Event type: AA_RECORD_DENIED
|
|
||||||
Audit ID: 1649187389.828:262
|
|
||||||
Operation: open
|
|
||||||
Mask: read create
|
|
||||||
Denied Mask: read
|
|
||||||
fsuid: 0
|
|
||||||
ouid: 0
|
|
||||||
Profile: /root/apparmor/tests/regression/apparmor/posix_mq_rcv
|
|
||||||
Name: /queuename
|
|
||||||
Command: posix_mq_rcv
|
|
||||||
PID: 848
|
|
||||||
Class: posix_mqueue
|
|
||||||
Epoch: 1649187389
|
|
||||||
Audit subid: 262
|
|
@@ -1,4 +0,0 @@
|
|||||||
/root/apparmor/tests/regression/apparmor/posix_mq_rcv {
|
|
||||||
mqueue read type=posix /queuename,
|
|
||||||
|
|
||||||
}
|
|
@@ -1 +0,0 @@
|
|||||||
Apr 05 19:36:39 ubuntu kernel: audit: type=1400 audit(1649187399.973:265): apparmor="DENIED" operation="unlink" profile="/root/apparmor/tests/regression/apparmor/posix_mq_rcv" name="/queuename" pid=897 comm="posix_mq_rcv" requested="delete" denied="delete" class="posix_mqueue" fsuid=0 ouid=0
|
|
@@ -1,16 +0,0 @@
|
|||||||
START
|
|
||||||
File: testcase_mqueue_03.in
|
|
||||||
Event type: AA_RECORD_DENIED
|
|
||||||
Audit ID: 1649187399.973:265
|
|
||||||
Operation: unlink
|
|
||||||
Mask: delete
|
|
||||||
Denied Mask: delete
|
|
||||||
fsuid: 0
|
|
||||||
ouid: 0
|
|
||||||
Profile: /root/apparmor/tests/regression/apparmor/posix_mq_rcv
|
|
||||||
Name: /queuename
|
|
||||||
Command: posix_mq_rcv
|
|
||||||
PID: 897
|
|
||||||
Class: posix_mqueue
|
|
||||||
Epoch: 1649187399
|
|
||||||
Audit subid: 265
|
|
@@ -1,4 +0,0 @@
|
|||||||
/root/apparmor/tests/regression/apparmor/posix_mq_rcv {
|
|
||||||
mqueue delete type=posix /queuename,
|
|
||||||
|
|
||||||
}
|
|
@@ -1 +0,0 @@
|
|||||||
Jun 02 16:58:20 ubuntu kernel: audit: type=1400 audit(1654189100.680:1011): apparmor="DENIED" operation="sysv_mqueue" profile="/root/apparmor/tests/regression/apparmor/sysv_mq_rcv" name="123" pid=13574 comm="sysv_mq_rcv" requested="create" denied="create" class="sysv_mqueue" fsuid=0 ouid=0
|
|
@@ -1,16 +0,0 @@
|
|||||||
START
|
|
||||||
File: testcase_mqueue_04.in
|
|
||||||
Event type: AA_RECORD_DENIED
|
|
||||||
Audit ID: 1654189100.680:1011
|
|
||||||
Operation: sysv_mqueue
|
|
||||||
Mask: create
|
|
||||||
Denied Mask: create
|
|
||||||
fsuid: 0
|
|
||||||
ouid: 0
|
|
||||||
Profile: /root/apparmor/tests/regression/apparmor/sysv_mq_rcv
|
|
||||||
Name: 123
|
|
||||||
Command: sysv_mq_rcv
|
|
||||||
PID: 13574
|
|
||||||
Class: sysv_mqueue
|
|
||||||
Epoch: 1654189100
|
|
||||||
Audit subid: 1011
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user