diff options
| author | Oskari Rauta <oskari.rauta@gmail.com> | 2021-05-18 04:27:21 +0300 |
|---|---|---|
| committer | Polynomdivision <vincent@systemli.org> | 2021-06-10 18:11:57 +0200 |
| commit | 3ba2a3411dea519ae82829a8eba8a5c84472dc6e (patch) | |
| tree | 0830057513f3f20333f3b79327018edd32e5629a /utils/apparmor | |
| parent | 66173efd5068d5e815c2beeb6e13f2d15acb5662 (diff) | |
apparmor: add package
Signed-off-by: Oskari Rauta <oskari.rauta@gmail.com>
Diffstat (limited to 'utils/apparmor')
| -rw-r--r-- | utils/apparmor/Makefile | 216 | ||||
| -rwxr-xr-x | utils/apparmor/files/apparmor.init | 22 | ||||
| -rwxr-xr-x | utils/apparmor/files/apparmor.sh | 380 | ||||
| -rw-r--r-- | utils/apparmor/patches/010-autoconf-libapparmor.patch | 10 | ||||
| -rw-r--r-- | utils/apparmor/patches/020-fix-ss-path.patch | 11 | ||||
| -rw-r--r-- | utils/apparmor/patches/030-remove-pynotify2-dep.patch | 416 | ||||
| -rw-r--r-- | utils/apparmor/patches/040-remove-bash-dep.patch | 134 | ||||
| -rw-r--r-- | utils/apparmor/patches/050-disable-man-pages.patch | 69 | ||||
| -rw-r--r-- | utils/apparmor/patches/060-openwrt-dnsmasq-profile.patch | 190 |
9 files changed, 1448 insertions, 0 deletions
diff --git a/utils/apparmor/Makefile b/utils/apparmor/Makefile new file mode 100644 index 000000000..c72ea681a --- /dev/null +++ b/utils/apparmor/Makefile @@ -0,0 +1,216 @@ +# SPDX-License-Identifier: GPL-2.0-only + +include $(TOPDIR)/rules.mk + +PKG_NAME:=apparmor +PKG_VERSION:=3.0.1 +PKG_RELEASE:=$(AUTORELEASE) + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://gitlab.com/apparmor/apparmor.git +PKG_SOURCE_VERSION:=0325ba06da6eeb5acf3e568063a08136fd0913e0 +PKG_MIRROR_HASH:=303ceca041ad8023fa44cdda366448d60b6299790266834b4078d30b70ad27f9 + +PKG_LICENSE:=GPL-2.0-only +PKG_LICENSE_FILES:=LICENSE +PKG_MAINTAINER:=Oskari Rauta <oskari.rauta@gmail.com> +BUILDONLY:=1 + +PKG_BUILD_DEPENDS:=swig/host +HOST_PYTHON3_PACKAGE_BUILD_DEPENDS:=setuptools-scm + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/nls.mk +include ../../../packages/lang/python/python3-package.mk + +define Package/apparmor/Default + SECTION:=utils + CATEGORY:=Utilities + SUBMENU:=AppArmor + URL:=https://apparmor.net +endef + +define Package/libapparmor + TITLE:=AppArmor library + SECTION:=libs + CATEGORY:=Libraries + URL:=https://apparmor.net +endef + +define Package/python3-apparmor + TITLE:=AppArmor Python bindings + SECTION:=lang + CATEGORY:=Languages + SUBMENU:=Python + URL:=https://apparmor.net + DEPENDS:=+libapparmor +python3 +endef + +define Package/apparmor-utils + $(call Package/apparmor/Default) + TITLE:=AppArmor utils + DEPENDS:=$(INTL_DEPENDS) +libapparmor +python3-apparmor +python3 +python3-readline +python3-psutil +ss +findutils-xargs +endef + +define Package/apparmor-profiles + $(call Package/apparmor/Default) + TITLE:=AppArmor default profiles +endef + +define Package/libapparmor/description + Library to support AppArmor userspace utilities +endef + +define Package/apparmor-utils/description + AppArmor application security system init script and + userspace utils to assist with AppArmor profile management +endef + +define Package/apparmor-profiles/description + A collection of profiles for the AppArmor application security system +endef + +CONFIGURE_PATH=libraries/libapparmor + +TARGET_LDFLAGS += \ + -L$(PYTHON3_LIB_DIR) + +CONFIGURE_VARS += \ + SHELL=$(bash) \ + PYTHON_VERSION=$(PYTHON3_VERSION) \ + PYTHON_VERSIONS=$(PYTHON3) \ + PYTHON=$(PYTHON3) \ + PYTHON_CONFIG=$(STAGING_DIR_ROOT)/host/bin/python$(PYTHON3_VERSION)-config \ + PYTHON_LDFLAGS="-L$(STAGING_DIR)/usr/lib -L$(PYTHON3_LIB_DIR)" \ + PYTHON_CPPFLAGS="-I$(STAGING_DIR)/usr/include/python$(PYTHON3_VERSION)" \ + PYTHON_LDFLAGS="-I$(PYTHON3_INC_DIR) -L$(STAGING_DIR)/usr/lib -L$(PYTHON3_LIB_DIR)" \ + PYTHON_EXTRA_LDFLAGS="-L$(STAGING_DIR)/usr/lib -L$(PYTHON3_LIB_DIR)/config-$(PYTHON3_VERSION) -lpthread -ldl -lm -lz -lpython$(PYTHON3_VERSION)" \ + ac_cv_path_PYTHON_CONFIG="$(STAGING_DIR)/host/bin/python$(PYTHON3_VERSION)-config" + +CONFIGURE_ARGS += \ + --with-python \ + --without-perl \ + --without-ruby \ + --disable-man-pages + +ifeq ($(CONFIG_BUILD_NLS),y) + MAKE_VARS += WITH_LIBINTL=1 + MAKE_FLAGS += WITH_LIBINTL=1 +endif + +APPARMOR_CFLAGS = -I$(PKG_BUILD_DIR)/libraries/libapparmor/include +APPARMOR_LDFLAGS = -L$(PKG_BUILD_DIR)/libraries/libapparmor/src/.libs + +define Build/Configure + $(MAKE) -C $(PKG_BUILD_DIR)/libraries/libapparmor configure + $(RM) $(PKG_BUILD_DIR)/libraries/libapparmor/Makefile + $(SED) 's#ac_cv_path_PYTHON_CONFIG=#ac_cv_path_X_PYTHON_CONFIG=#g' $(PKG_BUILD_DIR)/libraries/libapparmor/configure + $(call Build/Configure/Default) +endef + +define Build/Compile + # Building libapparmor + +$(MAKE_VARS) \ + CFLAGS="$(TARGET_CFLAGS)" CPPFLAGS="$(TARGET_CPPFLAGS)" LDFLAGS="$(TARGET_LDFLAGS)" $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR)/libraries/libapparmor \ + $(MAKE_FLAGS) + # Building parser + +$(MAKE_VARS) PYTHON=$(HOST_PYTHON) \ + CFLAGS="$(TARGET_CFLAGS) $(APPARMOR_CFLAGS)" CPPFLAGS="$(TARGET_CPPFLAGS) $(APPARMOR_CFLAGS)" LDFLAGS="$(TARGET_LDFLAGS) $(APPARMOR_LDFLAGS) -lgcc_s" USE_SYSTEM=0 $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR)/parser \ + $(MAKE_FLAGS) apparmor_parser + # Building binutils + +$(MAKE_VARS) PYTHON=$(HOST_PYTHON) \ + CFLAGS="$(TARGET_CFLAGS) $(APPARMOR_CFLAGS)" CPPFLAGS="$(TARGET_CPPFLAGS) $(APPARMOR_CFLAGS)" LDFLAGS="$(TARGET_LDFLAGS) $(APPARMOR_LDFLAGS)" USE_SYSTEM=0 $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR)/binutils \ + $(MAKE_FLAGS) + # Building utils + +$(MAKE_VARS) PYTHON=$(HOST_PYTHON) \ + CFLAGS="$(TARGET_CFLAGS) $(APPARMOR_CFLAGS)" CPPFLAGS="$(TARGET_CPPFLAGS) $(APPARMOR_CFLAGS)" LDFLAGS="$(TARGET_LDFLAGS) $(APPARMOR_LDFLAGS)" USE_SYSTEM=0 $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR)/utils \ + $(MAKE_FLAGS) + # Building profiles + +$(MAKE_VARS) PYTHON=$(HOST_PYTHON) \ + CFLAGS="$(TARGET_CFLAGS) $(APPARMOR_CFLAGS)" CPPFLAGS="$(TARGET_CPPFLAGS) $(APPARMOR_CFLAGS")" LDFLAGS="$(TARGET_LDFLAGS) $(APPARMOR_LDFLAGS)" USE_SYSTEM=0 $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR)/profiles \ + $(MAKE_FLAGS) +endef + +define Build/Install + # Make sure we have python's setup tools installed + $(if $(PYTHON3_PKG_HOST_PIP_INSTALL_ARGS), \ + $(call HostPython3/PipInstall,$(PYTHON3_PKG_HOST_PIP_INSTALL_ARGS)) \ + ) + $(INSTALL_DIR) $(PKG_INSTALL_DIR)-libapparmor $(PKG_INSTALL_DIR)-utils $(PKG_INSTALL_DIR)-profiles + # Installing libapparmor + +$(MAKE_VARS) PYTHON=$(HOST_PYTHON) VERSION=$(PYTHON3_VERSION) \ + CFLAGS="$(TARGET_CFLAGS)" CPPFLAGS="$(TARGET_CPPFLAGS)" LDFLAGS="$(TARGET_LDFLAGS)" \ + $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR)/libraries/libapparmor \ + $(MAKE_FLAGS) DESTDIR="$(PKG_INSTALL_DIR)-libapparmor" install + # Installing parser + +$(MAKE_VARS) PYTHON=$(HOST_PYTHON) VERSION=$(PYTHON3_VERSION) \ + CFLAGS="$(TARGET_CFLAGS)" LDFLAGS="$(TARGET_LDFLAGS)" USE_SYSTEM=1 $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR)/parser \ + $(MAKE_FLAGS) DESTDIR="$(PKG_INSTALL_DIR)-utils" install + # Installing binutils + +$(MAKE_VARS) PYTHON=$(HOST_PYTHON) VERSION=$(PYTHON3_VERSION) \ + CFLAGS="$(TARGET_CFLAGS)" LDFLAGS="$(TARGET_LDFLAGS)" USE_SYSTEM=1 $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR)/binutils \ + $(MAKE_FLAGS) DESTDIR="$(PKG_INSTALL_DIR)-utils" install + # Installing utils + +$(MAKE_VARS) PYTHON=$(HOST_PYTHON) VERSION=$(PYTHON3_VERSION) \ + CFLAGS="$(TARGET_CFLAGS)" LDFLAGS="$(TARGET_LDFLAGS)" USE_SYSTEM=1 $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR)/utils \ + $(MAKE_FLAGS) DESTDIR="$(PKG_INSTALL_DIR)-utils" install + # Installing profiles + +$(MAKE_VARS) PYTHON=$(HOST_PYTHON) VERSION=$(PYTHON3_VERSION) \ + CFLAGS="$(TARGET_CFLAGS)" LDFLAGS="$(TARGET_LDFLAGS)" USE_SYSTEM=1 $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR)/profiles \ + $(MAKE_FLAGS) DESTDIR="$(PKG_INSTALL_DIR)-profiles" install +endef + +define Package/libapparmor/install + $(INSTALL_DIR) $(1)/usr/lib + $(INSTALL_BIN) $(PKG_INSTALL_DIR)-libapparmor/usr/lib/libapparmor.so.1 $(1)/usr/lib/ + $(LN) libapparmor.so.1 $(1)/usr/lib/libapparmor.so +endef + +define Package/python3-apparmor/install + $(INSTALL_DIR) \ + $(1)/usr/lib/python$(PYTHON3_VERSION)/site-packages \ + $(1)/usr/lib/python$(PYTHON3_VERSION)/site-packages/LibAppArmor + $(INSTALL_DATA) $(PKG_INSTALL_DIR)-libapparmor/usr/lib/python$(PYTHON3_VERSION)/site-packages/*.egg-info \ + $(1)/usr/lib/python$(PYTHON3_VERSION)/site-packages/ + $(INSTALL_DATA) $(PKG_INSTALL_DIR)-libapparmor/usr/lib/python$(PYTHON3_VERSION)/site-packages/LibAppArmor/*.py \ + $(1)/usr/lib/python$(PYTHON3_VERSION)/site-packages/LibAppArmor + $(INSTALL_BIN) $(PKG_INSTALL_DIR)-libapparmor/usr/lib/python$(PYTHON3_VERSION)/site-packages/LibAppArmor/*.so \ + $(1)/usr/lib/python$(PYTHON3_VERSION)/site-packages/LibAppArmor/ + $(LN) -s _LibAppArmor.cpython-$(PYTHON3_VERSION_MAJOR)$(PYTHON3_VERSION_MINOR).so \ + $(1)/usr/lib/python$(PYTHON3_VERSION)/site-packages/LibAppArmor/_LibAppArmor.so +endef + +define Package/apparmor-utils/install + $(INSTALL_DIR) $(1)/etc/apparmor $(1)/usr/sbin $(1)/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)-utils/sbin/apparmor_parser $(1)/sbin/ + $(INSTALL_CONF) $(PKG_INSTALL_DIR)-utils/etc/apparmor/*.conf $(1)/etc/apparmor/ + $(INSTALL_DATA) $(PKG_INSTALL_DIR)-utils/etc/apparmor/severity.db $(1)/etc/apparmor/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)-utils/sbin/apparmor_parser $(1)/sbin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)-utils/usr/bin/{aa-exec,aa-easyprof,aa-enabled,aa-features-abi} $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)-utils/usr/sbin/{aa-audit,aa-autodep,aa-cleanprof,aa-complain,aa-decode,aa-disable,aa-enforce,aa-genprof,aa-logprof,aa-mergeprof,aa-notify,aa-remove-unknown,aa-status,aa-unconfined} $(1)/usr/sbin/ + $(LN) aa-status $(1)/usr/sbin/apparmor_status + $(INSTALL_DIR) $(1)/usr/share/apparmor/easyprof/templates $(1)/usr/share/apparmor/easyprof/policygroups + $(INSTALL_DATA) $(PKG_INSTALL_DIR)-utils/usr/share/apparmor/easyprof/templates/* $(1)/usr/share/apparmor/easyprof/templates/ + $(INSTALL_DATA) $(PKG_INSTALL_DIR)-utils/usr/share/apparmor/easyprof/policygroups/* $(1)/usr/share/apparmor/easyprof/policygroups/ + $(INSTALL_DIR) $(1)/usr/lib/python3.9/site-packages $(1)/usr/lib/python3.9/site-packages/apparmor $(1)/usr/lib/python3.9/site-packages/apparmor/rule + $(INSTALL_DATA) $(PKG_INSTALL_DIR)-utils/usr/lib/python3.9/site-packages/*.egg-info \ + $(1)/usr/lib/python3.9/site-packages/ + $(INSTALL_DATA) $(PKG_INSTALL_DIR)-utils/usr/lib/python3.9/site-packages/apparmor/*.py \ + $(1)/usr/lib/python3.9/site-packages/apparmor/ + $(INSTALL_DATA) $(PKG_INSTALL_DIR)-utils/usr/lib/python3.9/site-packages/apparmor/rule/*.py \ + $(1)/usr/lib/python3.9/site-packages/apparmor/rule + $(INSTALL_DIR) $(1)/etc/init.d $(1)/lib/functions + $(INSTALL_BIN) ./files/apparmor.sh $(1)/lib/functions/ + $(INSTALL_BIN) ./files/apparmor.init $(1)/etc/init.d/apparmor +endef + +define Package/apparmor-profiles/install + $(INSTALL_DIR) $(1)/etc/apparmor.d $(1)/usr/share/apparmor/extra-profiles + $(CP) -aR $(PKG_INSTALL_DIR)-profiles/etc/apparmor.d/** $(1)/etc/apparmor.d/ + $(INSTALL_CONF) $(PKG_INSTALL_DIR)-profiles/usr/share/apparmor/extra-profiles/** $(1)/usr/share/apparmor/extra-profiles/ +endef + +$(eval $(call BuildPackage,libapparmor)) +$(eval $(call BuildPackage,python3-apparmor)) +$(eval $(call BuildPackage,apparmor-utils)) +$(eval $(call BuildPackage,apparmor-profiles)) diff --git a/utils/apparmor/files/apparmor.init b/utils/apparmor/files/apparmor.init new file mode 100755 index 000000000..576df39ac --- /dev/null +++ b/utils/apparmor/files/apparmor.init @@ -0,0 +1,22 @@ +#!/bin/sh /etc/rc.common + +START=75 +USE_PROCD=1 + +. /lib/functions/apparmor.sh + +restart() { + apparmor_restart +} + +start_service() { + apparmor_start +} + +stop_service() { + apparmor_stop +} + +reload_service() { + apparmor_reload +} diff --git a/utils/apparmor/files/apparmor.sh b/utils/apparmor/files/apparmor.sh new file mode 100755 index 000000000..5e9edb9dd --- /dev/null +++ b/utils/apparmor/files/apparmor.sh @@ -0,0 +1,380 @@ +#!/bin/sh + +log_write() { + local facility=kern.$1 + logger -t AppArmor -p $facility "$2" +} + +AA_STATUS=/usr/sbin/aa-status +SECURITYFS=/sys/kernel/security +SFS_MOUNTPOINT="${SECURITYFS}/apparmor" +PARSER=/sbin/apparmor_parser +PARSER_OPTS= +ADDITIONAL_PROFILE_DIR= + +[ -d /etc/apparmor.d ] && PROFILE_DIRS=/etc/apparmor.d || + log_write warning "Unable to find profiles: /etc/apparmor.d" + +[ -n "$ADDITIONAL_PROFILE_DIR" ] && [ -d "$ADDITIONAL_PROFILE_DIR" ] && + PROFILE_DIRS="$PROFILE_DIRS $ADDITIONAL_PROFILE_DIR" + +dir_is_empty() { + [ "$(du -s $1 | cut -f 1)" -eq 0 ] && return 0 || return 1 +} + +profiles_loaded_count() { + + [ -f ${SFS_MOUNTPOINT}/profiles ] && + return $(cat "${SFS_MOUNTPOINT}/profiles" | wc -l) || return 0 +} + +is_profiles_loaded() { + + [ -f ${SFS_MOUNTPOINT}/profiles ] && { + rc=$(cat "${SFS_MOUNTPOINT}/profiles" | wc -l) + [ "$rc" -ne 0 ] && return 0 || return 1 + } + return 1 +} + +is_container_with_internal_policy() { + + local ns_stacked_path="${SFS_MOUNTPOINT}/.ns_stacked" + local ns_name_path="${SFS_MOUNTPOINT}/.ns_name" + local ns_stacked + local ns_name + + if ! [ -f "$ns_stacked_path" ] || ! [ -f "$ns_name_path" ]; then + return 1 + fi + + read -r ns_stacked < "$ns_stacked_path" + if [ "$ns_stacked" != "yes" ]; then + return 1 + fi + + # LXD and LXC set up AppArmor namespaces starting with "lxd-" and + # "lxc-", respectively. Return non-zero for all other namespace + # identifiers. + + read -r ns_name < "$ns_name_path" + if [ "${ns_name#lxd-*}" = "$ns_name" ] && \ + [ "${ns_name#lxc-*}" = "$ns_name" ]; then + return 1 + fi + + return 0 +} + +skip_profile() { + + local profile="$1" + + if [ "${profile%.rpmnew}" != "$profile" ] || \ + [ "${profile%.rpmsave}" != "$profile" ] || \ + [ "${profile%.orig}" != "$profile" ] || \ + [ "${profile%.rej}" != "$profile" ] || \ + [ "${profile%\~}" != "$profile" ] ; then + return 1 + fi + + # Silently ignore the dpkg, pacman, ipk and xbps files + + if [ "${profile%.dpkg-new}" != "$profile" ] || \ + [ "${profile%.dpkg-old}" != "$profile" ] || \ + [ "${profile%.dpkg-dist}" != "$profile" ] || \ + [ "${profile%.dpkg-bak}" != "$profile" ] || \ + [ "${profile%.dpkg-remove}" != "$profile" ] || \ + [ "${profile%.ipk}" != "$profile" ] || \ + [ "${profile%.ipk-new}" != "$profile" ] || \ + [ "${profile%.ipk-old}" != "$profile" ] || \ + [ "${profile%.ipk-dist}" != "$profile" ] || \ + [ "${profile%.ipk-bak}" != "$profile" ] || \ + [ "${profile%.ipk-remove}" != "$profile" ] || \ + [ "${profile%.pacsave}" != "$profile" ] || \ + [ "${profile%.pacnew}" != "$profile" ] ; then + return 2 + fi + + $(echo "$profile" | grep -E -q '^.+\.new-[0-9\.]+_[0-9]+$'); [ "$?" -eq 0 ] && return 2 + + return 0 +} + +__parse_profiles_dir() { + + local parser_cmd="$1" + local profile_dir="$2" + local status=0 + + [ -x "$PARSER" ] || { + log_write err "Unable to execute AppArmor parser" + return 1 + } + + [ -d "$profile_dir" ] || { + log_write warning "AppArmor profiles not found: $profile_dir" + return 1 + } + + dir_is_empty "$profile_dir"; [ "$?" -eq 0 ] && { + log_write err "No profiles found in $profile_dir" + return 1 + } + + local nprocs=$(cat /proc/cpuinfo |grep "processor\t:"|wc -l) + local rc=0 + local xargs_args="" + [ "$nprocs" -ge 2 ] && xargs_args="--max-procs=$nprocs" + + "$PARSER" $PARSER_OPTS "$parser_cmd" -- "$profile_dir" || { + + for profile in "$profile_dir"/*; do + skip_profile "$profile" + skip=$? + [ "$skip" -ne 0 ] && { + [ "$skip" -ne 2 ] && log_write info "Skipped loading profile $profile" + continue + } + [ -f "$profile" ] || continue + echo "$profile" + done | \ + + # Use xargs to parallelize calls to the parser over all CPUs + + /usr/libexec/xargs-findutils -n1 -d"\n" $xargs_args \ + "$PARSER" $PARSER_OPTS "$parser_cmd" -- + + [ "$?" -ne 0 ] && { + rc=1 + log_write err "At least one profile failed to load" + } + } + + return $rc +} + +parse_profiles() { + + case "$1" in + load) + PARSER_CMD="--add" + PARSER_MSG="Loading profiles" + ;; + reload) + PARSER_CMD="--replace" + PARSER_MSG="Reloading profiles" + ;; + *) + log_write err "Unknown parameter $1" + log_write info "parse_profiles parameter must be either 'load' or 'reload'" + return 1 + ;; + esac + + log_write info "$PARSER_MSG" + + [ -w "$SFS_MOUNTPOINT/.load" ] || { + log_write err "${SFS_MOUNTPOINT}/.load not writable" + return 1 + } + + [ -f "$PARSER" ] || { + log_write err "AppArmor parser not found" + return 1 + } + + # run parser on all profiles + local rc=0 + for profile_dir in $PROFILE_DIRS; do + __parse_profiles_dir "$PARSER_CMD" "$profile_dir" || rc=$? + done + + return $rc +} + +is_apparmor_loaded() { + + is_securityfs_mounted; [ "$?" -eq 0 ] || { + mount_securityfs + } + + [ -f "${SFS_MOUNTPOINT}/profiles" ] && return 0 + [ -d /sys/module/apparmor ] && return 0 || return 1 +} + +is_securityfs_mounted() { + + [ -d "$SECURITYFS" ] && { + grep -q securityfs /proc/filesystems && grep -q securityfs /proc/mounts + return $? + } + return 1 +} + +mount_securityfs() { + + local rc=0 + + grep -q securityfs /proc/filesystems; [ "$?" -eq 0 ] && { + mount -t securityfs securityfs "$SECURITYFS" + rc=$? + [ "$rc" -eq 0 ] && log_write info "Mounting securityfs" || + log_write err "Failed to mount securityfs" + } + return $rc +} + +apparmor_start() { + + local announced=0 + is_securityfs_mounted; [ "$?" -ne 0 ] && { + log_write info "Starting AppArmor" + announced=1 + mount_securityfs; [ "$?" -eq 0 ] || return $? + } + + is_apparmor_loaded; [ "$?" -eq 0 ] || { + [ "$announced" -eq 0 ] && log_write info "Starting AppArmor" + announced=1 + log_write err "AppArmor kernel support is not present" + return 1 + } + + [ -d /var/lib/apparmor ] || mkdir -p /var/lib/apparmor > /dev/null + + is_profiles_loaded; [ "$?" -eq 0 ] || { + [ "$announced" -eq 0 ] && log_write info "Starting AppArmor" + announced=1 + parse_profiles load + return $? + } || { + parse_profiles reload + return $? + } +} + +remove_profiles() { + + log_write info "Unloading profiles" + + is_apparmor_loaded; [ "$?" -eq 0 ] || { + log_write err "AppArmor kernel support is not present" + return 1 + } + + [ -w "$SFS_MOUNTPOINT/.remove" ] || { + log_write err "${SFS_MOUNTPOINT}/.remove not writable" + return 1 + } + + [ -x "$PARSER" ] || { + log_write err "Unable to execute AppArmor parser" + return 1 + } + + local rc=0 + + sed -e "s/ (\(enforce\|complain\))$//" "$SFS_MOUNTPOINT/profiles" | \ + LC_COLLATE=C sort | grep -v // | { + while read -r profile ; do + printf "%s" "$profile" > "$SFS_MOUNTPOINT/.remove" + result=$? + [ "$result" -eq 0 ] || rc=$result + done + } + return $rc +} + +apparmor_stop() { + + is_apparmor_loaded; [ "$?" -eq 0 ] || return 1 + is_profiles_loaded; [ "$?" -eq 0 ] && { + log_write info "Stopping AppArmor" + remove_profiles + return $? + } || return 0 +} + +apparmor_restart() { + + is_profiles_loaded; [ "$?" -eq 0 ] || { + apparmor_start + return $? + } + + is_apparmor_loaded; [ "$?" -eq 0 ] || { + apparmor_start + return $? + } + + log_write info "Restarting AppArmor" + parse_profiles reload + return $? +} + +apparmor_reload() { + + is_profiles_loaded; [ "$?" -eq 0 ] || { + apparmor_start + return $? + } + + is_apparmor_loaded; [ "$?" -eq 0 ] || { + apparmor_start + return $? + } + + log_write info "Reloading AppArmor" + parse_profiles reload + return $? +} + +apparmor_list_profiles() { + + is_apparmor_loaded; [ "$?" -eq 0 ] || { + echo "AppArmor kernel support is not present" + return 1 + } + + [ -x "$PARSER" ] || { + echo "Unable to execute AppArmor parser" + return 1 + } + + # run parser on all profiles + for profile_dir in $PROFILE_DIRS; do + [ -d "$profile_dir" ] || { + echo "AppArmor profiles not found: $profile_dir" + continue + } + + for profile in "$profile_dir"/*; do + if skip_profile "$profile" && [ -f "$profile" ] ; then + LIST_ADD=$("$PARSER" -N "$profile" ) + [ "$?" -eq 0 ] && echo "$LIST_ADD" + fi + done + done + return 0 +} + + +apparmor_status() { + + is_apparmor_loaded; [ "$?" -eq 0 ] || { + echo "AppArmor kernel support is not present" + return 1 + } + + [ -x "$AA_STATUS" ] && { + "$AA_STATUS" --verbose + return $? + } + + echo "AppArmor is enabled." + echo "Install apparmor-utils to receive more detailed status" + echo "information or examine $SFS_MOUNTPOINT directly." + + return 0 +} diff --git a/utils/apparmor/patches/010-autoconf-libapparmor.patch b/utils/apparmor/patches/010-autoconf-libapparmor.patch new file mode 100644 index 000000000..bcb47d090 --- /dev/null +++ b/utils/apparmor/patches/010-autoconf-libapparmor.patch @@ -0,0 +1,10 @@ +--- /dev/null ++++ b/libraries/libapparmor/Makefile +@@ -0,0 +1,7 @@ ++package=libapparmor ++ ++configure: ++ $(STAGING_DIR_HOST)/bin/aclocal ++ $(STAGING_DIR_HOST)/bin/autoconf --force ++ $(STAGING_DIR_HOST)/bin/libtoolize --automake -c --force ++ $(STAGING_DIR_HOST)/bin/automake -ac diff --git a/utils/apparmor/patches/020-fix-ss-path.patch b/utils/apparmor/patches/020-fix-ss-path.patch new file mode 100644 index 000000000..11e53b021 --- /dev/null +++ b/utils/apparmor/patches/020-fix-ss-path.patch @@ -0,0 +1,11 @@ +--- a/utils/aa-unconfined ++++ b/utils/aa-unconfined +@@ -118,7 +118,7 @@ def read_proc_current(filename): + pids = set() + if paranoid: + pids = get_all_pids() +-elif args.with_ss or (not args.with_netstat and (os.path.exists('/bin/ss') or os.path.exists('/usr/bin/ss'))): ++elif args.with_ss or (not args.with_netstat and (os.path.exists('/usr/sbin/ss') or os.path.exists('/bin/ss') or os.path.exists('/usr/bin/ss') or os.path.exists('/sbin/ss'))): + pids = get_pids_ss() + else: + pids = get_pids_netstat() diff --git a/utils/apparmor/patches/030-remove-pynotify2-dep.patch b/utils/apparmor/patches/030-remove-pynotify2-dep.patch new file mode 100644 index 000000000..7de4ddc1e --- /dev/null +++ b/utils/apparmor/patches/030-remove-pynotify2-dep.patch @@ -0,0 +1,416 @@ +--- a/utils/aa-notify ++++ b/utils/aa-notify +@@ -13,17 +13,6 @@ + # + # ---------------------------------------------------------------------- + # +-# /etc/apparmor/notify.conf: +-# # set to 'yes' to enable AppArmor DENIED notifications +-# show_notifications="yes" +-# +-# # only people in use_group can run this script +-# use_group="admin" +-# +-# $HOME/.apparmor/notify.conf can have: +-# # set to 'yes' to enable AppArmor DENIED notifications +-# show_notifications="yes" +-# + # In a typical desktop environment one would run as a service the + # command: + # /usr/bin/aa-notify -p -w 10 +@@ -35,7 +24,6 @@ import re + import sys + import time + import struct +-import notify2 + import psutil + import pwd + import grp +@@ -60,56 +48,9 @@ def get_user_login(): + username = os.getlogin() + return username + +- +-def get_last_login_timestamp(username): +- '''Directly read wtmp and get last login for user as epoch timestamp''' +- timestamp = 0 +- filename = '/var/log/wtmp' +- last_login = 0 +- +- debug_logger.debug('Username: {}'.format(username)) +- +- with open(filename, "rb") as wtmp_file: +- offset = 0 +- wtmp_filesize = os.path.getsize(filename) +- debug_logger.debug('WTMP filesize: {}'.format(wtmp_filesize)) +- while offset < wtmp_filesize: +- wtmp_file.seek(offset) +- offset += 384 # Increment for next entry +- +- type = struct.unpack("<L", wtmp_file.read(4))[0] +- debug_logger.debug('WTMP entry type: {}'.format(type)) +- +- # Only parse USER lines +- if type == 7: +- # Read each item and move pointer forward +- pid = struct.unpack("<L", wtmp_file.read(4))[0] +- line = wtmp_file.read(32).decode("utf-8", "replace").split('\0', 1)[0] +- id = wtmp_file.read(4).decode("utf-8", "replace").split('\0', 1)[0] +- user = wtmp_file.read(32).decode("utf-8", "replace").split('\0', 1)[0] +- host = wtmp_file.read(256).decode("utf-8", "replace").split('\0', 1)[0] +- term = struct.unpack("<H", wtmp_file.read(2))[0] +- exit = struct.unpack("<H", wtmp_file.read(2))[0] +- session = struct.unpack("<L", wtmp_file.read(4))[0] +- timestamp = struct.unpack("<L", wtmp_file.read(4))[0] +- usec = struct.unpack("<L", wtmp_file.read(4))[0] +- entry = (pid, line, id, user, host, term, exit, session, timestamp, usec) +- debug_logger.debug('WTMP entry: {}'.format(entry)) +- +- # Store login timestamp for requested user +- if user == username: +- last_login = timestamp +- +- # When loop is done, last value should be the latest login timestamp +- return last_login +- +- + def format_event(event, logsource): + output = [] + +- if 'message_body' in config['']: +- output += [config['']['message_body']] +- + if event.profile: + output += ['Profile: {}'.format(event.profile)] + if event.operation: +@@ -126,7 +67,6 @@ def format_event(event, logsource): + + return "\n".join(output) + +- + def notify_about_new_entries(logfile, wait=0): + # Kill other instances of aa-notify if already running + for process in psutil.process_iter(): +@@ -154,7 +94,6 @@ def notify_about_new_entries(logfile, wa + # print("parent: %d, child: %d\n" % pids) + os._exit(0) # Exit child without calling exit handlers etc + +- + def show_entries_since_epoch(logfile, epoch_since): + count = 0 + for event in get_apparmor_events(logfile, epoch_since): +@@ -172,26 +111,7 @@ def show_entries_since_epoch(logfile, ep + ) + + if args.verbose: +- if 'message_footer' in config['']: +- print(config['']['message_footer']) +- else: +- print(_('For more information, please see: {}').format(debug_docs_url)) +- +- +-def show_entries_since_last_login(logfile, username=get_user_login()): +- # If running as sudo, use username of sudo user instead of root +- if 'SUDO_USER' in os.environ.keys(): +- username = os.environ['SUDO_USER'] +- +- if args.verbose: +- print(_('Showing entries since {} logged in').format(username)) +- print() # Newline +- epoch_since = get_last_login_timestamp(username) +- if epoch_since == 0: +- print(_('ERROR: Could not find last login'), file=sys.stderr) +- sys.exit(1) +- show_entries_since_epoch(logfile, epoch_since) +- ++ print(_('For more information, please see: {}').format(debug_docs_url)) + + def show_entries_since_days(logfile, since_days): + day_in_seconds = 60*60*24 +@@ -199,7 +119,6 @@ def show_entries_since_days(logfile, sin + epoch_since = epoch_now - day_in_seconds * since_days + show_entries_since_epoch(logfile, epoch_since) + +- + def follow_apparmor_events(logfile, wait=0): + '''Follow AppArmor events and yield relevant entries until process stops''' + +@@ -247,7 +166,6 @@ def follow_apparmor_events(logfile, wait + + time.sleep(1) + +- + def reopen_logfile_if_needed(logfile, logdata, log_inode, log_size): + retry = True + +@@ -279,7 +197,6 @@ def reopen_logfile_if_needed(logfile, lo + + return (logdata, log_inode, log_size) + +- + def get_apparmor_events(logfile, since=0): + '''Read audit events from log source and yield all relevant events''' + +@@ -293,7 +210,6 @@ def get_apparmor_events(logfile, since=0 + except PermissionError: + sys.exit(_("ERROR: Cannot read {}. Please check permissions.".format(logfile))) + +- + def parse_logdata(logsource): + '''Traverse any iterable log source and extract relevant AppArmor events''' + +@@ -327,53 +243,6 @@ def parse_logdata(logsource): + if event.operation[0:8] != 'profile_': + yield event + +- +-def drop_privileges(): +- '''If running as root, drop privileges to USER if known, or fall-back to nobody_user/group''' +- +- if os.geteuid() == 0: +- +- if 'SUDO_USER' in os.environ.keys(): +- next_username = os.environ['SUDO_USER'] +- next_uid = os.environ['SUDO_UID'] +- next_gid = os.environ['SUDO_GID'] +- else: +- nobody_user_info = pwd.getpwnam(nobody_user) +- next_username = nobody_user_info[0] +- next_uid = nobody_user_info[2] +- next_gid = nobody_user_info[3] +- +- debug_logger.debug('Dropping to user "{}" privileges'.format(next_username)) +- +- # @TODO? +- # Remove group privileges, including potential 'adm' group that might +- # have had log read access but also other accesses. +- # os.setgroups([]) +- +- # Try setting the new uid/gid +- # Set gid first, otherwise the latter step would fail on missing permissions +- os.setegid(int(next_gid)) +- os.seteuid(int(next_uid)) +- +-def raise_privileges(): +- '''If was running as user with saved user ID 0, raise back to root privileges''' +- +- if os.geteuid() != 0 and original_effective_user == 0: +- +- debug_logger.debug('Rasing privileges from UID {} back to UID 0 (root)'.format(os.geteuid())) +- +- # os.setgid(int(next_gid)) +- os.seteuid(original_effective_user) +- +-def read_notify_conf(path, shell_config): +- try: +- shell_config.CONF_DIR = path +- conf_dict = shell_config.read_config('notify.conf') +- debug_logger.debug('Found configuration file in {}/notify.conf'.format(shell_config.CONF_DIR)) +- return conf_dict +- except FileNotFoundError: +- return {} +- + def main(): + ''' + Main function of aa-notify that parses command line +@@ -381,10 +250,9 @@ def main(): + ''' + + global _, debug_logger, config, args +- global debug_docs_url, nobody_user, original_effective_user, timeformat ++ global debug_docs_url, original_effective_user, timeformat + + debug_docs_url = "https://wiki.ubuntu.com/DebuggingApparmor" +- nobody_user = "nobody" + timeformat = "%c" # Automatically using locale format + original_effective_user = os.geteuid() + +@@ -403,180 +271,37 @@ def main(): + debug_logger.debug("Starting aa-notify") + + parser = argparse.ArgumentParser(description=_('Display AppArmor notifications or messages for DENIED entries.')) +- parser.add_argument('-p', '--poll', action='store_true', help=_('poll AppArmor logs and display notifications')) +- parser.add_argument('--display', type=str, help=_('set the DISPLAY environment variable (might be needed if sudo resets $DISPLAY)')) +- parser.add_argument('-f', '--file', type=str, help=_('search FILE for AppArmor messages')) +- parser.add_argument('-l', '--since-last', action='store_true', help=_('display stats since last login')) +- parser.add_argument('-s', '--since-days', type=int, metavar=('NUM'), help=_('show stats for last NUM days (can be used alone or with -p)')) +- parser.add_argument('-v', '--verbose', action='store_true', help=_('show messages with stats')) +- parser.add_argument('-u', '--user', type=str, help=_('user to drop privileges to when not using sudo')) +- parser.add_argument('-w', '--wait', type=int, metavar=('NUM'), help=_('wait NUM seconds before displaying notifications (with -p)')) +- parser.add_argument('--debug', action='store_true', help=_('debug mode')) +- parser.add_argument('--configdir', type=str, help=argparse.SUPPRESS) ++ parser.add_argument('-f', '--file', type=str, help=_('Logfile to parse for AppArmor messages')) ++ parser.add_argument('-s', '--since-days', type=int, metavar=('NUM'), help=_('Show stats for last NUM days')) ++ parser.add_argument('-v', '--verbose', action='store_true', help=_('Show messages with stats')) ++ parser.add_argument('--debug', action='store_true', help=_('Debug mode')) + + # If a TTY then assume running in test mode and fix output width + if not sys.stdout.isatty(): + parser.formatter_class = lambda prog: argparse.HelpFormatter(prog, width=80) + + args = parser.parse_args() ++ args.user = 'root' + + # Debug mode can be invoked directly with --debug or env LOGPROF_DEBUG=3 + if args.debug: + debug_logger.activateStderr() + debug_logger.debug('Logging level: {}'.format(debug_logger.debug_level)) + debug_logger.debug('Running as uid: {0[0]}, euid: {0[1]}, suid: {0[2]}'.format(os.getresuid())) +- if args.poll: +- debug_logger.debug('Running with --debug and --poll. Will exit in 100s') +- # Sanity checks +- user_ids = os.getresuid() +- groups_ids = os.getresgid() +- if user_ids[1] != user_ids[2]: +- sys.exit("ERROR: Cannot be started with suid set!") +- if groups_ids[1] != groups_ids[2]: +- sys.exit("ERROR: Cannot be started with sgid set!") + +- # Define global variables that will be populated by init_aa() +- # conf = None + logfile = None + +- if args.configdir: # prefer --configdir if given +- confdir = args.configdir +- else: # fallback to env variable (or None if not set) +- confdir = os.getenv('__AA_CONFDIR') +- +- aa.init_aa(confdir=confdir) +- + # Initialize aa.logfile +- aa.set_logfile(args.file) +- +- # Load global config reader +- shell_config = aaconfig.Config('shell') +- +- # Load system's notify.conf +- # By default aa.CONFDIR is /etc/apparmor on most production systems +- system_config = read_notify_conf(aa.CONFDIR, shell_config) +- # Set default is no system notify.conf was found +- if not system_config: +- system_config = {'': {'show_notifications': 'yes'}} +- +- # Load user's notify.conf +- if os.path.isfile(os.environ['HOME'] + '/.apparmor/notify.conf'): +- # Use legacy path if the conf file is there +- user_config = read_notify_conf(os.environ['HOME'] + '/.apparmor', shell_config) +- elif 'XDG_CONFIG_HOME' in os.environ and os.path.isfile(os.environ['XDG_CONFIG_HOME'] + '/apparmor/notify.conf'): +- # Use XDG_CONFIG_HOME if it is defined +- user_config = read_notify_conf(os.environ['XDG_CONFIG_HOME'] + '/apparmor', shell_config) +- else: +- # Fallback to the default value of XDG_CONFIG_HOME +- user_config = read_notify_conf(os.environ['HOME'] + '/.config/apparmor', shell_config) +- +- # Merge the two config dicts in an accurate and idiomatic way (requires Python 3.5) +- config = {**system_config, **user_config} +- +- """ +- Possible configuration options: +- - show_notifications +- - message_body +- - message_footer +- - use_group +- """ +- +- # # Config checks +- +- # Warn about unknown keys in the config +- allowed_config_keys = [ +- 'use_group', +- 'show_notifications', +- 'message_body', +- 'message_footer' +- ] +- found_config_keys = config[''].keys() +- unknown_keys = [item for item in found_config_keys if item not in allowed_config_keys] +- for item in unknown_keys: +- print(_('Warning! Configuration item "{}" is unknown!').format(item)) +- +- # Warn if use_group is defined and current group does not match defined +- if 'use_group' in config['']: +- user = pwd.getpwuid(os.geteuid())[0] +- user_groups = [g.gr_name for g in grp.getgrall() if user in g.gr_mem] +- gid = pwd.getpwnam(user).pw_gid +- user_groups.append(grp.getgrgid(gid).gr_name) +- +- if config['']['use_group'] not in user_groups: +- print( +- _('ERROR! User {user} not member of {group} group!').format( +- user=user, +- group=config['']['use_group'] +- ), +- file=sys.stderr +- ) +- sys.exit(1) +- # @TODO: Extend UI lib to have warning and error functions that +- # can be used in an uniform way with both text and JSON output. +- + if args.file: + logfile = args.file +- elif os.path.isfile('/var/run/auditd.pid') and os.path.isfile('/var/log/audit/audit.log'): +- # If auditd is running, look at /var/log/audit/audit.log +- logfile = '/var/log/audit/audit.log' +- elif os.path.isfile('/var/log/kern.log'): +- # For aa-notify, the fallback is kern.log, not syslog from aa.logfile +- logfile = '/var/log/kern.log' ++ aa.set_logfile(args.file) + else: +- # If all above failed, use aa cfg +- logfile = aa.logfile ++ logfile = '/var/log/audit/audit.log' ++ aa.set_logfile('/var/log/audit/audit.log') + + if args.verbose: + print(_('Using log file'), logfile) + +- if args.display: +- os.environ['DISPLAY'] = args.display +- +- if args.poll: +- # Exit immediately if show_notifications is no or any of the options below +- if config['']['show_notifications'] in [False, 'no', 'false', '0']: +- print(_('Showing notifications forbidden in notify.conf, aborting..')) +- sys.exit(0) +- +- # Don't allow usage of aa-notify by root, must be some user. Desktop +- # logins as root are not recommended and certainly not a use case for +- # aa-notify notifications. +- if not args.user and os.getuid() == 0 and 'SUDO_USER' not in os.environ.keys(): +- sys.exit("ERROR: Cannot be started a real root user. Use --user to define what user to use.") +- +- # At this point this script needs to be able to read 'logfile' but once +- # the for loop starts, privileges can be dropped since the file descriptor +- # has been opened and access granted. Further reads of the file will not +- # trigger any new permission checks. +- # @TODO Plan to catch PermissionError here or..? +- for message in notify_about_new_entries(logfile, args.wait): +- +- # Notifications should not be run as root, since root probably is +- # the wrong desktop user and not the one getting the notifications. +- drop_privileges() +- +- # sudo does not preserve DBUS address, so we need to guess it based on UID +- if 'DBUS_SESSION_BUS_ADDRESS' not in os.environ: +- os.environ['DBUS_SESSION_BUS_ADDRESS'] = 'unix:path=/run/user/{}/bus'.format(os.geteuid()) +- +- # Before use, notify2 must be initialized and the DBUS channel +- # should be opened using the non-root user. This this step needs to +- # be executed after the drop_privileges(). +- notify2.init('AppArmor') +- +- n = notify2.Notification( +- _('AppArmor notification'), +- message, +- 'gtk-dialog-warning' +- ) +- n.show() +- +- # When notification is sent, raise privileged back to root if the +- # original effective user id was zero (to be able to read AppArmor logs) +- raise_privileges() +- +- elif args.since_last: +- show_entries_since_last_login(logfile) + elif args.since_days: + show_entries_since_days(logfile, args.since_days) + else: diff --git a/utils/apparmor/patches/040-remove-bash-dep.patch b/utils/apparmor/patches/040-remove-bash-dep.patch new file mode 100644 index 000000000..98ef107a8 --- /dev/null +++ b/utils/apparmor/patches/040-remove-bash-dep.patch @@ -0,0 +1,134 @@ +--- a/utils/aa-decode ++++ b/utils/aa-decode +@@ -1,4 +1,4 @@ +-#!/bin/bash ++#!/bin/sh + # + # Copyright (C) 2009-2010, 2012 Canonical Ltd. + # Copyright (C) 2012 Christian Boltz +@@ -16,8 +16,6 @@ + # along with this program; if not, contact Canonical, Ltd. + # + +-set -e +- + help() { + cat <<EOM + USAGE: aa-decode [OPTIONS] <encoded string> +@@ -36,13 +34,15 @@ $ cat /var/log/kern.log | aa-decode + EOM + } + +-decode() { +- if echo "$1" | egrep -q "^[0-9A-Fa-f]+$" ; then +- python3 -c "import binascii; print(bytes.decode(binascii.unhexlify('$1'), errors='strict'));" +- else +- echo "" +- fi ++match_re() { ++ local result=$(echo "$1" | grep -E "$2" ) ++ [ -z "$result" ] && return 1 || return 0 ++} + ++ ++decode() { ++ $(echo "$1" | egrep -q "^[0-9A-Fa-f]+$"); [ "$?" -eq 0 ] && ++ python3 -c "import binascii; print(bytes.decode(binascii.unhexlify('$1'), errors='strict'));" || echo "" + } + + if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then +@@ -51,47 +51,61 @@ if [ "$1" = "-h" ] || [ "$1" = "--help" + fi + + # if have an argument, then use it, otherwise process stdin +-if [ -n "$1" ]; then +- e="$1" +- if ! echo "$e" | egrep -q "^[0-9A-Fa-f]+$" ; then +- echo "String should only contain hex characters (0-9, a-f, A-F)" +- exit 1 +- fi +- +- d=`decode $e` +- if [ -z "$d" ]; then +- echo "Could not decode string" +- exit 1 +- fi ++[ -n "$1" ] && { + +- echo "Decoded: $d" +- exit 0 +-fi ++ e="$1" + +-# For now just look at 'name=...' and 'profile=...', +-# so validate input against this and output based on it. +-# TODO: better handle other cases too +-while read line ; do ++ $(echo "$e" | egrep -q "^[0-9A-Fa-f]+$"); [ "$?" -ne 0 ] && { ++ echo "String should only contain hex characters (0-9, a-f, A-F)" ++ exit 1 ++ } + +- # check if line contains encoded name= or profile= +- if [[ "$line" =~ \ (name|profile|proctitle)=[0-9a-fA-F] ]]; then ++ d=$(decode $e) + +- # cut the encoded filename/profile name out of the line and decode it +- ne=`echo "$line" | sed 's/.* name=\([^ ]*\).*$/\\1/g'` +- nd="$(decode ${ne/\'/\\\'})" ++ [ -z "$d" ] && { ++ echo "Could not decode string" ++ exit 1 ++ } + +- pe=`echo "$line" | sed 's/.* profile=\([^ ]*\).*$/\\1/g'` +- pd="$(decode ${pe/\'/\\\'})" ++ echo "Decoded: $d" ++ exit 0 ++} + +- pce=`echo "$line" | sed 's/.* proctitle=\([^ ]*\).*$/\\1/g'` +- pcd="$(decode ${pce/\'/\\\'})" ++[ -t 0 ] && { ++ help ++ exit ++} ++ ++while read line ; do + +- # replace encoded name and profile with its decoded counterparts (only if it was encoded) +- test -n "$nd" && line="${line/name=$ne/name=\"$nd\"}" +- test -n "$pd" && line="${line/profile=$pe/profile=\"$pd\"}" +- test -n "$pcd" && line="${line/proctitle=$pce/proctitle=\"$pcd\"}" ++ # check if line contains encoded name= or profile= + +- fi ++ matches=0 ++ match_re "$line" "^[[:blank:]](name|profile|proctitle)=[0-9a-fA-F]+"; [ "$?" -eq 0 ] && matches=1 || { ++ match_re "$line" "^(name|profile|proctitle)=[0-9a-fA-F]+"; [ "$?" -eq 0 ] && matches=1 ++ } ++ ++ [ "$matches" -eq 0 ] || { ++ ++ # cut the encoded filename/profile name out of the line and decode it ++ ne=$(echo "$line" | sed 's/.* name=\([^ ]*\).*$/\\1/g') ++ [ "$line" = "$ne" ] && ne=$(echo "$line" | sed 's/.*name=\([^ ]*\).*$/\\1/g') ++ echo var: $ne ++ nd="$(decode ${ne/\'/\\\'})" ++ ++ pe=$(echo "$line" | sed 's/.* profile=\([^ ]*\).*$/\\1/g') ++ [ "$line" = "$pe" ] && pe=$(echo "$line" | sed 's/.*profile=\([^ ]*\).*$/\\1/g') ++ pd="$(decode ${pe/\'/\\\'})" ++ ++ pce=$(echo "$line" | sed 's/.* proctitle=\([^ ]*\).*$/\\1/g') ++ [ "$line" = "$pce" ] && pce=$(echo "$line" | sed 's/.*proctitle=\([^ ]*\).*$/\\1/g') ++ pcd="$(decode ${pce/\'/\\\'})" ++ ++ # replace encoded name and profile with its decoded counterparts (only if it was encoded) ++ test -n "$nd" && line="${line/name=$ne/name=\"$nd\"}" ++ test -n "$pd" && line="${line/profile=$pe/profile=\"$pd\"}" ++ test -n "$pcd" && line="${line/proctitle=$pce/proctitle=\"$pcd\"}" ++ } + + echo "$line" + diff --git a/utils/apparmor/patches/050-disable-man-pages.patch b/utils/apparmor/patches/050-disable-man-pages.patch new file mode 100644 index 000000000..a0463f152 --- /dev/null +++ b/utils/apparmor/patches/050-disable-man-pages.patch @@ -0,0 +1,69 @@ +--- a/binutils/Makefile ++++ b/binutils/Makefile +@@ -107,7 +107,7 @@ docs: manpages + indep: docs + $(Q)$(MAKE) -C po all + +-all: arch indep ++all: arch + + .PHONY: coverage + coverage: +@@ -147,7 +147,7 @@ tests: $(BINTOOLS) $(SBINTOOLS) $(TESTS) + echo "no tests atm" + + .PHONY: install +-install: install-indep install-arch ++install: install-arch + + .PHONY: install-arch + install-arch: arch +--- a/parser/Makefile ++++ b/parser/Makefile +@@ -195,7 +195,7 @@ extra_docs: pdf + indep: docs + $(Q)$(MAKE) -C po all + +-all: arch indep ++all: arch + + .PHONY: coverage + coverage: +@@ -396,7 +396,6 @@ endif + + .PHONY: install + install: +- $(MAKE) install-indep + $(MAKE) install-arch + + .PHONY: install-arch +--- a/utils/Makefile ++++ b/utils/Makefile +@@ -31,9 +31,7 @@ MANPAGES = ${TOOLS:=.8} logprof.conf.5 + + PYFLAKES ?= pyflakes3 + +-all: docs +- $(MAKE) -C po all +- $(MAKE) -C vim all ++all: clean + + .PHONY: docs + docs: ${MANPAGES} ${HTMLMANPAGES} +@@ -49,15 +47,12 @@ po/${NAME}.pot: ${TOOLS} ${PYMODULES} + $(MAKE) -C po ${NAME}.pot NAME=${NAME} SOURCES="${TOOLS} ${PYMODULES}" + + .PHONY: install +-install: ${MANPAGES} ${HTMLMANPAGES} ++install: + install -d ${CONFDIR} + install -m 644 logprof.conf severity.db notify.conf ${CONFDIR} + install -d ${BINDIR} + # aa-easyprof is installed by python-tools-setup.py + install -m 755 $(filter-out aa-easyprof, ${TOOLS}) ${BINDIR} +- $(MAKE) -C po install DESTDIR=${DESTDIR} NAME=${NAME} +- $(MAKE) install_manpages DESTDIR=${DESTDIR} +- $(MAKE) -C vim install DESTDIR=${DESTDIR} + ${PYTHON} ${PYSETUP} install --prefix=${PYPREFIX} --root=${DESTDIR} --version=${VERSION} + + .PHONY: clean diff --git a/utils/apparmor/patches/060-openwrt-dnsmasq-profile.patch b/utils/apparmor/patches/060-openwrt-dnsmasq-profile.patch new file mode 100644 index 000000000..cc957ecdf --- /dev/null +++ b/utils/apparmor/patches/060-openwrt-dnsmasq-profile.patch @@ -0,0 +1,190 @@ +--- a/profiles/apparmor.d/usr.sbin.dnsmasq ++++ b/profiles/apparmor.d/usr.sbin.dnsmasq +@@ -1,3 +1,10 @@ ++# Last Modified: Thu Jun 10 01:23:44 2021 ++abi <abi/3.0>, ++ ++include <tunables/global> ++ ++@{TFTP_DIR} = /srv/tftp /srv/tftpboot /var/tftp ++ + # ------------------------------------------------------------------ + # + # Copyright (C) 2009 John Dong <jdong@ubuntu.com> +@@ -9,126 +16,95 @@ + # + # ------------------------------------------------------------------ + +-abi <abi/3.0>, +- +-@{TFTP_DIR}=/var/tftp /srv/tftp /srv/tftpboot + +-include <tunables/global> + profile dnsmasq /usr/{bin,sbin}/dnsmasq flags=(attach_disconnected) { + include <abstractions/base> + include <abstractions/dbus> + include <abstractions/nameservice> ++ include <abstractions/user-tmp> ++ include if exists <local/usr.sbin.dnsmasq> + + capability chown, ++ capability dac_override, ++ capability net_admin, # for DHCP server + capability net_bind_service, ++ capability net_raw, # for DHCP server ping checks + capability setgid, + capability setuid, +- capability dac_override, +- capability net_admin, # for DHCP server +- capability net_raw, # for DHCP server ping checks ++ + network inet raw, + network inet6 raw, + +- signal (receive) peer=/usr/{bin,sbin}/libvirtd, +- signal (receive) peer=libvirtd, +- ptrace (readby) peer=/usr/{bin,sbin}/libvirtd, +- ptrace (readby) peer=libvirtd, ++ signal receive peer=/usr/{bin,sbin}/libvirtd, ++ signal receive peer=libvirtd, + +- owner /dev/tty rw, ++ ptrace readby peer=/usr/{bin,sbin}/libvirtd, ++ ptrace readby peer=libvirtd, + +- @{PROC}/@{pid}/fd/ r, +- +- /etc/dnsmasq.conf r, +- /etc/dnsmasq.d/ r, +- /etc/dnsmasq.d/* r, +- /etc/dnsmasq.d-available/ r, +- /etc/dnsmasq.d-available/* r, +- /etc/ethers r, +- /etc/NetworkManager/dnsmasq.d/ r, +- /etc/NetworkManager/dnsmasq.d/* r, + /etc/NetworkManager/dnsmasq-shared.d/ r, + /etc/NetworkManager/dnsmasq-shared.d/* r, ++ /etc/NetworkManager/dnsmasq.d/ r, ++ /etc/NetworkManager/dnsmasq.d/* r, + /etc/dnsmasq-conf.conf r, + /etc/dnsmasq-resolv.conf r, +- +- /usr/{bin,sbin}/dnsmasq mr, +- +- /var/log/dnsmasq*.log w, +- ++ /etc/dnsmasq.conf r, ++ /etc/dnsmasq.d-available/ r, ++ /etc/dnsmasq.d-available/* r, ++ /etc/dnsmasq.d/ r, ++ /etc/dnsmasq.d/* r, ++ /etc/ethers r, ++ /tmp/** r, ++ /usr/libexec/libvirt_leaseshelper Cx -> libvirt_leaseshelper, ++ /usr/lib{,64}/libvirt/libvirt_leaseshelper Cx -> libvirt_leaseshelper, + /usr/share/dnsmasq{-base,}/ r, + /usr/share/dnsmasq{-base,}/* r, +- +- @{run}/*dnsmasq*.pid w, +- @{run}/dnsmasq-forwarders.conf r, +- @{run}/dnsmasq/ r, +- @{run}/dnsmasq/* rw, +- ++ /usr/{bin,sbin}/dnsmasq mr, ++ /var/lib/NetworkManager/dnsmasq-*.leases rw, ++ /var/lib/libvirt/dnsmasq/ r, ++ /var/lib/libvirt/dnsmasq/* r, ++ /var/lib/lxd-bridge/dnsmasq.*.leases rw, ++ /var/lib/lxd/networks/*/dnsmasq.* r, ++ /var/lib/lxd/networks/*/dnsmasq.leases rw, ++ /var/lib/lxd/networks/*/dnsmasq.pid rw, ++ /var/lib/misc/dnsmasq.*.leases rw, + /var/lib/misc/dnsmasq.leases rw, # Required only for DHCP server usage +- ++ /var/log/dnsmasq*.log w, + /{,usr/}bin/{ba,da,}sh ix, # Required to execute --dhcp-script argument +- +- # access to iface mtu needed for Router Advertisement messages in IPv6 +- # Neighbor Discovery protocol (RFC 2461) ++ @{PROC}/@{pid}/fd/ r, + @{PROC}/sys/net/ipv6/conf/*/mtu r, +- +- # for the read-only TFTP server + @{TFTP_DIR}/ r, + @{TFTP_DIR}/** r, +- +- # libvirt config and hosts file for dnsmasq +- /var/lib/libvirt/dnsmasq/ r, +- /var/lib/libvirt/dnsmasq/* r, +- +- # libvirt pid files for dnsmasq +- @{run}/libvirt/network/ r, ++ @{run}/*dnsmasq*.pid w, ++ @{run}/NetworkManager/NetworkManager.pid w, ++ @{run}/NetworkManager/dnsmasq.conf r, ++ @{run}/NetworkManager/dnsmasq.pid w, ++ @{run}/dnsmasq-forwarders.conf r, ++ @{run}/dnsmasq/ r, ++ @{run}/dnsmasq/* rw, ++ @{run}/libvirt/network/ r, + @{run}/libvirt/network/*.pid rw, +- +- # libvirt lease helper +- /usr/lib{,64}/libvirt/libvirt_leaseshelper Cx -> libvirt_leaseshelper, +- /usr/libexec/libvirt_leaseshelper Cx -> libvirt_leaseshelper, +- +- # lxc-net pid and lease files +- @{run}/lxc/dnsmasq.pid rw, +- /var/lib/misc/dnsmasq.*.leases rw, +- +- # lxd-bridge pid and lease files +- @{run}/lxd-bridge/dnsmasq.pid rw, +- /var/lib/lxd-bridge/dnsmasq.*.leases rw, +- /var/lib/lxd/networks/*/dnsmasq.* r, +- /var/lib/lxd/networks/*/dnsmasq.leases rw, +- /var/lib/lxd/networks/*/dnsmasq.pid rw, +- +- # NetworkManager integration +- /var/lib/NetworkManager/dnsmasq-*.leases rw, ++ @{run}/lxc/dnsmasq.pid rw, ++ @{run}/lxd-bridge/dnsmasq.pid rw, + @{run}/nm-dns-dnsmasq.conf r, + @{run}/nm-dnsmasq-*.pid rw, + @{run}/sendsigs.omit.d/*dnsmasq.pid w, +- @{run}/NetworkManager/dnsmasq.conf r, +- @{run}/NetworkManager/dnsmasq.pid w, +- @{run}/NetworkManager/NetworkManager.pid w, ++ owner /dev/tty rw, ++ + + profile libvirt_leaseshelper { + include <abstractions/base> + + /etc/libnl-3/classid r, +- +- /usr/lib{,64}/libvirt/libvirt_leaseshelper m, + /usr/libexec/libvirt_leaseshelper m, +- +- owner @{PROC}/@{pid}/net/psched r, +- owner @{PROC}/@{pid}/status r, +- ++ /usr/lib{,64}/libvirt/libvirt_leaseshelper m, ++ /var/lib/libvirt/dnsmasq/*.leases rw, ++ /var/lib/libvirt/dnsmasq/*.status* rw, ++ @{run}/leaseshelper.pid rwk, + @{sys}/devices/system/cpu/ r, + @{sys}/devices/system/node/ r, + @{sys}/devices/system/node/*/meminfo r, ++ owner @{PROC}/@{pid}/net/psched r, ++ owner @{PROC}/@{pid}/status r, + +- # libvirt lease and status files for dnsmasq +- /var/lib/libvirt/dnsmasq/*.leases rw, +- /var/lib/libvirt/dnsmasq/*.status* rw, +- +- @{run}/leaseshelper.pid rwk, + } +- +- # Site-specific additions and overrides. See local/README for details. +- include if exists <local/usr.sbin.dnsmasq> + } |
