apparmor: cleanup
authorMichal Vasilek <michal.vasilek@nic.cz>
Fri, 12 Nov 2021 16:02:51 +0000 (17:02 +0100)
committerMichal Vasilek <michal.vasilek@nic.cz>
Thu, 13 Jan 2022 10:59:58 +0000 (11:59 +0100)
* replace 020-fix-ss-path.patch with an upstream patch 020-remove-which-dep.patch
* remove 030-remove-pynotify2-dep.patch and do not install aa-notify
* simplify 060-openwrt-dnsmasq-profile.patch
* add two upstream patches for Python 3.10 compatibility
* add an upstream patch to move from deprecated distutils which broke
  the build with Python 3.10+

Signed-off-by: Michal Vasilek <michal.vasilek@nic.cz>
utils/apparmor/Makefile
utils/apparmor/patches/020-fix-ss-path.patch [deleted file]
utils/apparmor/patches/020-remove-which-dep.patch [new file with mode: 0644]
utils/apparmor/patches/030-remove-pynotify2-dep.patch [deleted file]
utils/apparmor/patches/030-systemd.patch [new file with mode: 0644]
utils/apparmor/patches/060-openwrt-dnsmasq-profile.patch
utils/apparmor/patches/070-python-3.10.patch [new file with mode: 0644]
utils/apparmor/patches/070-systemd.patch [deleted file]
utils/apparmor/patches/080-add-new-python-versions-to-logprof-conf.patch [new file with mode: 0644]
utils/apparmor/patches/090-setuptools.patch [new file with mode: 0644]

index 6a100aabc085b649eb2468462740b08196726460..3073fb605115745a9aab988896eafc4d98bdbd3d 100644 (file)
@@ -6,10 +6,10 @@ PKG_NAME:=apparmor
 PKG_VERSION:=3.0.3
 PKG_RELEASE:=$(AUTORELEASE)
 
-PKG_SOURCE_PROTO:=git
-PKG_SOURCE_URL:=https://gitlab.com/apparmor/apparmor.git
-PKG_SOURCE_VERSION:=0325ba06da6eeb5acf3e568063a08136fd0913e0
-PKG_MIRROR_HASH:=2c8f4607b9936f401a3fcb92cbc3627dc5b551fbde089162172e1801faba68bc
+PKG_SOURCE:=$(PKG_NAME)-v$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=https://gitlab.com/apparmor/apparmor/-/archive/v$(PKG_VERSION)
+PKG_HASH:=66db49cc578e6a85ba2fc350507ad1741d2534cdfc7ed71a81261f84d6e2262d
+PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)-v$(PKG_VERSION)
 
 PKG_LICENSE:=GPL-2.0-only
 PKG_LICENSE_FILES:=LICENSE
@@ -168,13 +168,15 @@ 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/
+               $(1)/usr/lib/python$(PYTHON3_VERSION)/site-packages/LibAppArmor \
+               $(1)/usr/lib/python$(PYTHON3_VERSION)/site-packages/LibAppArmor \
+               $(1)/usr/lib/python$(PYTHON3_VERSION)/site-packages/LibAppArmor-$(PKG_VERSION)-py$(PYTHON3_VERSION).egg-info
        $(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/
+       $(INSTALL_DATA) $(PKG_INSTALL_DIR)-libapparmor/usr/lib/python$(PYTHON3_VERSION)/site-packages/LibAppArmor-$(PKG_VERSION)-py$(PYTHON3_VERSION).egg-info/* \
+               $(1)/usr/lib/python$(PYTHON3_VERSION)/site-packages/LibAppArmor-$(PKG_VERSION)-py$(PYTHON3_VERSION).egg-info/
        $(LN) -s _LibAppArmor.cpython-$(PYTHON3_VERSION_MAJOR)$(PYTHON3_VERSION_MINOR).so \
                $(1)/usr/lib/python$(PYTHON3_VERSION)/site-packages/LibAppArmor/_LibAppArmor.so
 endef
@@ -187,18 +189,21 @@ define Package/apparmor-utils/install
        $(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/
+       $(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-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/python$(PYTHON3_VERSION)/site-packages $(1)/usr/lib/python$(PYTHON3_VERSION)/site-packages/apparmor $(1)/usr/lib/python$(PYTHON3_VERSION)/site-packages/apparmor/rule
-       $(INSTALL_DATA) $(PKG_INSTALL_DIR)-utils/usr/lib/python$(PYTHON3_VERSION)/site-packages/*.egg-info \
-               $(1)/usr/lib/python$(PYTHON3_VERSION)/site-packages/
+       $(INSTALL_DIR) $(1)/usr/lib/python$(PYTHON3_VERSION)/site-packages \
+               $(1)/usr/lib/python$(PYTHON3_VERSION)/site-packages/apparmor \
+               $(1)/usr/lib/python$(PYTHON3_VERSION)/site-packages/apparmor/rule \
+               $(1)/usr/lib/python$(PYTHON3_VERSION)/site-packages/apparmor-$(PKG_VERSION)-py$(PYTHON3_VERSION).egg-info
        $(INSTALL_DATA) $(PKG_INSTALL_DIR)-utils/usr/lib/python$(PYTHON3_VERSION)/site-packages/apparmor/*.py \
                $(1)/usr/lib/python$(PYTHON3_VERSION)/site-packages/apparmor/
        $(INSTALL_DATA) $(PKG_INSTALL_DIR)-utils/usr/lib/python$(PYTHON3_VERSION)/site-packages/apparmor/rule/*.py \
                $(1)/usr/lib/python$(PYTHON3_VERSION)/site-packages/apparmor/rule
+       $(INSTALL_DATA) $(PKG_INSTALL_DIR)-utils/usr/lib/python$(PYTHON3_VERSION)/site-packages/apparmor-$(PKG_VERSION)-py$(PYTHON3_VERSION).egg-info/* \
+               $(1)/usr/lib/python$(PYTHON3_VERSION)/site-packages/apparmor-$(PKG_VERSION)-py$(PYTHON3_VERSION).egg-info/
        $(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
diff --git a/utils/apparmor/patches/020-fix-ss-path.patch b/utils/apparmor/patches/020-fix-ss-path.patch
deleted file mode 100644 (file)
index 11e53b0..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
---- 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/020-remove-which-dep.patch b/utils/apparmor/patches/020-remove-which-dep.patch
new file mode 100644 (file)
index 0000000..07b481d
--- /dev/null
@@ -0,0 +1,92 @@
+From c31d49234f0c7a81b69d525e249b154e11c486a9 Mon Sep 17 00:00:00 2001
+From: Michal Vasilek <michal.vasilek@nic.cz>
+Date: Thu, 12 Aug 2021 15:57:01 +0200
+Subject: [PATCH] utils: use internal which implementation
+
+* removes runtime dependency on which
+* fixes aa-unconfined when ss is installed outside {/usr,}/bin
+
+Signed-off-by: Michal Vasilek <michal.vasilek@nic.cz>
+---
+ utils/aa-unconfined        |  2 +-
+ utils/apparmor/easyprof.py |  8 +++-----
+ utils/apparmor/sandbox.py  | 10 ++++------
+ 3 files changed, 8 insertions(+), 12 deletions(-)
+
+--- a/utils/aa-unconfined
++++ b/utils/aa-unconfined
+@@ -116,7 +116,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 (aa.which("ss") is not None)):
+     pids = get_pids_ss()
+ else:
+     pids = get_pids_netstat()
+--- a/utils/apparmor/easyprof.py
++++ b/utils/apparmor/easyprof.py
+@@ -22,6 +22,8 @@ import subprocess
+ import sys
+ import tempfile
++from apparmor.aa import which
++
+ #
+ # TODO: move this out to the common library
+ #
+@@ -294,13 +296,9 @@ class AppArmorEasyProfile:
+         if os.path.isfile(self.conffile):
+             self._get_defaults()
+-        self.parser_path = '/sbin/apparmor_parser'
++        self.parser_path = which('apparmor_parser')
+         if opt.parser_path:
+             self.parser_path = opt.parser_path
+-        elif not os.path.exists(self.parser_path):
+-            rc, self.parser_path = cmd(['which', 'apparmor_parser'])
+-            if rc != 0:
+-                self.parser_path = None
+         self.parser_base = "/etc/apparmor.d"
+         if opt.parser_base:
+--- a/utils/apparmor/sandbox.py
++++ b/utils/apparmor/sandbox.py
+@@ -9,6 +9,7 @@
+ # ------------------------------------------------------------------
+ from apparmor.common import AppArmorException, debug, error, msg, cmd
++from apparmor.aa import which
+ import apparmor.easyprof
+ import optparse
+ import os
+@@ -31,8 +32,7 @@ def check_requirements(binary):
+     for e in exes:
+         debug("Searching for '%s'" % e)
+-        rc, report = cmd(['which', e])
+-        if rc != 0:
++        if which(e) is None:
+             error("Could not find '%s'" % e, do_exit=False)
+             return False
+@@ -306,8 +306,7 @@ class SandboxXephyr(SandboxXserver):
+     def start(self):
+         for e in ['Xephyr', 'matchbox-window-manager']:
+             debug("Searching for '%s'" % e)
+-            rc, report = cmd(['which', e])
+-            if rc != 0:
++            if which(e) is None:
+                 raise AppArmorException("Could not find '%s'" % e)
+         '''Run any setup code'''
+@@ -567,8 +566,7 @@ EndSection
+     def start(self):
+         debug("Searching for '%s'" % 'xpra')
+-        rc, report = cmd(['which', 'xpra'])
+-        if rc != 0:
++        if which('xpra') is None:
+             raise AppArmorException("Could not find '%s'" % 'xpra')
+         if self.driver == "xdummy":
diff --git a/utils/apparmor/patches/030-remove-pynotify2-dep.patch b/utils/apparmor/patches/030-remove-pynotify2-dep.patch
deleted file mode 100644 (file)
index 7de4ddc..0000000
+++ /dev/null
@@ -1,416 +0,0 @@
---- 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/030-systemd.patch b/utils/apparmor/patches/030-systemd.patch
new file mode 100644 (file)
index 0000000..1023c36
--- /dev/null
@@ -0,0 +1,26 @@
+--- a/parser/Makefile
++++ b/parser/Makefile
+@@ -351,7 +351,7 @@ install-redhat:
+       install -m 755 rc.apparmor.$(subst install-,,$@) $(DESTDIR)/etc/init.d/apparmor
+ .PHONY: install-suse
+-install-suse: install-systemd
++install-suse:
+       install -m 755 -d $(SBINDIR)
+       ln -sf service $(SBINDIR)/rcapparmor
+@@ -414,14 +414,6 @@ install-indep: indep
+       $(MAKE) -C po install NAME=${NAME} DESTDIR=${DESTDIR}
+       $(MAKE) install_manpages DESTDIR=${DESTDIR}
+-.PHONY: install-systemd
+-install-systemd:
+-      install -m 755 -d $(SYSTEMD_UNIT_DIR)
+-      install -m 644 apparmor.service $(SYSTEMD_UNIT_DIR)
+-      install -m 755 apparmor.systemd $(APPARMOR_BIN_PREFIX)
+-      install -m 755 -d $(USR_SBINDIR)
+-      install -m 755 aa-teardown $(USR_SBINDIR)
+-
+ ifndef VERBOSE
+ .SILENT: clean
+ endif
index cc957ecdfa0a463f937fafc3551964094ffa8db0..527ced972b2bdc9ef0d1a0def32e9cf3a636d574 100644 (file)
 --- 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) {
+@@ -18,6 +18,7 @@ profile dnsmasq /usr/{bin,sbin}/dnsmasq
    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,
+@@ -38,6 +39,8 @@ profile dnsmasq /usr/{bin,sbin}/dnsmasq
  
--  owner /dev/tty rw,
-+  ptrace readby peer=/usr/{bin,sbin}/libvirtd,
-+  ptrace readby peer=libvirtd,
+   @{PROC}/@{pid}/fd/ r,
  
--  @{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>
- }
+   /etc/dnsmasq.conf r,
+   /etc/dnsmasq.d/ r,
+   /etc/dnsmasq.d/* r,
diff --git a/utils/apparmor/patches/070-python-3.10.patch b/utils/apparmor/patches/070-python-3.10.patch
new file mode 100644 (file)
index 0000000..8e80dea
--- /dev/null
@@ -0,0 +1,81 @@
+From 6cfc6eeec22d3c9ffae413819654359b76680150 Mon Sep 17 00:00:00 2001
+From: John Johansen <john@jjmx.net>
+Date: Fri, 13 Aug 2021 20:13:59 +0000
+Subject: [PATCH] Merge Update abstractions/python and profiles for python 3.10
+
+Add support for python 3.10 in abstractions and profiles.
+
+Fixes: https://gitlab.com/apparmor/apparmor/-/issues/187
+MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/783
+Acked-by: John Johansen <john.johansen@canonical.com>
+(cherry picked from commit 31fda3eee7b1e5f936b31d3578ed596789d5fcce)
+Signed-off-by: John Johansen <john.johansen@canonical.com>
+---
+ profiles/apparmor.d/abstractions/python        | 18 +++++++++---------
+ profiles/apparmor.d/lsb_release                |  2 +-
+ .../profiles/extras/usr.bin.chromium-browser   |  4 ++--
+ 3 files changed, 12 insertions(+), 12 deletions(-)
+
+--- a/profiles/apparmor.d/abstractions/python
++++ b/profiles/apparmor.d/abstractions/python
+@@ -12,18 +12,18 @@
+   abi <abi/3.0>,
+-  /usr/lib{,32,64}/python{2.[4-7],3.[0-9]}/**.{pyc,so}           mr,
+-  /usr/lib{,32,64}/python{2.[4-7],3.[0-9]}/**.{egg,py,pth}       r,
+-  /usr/lib{,32,64}/python{2.[4-7],3.[0-9]}/{site,dist}-packages/ r,
++  /usr/lib{,32,64}/python{2.[4-7],3.[0-9],3.1[0-9]}/**.{pyc,so}           mr,
++  /usr/lib{,32,64}/python{2.[4-7],3.[0-9],3.1[0-9]}/**.{egg,py,pth}       r,
++  /usr/lib{,32,64}/python{2.[4-7],3.[0-9],3.1[0-9]}/{site,dist}-packages/ r,
+   /usr/lib{,32,64}/python3.[0-9]/lib-dynload/*.so            mr,
+-  /usr/local/lib{,32,64}/python{2.[4-7],3,3.[0-9]}/**.{pyc,so}           mr,
+-  /usr/local/lib{,32,64}/python{2.[4-7],3,3.[0-9]}/**.{egg,py,pth}       r,
+-  /usr/local/lib{,32,64}/python{2.[4-7],3,3.[0-9]}/{site,dist}-packages/ r,
+-  /usr/local/lib{,32,64}/python3.[0-9]/lib-dynload/*.so            mr,
++  /usr/local/lib{,32,64}/python{2.[4-7],3,3.[0-9],3.1[0-9]}/**.{pyc,so}           mr,
++  /usr/local/lib{,32,64}/python{2.[4-7],3,3.[0-9],3.1[0-9]}/**.{egg,py,pth}       r,
++  /usr/local/lib{,32,64}/python{2.[4-7],3,3.[0-9],3.1[0-9]}/{site,dist}-packages/ r,
++  /usr/local/lib{,32,64}/python3.{1,}[0-9]/lib-dynload/*.so            mr,
+   # Site-wide configuration
+-  /etc/python{2.[4-7],3.[0-9]}/** r,
++  /etc/python{2.[4-7],3.[0-9],3.1[0-9]}/** r,
+   # shared python paths
+   /usr/share/{pyshared,pycentral,python-support}/**      r,
+@@ -36,7 +36,7 @@
+   /usr/lib/wx/python/*.pth r,
+   # python build configuration and headers
+-  /usr/include/python{2.[4-7],3.[0-9]}*/pyconfig.h r,
++  /usr/include/python{2.[4-7],3.[0-9],3.1[0-9]}*/pyconfig.h r,
+   # Include additions to the abstraction
+   include if exists <abstractions/python.d>
+--- a/profiles/apparmor.d/lsb_release
++++ b/profiles/apparmor.d/lsb_release
+@@ -18,7 +18,7 @@ profile lsb_release {
+   /dev/tty rw,
+   /usr/bin/lsb_release r,
+-  /usr/bin/python3.[0-9] mr,
++  /usr/bin/python3.{1,}[0-9] mr,
+   /etc/debian_version r,
+   /etc/default/apport r,
+--- a/profiles/apparmor/profiles/extras/usr.bin.chromium-browser
++++ b/profiles/apparmor/profiles/extras/usr.bin.chromium-browser
+@@ -267,9 +267,9 @@ profile chromium_browser /usr/lib/@{chro
+     /usr/share/distro-info/** r,
+     /var/lib/dpkg/** r,
+-    /usr/local/lib/python3.[0-9]/dist-packages/ r,
++    /usr/local/lib/python3.{1,}[0-9]/dist-packages/ r,
+     /usr/bin/ r,
+-    /usr/bin/python3.[0-9] mr,
++    /usr/bin/python3.{1,}[0-9] mr,
+   }
+   profile sandbox {
diff --git a/utils/apparmor/patches/070-systemd.patch b/utils/apparmor/patches/070-systemd.patch
deleted file mode 100644 (file)
index 667f270..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
---- a/parser/Makefile
-+++ b/parser/Makefile
-@@ -351,7 +351,7 @@ install-redhat:
-       install -m 755 rc.apparmor.$(subst install-,,$@) $(DESTDIR)/etc/init.d/apparmor
- .PHONY: install-suse
--install-suse: install-systemd
-+install-suse:
-       install -m 755 -d $(SBINDIR)
-       ln -sf service $(SBINDIR)/rcapparmor
-@@ -413,14 +413,6 @@ install-indep: indep
-       $(MAKE) -C po install NAME=${NAME} DESTDIR=${DESTDIR}
-       $(MAKE) install_manpages DESTDIR=${DESTDIR}
--.PHONY: install-systemd
--install-systemd:
--      install -m 755 -d $(SYSTEMD_UNIT_DIR)
--      install -m 644 apparmor.service $(SYSTEMD_UNIT_DIR)
--      install -m 755 apparmor.systemd $(APPARMOR_BIN_PREFIX)
--      install -m 755 -d $(USR_SBINDIR)
--      install -m 755 aa-teardown $(USR_SBINDIR)
--
- ifndef VERBOSE
- .SILENT: clean
- endif
diff --git a/utils/apparmor/patches/080-add-new-python-versions-to-logprof-conf.patch b/utils/apparmor/patches/080-add-new-python-versions-to-logprof-conf.patch
new file mode 100644 (file)
index 0000000..cdee6cc
--- /dev/null
@@ -0,0 +1,38 @@
+From 06dc32a9f3ede351c46167afa5002a0fe062c0f7 Mon Sep 17 00:00:00 2001
+From: Steve Beattie <gitlab@nxnw.org>
+Date: Thu, 26 Aug 2021 17:43:43 +0000
+Subject: [PATCH] utils: Add new python versions to logprof.conf
+
+Adding everything up to 3.19 should make the file future-proof for a
+while ;-)
+
+Fixes: https://gitlab.com/apparmor/apparmor/-/issues/193
+MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/795
+Acked-by: Steve Beattie <steve.beattie@canonical.com>
+(cherry picked from commit 4559a2997cf162b0f54f602180fd352e8d2486c1)
+Signed-off-by: Steve Beattie <steve.beattie@canonical.com>
+---
+ utils/logprof.conf | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+--- a/utils/logprof.conf
++++ b/utils/logprof.conf
+@@ -112,6 +112,18 @@
+   /usr/bin/python3.5    = icn
+   /usr/bin/python3.6    = icn
+   /usr/bin/python3.7    = icn
++  /usr/bin/python3.8    = icn
++  /usr/bin/python3.9    = icn
++  /usr/bin/python3.10   = icn
++  /usr/bin/python3.11   = icn
++  /usr/bin/python3.12   = icn
++  /usr/bin/python3.13   = icn
++  /usr/bin/python3.14   = icn
++  /usr/bin/python3.15   = icn
++  /usr/bin/python3.16   = icn
++  /usr/bin/python3.17   = icn
++  /usr/bin/python3.18   = icn
++  /usr/bin/python3.19   = icn
+   /usr/bin/tr   = icn
+ [required_hats]
diff --git a/utils/apparmor/patches/090-setuptools.patch b/utils/apparmor/patches/090-setuptools.patch
new file mode 100644 (file)
index 0000000..b5f9db3
--- /dev/null
@@ -0,0 +1,254 @@
+From ab4cfb5e84a95decd06487dc4e59827ddb8ce79d Mon Sep 17 00:00:00 2001
+From: Georgia Garcia <georgia.garcia@canonical.com>
+Date: Wed, 10 Nov 2021 19:50:35 +0000
+Subject: [PATCH] replace deprecated distutils with setuptools
+
+Adds python3 setuptools as a build dependency for libapparmor
+
+Fixes: https://gitlab.com/apparmor/apparmor/-/issues/202
+MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/813
+Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
+Acked-by: Christian Boltz <apparmor@cboltz.de>
+(cherry picked from commit 21e5a721ab2abe26bb12b9da7accc39d4fff9804)
+Signed-off-by: John Johansen <john.johansen@canonical.com>
+---
+ .gitignore                                    |  3 ++
+ .gitlab-ci.yml                                |  2 +-
+ libraries/libapparmor/m4/ac_python_devel.m4   | 36 +++++++++----------
+ libraries/libapparmor/swig/python/Makefile.am |  2 +-
+ libraries/libapparmor/swig/python/setup.py.in |  2 +-
+ .../libapparmor/swig/python/test/Makefile.am  |  2 +-
+ profiles/Makefile                             |  2 +-
+ utils/Makefile                                |  1 +
+ utils/python-tools-setup.py                   |  6 ++--
+ utils/test/Makefile                           |  2 +-
+ utils/test/README.md                          | 18 ++++++++++
+ 11 files changed, 49 insertions(+), 27 deletions(-)
+ create mode 100644 utils/test/README.md
+
+--- a/.gitignore
++++ b/.gitignore
+@@ -159,6 +159,7 @@ libraries/libapparmor/swig/perl/libappar
+ libraries/libapparmor/swig/perl/libapparmor_wrap.o
+ libraries/libapparmor/swig/perl/pm_to_blib
+ libraries/libapparmor/swig/python/LibAppArmor.py
++libraries/libapparmor/swig/python/LibAppArmor.egg-info/
+ libraries/libapparmor/swig/python/build/
+ libraries/libapparmor/swig/python/libapparmor_wrap.c
+ libraries/libapparmor/swig/python/Makefile
+@@ -203,6 +204,8 @@ utils/*.tmp
+ utils/po/*.mo
+ utils/apparmor/*.pyc
+ utils/apparmor/rule/*.pyc
++utils/apparmor.egg-info/
++utils/build/
+ utils/htmlcov/
+ utils/test/common_test.pyc
+ utils/test/.coverage
+--- a/.gitlab-ci.yml
++++ b/.gitlab-ci.yml
+@@ -1,7 +1,7 @@
+ ---
+ image: ubuntu:latest
+ before_script:
+-  - export DEBIAN_FRONTEND=noninteractive && apt-get update -qq && apt-get install --no-install-recommends -y build-essential apache2-dev autoconf automake bison dejagnu flex libpam-dev libtool perl liblocale-gettext-perl pkg-config python-all-dev python3-all-dev pyflakes3 ruby-dev swig lsb-release python3-notify2 python3-psutil zlib1g-dev
++  - export DEBIAN_FRONTEND=noninteractive && apt-get update -qq && apt-get install --no-install-recommends -y build-essential apache2-dev autoconf automake bison dejagnu flex libpam-dev libtool perl liblocale-gettext-perl pkg-config python-all-dev python3-all-dev pyflakes3 ruby-dev swig lsb-release python3-notify2 python3-psutil python3-setuptools zlib1g-dev
+   - lsb_release -a
+   - uname -a
+--- a/libraries/libapparmor/m4/ac_python_devel.m4
++++ b/libraries/libapparmor/m4/ac_python_devel.m4
+@@ -66,17 +66,17 @@ variable to configure. See ``configure -
+         fi
+         #
+-        # Check if you have distutils, else fail
++        # Check if you have setuptools, else fail
+         #
+-        AC_MSG_CHECKING([for the distutils Python package])
+-        ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`
+-        if test -z "$ac_distutils_result"; then
++        AC_MSG_CHECKING([for the setuptools Python package])
++        ac_setuptools_result=`$PYTHON -c "import setuptools" 2>&1`
++        if test -z "$ac_setuptools_result"; then
+                 AC_MSG_RESULT([yes])
+         else
+                 AC_MSG_RESULT([no])
+-                AC_MSG_ERROR([cannot import Python module "distutils".
++                AC_MSG_ERROR([cannot import Python module "setuptools".
+ Please check your Python installation. The error was:
+-$ac_distutils_result])
++$ac_setuptools_result])
+                 PYTHON_VERSION=""
+         fi
+@@ -88,8 +88,8 @@ $ac_distutils_result])
+                 PYTHON_CPPFLAGS=`$PYTHON_CONFIG --includes`
+         fi
+         if test -z "$PYTHON_CPPFLAGS"; then
+-                python_path=`$PYTHON -c "import sys; import distutils.sysconfig;\
+-sys.stdout.write('%s\n' % distutils.sysconfig.get_python_inc());"`
++                python_path=`$PYTHON -c "import sys; import sysconfig;\
++sys.stdout.write('%s\n' % sysconfig.get_path('include'));"`
+                 if test -n "${python_path}"; then
+                         python_path="-I$python_path"
+                 fi
+@@ -108,8 +108,8 @@ sys.stdout.write('%s\n' % distutils.sysc
+         if test -z "$PYTHON_LDFLAGS"; then
+                 # (makes two attempts to ensure we've got a version number
+                 # from the interpreter)
+-                py_version=`$PYTHON -c "import sys; from distutils.sysconfig import *; \
+-sys.stdout.write('%s\n' % ''.join(get_config_vars('VERSION')))"`
++                py_version=`$PYTHON -c "import sys; import sysconfig; \
++sys.stdout.write('%s\n' % ''.join(sysconfig.get_config_vars('VERSION')))"`
+                 if test "$py_version" == "[None]"; then
+                         if test -n "$PYTHON_VERSION"; then
+                                 py_version=$PYTHON_VERSION
+@@ -119,8 +119,8 @@ sys.stdout.write("%s\n" % sys.version[[:
+                         fi
+                 fi
+-                PYTHON_LDFLAGS=`$PYTHON -c "import sys; from distutils.sysconfig import *; \
+-sys.stdout.write('-L' + get_python_lib(0,1) + ' -lpython\n')"`$py_version`$PYTHON -c \
++                PYTHON_LDFLAGS=`$PYTHON -c "import sys; import sysconfig; \
++sys.stdout.write('-L' + sysconfig.get_path('stdlib') + ' -lpython\n')"`$py_version`$PYTHON -c \
+ "import sys; sys.stdout.write('%s' % getattr(sys,'abiflags',''))"`
+         fi
+         AC_MSG_RESULT([$PYTHON_LDFLAGS])
+@@ -131,8 +131,8 @@ sys.stdout.write('-L' + get_python_lib(0
+         #
+         AC_MSG_CHECKING([for Python site-packages path])
+         if test -z "$PYTHON_SITE_PKG"; then
+-                PYTHON_SITE_PKG=`$PYTHON -c "import sys; import distutils.sysconfig; \
+-sys.stdout.write('%s\n' % distutils.sysconfig.get_python_lib(0,0));"`
++                PYTHON_SITE_PKG=`$PYTHON -c "import sys; import sysconfig; \
++sys.stdout.write('%s\n' % sysconfig.get_path('purelib'));"`
+         fi
+         AC_MSG_RESULT([$PYTHON_SITE_PKG])
+         AC_SUBST([PYTHON_SITE_PKG])
+@@ -146,8 +146,8 @@ sys.stdout.write('%s\n' % distutils.sysc
+                         PYTHON_EXTRA_LIBS=''
+         fi
+         if test -z "$PYTHON_EXTRA_LIBS"; then
+-           PYTHON_EXTRA_LIBS=`$PYTHON -c "import sys; import distutils.sysconfig; \
+-conf = distutils.sysconfig.get_config_var; \
++           PYTHON_EXTRA_LIBS=`$PYTHON -c "import sys; import sysconfig; \
++conf = sysconfig.get_config_var; \
+ sys.stdout.write('%s %s %s\n' % (conf('BLDLIBRARY'), conf('LOCALMODLIBS'), conf('LIBS')))"`
+         fi
+         AC_MSG_RESULT([$PYTHON_EXTRA_LIBS])
+@@ -162,8 +162,8 @@ sys.stdout.write('%s %s %s\n' % (conf('B
+                         PYTHON_EXTRA_LDFLAGS=''
+         fi
+         if test -z "$PYTHON_EXTRA_LDFLAGS"; then
+-                PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import sys; import distutils.sysconfig; \
+-conf = distutils.sysconfig.get_config_var; \
++                PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import sys; import sysconfig; \
++conf = sysconfig.get_config_var; \
+ sys.stdout.write('%s\n' % conf('LINKFORSHARED'))"`
+         fi
+         AC_MSG_RESULT([$PYTHON_EXTRA_LDFLAGS])
+--- a/libraries/libapparmor/swig/python/Makefile.am
++++ b/libraries/libapparmor/swig/python/Makefile.am
+@@ -21,7 +21,7 @@ install-exec-local:
+ clean-local:
+       if test -x "$(PYTHON)"; then $(PYTHON) setup.py clean; fi
+-      rm -rf build
++      rm -rf build LibAppArmor.egg-info
+       if test $(top_srcdir) != $(top_builddir) ; then rm -f libapparmor_wrap.c ; fi
+ endif
+--- a/libraries/libapparmor/swig/python/setup.py.in
++++ b/libraries/libapparmor/swig/python/setup.py.in
+@@ -1,4 +1,4 @@
+-from distutils.core import setup, Extension
++from setuptools import setup, Extension
+ import string
+ setup(name          = 'LibAppArmor',
+--- a/libraries/libapparmor/swig/python/test/Makefile.am
++++ b/libraries/libapparmor/swig/python/test/Makefile.am
+@@ -11,7 +11,7 @@ test_python.py: test_python.py.in $(top_
+ CLEANFILES = test_python.py
+ # bah, how brittle is this?
+-PYTHON_DIST_BUILD_PATH = '$(builddir)/../build/$$($(PYTHON) -c "import distutils.util; import platform; print(\"lib.%s-%s\" %(distutils.util.get_platform(), platform.python_version()[:3]))")'
++PYTHON_DIST_BUILD_PATH = '$(builddir)/../build/$$($(PYTHON) -c "import sysconfig; print(\"lib.%s-%s\" %(sysconfig.get_platform(), sysconfig.get_python_version()))")'
+ TESTS = test_python.py
+ TESTS_ENVIRONMENT = \
+--- a/profiles/Makefile
++++ b/profiles/Makefile
+@@ -41,7 +41,7 @@ ifdef USE_SYSTEM
+     LOGPROF?=aa-logprof
+ else
+     # PYTHON_DIST_BUILD_PATH based on libapparmor/swig/python/test/Makefile.am
+-    PYTHON_DIST_BUILD_PATH = ../libraries/libapparmor/swig/python/build/$$($(PYTHON) -c "import distutils.util; import platform; print(\"lib.%s-%s\" %(distutils.util.get_platform(), platform.python_version()[:3]))")
++    PYTHON_DIST_BUILD_PATH = ../libraries/libapparmor/swig/python/build/$$($(PYTHON) -c "import sysconfig; print(\"lib.%s-%s\" %(sysconfig.get_platform(), sysconfig.get_python_version()))")
+     LIBAPPARMOR_PATH=../libraries/libapparmor/src/.libs/
+     LD_LIBRARY_PATH=$(LIBAPPARMOR_PATH):$(PYTHON_DIST_BUILD_PATH)
+     PYTHONPATH=../utils/:$(PYTHON_DIST_BUILD_PATH)
+--- a/utils/Makefile
++++ b/utils/Makefile
+@@ -67,6 +67,7 @@ clean: pod_clean
+       rm -rf staging/ build/
+       rm -f apparmor/*.pyc apparmor/rule/*.pyc
+       rm -rf apparmor/__pycache__/ apparmor/rule/__pycache__/
++      rm -rf apparmor.egg-info/
+ # ${CAPABILITIES} is defined in common/Make.rules
+ .PHONY: check_severity_db
+--- a/utils/python-tools-setup.py
++++ b/utils/python-tools-setup.py
+@@ -20,14 +20,14 @@
+ # Note: --version=... must be the last argument to this script
+ #
+-from distutils.command.install import install as _install
+-from distutils.core import setup
++from setuptools.command.install import install as _install
++from setuptools import setup
+ import os
+ import shutil
+ import sys
+ class Install(_install, object):
+-    '''Override distutils to install the files where we want them.'''
++    '''Override setuptools to install the files where we want them.'''
+     def run(self):
+         # Now byte-compile everything
+         super(Install, self).run()
+--- a/utils/test/Makefile
++++ b/utils/test/Makefile
+@@ -28,7 +28,7 @@ ifdef USE_SYSTEM
+     PARSER=
+ else
+     # PYTHON_DIST_BUILD_PATH based on libapparmor/swig/python/test/Makefile.am
+-    PYTHON_DIST_BUILD_PATH = ../../libraries/libapparmor/swig/python/build/$$($(PYTHON) -c "import distutils.util; import platform; print(\"lib.%s-%s\" %(distutils.util.get_platform(), platform.python_version()[:3]))")
++    PYTHON_DIST_BUILD_PATH = ../../libraries/libapparmor/swig/python/build/$$($(PYTHON) -c "import sysconfig; print(\"lib.%s-%s\" %(sysconfig.get_platform(), sysconfig.get_python_version()))")
+     LIBAPPARMOR_PATH=../../libraries/libapparmor/src/.libs/
+     LD_LIBRARY_PATH=$(LIBAPPARMOR_PATH):$(PYTHON_DIST_BUILD_PATH)
+     PYTHONPATH=..:$(PYTHON_DIST_BUILD_PATH)
+--- /dev/null
++++ b/utils/test/README.md
+@@ -0,0 +1,18 @@
++# Running individual tests
++
++Python's unittest allows individual tests to be executed by specifying the class name and the test on the command line.
++When running tests individually, the unittest framework executes the "setUp" and "tearDown" methods automatically.
++For more information, refer to the [unittest documentation](https://docs.python.org/3/library/unittest.html).
++
++Make sure to set the environment variables pointing to the in-tree apparmor modules, and the in-tree libapparmor and its python wrapper:
++
++```bash
++$ export PYTHONPATH=..:../../libraries/libapparmor/swig/python/build/$(/usr/bin/python3 -c "import sysconfig; print(\"lib.%s-%s\" %(sysconfig.get_platform(), sysconfig.get_python_version()))")
++$ export __AA_CONFDIR=.
++```
++
++To execute the test individually, run:
++
++```bash
++$ python3 ./test-tile.py ClassFoo.test_bar
++```
+\ No newline at end of file