Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package apparmor for openSUSE:Factory 
checked in at 2021-11-12 15:58:56
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/apparmor (Old)
 and      /work/SRC/openSUSE:Factory/.apparmor.new.1890 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "apparmor"

Fri Nov 12 15:58:56 2021 rev:159 rq:930527 version:3.0.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/apparmor/apparmor.changes        2021-10-19 
23:03:32.497265163 +0200
+++ /work/SRC/openSUSE:Factory/.apparmor.new.1890/apparmor.changes      
2021-11-12 15:58:58.062556784 +0100
@@ -1,0 +2,6 @@
+Tue Nov  9 17:45:22 UTC 2021 - Christian Boltz <suse-b...@cboltz.de>
+
+- add aa-notify-more-arch-mr809.diff: Add support for reading s390x
+  and aarch64 wtmp files (boo#1181155)
+
+-------------------------------------------------------------------

New:
----
  aa-notify-more-arch-mr809.diff

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ apparmor.spec ++++++
--- /var/tmp/diff_new_pack.2iLaA6/_old  2021-11-12 15:58:58.862557148 +0100
+++ /var/tmp/diff_new_pack.2iLaA6/_new  2021-11-12 15:58:58.866557150 +0100
@@ -84,6 +84,9 @@
 # add samba-bgqd profile (submitted upstream 2021-10-15 
https://gitlab.com/apparmor/apparmor/-/merge_requests/807)
 Patch8:         add-samba-bgqd.diff
 
+# aa-notify: Add support for reading s390x and aarch64 wtmp file (boo#1181155) 
(merged upstream 2021-11-08 in master and 3.0 branch - 
https://gitlab.com/apparmor/apparmor/-/merge_requests/809)
+Patch9:         aa-notify-more-arch-mr809.diff
+
 PreReq:         sed
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
 %define apparmor_bin_prefix %{?usrmerged:/usr}/lib/apparmor
@@ -348,6 +351,7 @@
 %patch5
 %patch7 -p1
 %patch8 -p1
+%patch9 -p1
 
 %build
 %define _lto_cflags %{nil}

++++++ aa-notify-more-arch-mr809.diff ++++++
This patch contains the code changes from
https://gitlab.com/apparmor/apparmor/-/merge_requests/809

It does NOT include the added unit tests because adding binary test files with 
a patch is too hard.




diff --git a/utils/aa-notify b/utils/aa-notify
index 
91d0f3b9c240e1ff0fec8aa673ef70fa78cf33bc..024044a0c58ed4827502da66786acb4e9b54fc2f
 100755
--- a/utils/aa-notify
+++ b/utils/aa-notify
@@ -34,7 +34,6 @@ import os
 import re
 import sys
 import time
-import struct
 import notify2
 import psutil
 import pwd
@@ -45,6 +44,7 @@ import apparmor.ui as aaui
 import apparmor.config as aaconfig
 from apparmor.common import DebugLogger, open_file_read
 from apparmor.fail import enable_aa_exception_handler
+from apparmor.notify import get_last_login_timestamp
 from apparmor.translations import init_translation
 
 import LibAppArmor  # C-library to parse one log line
@@ -61,48 +61,6 @@ def get_user_login():
     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 = []
diff --git a/utils/apparmor/notify.py b/utils/apparmor/notify.py
new file mode 100644
index 
0000000000000000000000000000000000000000..1101a29346d79dd873c347fd12dd79cda1e1c786
--- /dev/null
+++ b/utils/apparmor/notify.py
@@ -0,0 +1,105 @@
+#! /usr/bin/python3
+# ----------------------------------------------------------------------
+#    Copyright (C) 2018???2019 Otto Kek??l??inen <o...@kekalainen.net>
+#    Copyright (C) 2021 Christian Boltz
+#
+#    This program is free software; you can redistribute it and/or
+#    modify it under the terms of version 2 of the GNU General Public
+#    License as published by the Free Software Foundation.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU General Public License for more details.
+#
+# ----------------------------------------------------------------------
+
+import os
+import struct
+
+from apparmor.common import AppArmorBug, DebugLogger
+
+debug_logger = DebugLogger('apparmor.notify')
+
+
+def sane_timestamp(timestamp):
+    ''' Check if the given timestamp is in a date range that makes sense for a 
wtmp file '''
+
+    if timestamp < 946681200:  # 2000-01-01
+        return False
+    elif timestamp > 2524604400:  # 2050-01-01
+        return False
+
+    return True
+
+def get_last_login_timestamp(username, filename='/var/log/wtmp'):
+    '''Directly read wtmp and get last login for user as epoch timestamp'''
+    timestamp = 0
+    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))
+
+        if wtmp_filesize < 356:
+            return 0  # (nearly) empty wtmp file, no entries
+
+        # detect architecture based on utmp format differences
+        wtmp_file.seek(340)  # first possible timestamp position
+        timestamp_x86_64    = struct.unpack("<L", wtmp_file.read(4))[0]
+        timestamp_aarch64   = struct.unpack("<L", wtmp_file.read(4))[0]
+        timestamp_s390x     = struct.unpack(">L", wtmp_file.read(4))[0]
+        debug_logger.debug('WTMP timestamps: x86_64 %s, aarch64 %s, s390x %s' 
% (timestamp_x86_64, timestamp_aarch64, timestamp_s390x))
+
+        if sane_timestamp(timestamp_x86_64):
+            endianness = '<'  # little endian
+            extra_offset_before = 0
+            extra_offset_after = 0
+        elif sane_timestamp(timestamp_aarch64):
+            endianness = '<'  # little endian
+            extra_offset_before = 4
+            extra_offset_after = 12
+        elif sane_timestamp(timestamp_s390x):
+            endianness = '>'  # big endian
+            extra_offset_before = 8
+            extra_offset_after = 8
+        else:
+            raise AppArmorBug('Your /var/log/wtmp is broken or has an unknown 
format. Please open a bugreport with /var/log/wtmp and the output of "last" 
attached!')
+
+        while offset < wtmp_filesize:
+            wtmp_file.seek(offset)
+            offset += 384 + extra_offset_before + extra_offset_after  # 
Increment for next entry
+
+            type = struct.unpack('%sH' % endianness, wtmp_file.read(2))[0]
+            debug_logger.debug('WTMP entry type: {}'.format(type))
+            wtmp_file.read(2)  # skip padding
+
+            # 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]
+                if extra_offset_before:
+                    wtmp_file.read(extra_offset_before)
+                timestamp = struct.unpack('%sL' % endianness, 
wtmp_file.read(4))[0]
+                if extra_offset_after:
+                    wtmp_file.read(extra_offset_after)
+                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

Reply via email to