Commit Graph

1661 Commits

Author SHA1 Message Date
Stefan Berger
441d8839d2 CHANGES: Add more documentation for changes in 0.8.0
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-11-10 12:24:08 -05:00
Stefan Berger
22e975dc05 tests: Pass --verify-profile=medium to certtool if supported
certtool emits the following message if --verify-profile is not
passed:

Note that no verification profile was selected. In the future the medium profile will be enabled by default.
Use --verify-profile low to apply the default verification of NORMAL priority string.

Pass the --verify-profile option if certtool supports it (since ~3.6.12).

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-11-02 11:14:19 -04:00
Ross Lagerwall
a2abd3b67d swtpm_setup: Configure swtpm to log to stdout/err if needed
If swtpm_setup is configured with a log file, it launches swtpm
configured with the same log file. If not, swtpm_setup logs will go to
stdout/stderr and it should configure swtpm to do the same.

Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>
2022-11-01 18:01:47 -04:00
Stefan Berger
66117eefa8
Update bug_report.md
Make exact steps to recreate the issue a requirement for the bug report.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-10-10 07:53:26 -04:00
Stefan Berger
87ce53ffc4 swtpm: Add another exit label to avoid gcc -fanalyzer false positive
Move existing exit label before the return statement and add another
label that includes the free(filebuffer). This avoids a false positive
by 'gcc -fanalyzer' that seems to think that free(filebuffer)
would double-free filebuffer after filebuffer = realloc(tmp, ..)
failure.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-10-05 07:37:14 -04:00
Stefan Berger
7d79ecd694 swtpm: Return TPM_FAIL if SWTPM_NVRAM_DecrytpData is called without key
Return TPM_FAIL if SWTPM_NVRAM_DecryptData() is called without a key or
if an unhandle type of encryption mode is encountered. Previously this
function would return no error but also would not do any decryption if
no key was provided. Consequently, it would then also not return a byte
array with decrypted data which in turn could led to potential NULL
pointer accesses in subsequent calls. However, all current callers check
whether they have a valid key before they call this function. So the
change is primarily done for static analyzers, such as gcc -fanalyzer,
to ease code analysis.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-09-30 13:12:06 -04:00
Stefan Berger
c94a1c4cbd swtpm: Fix memory leak in case realloc fails
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-09-30 11:06:13 -04:00
Stefan Berger
8cbb6dae18 CHANGES: Add documentation for changes in 0.8.0
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-09-29 07:36:32 -04:00
Stefan Berger
aa92bbf615 tests: Replicate test_ctrlchannel3 for TPM 2 to test_tpm2_ctrlchannel3
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-09-22 13:27:38 -04:00
Stefan Berger
9c5bb4ac73 tests: Test automatic termination upon loss of ctrl channel connection
Extend the test_ctrlchannel3 to test for automatic termination of swtpm
upon loss of control channel connection.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-09-22 13:27:38 -04:00
Stefan Berger
1f36b7fec4 tests: Use SOCK_STREAM for CMD_SET_DATAFD socketpair
Switch to SOCK_STREAM for the CMD_SET_DATAFD socketpair where the one
end is passed to swtpm to test that this type of socket will cause
automatic termination of swtpm when the connection is lost. This is also
the socket type that QEMU uses.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-09-22 13:27:38 -04:00
Stefan Berger
d5296e19e7 swtpm: Extend capabilities JSON and show ctrl-opt-terminate
Extend the capabilities JSON and show the support for the terminate
parameter of the --ctrl option.

Adjust test cases.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-09-22 13:27:38 -04:00
Stefan Berger
6ecf5880ed swtpm: Implement terminate parameter for ctrl channel loss
Implement support for the terminate parameter for the control channel
option so that swtpm terminates once the control channel connection is
lost. The primary use case is QEMU that holds the control channel
permanently.

Resolves: https://github.com/stefanberger/swtpm/issues/753
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-09-22 13:27:38 -04:00
Stefan Berger
185832c8d4 swtpm: Set tpm_running = false after TPMLIB_Terminate() on CMD_SHUTDOWN
Set tpm_running = false after TPMLIB_Terminate() call on CMD_SHUTDOWN
to prevent a call to tpmlib_maybe_send_tpm2_shutdown() at the exit
of the mainloop.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-09-22 09:52:10 -04:00
Stefan Berger
aa2ed3e460 swtpm: Also send TPM2_Shutdown when swtpm terminates by signal
Also send TPM2_Shutdown when swtpm is terminated by a signal or due to
lost connection (--terminate option). Previously supported reasons for
sending the TPM2_Shutdown were primarily related to commands sent via
the command channel.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-09-22 09:52:10 -04:00
Stefan Berger
fd5bad56d5 swtpm: Add missing '%' to %08x
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-09-22 09:52:10 -04:00
Stefan Berger
448f6326d7 swtpm,man: Clarify that --terminate works only for TCP data channel
The --terminate option is only for the TCP data channel.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-09-21 17:20:18 -04:00
Stefan Berger
4e4e6e82cb swtpm: Do 300 locking retries instead of only 100
Increase the number of locking retries to 300 over 3 seconds
instead of 100 over 1 second. This gives the failing side more
time to release the lock.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-09-20 13:00:34 -04:00
Stefan Berger
34886d2841 debian: Do not remove swtpm_cuse.8 via clean file
swtpm_cuse.8 is not generated anymore but its a static file now
that must not be removed anymore via the debian/clean file.

Resolves: https://github.com/stefanberger/swtpm/issues/751
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-09-19 10:00:46 -04:00
Stefan Berger
e5fdd1c181 tests: Add test case for state migration and storage locking
Add a test case that monitors the locking of the storage by swtpm using the
directory storage backend to ensure that the lock is taken at the right
time and released when required.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-09-06 14:08:45 -04:00
Stefan Berger
6fbb219db9 swtpm: Implement CMD_LOCK_STORAGE to lock storage
Implement CMD_LOCK_STORAGE / PTM_LOCK_STORAGE for a user to be able to
lock the storage of the storage backend (if supported) after its lock
has been released for example when the 'savestate' blob was received
while the TPM state was migrated.

Also adjust test case and extend man pages.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-09-06 14:08:45 -04:00
Stefan Berger
e821754bb6 swtpm: Advertise --migration option in capabilities JSON
Advertise the capability of supporting the --migration option
in the capabilies JSON that now has the cmdarg-migration verb:

$ swtpm socket --print-capabilities | jq
{
  "type": "swtpm",
  "features": [
    "tpm-1.2",
    "tpm-2.0",
    "tpm-send-command-header",
    "flags-opt-startup",
    "flags-opt-disable-auto-shutdown",
    "cmdarg-seccomp",
    "cmdarg-key-fd",
    "cmdarg-pwd-fd",
    "cmdarg-print-states",
    "cmdarg-migration",
    "nvram-backend-dir",
    "nvram-backend-file"
  ],
  "version": "0.8.0"
}

Adjust test cases and extend man page.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-09-06 14:08:45 -04:00
Stefan Berger
120d414693 swtpm: Implement release-lock-outgoing parameter for --migration option
Implement the release-lock-outgoing parameter for the --migration option
that causes the storage lock to be released once the 'savestate' blob
transfer has been initiated. To not release the lock too early users must
first get the 'permanent' and 'volatile' state blobs and the 'savestate'
blob must be transferred as the last blob.

When migrating a VM the migration may fail and execution will then resume
on the originating side. In this fallback case the swtpm on the
destination side may need some time to terminate and release the lock.
Therefore, add a loop to the code attempting to re-lock the storage
directory on the source side for a few times until on the destination
side swtpm has released the lock. Retry the locking for 100 times
with 10ms in between. The retries will only ever be necessary if a TPM
command is immediately executed upon resume [this may be difficult
to test]. The negative side effects of this could be that the loop is not
long enough to grab the lock or that a short-duration TPM command will
time out inside the VM due to the retries delaying when it is processed.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Resolves: https://github.com/stefanberger/swtpm/issues/724
2022-09-06 14:08:45 -04:00
Stefan Berger
8a2bbeceba swtpm: Introduce --migration option and 'incoming' parameter
Introduce the --migration option along with the 'incoming' parameter
that allows to defer the locking of the storage until either

- the reception of the TPM's state is started
- a TPM command is about to be processed

Note that the reception of CMD_INIT does not enable the storage lock.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Resolves: https://github.com/stefanberger/swtpm/issues/724
2022-09-06 14:08:45 -04:00
Stefan Berger
44acf591c8 swtpm: Move locking of storage into tpmlib_start()
Move the locking of the storage into tpmlib_start() after the call to
TPMLIB_MainInit() which was previously doing the locking when the prepare
function was called in the SWTPM_NVRAM_Init() callback invoked by
TPMLIB_MainInit().

This allows for conditional locking in tpmlib_start() using a flag later
on.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-09-06 14:08:45 -04:00
Stefan Berger
b4e6725cb0 headers: Apply #ifndef's for _WIN32 from QEMU project
Apply recent changes to this file from upstream QEMU project using
a few #ifndef _WIN32 to make code compileable on Windows.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-09-01 11:43:33 -04:00
Stefan Berger
959bbb5a19 tests: Check for fallocate tool and its support for --posix
Older versions of fallocate do not support the --posix option that the test
needs. If --posix is not supported, skip the test.

Also check for availability of the losetup tool.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-08-26 14:41:06 -04:00
Stefan Berger
e86fd8e225 headers: Synchronize with header in QEMU project
QEMU has made a change to a copy of this header file with the following
reason:

On Solaris and Haiku, the _IO() macros are defined in <sys/ioccom.h>.
Add a proper check for this header to our build system, and make sure
to include the header in tpm_ioctl.h to fix a build failure on Solaris
and Haiku.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-08-26 09:20:30 -04:00
Stefan Berger
98d009bc99 swtpm: Implement stub for fips_mode_enabled (OpenBSD)
On OpenBSD openssl/fips.h is not available and FIPS_mode() is not
available, so implement a stub for fips_mode_enabled().

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-08-25 19:06:19 -04:00
Stefan Berger
cdc39fd977 swtpm: Advertise the --chroot option with cmdarg-chroot
Advertise the availability of the chroot option with the cmdarg-chroot
verb. Document it in the man page.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-08-25 13:13:20 -04:00
Stefan Berger
a44b642d70 tests: If filesystem is mounted with nodev opt skip CUSE chroot test
The CUSE TPM test will not work if the filesystem the test case runs
on is mounted with the 'nodev' option since the CUSE TPM can then
not use /tmp/.../dev/cuse.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-08-25 13:13:20 -04:00
Jennifer Herbert
68e5428492 swtpm: Add a chroot option
Add an option to enter a chroot after starting swtpm. This is useful for
sandboxing purposes. When this option is used, it is expected that swtpm
is started as root and the --runas option is used to subsequently drop
privileges (otherwise the chroot could be escaped).

Signed-off-by: Jennifer Herbert <jennifer.herbert@citrix.com>
Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>
2022-08-25 10:04:35 -04:00
Stefan Berger
ef005d9f0b swtpm_setup: Add missing description for --vmid to help screen
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-08-24 10:26:56 -04:00
Stefan Berger
df494163fa swtpm: Check for defined __SNR_MOUNT_setattr and __NR_mount_setattr
Address the following compilation error on Debian:

In file included from /usr/include/seccomp.h:821,
                 from seccomp_profile.c:44:
seccomp_profile.c: In function 'create_seccomp_profile':
seccomp_profile.c:115:9: error: '__NR_mount_setattr' undeclared (first use in this function)
  115 |         SCMP_SYS(mount_setattr),
      |         ^~~~~~~~
seccomp_profile.c:115:9: note: each undeclared identifier is reported only once for each function it appears in
seccomp_profile.c:172:9: error: '__NR_quotactl_fd' undeclared (first use in this function)
  172 |         SCMP_SYS(quotactl_fd),
      |         ^~~~~~~~

We need to do this since they are defined like this:

 #define __SNR_mount_setattr             __NR_mount_setattr
 #define __SNR_quotactl_fd               __NR_quotactl_fd

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-08-22 15:27:17 -04:00
Stefan Berger
98e84b2a85 swtpm: Include opensslv.h to get OPENSSL_VERSION_NUMBER
Include openssl/opensslv.h to avoid the following error on Ubuntu:

fips.c: In function 'fips_mode_enabled':
fips.c:61:16: error: implicit declaration of function 'EVP_default_properties_is_fips_enabled' [-Werror=implicit-function-declaration]
   61 |     int mode = EVP_default_properties_is_fips_enabled(NULL);
      |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Resolves: https://github.com/stefanberger/libtpms/issues/345
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-08-22 15:27:17 -04:00
Stefan Berger
0ebe80466f swtpm: Refactor existing function to use new tpmlib_get_cmd_ordinal()
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-08-18 09:50:16 -04:00
Stefan Berger
487892f2fc tests: Add test case to check that swtpm sends a TPM2_Shutdown
Add a test case that checks that swtpm sends a TPM2_Shutdown() to the
TPM 2 upon abrupt re-initialization (CMD_INIT) or graceful shutdown
(control channel, CMD_SHUTDOWN) of the TPM 2 and avoids a potential
dictionary attack (DA) lock-out. A previously sent command failing
authorization with DA implications would otherwise trigger the
TPM_PT_LOCKOUT_COUNTER to increase by '1' if the TPM 2 was not properly
shut down by the client (guest OS) with a TPM2_Shutdown() command.

The test case tests whether a TPM2_Shutdown() is now sent before a reset.
The defined password-protected NVRAM area has the DA flag set and the test
case tries to read from it without providing a password. If we didn't send
the TPM2_Shutdown() before the test cases sends the reset (CMD_INIT), then
the dictionary attack lockout counter would be increased by one. With the
instrumentation in the previous patch the automatically sent
TPM2_Shutdown() keeps the counter at 0.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-08-18 09:50:16 -04:00
Stefan Berger
97e910af58 swtpm: Introduce disable-auto-shutdown flag for --flags option
Introduce disable-auto-shutdown flag for the --flags option to disable
the sending of TPM2_Shutdown() if swtpm determines that it needs to send
this command to a TPM 2 before device reset or swtpm program termination.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-08-18 09:50:16 -04:00
Stefan Berger
9b3add22ac swtpm: If necessary send TPM2_Shutdown() before TPMLIB_Terminate()
If necessary send a TPM2_Shutdown() command to libtpms before processing
CMD_INIT. However, this is only necessary for a TPM 2 and only if the
TPM2_Shutdown command has not been sent by the client (VM TPM driver) as
the last command as it should do under normal circumstances, for example
upon graceful VM shutdown.

This fixes a bug where abrupt VM resets may trigger the TPM 2's dictionary
attack lockout logic due to the TPM 2 not having received a TPM2_Shutdown
command before it was reset using CMD_INIT for example. An OS driver is
typically supposed to send a TPM2_Shutdown to the TPM 2 but an abrupt VM
reset prevents it.

There are 3 control commands where this needs to be done since they
call TPMLIB_Terminate():

- CMD_STOP:
   This command is typically called before setting the state blobs of the
   TPM or before configuring the buffer size [QEMU, test cases].

- CMD_INIT:
   This command is called for resetting and initializing the TPM 2.

- CMD_SHUTDOWN:
   This command is called for a graceful shutdown of the TPM 2.

There are no negative side effects to be expected if TPM2_Shutdown()
is sent before any of these. Also, since none of these are sent before
the state of the TPM is marshalled (for migration for example) migrated
state will not have a TPM2_Shutdown() applied to it (accidentally).

Edk2 sends a sequence of TPM2_Shutdown(SU_STATE) + TPM2_GetRandom()
before suspend-to-ram. Upon wake up a CMD_INIT is sent to the TPM to
reset it, which in this case now requires a TPM2_Shutdown(SU_STATE)
to be sent to the TPM 2 so that certain TPM 2 state is available
again upon resume. To avoid invaliding the SU_STATE, first send a
TPM2_Shutdown(SU_STATE) in *all cases* and only if this fails send a
TPM2_Shutdown(SU_CLEAR). This way the internal state is preserved and
the VM (or user) are expected to use TPM2_Startup(SU_CLEAR) when
staring up the TPM 2 and no previous state needs to be resumed.

Note: The VM's firmware is trusted to use SU_CLEAR under normal circum-
stances and SU_STATE upon resume. So it wouldn't restore the state if
it wasn't needed.

Note: The TPM 2 spec describes the command as follows:

"This command is used to prepare the TPM for a power cycle. The
shutdownType parameter indicates how the subsequent TPM2_Startup() will be
processed.[...]
This command saves TPM state but does not change the state other than the
internal indication that the context has been saved. The TPM shall
continue to accept commands. If a subsequent command changes TPM state
saved by this command, then the effect of this command is nullified. The
TPM MAY nullify this command for any subsequent command rather than check
whether the command changed state saved by this command. If this command
is nullified and if no TPM2_Shutdown() occurs before the next
TPM2_Startup(), then the next TPM2_Startup() shall be
TPM2_Startup(CLEAR)."

Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2087538
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-08-18 09:50:16 -04:00
Stefan Berger
75fbda26f6 swtpm: Track last command processed by the TPM
Track the last command processed by the TPM so we can determine whether
we may need to send a TPM2_Shutdown() before reset of the TPM 2.

Introduce a variable lastCommand to help track the last command that
was sent to the TPM 2.

In relation to deciding whether a TPM2_Shutdown() needs to be sent, the
tracking of the last-sent command is merely an optimization since for
example a VM with EDK2 will send a TPM2_Shutdown() followed by a
TPM2_GetRandom() upon suspend-to-ram, thus indicating that the last
command was TPM2_GetRandom(). However, under most circumstances it helps
to avoid sending an additional TPM2_Shutdown() if the OS TPM driver sent
one already.

When the suspended VM resume swtpm gets a CMD_INIT that requires swtpm
to decide whether a TPM2_Shutdown() needs to be sent and per the last-sent
command it will then send a TPM2_Shutdown(SU_STATE) as in the abrupt
termination case.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-08-18 09:50:16 -04:00
Stefan Berger
132f51d41b swtpm_ioctl: Only close file descriptor if >= 0 (Coverity)
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-08-16 09:00:42 -04:00
Stefan Berger
841b9319e8 swtpm: seccomp: Check for __SNR_xyz rather than __NR_xyz
If seccomp-syscalls.h lags behind the syscall definition of __NR_xyz then
the __SNR_xyz #define is not available. Therefore, switch to check for
__SNR_xyz #define because they are available if __NR_xyz is available.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-08-15 15:44:51 -04:00
Stefan Berger
5e03ed6c32 swtpm: Implement fips_mode_enabled()
Implement fips_mode_enabeld() to check whether FIPS is enabledand
use the new function to check for FIPS mode enablement before
trying to disable it.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-08-15 12:56:43 -04:00
Stefan Berger
412a9067fd swtpm: Rename disable_fips_mode() and move into tpmlib_start()
Rename disable_fips_mode() to fips_mode_disable() amd move into
tpmlib_start() after TPMLIB_MainInit(). Clean up the duplicate
prototype.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-08-15 12:56:43 -04:00
Hans
eaa9f92201 swtpm: Fixed typo fs_mount vs fsmount and removed duplicates.
The project wouldn't compile on my ubuntu 20.04.1 based system with the error message:
```
  CC       libswtpm_libtpms_la-seccomp_profile.lo
In file included from seccomp_profile.c:44:
seccomp_profile.c: In function ‘create_seccomp_profile’:
seccomp_profile.c:105:9: error: ‘__SNR_fs_mount’ undeclared (first use in this function)
  105 |         SCMP_SYS(fs_mount),
      |         ^~~~~~~~
seccomp_profile.c:105:9: note: each undeclared identifier is reported only once for each function it appears in
```

Additionally, there were some duplicates in the profile.

Signed-off-by: Hans Niklas Jacob <hnj@posteo.de>
2022-08-15 11:33:01 -04:00
Stefan Berger
cf1f966c25 swtpm: Add some more recent syscalls to seccomp profile
Add some more recent syscalls to the disallowlist in the seccomp
profile.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-08-12 13:51:34 -04:00
Stefan Berger
c4adfa3e57 swtpm: cuse: Extend usage of FILE_OPS_LOCK to protect a reading thread
Extend usage of the FILE_OPS_LOCK to prevent other threads from reading or
writing commands or doing ioctls while the current thread is reading a
response. This prevents a race condition where ptm_read_offset is set to 0
by a thread writing a new command to the device while the current thread
is reading a response from the device and needs this offset.

Resolves: https://github.com/stefanberger/swtpm/issues/725
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-08-12 08:54:50 -04:00
Stefan Berger
54de243efd tests: Remove dump of logfile at end of test
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-08-11 15:02:25 -04:00
Stefan Berger
b8c1a0fc88 swtpm_setup: Add missing newline to help screen
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-08-10 20:38:59 -04:00
Stefan Berger
0fb6f9001b man: Replace swtpm_cuse man page with redirect to swtpm man page
The swtpm man page also covers the CUSE TPM, so do not maintain the
swtpm_cuse man page anymore but replace it with a redirect to the swtpm
mane page instead.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2022-08-10 19:30:35 -04:00