mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-22 10:07:12 +00:00
Add support for reading s390x and aarch64 wtmp file
Both aarch64 and s390x have a bigger wtmp record size (16 bytes more than x86_64, 400 bytes total). The byte position of the timestamp is also different on each architecture. To make things even more interesting, s390x is big endian. Fixes: https://bugzilla.opensuse.org/show_bug.cgi?id=1181155
This commit is contained in:
parent
f79b335b6c
commit
255716b90a
@ -22,6 +22,16 @@ 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
|
||||
@ -33,11 +43,37 @@ def get_last_login_timestamp(username, filename='/var/log/wtmp'):
|
||||
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 # Increment for next entry
|
||||
offset += 384 + extra_offset_before + extra_offset_after # Increment for next entry
|
||||
|
||||
type = struct.unpack("<H", wtmp_file.read(2))[0]
|
||||
type = struct.unpack('%sH' % endianness, wtmp_file.read(2))[0]
|
||||
debug_logger.debug('WTMP entry type: {}'.format(type))
|
||||
wtmp_file.read(2) # skip padding
|
||||
|
||||
@ -52,7 +88,11 @@ def get_last_login_timestamp(username, filename='/var/log/wtmp'):
|
||||
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]
|
||||
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))
|
||||
|
@ -18,6 +18,11 @@ class TestGet_last_login_timestamp(AATest):
|
||||
tests = [
|
||||
(['wtmp-x86_64', 'root' ], 1635070346), # Sun Oct 24 12:12:26 CEST 2021
|
||||
(['wtmp-x86_64', 'whoever' ], 0),
|
||||
(['wtmp-s390x', 'root' ], 1626368763), # Thu Jul 15 19:06:03 CEST 2021
|
||||
(['wtmp-s390x', 'linux1' ], 1626368772), # Thu Jul 15 19:06:12 CEST 2021
|
||||
(['wtmp-s390x', 'whoever' ], 0),
|
||||
(['wtmp-aarch64', 'guillaume' ], 1611562789), # Mon Jan 25 09:19:49 CET 2021
|
||||
(['wtmp-aarch64', 'whoever' ], 0),
|
||||
]
|
||||
|
||||
def _run_test(self, params, expected):
|
||||
|
BIN
utils/test/wtmp-examples/wtmp-aarch64
Normal file
BIN
utils/test/wtmp-examples/wtmp-aarch64
Normal file
Binary file not shown.
5
utils/test/wtmp-examples/wtmp-aarch64-expected-output
Normal file
5
utils/test/wtmp-examples/wtmp-aarch64-expected-output
Normal file
@ -0,0 +1,5 @@
|
||||
guillaum pts/3 192.168.0.2 Mon Jan 25 08:19 - 09:36 (01:17)
|
||||
|
||||
Example and expected output taken from https://bugzilla.opensuse.org/show_bug.cgi?id=1181155
|
||||
|
||||
On openSUSE, aarch64 is little endian.
|
BIN
utils/test/wtmp-examples/wtmp-s390x
Normal file
BIN
utils/test/wtmp-examples/wtmp-s390x
Normal file
Binary file not shown.
13
utils/test/wtmp-examples/wtmp-s390x-expected-output
Normal file
13
utils/test/wtmp-examples/wtmp-s390x-expected-output
Normal file
@ -0,0 +1,13 @@
|
||||
linux1@opensuse03:~> last
|
||||
linux1 pts/0 77.21.253.246 Thu Jul 15 13:06 still logged in
|
||||
root pts/0 77.21.253.246 Thu Jul 15 13:06 - 13:06 (00:00)
|
||||
linux1 pts/0 77.21.253.246 Thu Jul 15 13:01 - 13:05 (00:04)
|
||||
linux1 pts/0 94.134.117.140 Thu Jul 15 08:15 - 08:16 (00:01)
|
||||
linux1 pts/0 10.6.22.160 Tue Jul 13 07:42 - 07:42 (00:00)
|
||||
reboot system boot 5.3.18-24.67-def Tue Jul 13 07:41 still running
|
||||
linux1 pts/0 10.6.22.160 Tue Jul 13 07:41 - 07:41 (00:00)
|
||||
linux1 pts/0 10.6.22.160 Tue Jul 13 07:37 - 07:41 (00:03)
|
||||
reboot system boot 5.3.18-24.64-def Tue Jul 13 07:30 - 07:41 (00:11)
|
||||
|
||||
wtmp beginnt Tue Jul 13 07:30:36 2021
|
||||
linux1@opensuse03:~>
|
Loading…
x
Reference in New Issue
Block a user