Compare commits

...

49 Commits

Author SHA1 Message Date
Marc Hartmayer
074de1e14e genprotimg: add host-key document verification support
Add host-key document verification support to genprotimg. This ensures
that a host-key document is genuine and provided by IBM. For this the
user must provide the IBM Z signing key, the intermediate CA
certificate (signed by the root CA used) so a chain of trust starting
from the host-key document and ending in the root CA can be
established.

By default, genprotimg tries to download all revocation lists needed
by looking up in the corresponding certificate on how CRL information
can be obtained (see https://tools.ietf.org/html/rfc5280#section-4.2.1.13
for details).

Acked-by: Patrick Steuer <patrick.steuer@de.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-11-18 11:28:35 +01:00
Ingo Franzki
07d181e29b zkey: Fix APQN property names
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-11-18 11:28:35 +01:00
Marc Hartmayer
895a88b2f8 genprotimg: require argument for 'ramdisk' and 'parmfile' options
A argument is required for the optional options 'ramdisk' and
'parmfile'.

Fixes: 65b9fc442c ("genprotimg: introduce new tool for the creation of PV images")
Reviewed-by: Bjoern Walk <bwalk@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-11-18 11:28:35 +01:00
Ingo Franzki
f01f8b240c zkey-ekmfweb: Fix typo in message
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-11-18 11:28:35 +01:00
Jan Höppner
be2bc610b7 netboot: Add version information to scripts
Add the -v short option for version information to the mk-s390image and
mk-pxelinux-ramfs. Adjust the Makefile accordingly to set the correct
s390-tools version during installation.

Acked-by: Viktor Mihajlovski <mihajlov@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-11-18 11:28:35 +01:00
Marc Hartmayer
c48d45ba92 common.mak: use '--' for rm calls to distinguish between options and files
Use '--' for rm calls to distinguish between options and files. This
fixes, for example, the following error:

make[1]: Entering directory '/root/git/s390-tools/genprotimg/src'
rm -f *.gcda *.gcno *.gcov
rm: invalid option -- '.'
Try 'rm ./-.gcno' to remove the file '-.gcno'.
Try 'rm --help' for more information.
make[1]: *** [../../common.mak:369: clean_gcov] Error 1

Acked-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-11-18 11:28:35 +01:00
Thomas Richter
886476a207 cpumf/chcpumf.c: Print proper error message on non-root invocation
chcpumf must be executed as root. A non-root user sees this error
message:

[tester@t35lp46 ~]$ chcpumf -m 1000
Error: /sys/module/kernel/parameters/cpum_sfb_size: Permission denied
[tester@t35lp46 ~]$

Enhance the error message and be clear about the root cause:
[tester@t35lp46 ~]$ chcpumf-new  -m 1000
Error: Must run as root
[tester@t35lp46 ~]$

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Acked-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-11-18 11:28:35 +01:00
Thomas Richter
86685f001d cpumf/lscpumf.c: Check for help and version options first
Check command line arguments for help text and version
string first, before doing any action. This ensures this
information is always printed, even when invoked as non-root
user.

Fixes: https://github.com/ibm-s390-tools/s390-tools/issues/97
Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-11-18 11:28:35 +01:00
Jan Höppner
d619b492e9 lsdasd: Add FC Endpoint Security information
Provide the status of the FC Endpoint Security information via the long
output of lsdasd for online Base and Alias devices.

New Output:

$ lsdasd -l c600
0.0.c600/dasdd/9412
  status:                               n/f
  type:                                 ECKD
  blksz:                                512
  size:
  blocks:
  extent_size:                          1113
  logical_capacity:                     1113
  space_allocated:                      1113
  use_diag:                             0
  readonly:                             0
  eer_enabled:                          0
  erplog:                               0
  hpf:                                  1
  uid:                                  IBM.750000000KMV11.c600.00
  fc_security:                          Encryption
  paths_installed:                      38 39 3a 3b
  paths_in_use:                         38 39 3a 3b
  paths_non_preferred:
  paths_invalid_cabling:
  paths_cuir_quiesced:
  paths_invalid_hpf_characteristics:
  paths_error_threshold_exceeded:

Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-11-12 10:50:48 +01:00
Jan Höppner
79e4798061 zdev: Add FC Endpoint Security information for DASD devices
Provide information for the DASD device attribute 'fc_security'.
The help output for this attribute can be queried like this:

chzdev dasd --help-attribute

The lszdev tool can be used to display the current state of the FC
Endpoint Security information:

lszdev dasd -a -c TYPE,ID,ATTR:fc_security,ATTRPATH:fc_security

Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-11-12 10:50:48 +01:00
Ingo Franzki
cf2311f1f1 zcryptstats: Fix handling of partial results with many domains
When many domains per card are available, then the results of the SCDMD
CHSC call may not fit into the output area, and a partial result is
returned. The further results must be retrieved with another CHSC call.

Fix the code to pass the correct next-domain to the subsequent CHSC call
of a partial response. Otherwise the same set of domains 1 to n are
retrieved again, resulting in an infinite loop, because this will always
produce a partial result.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-11-12 08:06:11 +01:00
Colin Walters
7e832da790 systemd/cpi.service: Add RemainAfterExit=yes
Noticed this while looking at the unit file for a different
RHEL CoreOS issue.

See https://github.com/ostreedev/ostree/pull/1697
and https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=750683

Omitting this can cause the service to run multiple times if
something else ends up depending on it, which I'm guessing
we don't want.

Closes: https://github.com/ibm-s390-tools/s390-tools/pull/72
Signed-off-by: Colin Walters <walters@verbum.org>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-11-11 14:25:46 +01:00
Dan Horák
3b402a0630 lscpumf: add z15 Model T02
Closes: https://github.com/ibm-s390-tools/s390-tools/pull/87
Signed-off-by: Dan Horák <dan@danny.cz>
Reviewed-by: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-11-11 14:25:46 +01:00
Dan Horák
3437c9bb90 netboot/mk-s390image: add simple man page
Closes: https://github.com/ibm-s390-tools/s390-tools/pull/94
Signed-off-by: Dan Horák <dan@danny.cz>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-11-11 14:25:46 +01:00
Philipp Kern
8898650266 scripts/zipl-switch-to-blscfg.1: Fix some typos
Closes: https://github.com/ibm-s390-tools/s390-tools/pull/90
Signed-off-by: Philipp Kern <pkern@google.com>
Acked-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-11-11 14:25:46 +01:00
Prashanth Sundararaman
3ae2100d5e systemd/cpi.service: Add sysinit.target dependency to make sure /var is created
Noticed on RHEL CoreOS that the CPI service failed to start with:

"Cannot access lock file: /var/lock/cpictl.lock"

This was a timing issue where /var was not created yet and the symlink
to /run/lock was not present. Add sysinit.target to fix this.
This fix has been tested with RHEL CoreOS.

Closes: https://github.com/ibm-s390-tools/s390-tools/pull/82
Signed-off-by: Prashanth Sundararaman <psundara@redhat.com>
Suggested-by: Colin Walters <walters@verbum.org>
Reviewed-by: Dan Horák <dan@danny.cz>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-11-11 14:25:46 +01:00
Alexander Egorenkov
93e4249fd3 zkey/ekmfweb: fix linking of libekmfweb
Use -L compiler's parameter instead of the environment variable
LIBRARY_PATH.

Fixes the following problem on buildroot:

buildroot/qemu-s390x/host/bin/s390x-linux-gcc -shared -Wl,--version-script=zkey-ekmfweb.map -Wl,-z,defs,-Bsymbolic -Wl,-soname,zkey-ekmfweb.so.1 zkey-ekmfweb.o properties.o pkey.o cca.o ep11.o utils.o ../..//libutil/libutil.a -lekmfweb -ldl -lcrypto -o zkey-ekmfweb.so
buildroot/qemu-s390x/host/bin/s390x-linux-gcc -I ../../include -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -I ../include -std=gnu99 -Wno-unused-parameter -Wno-missing-field-initializers -DS390_TOOLS_RELEASE=2.15.1-build-20201105 -DS390_TOOLS_LIBDIR=/lib/s390-tools -DS390_TOOLS_DATADIR=/usr/share/s390-tools -DS390_TOOLS_SYSCONFDIR=/etc -DS390_TOOLS_BINDIR=/sbin -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64  -Os   -D_GNU_SOURCE -c udev_ccwgroup.c -o udev_ccwgroup.o
buildroot/qemu-s390x/host/bin/s390x-linux-gcc -I ../../include -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -I ../include -std=gnu99 -Wno-unused-parameter -Wno-missing-field-initializers -DS390_TOOLS_RELEASE=2.15.1-build-20201105 -DS390_TOOLS_LIBDIR=/lib/s390-tools -DS390_TOOLS_DATADIR=/usr/share/s390-tools -DS390_TOOLS_SYSCONFDIR=/etc -DS390_TOOLS_BINDIR=/sbin -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64  -Os   -D_GNU_SOURCE -c iscsi.c -o iscsi.o
buildroot/qemu-s390x/host/bin/s390x-linux-gcc -I ../../include -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -I ../include -std=gnu99 -Wno-unused-parameter -Wno-missing-field-initializers -DS390_TOOLS_RELEASE=2.15.1-build-20201105 -DS390_TOOLS_LIBDIR=/lib/s390-tools -DS390_TOOLS_DATADIR=/usr/share/s390-tools -DS390_TOOLS_SYSCONFDIR=/etc -DS390_TOOLS_BINDIR=/sbin -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64  -Os   -D_GNU_SOURCE -c dasd.c -o dasd.o
buildroot/qemu-s390x/host/opt/ext-toolchain/bin/../lib/gcc/s390x-buildroot-linux-gnu/9.3.0/../../../../s390x-buildroot-linux-gnu/bin/ld: cannot find -lekmfweb
collect2: error: ld returned 1 exit status
make[4]: *** [Makefile:36: zkey-ekmfweb.so] Error 1
make[3]: *** [Makefile:128: ekmfweb] Error 2
buildroot/qemu-s390x/host/bin/s390x-linux-gcc -I ../../include -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -I ../include -std=gnu99 -Wno-unused-parameter -Wno-missing-field-initializers -DS390_TOOLS_RELEASE=2.15.1-build-20201105 -DS390_TOOLS_LIBDIR=/lib/s390-tools -DS390_TOOLS_DATADIR=/usr/share/s390-tools -DS390_TOOLS_SYSCONFDIR=/etc -DS390_TOOLS_BINDIR=/sbin -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64  -Os   -D_GNU_SOURCE -c zfcp.c -o zfcp.o
make[2]: *** [Makefile:43: zkey] Error 2
make[2]: *** Waiting for unfinished jobs....

Signed-off-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Acked-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-11-11 14:25:46 +01:00
Jan Höppner
8ec4705239 libutil: Compare proc entries to vfstype
Modern systems have systemd manage system mount points like sysfs which
specify 'sysfs' as a keyword for the device as there is no device
associated with this special filesystem. However, any arbitrary string
could be specified here and the determination of the sysfs mount point
would fail in such a case.
To make sure that the mount point of the sysfs is still found when
mounted with a device keyword specified other than 'sysfs', check for
the filesystem type instead, which is more specific.

Fixes: https://github.com/ibm-s390-tools/s390-tools/issues/91
Suggested-by: Mark Post <mpost@suse.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-11-09 12:24:32 +01:00
Jan Höppner
cad450fdf9 dasdfmt: Make error function less error-prone
Add a proper definition to the dasdfmt header file of the error()
function that lets the compiler check the format string against the
provided parameters.

Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-11-09 12:24:32 +01:00
Dan Horák
3a1cda59ce libekmfweb: fix permissions for ekmfweb.h
Closes: https://github.com/ibm-s390-tools/s390-tools/pull/96
Signed-off-by: Dan Horák <dan@danny.cz>
Acked-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-11-09 10:39:46 +01:00
Wenjia Zhang
0566a492ae hsci: Add new tool to control HiperSockets Converged Interfaces
hsci is used to control and show HSCI (HiperSockets Converged Interfaces)
settings. A HiperSockets interface and an external network interface are
converged to an HSCI interface.

Signed-off-by: Alexandra Winter <wintera@linux.ibm.com>
Signed-off-by: Wenjia Zhang <wenjia@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-11-09 10:16:22 +01:00
Marc Hartmayer
bc7359d2a3 iucvterm: abort if one of the recursive targets is failing
Abort processing as soon as one of the recursive targets is failing.

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-11-06 16:18:21 +01:00
Marc Hartmayer
db6f272607 genprotimg: fix two memory leaks
==1005844== HEAP SUMMARY:
==1005844==     in use at exit: 18,907 bytes in 14 blocks
==1005844==   total heap usage: 82 allocs, 68 frees, 32,529 bytes allocated
==1005844==
==1005844== 136 (104 direct, 32 indirect) bytes in 1 blocks are definitely lost in loss record 12 of 14
==1005844==    at 0x483885A: calloc (vg_replace_malloc.c:760)
==1005844==    by 0x48C950D: g_malloc0 (gmem.c:132)
==1005844==    by 0x100EC41: pv_args_new (pv_args.c:364)
==1005844==    by 0x100587F: main (genprotimg.c:122)
==1005844==
==1005844== LEAK SUMMARY:
==1005844==    definitely lost: 104 bytes in 1 blocks
==1005844==    indirectly lost: 32 bytes in 1 blocks
==1005844==      possibly lost: 0 bytes in 0 blocks
==1005844==    still reachable: 18,771 bytes in 12 blocks
==1005844==         suppressed: 0 bytes in 0 blocks
==1005844== Reachable blocks (those to which a pointer was found) are not shown.
==1005844== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==1005844==
==1005844== For lists of detected and suppressed errors, rerun with: -s
==1005844== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-11-06 16:18:21 +01:00
Marc Hartmayer
6db7fbe018 genprotimg: abort if one of the recursive targets is failing
Abort compilation as soon as one of the recursive targets is failing.

Fixes: 65b9fc442c ("genprotimg: introduce new tool for the creation of PV images")
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-11-06 16:18:21 +01:00
Sven Schnelle
2f154fa49d cmsfs-fuse: fix pointer block level calculation
Adding one to the pointer per block value results in a wrong
calculation of pointer block levels. When writing a file that
would result in about 454MB size, the code would calculate that
it needs a two level pointer directory but correct would be a three
level pointer directory. This causes an invalid filesystem state:
besides missing all the records of one top level pointer directory
entry, it would also record a higher record number in the FST than
what is present in the pointer blocks.

Note that this bug only hits when the file is about 454MB and the write
is stopped (means the file is closed) - if file writing continues the
problem doesn't happen because at some point in time cmsfs-fuse would
switch to three levels of pointer blocks anyways as the file grows.

Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-11-06 16:18:21 +01:00
Jan Höppner
148d3f9b64 dasdfmt: Fix segfault when an incorrect option is specified
When specifying an incorrect program option, dasdfmt segfaults as the
format string for the corresponding error message has no parameter.
Add the missing parameter to fix this.

Fixes: 732b3dddab ("dasdfmt: Replace ERRMSG_EXIT macro with an error handling function")
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-11-03 09:05:29 +01:00
Brian C. Lane
702dc96264 netboot: Clear kernel cmdline data before writing new parmfile
If this isn't cleared first it can end up with an unexpected cmdline if
it doesn't completely overwrite the default data.

Closes: https://github.com/ibm-s390-tools/s390-tools/pull/95
Reviewed-by: Viktor Mihajlovski <mihajlov@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-11-03 09:05:29 +01:00
Jan Höppner
313092b202 Prepare for next release
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-11-03 09:05:29 +01:00
Jan Höppner
b098990abe New release s390-tools-2.15.1
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-10-28 15:31:59 +01:00
Stefan Haberland
6802b86414 libutil: determine base device address in case of given partition
util_sys_get_dev_addr() returns the device address for a given blockdevice.
This does not work for partitions but some tools rely on the ability to get
the device address for partitions.

Add code that first determines the base device for a partition.

Fixes: 6014d07cb1 ("dasdview/libdasd/zipl: Use util_sys_get_dev_addr() instead of u2s_getbusid()")
Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-10-28 15:08:29 +01:00
Stefan Haberland
aa8c2945cc zipl: make use of util_sys functions to get base device
Remove the implementation in zipl and use the util_sys one.

Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-10-28 15:08:24 +01:00
Stefan Haberland
fa7a4dafa3 libutil: add function to get base device for blockdevice
Some operations are only possible on base devices not on partitions.
Add functions to determine if a given device is a partition or a base
device and to get the base device to a given partition.

Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-10-28 15:08:02 +01:00
Jan Höppner
7eb04cdc54 zfcpdump: Fix dump location in README
Commit 724f1fea2c ("Makefile: Rename ZFCPDUMP_PART_* macros") renamed
the zfcpdump image from zfcpdump_part.image to zfcpdump-image. Fix the
image name in the README as well.

Closes: https://github.com/ibm-s390-tools/s390-tools/issues/89
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-10-28 13:22:45 +01:00
Jan Höppner
d55b787d05 zgetdump: Fix device node determination via sysfs
When using zgetdump on a multi-volume device dump, the sysfs path to
determine the device node is incomplete, resulting in the following
error:

$ zgetdump -i /dev/dasdb1
zgetdump: Could not open "/sys/bus/ccw/devices/0.0.9300/dasdb/dev" (No
such file or directory)

A simple fix would be to add the missing "block" part in the sysfs path.
However, the logic still assumes sysfs links like "block:" that have
been deprecated a decade ago and are no longer present on modern
systems anyway.
Therefore, the logic can greatly be improved. Create a separate function
to determine whether a device is online, remove the logic for "block:"
entries, and use libutil functions to reduce the complexity even further.

Fixes: 70a79fab3c ("zgetdump: Avoid using PATH_MAX")
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-10-28 13:22:45 +01:00
Jan Höppner
da4fdeeb82 dasdfmt: Set prog_name to last component of program name
In the process of switching to glibc defined error functions it becomes
apparent that self-defined error functions that do special things are
not in line with the output of the glibc functions.

To address this, set the prog_name variable to the last component of the
program name (stored in argv[0]) and guarantee a uniform error output.

Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-10-28 13:22:45 +01:00
Jan Höppner
9fe491df27 dasdfmt: Improve error message construction
In check_track_format() the base error message is the same for all cases
but has different additional content depending on which mode dasdfmt is
running.

Currently the message is compiled by using different outputs. To make it
a little bit cleaner and for a better error message handling, construct
the message string completely before passing it to the error() function
for output.

Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-10-28 13:22:45 +01:00
Jan Höppner
732b3dddab dasdfmt: Replace ERRMSG_EXIT macro with an error handling function
The ERRMSG_EXIT macro is a bit clunky in its usage and a change is
necessary in order to free memory in error cases.

Create a new function error() that takes only a format string and adds
all other relevant information by itself. This function frees memory
before terminating the program with the EXIT_FAILURE exit code.

This simplifies the error handling for pretty much all calls and makes
the code a bit cleaner.

While at it, the defines EXIT_MISUSE and EXIT_BUSY don't provide any
value. Neither are they documented nor are these standardized. Also, a
parent process is mostly interessted in success or failure only anyway.
Replace these by using only EXIT_FAILURE in the error() function.

Also, change multiline output to a combination of warnx and error to
have a uniformed output. So this:

WARNING: Device is formatted with a different blocksize (4096).
Use --mode=full to perform a clean format.

becomes this:

dasdfmt: WARNING: Device is formatted with a different blocksize (4096).
dasdfmt: Use --mode=full to perform a clean format.

Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-10-28 13:22:45 +01:00
Jan Höppner
cb76e39cef dasdfmt: Fix bad file descriptor error when running on symlinks
When calling dasdfmt on device node symlinks like
/dev/disk/by-id/ccw-0X9300, dasdfmt fails with "dasdfmt: the ioctl to get
the blocksize of the device failed (Bad file descriptor)"

This is because before the actual formatting process starts, the disk
will be disabled calling the BIODASDDISABLE ioctl, resulting in the
removal of the symlink. Trying to open this file later in the process to
retrieve e.g. blocksize information results in the mentioned error, as
the file doesn't exist any longer.

This incorrect behaviour was introduced with commit 8826028bdc
("dasdfmt: Use libdasd provided ioctl functions") at which the use of a
globally available file descriptor was omitted. Instead, the ioctl
library functions require a device node to be passed as a function
parameter and will open a file descriptor themselves.
So, before that change, the global file descriptor was always valid even
when the file was removed.

In order to fix this without modifying the behaviour of libdasd,
introduce the two global variables dev_node and dev_path. dev_path is
the original device path entered by the user. dev_node on the other hand
is the reliable device node under /dev/block/ using the major and minor
numbers and is determined in get_device_name().
The dev_path is used for message output only and the dev_node variable
is used for the actual disk operations.

As these two variables are global, the device parameters for several
functions are removed to make the code a bit cleaner.

Fixes: 8826028bdc ("dasdfmt: Use libdasd provided ioctl functions")
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-10-28 13:22:45 +01:00
Jan Höppner
09be935c54 dasdfmt: Make program relevant information global
The global program options (and other actually globally used
information) are currently passed through via function parameter
whenever this information is needed. However, in reality, this
information is used almost everywhere across the program.

Make this information globally available and get rid of all the
unnecessary function parameters for dasdfmt_info_t. This makes the code
a little bit cleaner and more readable. Also, rename the global struct
to a more suitable name.

Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-10-28 13:22:45 +01:00
Jan Höppner
65e18bff67 dasdfmt: Remove function dasdfmt_format
dasdfmt_format() does nothing but calling process_tracks() with the same
parameters. Get rid of it, call process_tracks() directly, and avoid
confusion.

Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-10-28 13:22:45 +01:00
Jan Höppner
07ab32fa8b dasdfmt: Fix whitespace
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-10-28 13:22:45 +01:00
Jan Höppner
353403824b libdasd: Fix dasd_get_host_access_count()
Since commit 75e3afb6a0 ("libdasd: Move get_host_access_count() to
libdasd") dasd_get_host_access_count() reports always 0 as the check for
unsuccessful execution of util_sys_get_dev_addr() is incorrect.
Fix the behaviour by turning the check around.

Fixes: 75e3afb6a0 ("libdasd: Move get_host_access_count() to libdasd")
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-10-28 13:22:45 +01:00
Ingo Franzki
8a58389e2f zkey: Add library versioning for libekmfweb and zkey-ekmfweb
Closes: https://github.com/ibm-s390-tools/s390-tools/issues/93

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-10-28 13:22:45 +01:00
Alexander Egorenkov
f2cc871b02 genprotimg/boot: disable SSP
SSP cannot work with boot loaders because it requires libc.

Signed-off-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-10-28 13:22:45 +01:00
Alexander Egorenkov
4dbdc8dfab zipl/boot: disable SSP
SSP cannot work with boot loaders because it requires libc.

Signed-off-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-10-28 13:22:45 +01:00
Ingo Franzki
60900de5e9 zkey: Skip build of zkey-ekmfweb.so if libekmfweb dependencies are missing
zkey-ekmfweb.so requires libekmfweb.so. If libekmfweb.so can not be built
due to missing build requirements, then zkey-ekmfweb.so can't be built
either.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-10-28 13:22:45 +01:00
Sven Schnelle
2bba362e9a lsstp: Improve wording and fix typos in man page
Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-10-28 13:22:45 +01:00
Ingo Franzki
76044be98d zkey: Ensure zkey and friends are skipped with HAVE_OPENSSL=0
Building zkey-ekmfweb.so will also trigger to build libekmfweb.so,
which requires OpenSSL. So, skip zkey-ekmfweb.so if HAVE_OPENSSL=0.

zkey-cryptsetup also has a dependency on OpenSSL, so skip it also
if HAVE_OPENSSL=0

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-10-28 13:22:29 +01:00
Jan Höppner
885ff0a03f Prepare for next release
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-10-15 15:56:15 +02:00
51 changed files with 3284 additions and 745 deletions

3
.gitignore vendored
View File

@@ -37,6 +37,8 @@ iucvterm/test/test_afiucv
libekmfweb/check-dep-libekmfweb
libekmfweb/detect-openssl-version.dep
libekmfweb/libekmfweb.so
libekmfweb/libekmfweb.so.1
libekmfweb/libekmfweb.so.1.0
libutil/util_base_example
libutil/util_file_example
libutil/util_libc_example
@@ -97,6 +99,7 @@ zipl/src/zipl_helper.device-mapper
zkey/check-dep-zkey
zkey/check-dep-zkey-cryptsetup
zkey/detect-libcryptsetup.dep
zkey/ekmfweb/libekmfweb.dep
zkey/ekmfweb/zkey-ekmfweb.so
zkey/zkey
zkey/zkey-cryptsetup

View File

@@ -1,5 +1,33 @@
Release history for s390-tools (MIT version)
--------------------------------------------
* __v2.15.x (2020-xx-xx)__
For Linux kernel version: 5.x
Changes of existing tools:
- hsci: New tool to manage HSCI interfaces
- genprotimg: Add host-key document verification support
Bug Fixes:
* __v2.15.1 (2020-10-28)__
For Linux kernel version: 5.9
Changes of existing tools:
- lsstp: Improve wording and fix typos in man page
- zkey: Ensure zkey and friends are skipped with HAVE_OPENSSL=0
- zkey: Add library versioning for libekmfweb and zkey-ekmfweb
- libutil: Add function to determine base device of a partition block device
Bug Fixes:
- dasdfmt: Fix bad file descriptor error when running on symlinks
- libdasd: Fix dasd_get_host_access_count()
- zipl: Fix multivolume dump
- zgetdump: Fix device node determination via sysfs to work with multivolume again
- genprotimg/boot: Fix build by disabling SSP
- zipl/boot: Fix build by disabling SSP
* __v2.15.0 (2020-10-15)__
For Linux kernel version: 5.9

View File

@@ -9,7 +9,7 @@ TOOL_DIRS = zipl zdump fdasd dasdfmt dasdview tunedasd \
vmconvert vmcp man mon_tools dasdinfo vmur cpuplugd ipl_tools \
ziomon iucvterm hyptop cmsfs-fuse qethqoat zfcpdump zdsfs cpumf \
systemd hmcdrvfs cpacfstats zdev dump2tar zkey netboot etc zpcictl \
genprotimg lsstp
genprotimg lsstp hsci
SUB_DIRS = $(LIB_DIRS) $(TOOL_DIRS)

View File

@@ -249,6 +249,9 @@ Package contents
Management Foundation - Web Edition, and is used to manage keys in an
enterprise.
* hsci:
Manage HiperSockets Converged Interfaces (HSCI).
For more information refer to the following publications:
* "Device Drivers, Features, and Commands" chapter "Useful Linux commands"
@@ -277,7 +280,7 @@ build options:
| cryptsetup | `HAVE_CRYPTSETUP2` | zkey-cryptsetup |
| json-c | `HAVE_JSONC` | zkey-cryptsetup, libekmfweb |
| glib2 | `HAVE_GLIB2` | genprotimg |
| libcurl | `HAVE_LIBCURL` | libekmfweb |
| libcurl | `HAVE_LIBCURL` | genprotimg, libekmfweb |
This table lists additional build or install options:

View File

@@ -2050,7 +2050,7 @@ static int update_dir_levels(int blocks)
if (blocks < 2)
return 0;
while (blocks / (PTRS_PER_BLOCK + 1)) {
while (blocks / PTRS_PER_BLOCK) {
levels++;
blocks /= PTRS_PER_BLOCK;
}
@@ -3103,7 +3103,7 @@ static void update_levels(struct file *f)
return;
}
while (blocks / (per_block + 1)) {
while (blocks / per_block) {
levels++;
blocks /= per_block;
}

View File

@@ -6,7 +6,7 @@ COMMON_INCLUDED = true
# "make DISTRELEASE=%{release}" and "make install DISTRELEASE=%{release}"
VERSION = 2
RELEASE = 15
PATCHLEVEL = 0
PATCHLEVEL = 1
DISTRELEASE = build-$(shell date +%Y%m%d)
S390_TOOLS_RELEASE = $(VERSION).$(RELEASE).$(PATCHLEVEL)-$(DISTRELEASE)
export S390_TOOLS_RELEASE
@@ -163,7 +163,7 @@ USRSBINDIR = $(INSTALLDIR)/usr/sbin
USRBINDIR = $(INSTALLDIR)/usr/bin
BINDIR = $(INSTALLDIR)/sbin
LIBDIR = $(INSTALLDIR)/lib
LIB64DIR = $(INSTALLDIR)/lib64
USRLIB64DIR = $(INSTALLDIR)/usr/lib64
SYSCONFDIR = $(INSTALLDIR)/etc
MANDIR = $(INSTALLDIR)/usr/share/man
VARDIR = $(INSTALLDIR)/var
@@ -179,10 +179,10 @@ INSTDIRS = $(USRSBINDIR) $(USRBINDIR) $(BINDIR) $(LIBDIR) $(MANDIR) \
$(SYSCONFDIR) $(SYSCONFDIR)/sysconfig \
$(TOOLS_LIBDIR) $(TOOLS_DATADIR) \
$(ZFCPDUMP_DIR) $(SYSTEMDSYSTEMUNITDIR) \
$(LIB64DIR) $(USRINCLUDEDIR)
$(USRLIB64DIR) $(USRINCLUDEDIR)
OWNER = $(shell id -un)
GROUP = $(shell id -gn)
export INSTALLDIR BINDIR LIBDIR LIB64DIR MANDIR OWNER GROUP
export INSTALLDIR BINDIR LIBDIR USRLIB64DIR MANDIR OWNER GROUP
# Special defines for zfcpdump
ZFCPDUMP_IMAGE = zfcpdump-image
@@ -366,9 +366,9 @@ install: install_echo install_dirs
clean_echo:
$(call echocmd," CLEAN ")
clean_gcov:
rm -f *.gcda *.gcno *.gcov
rm -f -- *.gcda *.gcno *.gcov
clean_dep:
rm -f .*.o.d
rm -f -- .*.o.d
clean: clean_echo clean_gcov clean_dep
endif

View File

@@ -91,13 +91,18 @@ static int read_sfb(unsigned long *min, unsigned long *max)
int rc = EXIT_SUCCESS;
FILE *fp;
if (geteuid()) {
fprintf(stderr, "Error: Must run as root\n");
return EXIT_FAILURE;
}
fp = fopen(PERF_SFB_SIZE, "r");
if (fp == NULL) {
linux_error(PERF_SFB_SIZE);
return EXIT_FAILURE;
}
if (fscanf(fp, "%ld,%ld", &cur_min_sdb, &cur_max_sdb) != 2) {
fprintf(stderr, "Error: Can not parse file " PERF_SFB_SIZE);
fprintf(stderr, "Error: Can not parse file " PERF_SFB_SIZE
"\n");
rc = EXIT_FAILURE;
} else {
if (*min == 0)

View File

@@ -2572,6 +2572,7 @@ static const char *machine_name(void)
case 3906: return "IBM z14";
case 3907: return "IBM z14 ZR1";
case 8561: return "IBM z15";
case 8562: return "IBM z15 Model T02";
}
return "Unknown hardware model";
}
@@ -3094,11 +3095,11 @@ int main(int argc, char **argv)
util_prg_init(&prg);
util_opt_init(opt_vec, NULL);
ret = read_info();
if (ret == EXIT_FAILURE)
return ret;
ret = parse_args(argc, argv);
if (read_info() == EXIT_FAILURE)
return EXIT_FAILURE;
switch ((ret = parse_args(argc, argv))) {
switch (ret) {
case ACTION_CNT:
case ACTION_CNTALL:
all = ret == ACTION_CNTALL;
@@ -3114,6 +3115,7 @@ int main(int argc, char **argv)
case ACTION_NONE:
case ACTION_INFO:
show_info(&cpumf, ret == ACTION_INFO);
ret = EXIT_SUCCESS;
break;
}
return ret;

File diff suppressed because it is too large Load Diff

View File

@@ -41,6 +41,10 @@ static const char mode_str[3][10] = {
"Full", "Quick", "Expand"
};
/* Report error, free memory, and exit */
static void error(const char *format, ...)
__attribute__((__noreturn__, __format__(__printf__, 1, 2)));
#define DASD_PARTN_BITS 2
#define PARTN_MASK ((1 << DASD_PARTN_BITS) - 1)
@@ -65,47 +69,24 @@ static const char mode_str[3][10] = {
"is in invalid format\n",prog_name);}
typedef struct bootstrap1 {
u_int32_t key;
u_int32_t data[6];
u_int32_t key;
u_int32_t data[6];
} __attribute__ ((packed)) bootstrap1_t;
typedef struct bootstrap2 {
u_int32_t key;
u_int32_t data[36];
u_int32_t key;
u_int32_t data[36];
} __attribute__ ((packed)) bootstrap2_t;
typedef struct dasdfmt_info {
dasd_information2_t dasd_info;
int verbosity;
int testmode;
int withoutprompt;
int print_progressbar;
int print_hashmarks, hashstep;
int print_percentage;
int force;
int writenolabel;
int labelspec;
int cdl_format;
int blksize_specified;
int reqsize_specified;
int keep_volser;
int force_host;
int layout_specified;
int check;
int mode_specified;
int ese;
int no_discard;
} dasdfmt_info_t;
/*
C9D7D3F1 000A0000 0000000F 03000000 00000001 00000000 00000000
*/
static bootstrap1_t ipl1 = {
0xC9D7D3F1, {
0x000A0000, 0x0000000F, 0x03000000,
0x00000001, 0x00000000, 0x00000000
}
0xC9D7D3F1, {
0x000A0000, 0x0000000F, 0x03000000,
0x00000001, 0x00000000, 0x00000000
}
};
/*
@@ -116,21 +97,20 @@ C9D7D3F2 07003AB8 40000006 31003ABE 40000005 08003AA0 00000000 06000000
00000000 00000000 00000000 00000000 00000000
*/
static bootstrap2_t ipl2 = {
0xC9D7D3F2, {
0x07003AB8, 0x40000006, 0x31003ABE,
0x40000005, 0x08003AA0, 0x00000000,
0x06000000, 0x20000000, 0x00000000,
0x00000000, 0x00000400, 0x00000000,
0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000
}
0xC9D7D3F2, {
0x07003AB8, 0x40000006, 0x31003ABE,
0x40000005, 0x08003AA0, 0x00000000,
0x06000000, 0x20000000, 0x00000000,
0x00000000, 0x00000400, 0x00000000,
0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000
}
};
#endif /* DASDFMT_H */

View File

@@ -21,7 +21,7 @@ clean: clean-recursive
$(RECURSIVE_TARGETS):
@target=`echo $@ |sed s/-recursive//`; \
for d in $(SUBDIRS); do \
$(MAKE) -C $$d $$target; \
$(MAKE) -C $$d $$target || exit 1; \
done
.PHONY: all install clean $(RECURSIVE_TARGETS)

View File

@@ -12,7 +12,7 @@ ALL_CFLAGS := $(NO_PIE_CFLAGS) -Os -g \
-DENABLE_SCLP_ASCII=1 \
-DS390_TOOLS_RELEASE=$(S390_TOOLS_RELEASE) \
-fno-builtin -ffreestanding -fno-asynchronous-unwind-tables \
-fno-delete-null-pointer-checks \
-fno-delete-null-pointer-checks -fno-stack-protector \
-fexec-charset=IBM1047 -m64 -mpacked-stack \
-mstack-size=4096 -mstack-guard=128 -msoft-float \
-Wall -Wformat-security -Wextra -Werror

View File

@@ -2,7 +2,7 @@
.\" s390-tools is free software; you can redistribute it and/or modify
.\" it under the terms of the MIT license. See LICENSE for details.
.\"
.TH GENPROTIMG 8 "March 2020" "s390-tools"
.TH GENPROTIMG 8 "November 2020" "s390-tools"
.SH NAME
genprotimg \- Create a protected virtualization image
@@ -10,6 +10,7 @@ genprotimg \- Create a protected virtualization image
.SY
.B genprotimg
\fB\-k\fR \fIHOST_KEY_DOCUMENT\fR...
\fB\-C\fR \fICERTIFICATE\fR...
\fB\-i\fR \fIVMLINUZ\fR
[\fB\-r\fR \fIRAMDISK\fR]
[\fB\-p\fR \fIPARMFILE\fR]
@@ -21,15 +22,19 @@ genprotimg \- Create a protected virtualization image
.PP
Use \fBgenprotimg\fR to generate a single bootable image file with
encrypted and integrity-protected parts. The command requires a kernel
image, a host-key document, and an output file name. Optionally,
specify an initial RAM filesystem, and a file containing the kernel
parameters. Should special circumstances require it, you can
image, a host-key document, certificates for the host-key document
verification, and an output file name. Optionally, specify an initial
RAM filesystem, and a file containing the kernel parameters. If the
command should be run offline, use the \fB\-\-offline\fR option and
specify the certificate revocation lists (CRLs) by using the
\fB\-\-crl\fR option. Should special circumstances require it, you can
optionally specify your own keys for the encryption by using the
experimental options. In the resulting image file, a plain text boot
loader, the encrypted components for kernel, initial RAM disk, kernel
parameters, and the encrypted and integrity-protected header are
concatenated. The header contains metadata necessary for running the
guest in protected mode.
experimental options. For all certificates, CRLs, and host-key
documents, both the PEM and DER input formats are supported. In the
resulting image file, a plain text boot loader, the encrypted
components for kernel, initial RAM disk, kernel parameters, and the
encrypted and integrity-protected header are concatenated. The header
contains metadata necessary for running the guest in protected mode.
.PP
Use this image file as a kernel image for zipl or for a direct kernel
boot using QEMU.
@@ -53,6 +58,12 @@ Specifies a host-key document. At least one is required. Specify this
option multiple times to enable the image to run on more than one
host.
.TP
\fB\-C\fR, \fB\-\-cert\fR=\fI\,FILE\/\fR
Specifies the certificate that is used to establish a chain of trust
for the verification of the host-key documents. Specify this option
twice to specify the IBM Z signing key and the intermediate CA
certificate (signed by the root CA). Required.
.TP
\fB\-o\fR, \fB\-\-output\fR=\fI\,OUTPUT_FILE\/\fR
Specifies the output file. Required.
.TP
@@ -65,6 +76,20 @@ Specifies the RAM disk image. Optional.
\fB\-p\fR, \fB\-\-parmfile\fR=\fI\,PARMFILE\/\fR
Specifies the kernel command line stored in \fI\,PARMFILE\/\fR. Optional.
.TP
\fB\-\-crl\fR=\fI\,FILE\/\fR
Specifies the revocation list that is used to check whether a
certificate of the chain of trust is revoked. Specify this option
multiple times to use multiple CRLs. Optional.
.TP
\fB\-\-offline\fR
Specifies offline mode, in which no attempt is made to download
CRLs. Optional.
.TP
\fB\-\-root\-ca\fR=\fI\,FILE\/\fR
Specifies the root CA certificate for the verification. If omitted,
the DigiCert root CA certificate installed on the system is used. Use
this only if you trust the specified certificate. Optional.
.TP
\fB\-\-no-verify\fR
Do not require the host-key documents to be valid. For testing
purposes, do not use for a production image. Optional.
@@ -77,11 +102,13 @@ Prints version information, then exits.
Generate a protected virtualization image in
\fI\,/boot/vmlinuz.pv\/\fR, using the kernel file \fI\,vmlinuz\/\fR,
the initrd in \fI\,initramfs\/\fR, the kernel parameters contained in
\fI\,parmfile\/\fR, and the host-key document in \fI\,host_key.crt\/\fR:
\fI\,parmfile\/\fR, the intermediate CA in \fI\,DigiCertCA.crt\/\fR,
the IBM Z signing key in \fI\,ibm-z-host-key-signing.crt\/\fR, and the
host-key document in \fI\,host_key.crt\/\fR:
.PP
.Vb 1
.EX
\& genprotimg \-i \fI\,vmlinuz\/\fR \-r \fI\,initramfs\/\fR \-p \fI\,parmfile\/\fR \-k \fI\,host_key.crt\/\fR \-o \fI\,/boot/vmlinuz.pv\/\fR
\& genprotimg \-i \fI\,vmlinuz\/\fR \-r \fI\,initramfs\/\fR \-p \fI\,parmfile\/\fR \-k \fI\,host_key.crt\/\fR \-C \fI\,ibm-z-host-key-signing.crt\/\fR \-C \fI\,DigiCertCA.crt \-o \fI\,/boot/vmlinuz.pv\/\fR
.EE
.Ve
.PP

View File

@@ -23,16 +23,16 @@ WARNINGS := -Wall -Wextra -Wshadow \
$(bin_PROGRAM)_SRCS := $(bin_PROGRAM).c pv/pv_stage3.c pv/pv_image.c \
pv/pv_comp.c pv/pv_hdr.c pv/pv_ipib.c utils/crypto.c utils/file_utils.c \
pv/pv_args.c utils/buffer.c pv/pv_comps.c pv/pv_error.c \
pv/pv_opt_item.c \
pv/pv_opt_item.c utils/curl.c \
$(NULL)
$(bin_PROGRAM)_OBJS := $($(bin_PROGRAM)_SRCS:.c=.o)
ALL_CFLAGS += -std=gnu11 -DPKGDATADIR=$(PKGDATADIR) \
$(GLIB2_CFLAGS) $(LIBCRYPTO_CFLAGS) \
$(GLIB2_CFLAGS) $(LIBCRYPTO_CFLAGS) $(LIBCURL_CFLAGS) \
$(WARNINGS) \
$(NULL)
ALL_CPPFLAGS += $(INCLUDE_PARMS)
LDLIBS += $(GLIB2_LIBS) $(LIBCRYPTO_LIBS)
LDLIBS += $(GLIB2_LIBS) $(LIBCRYPTO_LIBS) $(LIBCURL_LIBS)
ifneq ($(shell sh -c 'command -v pkg-config'),)
@@ -40,21 +40,27 @@ GLIB2_CFLAGS := $(shell pkg-config --silence-errors --cflags glib-2.0)
GLIB2_LIBS := $(shell pkg-config --silence-errors --libs glib-2.0)
LIBCRYPTO_CFLAGS := $(shell pkg-config --silence-errors --cflags libcrypto)
LIBCRYPTO_LIBS := $(shell pkg-config --silence-errors --libs libcrypto)
LIBCURL_CFLAGS := $(shell pkg-config --silence-errors --cflags libcurl)
LIBCURL_LIBS := $(shell pkg-config --silence-errors --libs libcurl)
else
GLIB2_CFLAGS := -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include
GLIB2_LIBS := -lglib-2.0
LIBCRYPTO_CFLAGS :=
LIBCRYPTO_LIBS := -lcrypto
LIBCURL_CFLAGS :=
LIBCURL_LIBS := -lcurl
endif
BUILD_TARGETS := skip-$(bin_PROGRAM)
INSTALL_TARGETS := skip-$(bin_PROGRAM)
ifneq (${HAVE_OPENSSL},0)
ifneq (${HAVE_GLIB2},0)
ifneq (${HAVE_LIBCURL},0)
BUILD_TARGETS := $(bin_PROGRAM)
INSTALL_TARGETS := install-$(bin_PROGRAM)
endif
endif
endif
all: $(BUILD_TARGETS)
@@ -98,4 +104,9 @@ $($(bin_PROGRAM)_OBJS): .check-dep-$(bin_PROGRAM)
"openssl-devel / libssl-dev version >= 1.1.0", \
"HAVE_OPENSSL=0", \
"-I.")
$(call check_dep, \
"$(bin_PROGRAM)", \
"curl/curl.h", \
"libcurl-devel", \
"HAVE_LIBCURL=0")
touch $@

View File

@@ -18,6 +18,8 @@
#include "common.h"
#include "pv/pv_args.h"
#include "pv/pv_image.h"
#include "utils/crypto.h"
#include "utils/curl.h"
enum {
LOG_LEVEL_CRITICAL = 0,
@@ -117,6 +119,8 @@ static void remove_signal_handler(const gint *signals, const gsize signals_n)
signal(signals[i], SIG_DFL);
}
static void __attribute__((constructor)) __init(void);
static void __attribute__((destructor)) __cleanup(void);
gint main(gint argc, gchar *argv[])
{
g_autoptr(PvArgs) args = pv_args_new();
@@ -177,5 +181,20 @@ error:
rmdir_recursive(tmp_dir, NULL);
remove_signal_handler(signals, G_N_ELEMENTS(signals));
g_free(tmp_dir);
g_clear_pointer(&img, pv_img_free);
g_clear_pointer(&args, pv_args_free);
exit(ret);
}
static void __init(void)
{
pv_crypto_init();
if (curl_init() != 0)
g_abort();
}
static void __cleanup(void)
{
curl_cleanup();
pv_crypto_cleanup();
}

View File

@@ -14,6 +14,24 @@
#include "lib/zt_common.h"
/* IBM signing key subject */
#define PV_IBM_Z_SUBJECT_COMMON_NAME "International Business Machines Corporation"
#define PV_IBM_Z_SUBJECT_COUNTRY_NAME "US"
#define PV_IBM_Z_SUBJECT_LOCALITY_NAME "Poughkeepsie"
#define PV_IBM_Z_SUBJECT_ORGANIZATIONONAL_UNIT_NAME_SUFFIX "Key Signing Service"
#define PV_IBM_Z_SUBJECT_ORGANIZATION_NAME "International Business Machines Corporation"
#define PV_IBM_Z_SUBJECT_STATE "New York"
#define PV_IMB_Z_SUBJECT_ENTRY_COUNT 6
/* Minimum security level for the keys/certificates used to establish a chain of
* trust (see https://www.openssl.org/docs/man1.1.1/man3/X509_VERIFY_PARAM_set_auth_level.html
* for details).
*/
#define PV_CERTS_SECURITY_LEVEL 2
/* SKID for DigiCert Assured ID Root CA */
#define DIGICERT_ASSURED_ID_ROOT_CA_SKID "45EBA2AFF492CB82312D518BA7A7219DF36DC80F"
union ecdh_pub_key {
struct {
uint8_t x[80];

View File

@@ -18,7 +18,9 @@
static gchar summary[] =
"Use genprotimg to create a protected virtualization kernel image file,\n"
"which can be loaded using zipl or QEMU.";
"which can be loaded using zipl or QEMU. For all certificates, revocation\n"
"lists, and host-key documents, both the PEM and DER input formats are\n"
"supported.";
static gint pv_arg_compare(gconstpointer arg_1, gconstpointer arg_2)
{
@@ -97,9 +99,14 @@ static gint pv_args_validate_options(PvArgs *args, GError **err)
return -1;
}
if (!args->no_verify) {
g_set_error(err, PV_PARSE_ERROR, PR_PARSE_ERROR_MISSING_ARGUMENT,
_("Use the option '--no-verify' as the verification support is not available yet."));
if (!args->no_verify &&
(!args->untrusted_cert_paths ||
g_strv_length(args->untrusted_cert_paths) == 0)) {
g_set_error(
err, PV_PARSE_ERROR, PR_PARSE_ERROR_MISSING_ARGUMENT,
_("Either specify the IBM Z signing key and (DigiCert) intermediate CA certificate\n"
"by using the '--cert' option, or use the '--no-verify' flag to disable the\n"
"host-key document verification completely (at your own risk)."));
return -1;
}
@@ -141,6 +148,8 @@ static gboolean cb_set_string_option(const gchar *option, const gchar *value,
{
gchar **args_option = NULL;
if (g_str_equal(option, "--root-ca"))
args_option = &args->root_ca_path;
if (g_str_equal(option, "-o") || g_str_equal(option, "--output"))
args_option = &args->output_path;
if (g_str_equal(option, "--x-comp-key"))
@@ -211,6 +220,18 @@ gint pv_args_parse_options(PvArgs *args, gint *argc, gchar **argv[],
_("FILE specifies a host-key document. At least\n" INDENT
"one is required."),
.arg_description = _("FILE") },
{ .long_name = "cert",
.short_name = 'C',
.flags = G_OPTION_FLAG_NONE,
.arg = G_OPTION_ARG_FILENAME_ARRAY,
.arg_data = &args->untrusted_cert_paths,
.description = _(
"FILE contains a certificate that is used to\n" INDENT
"establish a chain of trust for the verification\n" INDENT
"of the host-key documents. The IBM Z signing\n" INDENT
"key and intermediate CA certificate (signed\n" INDENT
"by the root CA) are required."),
.arg_description = _("FILE") },
{ .long_name = "output",
.short_name = 'o',
.flags = G_OPTION_FLAG_FILENAME,
@@ -227,7 +248,7 @@ gint pv_args_parse_options(PvArgs *args, gint *argc, gchar **argv[],
.arg_description = _("IMAGE") },
{ .long_name = "ramdisk",
.short_name = 'r',
.flags = G_OPTION_FLAG_OPTIONAL_ARG | G_OPTION_FLAG_FILENAME,
.flags = G_OPTION_FLAG_FILENAME,
.arg = G_OPTION_ARG_CALLBACK,
.arg_data = cb_add_component,
.description = _("Use RAMDISK as the initial RAM disk\n" INDENT
@@ -235,12 +256,37 @@ gint pv_args_parse_options(PvArgs *args, gint *argc, gchar **argv[],
.arg_description = _("RAMDISK") },
{ .long_name = "parmfile",
.short_name = 'p',
.flags = G_OPTION_FLAG_OPTIONAL_ARG | G_OPTION_FLAG_FILENAME,
.flags = G_OPTION_FLAG_FILENAME,
.arg = G_OPTION_ARG_CALLBACK,
.arg_data = cb_add_component,
.description = _("Use the kernel parameters stored in PARMFILE\n" INDENT
"(optional)."),
.arg_description = _("PARMFILE") },
{ .long_name = "crl",
.short_name = 0,
.flags = G_OPTION_FLAG_NONE,
.arg = G_OPTION_ARG_FILENAME_ARRAY,
.arg_data = &args->crl_paths,
.description = _(
"FILE contains a certificate revocation list\n" INDENT
"(optional)."),
.arg_description = _("FILE") },
{ .long_name = "offline",
.short_name = 0,
.flags = G_OPTION_FLAG_NONE,
.arg = G_OPTION_ARG_NONE,
.arg_data = &args->offline,
.description = _("Don't download CRLs (optional)."),
.arg_description = NULL },
{ .long_name = "root-ca",
.short_name = 0,
.flags = G_OPTION_FLAG_FILENAME,
.arg = G_OPTION_ARG_CALLBACK,
.arg_data = cb_set_string_option,
.description = _(
"Set FILE as the trusted root CA and don't use the\n" INDENT
"root CAs that are installed on the system (optional)."),
.arg_description = _("FILE") },
{ .long_name = "no-verify",
.short_name = 0,
.flags = G_OPTION_FLAG_NONE,
@@ -378,6 +424,9 @@ void pv_args_free(PvArgs *args)
g_free(args->cust_root_key_path);
g_free(args->cust_comm_key_path);
g_free(args->gcm_iv_path);
g_free(args->root_ca_path);
g_strfreev(args->crl_paths);
g_strfreev(args->untrusted_cert_paths);
g_strfreev(args->host_keys);
g_free(args->xts_key_path);
g_slist_free_full(args->comps, (GDestroyNotify)pv_arg_free);

View File

@@ -25,6 +25,7 @@ void pv_arg_free(PvArg *arg);
typedef struct {
gint log_level;
gint no_verify;
gboolean offline;
gchar *pcf;
gchar *scf;
gchar *psw_addr; /* PSW address which will be used for the start of
@@ -34,6 +35,11 @@ typedef struct {
gchar *cust_comm_key_path;
gchar *gcm_iv_path;
gchar **host_keys;
gchar *root_ca_path; /* Trusted root CA used for the verification of the
* chain of trust (if specified).
*/
gchar **untrusted_cert_paths;
gchar **crl_paths;
gchar *xts_key_path;
GSList *comps;
gchar *output_path;

View File

@@ -28,6 +28,8 @@ typedef enum {
PV_ERROR_IPIB_SIZE,
PV_ERROR_PV_HDR_SIZE,
PV_ERROR_INTERNAL,
PV_ERROR_CURL_INIT_FAILED,
PV_ERROR_DOWNLOAD_FAILED,
} PvErrors;
typedef enum {
@@ -57,6 +59,31 @@ typedef enum {
PV_CRYPTO_ERROR_RANDOMIZATION,
PV_CRYPTO_ERROR_INVALID_PARM,
PV_CRYPTO_ERROR_INVALID_KEY_SIZE,
PV_CRYPTO_ERROR_INVALID_VALIDITY_PERIOD,
PV_CRYPTO_ERROR_EXPIRED,
PV_CRYPTO_ERROR_NOT_VALID_YET,
PV_CRYPTO_ERROR_LOAD_CRL,
PV_CRYPTO_ERROR_NO_PUBLIC_KEY,
PV_CRYPTO_ERROR_INVALID_SIGNATURE_ALGORITHM,
PV_CRYPTO_ERROR_SIGNATURE_ALGORITHM_MISMATCH,
PV_CRYPTO_ERROR_INVALID_URI,
PV_CRYPTO_ERROR_CRL_DOWNLOAD_FAILED,
PV_CRYPTO_ERROR_CERT_SIGNATURE_INVALID,
PV_CRYPTO_ERROR_CRL_SIGNATURE_INVALID,
PV_CRYPTO_ERROR_CERT_SUBJECT_ISSUER_MISMATCH,
PV_CRYPTO_ERROR_CRL_SUBJECT_ISSUER_MISMATCH,
PV_CRYPTO_ERROR_NO_IBM_Z_SIGNING_KEY,
PV_CRYPTO_ERROR_MALFORMED_CERTIFICATE,
PV_CRYPTO_ERROR_NO_CRL,
PV_CRYPTO_ERROR_LOAD_ROOT_CA,
PV_CRYPTO_ERROR_LOAD_DEFAULT_CA,
PV_CRYPTO_ERROR_MALFORMED_ROOT_CA,
PV_CRYPTO_ERROR_WRONG_CA_USED,
PV_CRYPTO_ERROR_SKID_AKID_MISMATCH,
PV_CRYPTO_ERROR_NO_ISSUER_IBM_Z_FOUND,
PV_CRYPTO_ERROR_FAILED_DOWNLOAD_CRL,
PV_CRYPTO_ERROR_NO_CRLDP,
PV_CRYPTO_ERROR_CERT_REVOKED,
} PvCryptoErrors;
#endif

View File

@@ -10,6 +10,7 @@
#include <errno.h>
#include <glib.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -138,22 +139,18 @@ static EVP_PKEY *pv_img_get_cust_pub_priv_key(gint nid, GError **err)
return generate_ec_key(nid, err);
}
static HostKeyList *pv_img_get_host_keys(gchar **host_cert_paths,
X509_STORE *store, gint nid,
static HostKeyList *pv_img_get_host_keys(GSList *host_keys_with_path, gint nid,
GError **err)
{
g_autoslist(EVP_PKEY) ret = NULL;
g_assert(host_cert_paths);
for (gchar **iterator = host_cert_paths; iterator != NULL && *iterator != NULL;
iterator++) {
for (GSList *iterator = host_keys_with_path; iterator;
iterator = iterator->next) {
x509_with_path *cert_with_path = iterator->data;
g_autoptr(EVP_PKEY) host_key = NULL;
const gchar *path = *iterator;
X509 *cert = cert_with_path->cert;
g_assert(path);
host_key = read_ec_pubkey_cert(store, nid, path, err);
host_key = read_ec_pubkey_cert(cert, nid, err);
if (!host_key)
return NULL;
@@ -253,10 +250,172 @@ static gint pv_img_set_control_flags(PvImage *img, const gchar *pcf_s,
return 0;
}
static gint pv_img_hostkey_verify(GSList *host_key_certs,
const gchar *root_ca_path,
const gchar *const *crl_paths,
const gchar *const *untrusted_cert_paths,
gboolean offline, GError **err)
{
g_autoslist(x509_with_path) untrusted_certs_with_path = NULL;
g_autoptr(STACK_OF_X509) ibm_signing_certs = NULL;
g_autoptr(STACK_OF_X509) untrusted_certs = NULL;
g_autoslist(x509_pair) ibm_z_pairs = NULL;
g_autoptr(X509_STORE) trusted = NULL;
gint ibm_signing_certs_count;
/* Load trusted root CAs of the system if and only if @root_ca_path is
* NULL, otherwise use the root CA specified by @root_ca_path.
*/
trusted = store_setup(root_ca_path, crl_paths, err);
if (!trusted)
goto error;
if (!offline) {
g_autoptr(STACK_OF_X509_CRL) downloaded_ibm_signing_crls = NULL;
/* Set up the download routine for the lookup of CRLs. */
store_setup_crl_download(trusted);
/* Try to download the CRLs of the IBM Z signing certificates
* specified in the host-key documents. Ignore download errors
* as it's still possible that a CRL is specified via command
* line.
*/
downloaded_ibm_signing_crls = try_load_crls_by_certs(host_key_certs);
/* Add the downloaded CRLs to the store so they can be used for
* the verification later.
*/
for (int i = 0; i < sk_X509_CRL_num(downloaded_ibm_signing_crls); i++) {
X509_CRL *crl = sk_X509_CRL_value(downloaded_ibm_signing_crls, i);
if (X509_STORE_add_crl(trusted, crl) != 1) {
g_set_error(err, PV_CRYPTO_ERROR,
PV_CRYPTO_ERROR_INTERNAL,
_("failed to load CRL"));
goto error;
}
}
}
/* Load all untrusted certificates (e.g. IBM Z signing key and
* DigiCert intermediate CA) that are required to establish a chain of
* trust starting from the host-key document up to the root CA (if not
* otherwise specified that's the DigiCert Assured ID Root CA).
*/
untrusted_certs_with_path = load_certificates(untrusted_cert_paths, err);
if (!untrusted_certs_with_path)
goto error;
/* Convert to STACK_OF(X509) */
untrusted_certs = get_x509_stack(untrusted_certs_with_path);
/* Find all IBM Z signing keys and remove them from the chain as we
* have to verify that they're valid. The last step of the chain of
* trust verification must be done manually, as the IBM Z signing keys
* are not marked as (intermediate) CA and therefore the standard
* `X509_verify_cert` function of OpenSSL cannot be used to verify the
* actual host-key documents.
*/
ibm_signing_certs = delete_ibm_signing_certs(untrusted_certs);
ibm_signing_certs_count = sk_X509_num(ibm_signing_certs);
if (ibm_signing_certs_count < 1) {
g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_NO_IBM_Z_SIGNING_KEY,
_("please specify at least one IBM Z signing key"));
goto error;
} else if (ibm_signing_certs_count > 1) {
g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_NO_IBM_Z_SIGNING_KEY,
_("please specify only one IBM Z signing key"));
goto error;
}
if (store_set_verify_param(trusted, err) < 0)
goto error;
/* Verify that the IBM Z signing keys are trustable.
* For this we must check:
*
* 1. Can a chain of trust be established ending in a root CA
* 2. Is the correct root CA ued? It has either to be the
* 'DigiCert Assured ID Root CA' or the root CA specified via
* command line.
*/
for (gint i = 0; i < sk_X509_num(ibm_signing_certs); ++i) {
X509 *ibm_signing_cert = sk_X509_value(ibm_signing_certs, i);
g_autoptr(STACK_OF_X509_CRL) ibm_signing_crls = NULL;
g_autoptr(X509_STORE_CTX) ctx = NULL;
x509_pair *pair = NULL;
g_assert(ibm_signing_cert);
/* Create the verification context and set the trusted
* and chain parameters.
*/
ctx = create_store_ctx(trusted, untrusted_certs, err);
if (!ctx)
goto error;
/* Verify the IBM Z signing key */
if (verify_cert(ibm_signing_cert, ctx, err) < 0)
goto error;
/* Verify the build chain of trust chain. If the user passes a
* trusted root CA on the command line then the check for the
* Subject Key Identifier (SKID) is skipped, otherwise let's
* check if the SKID meets our expectation.
*/
if (!root_ca_path &&
check_chain_parameters(X509_STORE_CTX_get0_chain(ctx),
get_digicert_assured_id_root_ca_skid(),
err) < 0) {
goto error;
}
ibm_signing_crls = store_ctx_find_valid_crls(ctx, ibm_signing_cert, err);
if (!ibm_signing_crls) {
g_prefix_error(err, _("IBM Z signing key: "));
goto error;
}
/* Increment reference counter of @ibm_signing_cert as the
* certificate will now also be owned by @ibm_z_pairs.
*/
if (X509_up_ref(ibm_signing_cert) != 1)
g_abort();
pair = x509_pair_new(&ibm_signing_cert, &ibm_signing_crls);
ibm_z_pairs = g_slist_append(ibm_z_pairs, pair);
g_assert(!ibm_signing_cert);
g_assert(!ibm_signing_crls);
}
/* Verify host-key documents by using the IBM Z signing
* certificates and the corresponding certificate revocation
* lists.
*/
for (GSList *iterator = host_key_certs; iterator; iterator = iterator->next) {
x509_with_path *host_key_with_path = iterator->data;
const gchar *host_key_path = host_key_with_path->path;
X509 *host_key = host_key_with_path->cert;
gint flags = X509_V_FLAG_CRL_CHECK;
if (verify_host_key(host_key, ibm_z_pairs, flags,
PV_CERTS_SECURITY_LEVEL, err) < 0) {
g_prefix_error(err, "'%s': ", host_key_path);
goto error;
}
}
return 0;
error:
g_prefix_error(err, _("Failed to verify host-key document: "));
return -1;
}
/* read in the keys or auto-generate them */
static gint pv_img_set_keys(PvImage *img, const PvArgs *args, GError **err)
{
g_autoptr(X509_STORE) store = NULL;
g_autoslist(x509_with_path) host_key_certs = NULL;
g_assert(img->xts_cipher);
g_assert(img->cust_comm_cipher);
@@ -285,8 +444,25 @@ static gint pv_img_set_keys(PvImage *img, const PvArgs *args, GError **err)
if (!img->cust_pub_priv_key)
return -1;
/* Load all host-key documents specified on the command line */
host_key_certs = load_certificates((const gchar **)args->host_keys,
err);
if (!host_key_certs)
return -1;
if (!args->no_verify &&
pv_img_hostkey_verify(host_key_certs, args->root_ca_path,
(const gchar * const *)args->crl_paths,
(const gchar * const *)args->untrusted_cert_paths,
args->offline, err) < 0) {
return -1;
}
/* Loads the public keys stored in the host-key documents and verify
* that the correct elliptic curve is used.
*/
img->host_pub_keys =
pv_img_get_host_keys(args->host_keys, store, img->nid, err);
pv_img_get_host_keys(host_key_certs, img->nid, err);
if (!img->host_pub_keys)
return -1;
@@ -406,6 +582,9 @@ PvImage *pv_img_new(PvArgs *args, const gchar *stage3a_path, GError **err)
if (args->no_verify)
g_warning(_("host-key document verification is disabled. Your workload is not secured."));
if (args->root_ca_path)
g_warning(_("A different root CA than the default DigiCert root CA is selected. Ensure that this root CA is trusted."));
ret->comps = pv_img_comps_new(EVP_sha512(), EVP_sha512(), EVP_sha512(), err);
if (!ret->comps)
return NULL;

File diff suppressed because it is too large Load Diff

View File

@@ -11,14 +11,18 @@
#define PV_UTILS_CRYPTO_H
#include <glib.h>
#include <openssl/asn1.h>
#include <openssl/bio.h>
#include <openssl/bn.h>
#include <openssl/ec.h>
#include <openssl/ecdh.h>
#include <openssl/evp.h>
#include <openssl/ossl_typ.h>
#include <openssl/rand.h>
#include <openssl/safestack.h>
#include <openssl/sha.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <stdint.h>
#include "common.h"
@@ -33,6 +37,9 @@
#define AES_256_XTS_TWEAK_SIZE 16
#define AES_256_XTS_KEY_SIZE 64
#define CRL_DOWNLOAD_TIMEOUT_MS 3000
#define CRL_DOWNLOAD_MAX_SIZE (1024 * 1024) /* in bytes */
enum PvCryptoMode {
PV_ENCRYPT,
PV_DECRYPT,
@@ -40,7 +47,34 @@ enum PvCryptoMode {
typedef GSList HostKeyList;
/* play nice with g_autoptr */
typedef STACK_OF(DIST_POINT) STACK_OF_DIST_POINT;
typedef STACK_OF(X509) STACK_OF_X509;
typedef STACK_OF(X509_CRL) STACK_OF_X509_CRL;
void STACK_OF_DIST_POINT_free(STACK_OF_DIST_POINT *stack);
void STACK_OF_X509_free(STACK_OF_X509 *stack);
void STACK_OF_X509_CRL_free(STACK_OF_X509_CRL *stack);
typedef struct {
X509 *cert;
const gchar *path;
} x509_with_path;
x509_with_path *x509_with_path_new(X509 *cert, const gchar *path);
void x509_with_path_free(x509_with_path *cert);
typedef struct {
X509 *cert;
STACK_OF_X509_CRL *crls;
} x509_pair;
x509_pair *x509_pair_new(X509 **cert, STACK_OF_X509_CRL **crls);
void x509_pair_free(x509_pair *pair);
/* Register auto cleanup functions */
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(ASN1_INTEGER, ASN1_INTEGER_free)
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(ASN1_OCTET_STRING, ASN1_OCTET_STRING_free)
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(BIGNUM, BN_free)
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(BIO, BIO_free_all)
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(BN_CTX, BN_CTX_free)
@@ -51,10 +85,18 @@ WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(EVP_CIPHER_CTX, EVP_CIPHER_CTX_free)
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(EVP_MD_CTX, EVP_MD_CTX_free)
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(EVP_PKEY, EVP_PKEY_free)
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(EVP_PKEY_CTX, EVP_PKEY_CTX_free)
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(STACK_OF_DIST_POINT, STACK_OF_DIST_POINT_free);
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(STACK_OF_X509, STACK_OF_X509_free);
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(STACK_OF_X509_CRL, STACK_OF_X509_CRL_free);
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(X509, X509_free)
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(X509_CRL, X509_CRL_free)
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(X509_LOOKUP, X509_LOOKUP_free)
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(X509_NAME, X509_NAME_free)
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(x509_pair, x509_pair_free)
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(X509_STORE, X509_STORE_free)
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(X509_STORE_CTX, X509_STORE_CTX_free)
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(X509_VERIFY_PARAM, X509_VERIFY_PARAM_free)
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(x509_with_path, x509_with_path_free)
union cmp_index {
struct {
@@ -79,8 +121,37 @@ struct cipher_parms {
const Buffer *iv_or_tweak;
};
EVP_PKEY *read_ec_pubkey_cert(X509_STORE *store, gint nid, const gchar *path,
GError **err);
int check_crl_valid_for_cert(X509_CRL *crl, X509 *cert,
gint verify_flags, GError **err);
void pv_crypto_init(void);
void pv_crypto_cleanup(void);
const ASN1_OCTET_STRING *get_digicert_assured_id_root_ca_skid(void);
gint verify_host_key(X509 *host_key, GSList *issuer_pairs,
gint verify_flags, int level, GError **err);
X509 *load_cert_from_file(const char *path, GError **err);
X509_CRL *load_crl_from_file(const gchar *path, GError **err);
GSList *load_certificates(const gchar *const *cert_paths, GError **err);
STACK_OF_X509 *get_x509_stack(const GSList *x509_with_path_list);
X509_STORE *store_setup(const gchar *root_ca_path,
const gchar * const *crl_paths,
GError **err);
int store_set_verify_param(X509_STORE *store, GError **err);
X509_CRL *load_crl_by_cert(X509 *cert, GError **err);
STACK_OF_X509_CRL *try_load_crls_by_certs(GSList *certs_with_path);
gint check_chain_parameters(const STACK_OF_X509 *chain,
const ASN1_OCTET_STRING *skid, GError **err);
X509_NAME *c2b_name(const X509_NAME *name);
STACK_OF_X509 *delete_ibm_signing_certs(STACK_OF_X509 *certs);
STACK_OF_X509_CRL *store_ctx_find_valid_crls(X509_STORE_CTX *ctx, X509 *cert,
GError **err);
X509_STORE_CTX *create_store_ctx(X509_STORE *trusted, STACK_OF_X509 *chain,
GError **err);
gint verify_cert(X509 *cert, X509_STORE_CTX *ctx, GError **err);
X509_CRL *get_first_valid_crl(X509_STORE_CTX *ctx, X509 *cert, GError **err);
void store_setup_crl_download(X509_STORE *st);
EVP_PKEY *read_ec_pubkey_cert(X509 *cert, gint nid, GError **err);
Buffer *compute_exchange_key(EVP_PKEY *cust, EVP_PKEY *host, GError **err);
Buffer *generate_aes_key(guint size, GError **err);
Buffer *generate_aes_iv(guint size, GError **err);

121
genprotimg/src/utils/curl.c Normal file
View File

@@ -0,0 +1,121 @@
/*
* Libcurl utils
*
* Copyright IBM Corp. 2020
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include <stdio.h>
#include <glib.h>
#include <glib/gtypes.h>
#include <curl/curl.h>
#include "lib/zt_common.h"
#include "pv/pv_error.h"
#include "curl.h"
struct UserData {
GByteArray *buffer;
guint max_size;
};
static size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
{
g_assert(userdata);
struct UserData *data = (struct UserData *)userdata;
GByteArray *buffer = data->buffer;
guint64 actual_size;
size_t err;
g_assert(buffer);
if (!g_uint64_checked_mul(&actual_size, size, nmemb))
g_abort();
/* Signal an error condition by returning a amount that differs
* from the amount passed to the callback. This results in a
* CURLE_WRITE_ERROR.
*/
err = actual_size + 1;
if (actual_size > G_MAXUINT)
return err;
data->buffer = g_byte_array_append(buffer, (guchar *)ptr, (guint)actual_size);
if (data->buffer->len > data->max_size)
return err;
return actual_size;
}
gint curl_init(void)
{
if (curl_global_init(CURL_GLOBAL_ALL) != 0)
return -1;
return 0;
}
void curl_cleanup(void)
{
curl_global_cleanup();
}
GByteArray *curl_download(const gchar *url, long timeout_ms, guint max_size,
GError **err)
{
g_autoptr(GByteArray) ret = NULL;
g_autoptr(CURL) handle = NULL;
g_autofree gchar *agent = NULL;
struct UserData userdata;
CURLcode rc;
/* set up curl session */
handle = curl_easy_init();
if (!handle)
g_abort();
/* follow redirection */
rc = curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1l);
if (rc != CURLE_OK)
goto curl_err;
rc = curl_easy_setopt(handle, CURLOPT_TIMEOUT_MS, timeout_ms);
if (rc != CURLE_OK)
goto curl_err;
rc = curl_easy_setopt(handle, CURLOPT_NOSIGNAL, 1l);
if (rc != CURLE_OK)
goto curl_err;
agent = g_strdup_printf("%s/%s", tool_name, RELEASE_STRING);
rc = curl_easy_setopt(handle, CURLOPT_USERAGENT, agent);
if (rc != CURLE_OK)
goto curl_err;
rc = curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_callback);
if (rc != CURLE_OK)
goto curl_err;
ret = g_byte_array_new();
userdata.buffer = ret;
userdata.max_size = max_size;
rc = curl_easy_setopt(handle, CURLOPT_WRITEDATA, (void *)&userdata);
if (rc != CURLE_OK)
goto curl_err;
rc = curl_easy_setopt(handle, CURLOPT_URL, url);
if (rc != CURLE_OK)
goto curl_err;
rc = curl_easy_perform(handle);
if (rc != CURLE_OK) {
g_set_error(err, PV_ERROR, PV_ERROR_DOWNLOAD_FAILED,
_("download failed: %s"), curl_easy_strerror(rc));
return NULL;
}
return g_steal_pointer(&ret);
curl_err:
g_set_error(err, PV_ERROR,
PV_ERROR_CURL_INIT_FAILED,
_("cURL initialization failed: %s"),
curl_easy_strerror(rc));
return NULL;
}

View File

@@ -0,0 +1,25 @@
/*
* Libcurl utils
*
* Copyright IBM Corp. 2020
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef PV_UTILS_LIBCURL_H
#define PV_UTILS_LIBCURL_H
#include <glib.h>
#include <curl/curl.h>
#include "common.h"
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(CURL, curl_easy_cleanup)
GByteArray *curl_download(const gchar *url, long timeout_ms, guint max_size,
GError **err);
gint curl_init(void);
void curl_cleanup(void);
#endif /* PV_UTILS_LIBCURL_H */

16
hsci/Makefile Normal file
View File

@@ -0,0 +1,16 @@
include ../common.mak
all:
install: hsci
$(SED) -e 's/%S390_TOOLS_VERSION%/$(S390_TOOLS_RELEASE)/' \
< hsci >$(DESTDIR)$(BINDIR)/hsci; \
chown $(OWNER).$(GROUP) $(DESTDIR)$(BINDIR)/hsci; \
chmod 755 $(DESTDIR)$(BINDIR)/hsci; \
$(INSTALL) -d -m 755 $(DESTDIR)$(BINDIR) $(DESTDIR)$(MANDIR)/man8
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 hsci.8 \
$(DESTDIR)$(MANDIR)/man8
clean:
.PHONY: all install clean

441
hsci/hsci Executable file
View File

@@ -0,0 +1,441 @@
#!/bin/bash
#
# hsci - Tool to manage HiperSockets Converged Interfaces (HSCI)
#
# Copyright IBM Corp. 2020
#
# s390-tools is free software; you can redistribute it and/or modify
# it under the terms of the MIT license. See LICENSE for details.
#
hsdev=""
ndev=""
hsci=""
hsdev_mac=""
hsif_pnetid=""
netif_pnetid=""
hsci_pnetid=""
function usage {
cat <<-EOD
Usage: hsci COMMAND [OPTION]
This tool is designed to control and show HSCI (HiperSockets Converged
Interfaces) settings. A HiperSockets interface and an external network
COMMANDS
add HIPERSOCKETS_DEV NET_DEV Adds an HSCI interface
del HSCI_NAME Deletes an HSCI interface
show Lists the configured HSCI interfaces
OPTIONS:
-v, --version Prints the version number of the hsci tool and exits
-h, --help Displays the help information for the command
EOD
}
function prereqs_check {
if ! [ -x "$(command -v ip)" ]; then
echo "Error: No iproute2 installed on this system" >&2
return 1
fi
}
function check_pnetids {
# get PNETID of the HS
local hsif_pnetids=""
local netif_pnetids=""
if [ -e /sys/class/net/$hsdev/device/util_string ]; then
hsif_pnetids="$(cat /sys/class/net/$hsdev/device/util_string | tr -d '\000' | iconv -f IBM-1047 -t ASCII)"
else
if [ -e /sys/class/net/$hsdev/device/chpid ]; then
chpid="$(cat /sys/class/net/$hsdev/device/chpid | tr [:upper:] [:lower:])"
hsif_pnetids="$(cat /sys/devices/css0/chp0.$chpid/util_string | tr -d '\000' | iconv -f IBM-1047 -t ASCII)"
fi
fi
if [ "$hsif_pnetids" != "" ]; then
port_hsif="$(cat /sys/class/net/$hsdev/dev_port)"
(( idx=16*$port_hsif+1 ))
(( end=$idx+15 ))
hsif_pnetid="$(echo "$hsif_pnetids" | cut -c $idx-$end | tr -d ' ')"
fi
# get PNETID of the NET_DEV
if [ -e /sys/class/net/$ndev/device/util_string ]; then
netif_pnetids="$(cat /sys/class/net/$ndev/device/util_string | tr -d '\000' | iconv -f IBM-1047 -t ASCII)"
else
if [ -e /sys/class/net/$ndev/device/chpid ]; then
chpid="$(cat /sys/class/net/$ndev/device/chpid | tr [:upper:] [:lower:])"
netif_pnetids="$(cat /sys/devices/css0/chp0.$chpid/util_string | tr -d '\000' | iconv -f IBM-1047 -t ASCII)"
fi
fi
if [ "$netif_pnetids" != "" ]; then
port_netif="$(cat /sys/class/net/$ndev/dev_port)"
(( idx=16*$port_netif+1 ))
(( end=$idx+15 ))
netif_pnetid="$(echo "$netif_pnetids" | cut -c $idx-$end | tr -d ' ')"
fi
#Check PNETIDs
if [ "$hsif_pnetid" != "" ] && [ "$netif_pnetid" != "" ] && [ "$netif_pnetid" != "$hsif_pnetid" ]; then
echo "Error: $hsdev and $ndev have different PNETIDs! They are $hsif_pnetid and $netif_pnetid respectively" >&2
return 1
fi
if [ "$hsif_pnetid" != "" ] && [ "$netif_pnetid" != "" ] && [ "$netif_pnetid" == "$hsif_pnetid" ]; then
hsci_pnetid=$hsif_pnetid
fi
}
function verify_precon {
echo "Verifying net dev $ndev and HiperSockets dev $hsdev"
if [ ! -e /sys/class/net/$hsdev ]; then
echo "Error: $hsdev does not exist" >&2
return 1
fi
if [ "$(cat /sys/class/net/$hsdev/device/card_type)" != "HiperSockets" ]; then
echo "Error: $hsdev is not a HiperSockets device" >&2
return 1
fi
if [ "$(cat /sys/class/net/$hsdev/device/layer2)" != "1" ]; then
echo "Error: $hsdev is not in layer 2 mode" >&2
return 1
fi
if [ ! -e /sys/class/net/$hsdev/device/vnicc/bridge_invisible ]; then
echo "Error: Missing vnic-characteristics support" >&2
return 1
fi
if [ "$(cat /sys/class/net/$hsdev/device/vnicc/bridge_invisible)" == "n/a" ]; then
echo "Error: $hsdev does not support vnicc" >&2
return 1
fi
if [ $(ip link show $hsdev | grep UP | wc -l) -eq 0 ]; then
echo "Error: $hsdev is not in state UP" >&2
return 1
fi
if [ $(bridge -d link show dev $hsdev self | grep learning_sync | wc -l) -eq 0 ]; then
echo "Error: $hsdev does not support attribute learning_sync" >&2
return 1
fi
if [ $(ip link show $hsdev | grep master | wc -l) -ne 0 ]; then
echo "Error: $hsdev is already a bridge port" >&2
return 1
fi
#Pre-verify net_dev
if [ ! -e /sys/class/net/$ndev ]; then
echo "Error: $ndev does not exist" >&2
return 1
fi
if [ "$(cat /sys/class/net/$ndev/device/card_type)" == "HiperSockets" ]; then
echo "Error: $ndev is also a HiperSockets device" >&2
return 1
fi
if [ $(ip link show $ndev | grep UP | wc -l) -eq 0 ]; then
echo "Error: $ndev is not in state UP" >&2
return 1
fi
if [ $(ip link show $ndev | grep master | wc -l) -ne 0 ]; then
echo "Error: $ndev is already a bridge port" >&2
return 1
fi
#Check PNETIDs
check_pnetids
if [ $? -ne 0 ]; then
return $?
fi
return 0
}
function clean_up {
bridge link set dev $hsdev learning_sync off self >/dev/null 2>&1
echo 0 > /sys/class/net/$hsdev/device/vnicc/bridge_invisible >/dev/null 2>&1
bridge fdb del $hsdev_mac dev $ndev >/dev/null 2>&1
ip link del $hsci >/dev/null 2>&1
}
##############################################################################
## add a new HSCI interface
##############################################################################
function add_hsci {
if [ $# != 2 ]; then
echo "hsci: Invalid parameters" >&2
echo "Use 'hsci --help' for more information" >&2
return 1
fi
hsdev=$1
ndev=$2
#### Verify preconditions
verify_precon
if [ $? -ne 0 ]; then
return $?
fi
hsci_postfix="$(readlink /sys/class/net/$hsdev/device/cdev0 | tail -c5)"
hsci=hsci$hsci_postfix
echo "Adding $hsci with a HiperSockets dev $hsdev and an external dev $ndev"
#### Create bridge
ip link add name $hsci type bridge stp_state 0 >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "Error: Could not create a bridge" >&2
return 1
fi
#### Prepare hsdev
# Set VNICC of hsdev to invisible
#(mandatory for co-existence with HS-OSA bridges!)
echo 1 > /sys/class/net/$hsdev/device/vnicc/bridge_invisible
#### Create bridge ports
ip link set dev $ndev master $hsci >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "Error: Could not set master for $ndev" >&2
clean_up
return 1
fi
ip link set dev $hsdev master $hsci >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "Error: Could not set master for $hsdev" >&2
clean_up
return 1
fi
# no forwarding between ndev and hsdev -> isolated on
# ndev is default for outgoing unknown targets -> flood on
# no need to learn external LAN targets into fdb -> learning off
bridge link set dev $ndev isolated on learning off flood on mcast_flood on >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "Error: Failed to set bridge attributes on $ndev" >&2
clean_up
return 1
fi
# no forwarding between ndev and hsdev -> isolated on
# fdb will be populated by dev-to-bridge-notification, no need to learn
# -> learning off
# only send to hsdev, if listed in fdb -> flood off
# don't send MC/BC on hsdev -> mcast_flood off
bridge link set dev $hsdev isolated on learning off flood off mcast_flood off >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "Error: Failed to set bridge attributes on $hsdev" >&2
clean_up
return 1
fi
# NOTE: Although not required, BCs will be sent out on hsdev.
# NOTE: We need to receive BCs on hsdev, as z/OS HSCI does ARP requests on HS.
hsdev_mac="$(cat /sys/class/net/$hsdev/address)"
echo "Set $hsdev MAC $hsdev_mac on $ndev and $hsci"
# set HS MAC on OSA as secondary MAC
bridge fdb add $hsdev_mac dev $ndev >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "Error: Failed to set HS MAC on OSA as secondary MAC" >&2
clean_up
return 1
fi
# set HS MAC (common MAC) on HSCI as primary MAC
ip link set address $hsdev_mac dev $hsci >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "Error: Failed to set HiperSockets MAC (common MAC) on HSCI as primary MAC" >&2
clean_up
return 1
fi
# use hsdev MTU
if [ -e /sys/class/net/$hsdev/mtu ]; then
hs_mtu="$(cat /sys/class/net/$hsdev/mtu)"
ip link set dev $hsci mtu $hs_mtu >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "Error: Failed to set MTU for $hsci " >&2
clean_up
return 1
fi
fi
ip link set dev $hsci up >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "Error: Failed to set $hsci up" >&2
clean_up
return 1
fi
# Turn on device for bridge notification
bridge link set dev $hsdev learning_sync on self >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "Error: Failed to turn on device for bridge notification" >&2
clean_up
return 1
fi
echo "Successfully added HSCI interface $hsci"
return 0
}
##############################################################################
## Delete HSCI
##############################################################################
function del_hsci {
if [ $# != 1 ]; then
echo "hsci: invalid parameters" >&2
echo "Use 'hsci --help' for more information" >&2
return 1
fi
hsci=$1
if [ $(ip link show dev $hsci | wc -l) -eq 0 ]; then
echo "Error: $hsci does not exit" >&2
return 1
fi
if [ $(ip link show | grep "master $hsci" | wc -l) -eq 0 ]; then
echo "Error: $hsci is not an active HSCI interface" >&2
return 1
fi
bports="$(ip link show | grep "master $hsci" | awk '{print $2}')"
for bport in $bports; do
if [ $(bridge -d link show dev $bport | grep "learning_sync on" | wc -l) -ne 0 ]; then
hsdev=${bport%:}
else
ndev=${bport%:}
fi
done
if [ "$hsdev" == "" ]; then
echo "Error: $hsci has no active HiperSockets port" >&2
return 1
fi
echo "Deleting HSCI interface $hsci with the HiperSockets $hsdev and the external $ndev"
bridge link set dev $hsdev learning_sync off self >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "Error: Failed to turn off learning_sync on $hsdev" >&2
return 1
fi
echo 0 > /sys/class/net/$hsdev/device/vnicc/bridge_invisible
hsdev_mac="$(cat /sys/class/net/$hsdev/address)"
echo "Deleting $hsev MAC $hsdev_mac on $ndev"
bridge fdb del $hsdev_mac dev $ndev >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "Error: Failed to delete $hsev MAC $hsdev_mac on $ndev" >&2
return 1
fi
ip link del $hsci >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "Error: Failed to delete $hsci" >&2
return 1
fi
echo "Successfully deleted device $hsci"
return 0
}
##############################################################################
## Show HSCI
##############################################################################
function list_active {
hsdev=$1
local ext=""
hsci="$(ip link show dev $hsdev | awk '{for(x=1;x<NF;x++) if($x~/master/) print $(x+1)}')"
ext="$(ip link show | grep "master $hsci" | grep --invert-match $hsdev | awk '{print $2}')"
# remove trailing ':'
ndev="${ext%:}"
check_pnetids
printf '%-8s %-16s %-15s %-15s\n' "$hsci" "$hsci_pnetid" "$hsdev" "$ndev"
return 0
}
function print_header {
if [ $header -eq 0 ]; then
echo "HSCI PNET_ID HiperSockets External "
echo "------------------------------------------------------------"
fi
}
function list_one {
local hsnetdev=$1
if [ $(bridge -d link show dev $hsnetdev | grep "learning_sync on" | wc -l) -ne 0 ]; then
print_header
list_active $hsnetdev
fi
return 0
}
function show_hsci {
if [ $# != 0 ]; then
echo "hsci: invalid parameters" >&2
echo "Use 'hsci --help' for more information" >&2
return 1
fi
header=0
for hs_net_dev in $(ls -1 /sys/class/net/); do
list_one $hs_net_dev
done
return 0
}
#==============================================================================
function print_version()
{
echo "hsci utility: version %S390_TOOLS_VERSION%"
echo "Copyright IBM Corp. 2020"
}
##############################################################################
##### Main
##############################################################################
prereqs_check
args="$(getopt -u -o hv -l help,version -- $*)"
[ $? -ne 0 ] && exit 2
set -- $args
while true; do
case $1 in
-v | --version)
print_version
exit 0
;;
-h | --help)
usage
exit 0
;;
--)
;;
add) shift
add_hsci "$@"
exit $?
;;
del) shift
del_hsci "$@"
exit $?
;;
show) shift
show_hsci "$@"
exit $?
;;
*) echo "hsci: Please specify a valid command or option" >&2
echo "Use 'hsci --help' for more information" >&2
exit 1
esac
shift
done

100
hsci/hsci.8 Normal file
View File

@@ -0,0 +1,100 @@
.\" Copyright IBM Corp. 2020
.TH HSCI 8 "November 2020" "s390-tools" "Linux Programmer's Manual"
.SH NAME
.B hsci
\- control and show HSCI settings.
.SH SYNOPSIS
.B hsci add
.I HSDEV
.I NETDEV
.br
.B hsci del
.I HSCINAME
.br
.B hsci show
.br
.B hsci [\-hv]
.SH DESCRIPTION
.BI hsci
is used to control and show HSCI (HiperSockets Converged Interfaces) settings. A HiperSockets interface and an external network interface are converged into an HSCI interface.
.SH COMMANDS
.TP
.B add \fIHSDEV\fR \fINETDEV\fR
.RS .4i
.PP
Adds an HSCI interface
.PP
.I HSDEV
is the interface name of the HiperSockets device to be converged into the HSCI interface.
.PP
.I NETDEV
is the interface name of the external network device to be converged into the HSCI interface.
.RE
.TP
.B del \fIHSCINAME\fR
.RS .4i
.PP
Deletes an HSCI interface
.PP
.I HSCINAME
is the name of the HSCI interface for the HiperSockets device and the external network device.
.RE
.TP
.B show
.RS .4i
.PP
Lists the configured HSCI interfaces.
.RE
.SH OPTIONS
.TP
.BR \-v ", " \-\-version
Prints the version number of hsci and exits.
.TP
.BR \-h ", " \-\-help
Displays the help information for the command.
.SH EXIT CODES
.TP
.BR "0"
The hsci command ran successfully.
.TP
.BR "1"
An error occurred.
.SH EXAMPLE
.BR "hsci show"
.TP
.RB
Lists the configured HSCI interfaces:
.RS 1.2i
HSCI PNET_ID HiperSockets External
.br
-----------------------------------------
.br
hsci8410 NET1 enc8410 encb040
.RE
.SH SEE ALSO
.nf
ip(8), bridge(8)
.fi
.SH AUTHOR
.nf
Written by Alexandra Winter <wintera@linux.ibm.com>
Wenjia Zhang <wenjia@linux.ibm.com>
.fi

View File

@@ -12,6 +12,11 @@
#ifndef LIB_UTIL_SYS_H
#define LIB_UTIL_SYS_H
#include <stdbool.h>
int util_sys_get_dev_addr(const char *dev, char *addr);
bool util_sys_dev_is_partition(dev_t dev);
int util_sys_get_partnum(dev_t dev);
int util_sys_get_base_dev(dev_t dev, dev_t *base_dev);
#endif /** LIB_UTIL_SYS_H @} */

View File

@@ -21,7 +21,7 @@ clean: clean-recursive
$(RECURSIVE_TARGETS):
@target=`echo $@ |sed s/-recursive//`; \
for d in $(SUBDIRS); do \
(cd $$d && $(MAKE) $$target) \
(cd $$d && $(MAKE) $$target) || exit 1; \
done

View File

@@ -214,7 +214,7 @@ int dasd_get_host_access_count(char *device)
char *path;
long value;
if (!util_sys_get_dev_addr(device, busid))
if (util_sys_get_dev_addr(device, busid) != 0)
return 0;
path = util_path_sysfs("bus/ccw/devices/%s/host_access_count", busid);

View File

@@ -1,10 +1,13 @@
include ../common.mak
VERSION = 1.0
VERM = $(shell echo $(VERSION) | cut -d '.' -f 1)
ifneq (${HAVE_OPENSSL},0)
ifneq (${HAVE_JSONC},0)
ifneq (${HAVE_LIBCURL},0)
BUILD_TARGETS += libekmfweb.so
INSTALL_TARGETS += install-libekmfweb.so
BUILD_TARGETS += libekmfweb.so.$(VERSION)
INSTALL_TARGETS += install-libekmfweb.so.$(VERSION)
else
BUILD_TARGETS += skip-libekmfweb-curl
INSTALL_TARGETS += skip-libekmfweb-curl
@@ -64,22 +67,26 @@ ekmfweb.o: check-dep-libekmfweb ekmfweb.c utilities.h cca.h $(rootdir)include/ek
utilities.o: check-dep-libekmfweb utilities.c utilities.h $(rootdir)include/ekmfweb/ekmfweb.h
cca.o: check-dep-libekmfweb cca.c cca.h utilities.h $(rootdir)include/ekmfweb/ekmfweb.h
libekmfweb.so: ALL_CFLAGS += -fPIC
libekmfweb.so: LDLIBS = -ljson-c -lcrypto -lssl -lcurl -ldl -shared
libekmfweb.so: LDFLAGS = -shared -Wl,--version-script=libekmfweb.map \
-Wl,-z,defs,-Bsymbolic
libekmfweb.so: ekmfweb.o utilities.o cca.o
libekmfweb.so.$(VERSION): ALL_CFLAGS += -fPIC
libekmfweb.so.$(VERSION): LDLIBS = -ljson-c -lcrypto -lssl -lcurl -ldl
libekmfweb.so.$(VERSION): ALL_LDFLAGS += -shared -Wl,--version-script=libekmfweb.map \
-Wl,-z,defs,-Bsymbolic -Wl,-soname,libekmfweb.so.$(VERM)
libekmfweb.so.$(VERSION): ekmfweb.o utilities.o cca.o
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
ln -srf libekmfweb.so.$(VERSION) libekmfweb.so.$(VERM)
ln -srf libekmfweb.so.$(VERSION) libekmfweb.so
install-libekmfweb.so: libekmfweb.so
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 -T libekmfweb.so $(DESTDIR)$(LIB64DIR)/libekmfweb.so
install-libekmfweb.so.$(VERSION): libekmfweb.so.$(VERSION)
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 -T libekmfweb.so.$(VERSION) $(DESTDIR)$(USRLIB64DIR)/libekmfweb.so.$(VERSION)
ln -srf $(DESTDIR)$(USRLIB64DIR)/libekmfweb.so.$(VERSION) $(DESTDIR)$(USRLIB64DIR)/libekmfweb.so.$(VERM)
ln -srf $(DESTDIR)$(USRLIB64DIR)/libekmfweb.so.$(VERSION) $(DESTDIR)$(USRLIB64DIR)/libekmfweb.so
$(INSTALL) -d -m 770 $(DESTDIR)$(USRINCLUDEDIR)/ekmfweb
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 $(rootdir)include/ekmfweb/ekmfweb.h $(DESTDIR)$(USRINCLUDEDIR)/ekmfweb
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 $(rootdir)include/ekmfweb/ekmfweb.h $(DESTDIR)$(USRINCLUDEDIR)/ekmfweb
install: all $(INSTALL_TARGETS)
clean:
rm -f *.o libekmfweb.so check-dep-libekmfweb detect-openssl-version.dep
rm -f *.o libekmfweb.so* check-dep-libekmfweb detect-openssl-version.dep
.PHONY: all install clean skip-libekmfweb-openssl skip-libekmfweb-jsonc \
skip-libekmfweb-curl install-libekmfweb.so
skip-libekmfweb-curl install-libekmfweb.so.$(VERSION)

View File

@@ -460,7 +460,7 @@ int util_proc_mnt_get_entry(const char *file_name, const char *spec,
rc = scan_mnt_entry(&file, entry);
if (rc)
goto out_free;
if (!strcmp(entry->spec, spec)) {
if (!strcmp(entry->vfstype, spec)) {
rc = 0;
goto out_free;
}

View File

@@ -11,17 +11,114 @@
#include <err.h>
#include <errno.h>
#include <linux/fs.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <unistd.h>
#include "lib/util_file.h"
#include "lib/util_libc.h"
#include "lib/util_path.h"
#include "lib/util_sys.h"
/* lstat() doesn't work for sysfs files, a fixed size is therefore inevitable */
#define READLINK_SIZE 256
#define PAGE_SIZE 4096
/**
* Return the partition number of a given partition.
*
* @param[in] dev Device node of interest
*
* @retval int Partition number of the device
* @retval -1 Error when trying to read the partition number.
*/
int util_sys_get_partnum(dev_t dev)
{
int partnum = -1;
char *path;
path = util_path_sysfs("dev/block/%u:%u/partition",
major(dev), minor(dev));
if (util_file_read_i(&partnum, 10, path)) {
warnx("Could not read from path '%s'", path);
goto out;
}
if (partnum <= 0) {
warnx("Bad partition number in '%s'", path);
partnum = -1;
goto out;
}
out:
free(path);
return partnum;
}
/**
* Determine if the given device is a partition.
*
* @param[in] dev Device node of interest
*
* @retval true Device is partition
* @retval false Device is not a partition
*/
bool util_sys_dev_is_partition(dev_t dev)
{
bool is_part;
char *path;
path = util_path_sysfs("dev/block/%u:%u/partition",
major(dev), minor(dev));
is_part = util_path_exists(path);
free(path);
return is_part;
}
/**
* Determine base device
*
* This function determines the base device \p base_dev of a given
* device \p dev. If \p dev is a base device, \p base_dev becomes \p dev.
*
* @param[in] dev Device node of interest
* @param[out] base_dev Identified base device
*
* @retval 0 Success
* @retval -1 Error while reading device information or
* constructed path
*/
int util_sys_get_base_dev(dev_t dev, dev_t *base_dev)
{
int base_major, base_minor;
char buf[PAGE_SIZE];
char *path;
/* check if the device already is a base device */
if (!util_sys_dev_is_partition(dev)) {
*base_dev = makedev(major(dev), minor(dev));
return 0;
}
path = util_path_sysfs("dev/block/%d:%d/../dev",
major(dev), minor(dev));
if (util_file_read_line(buf, sizeof(buf), path)) {
warnx("Could not read from path '%s'", path);
free(path);
return -1;
}
free(path);
if (sscanf(buf, "%i:%i", &base_major, &base_minor) != 2) {
warn("Could not parse major:minor from string '%s'", buf);
return -1;
}
*base_dev = makedev(base_major, base_minor);
return 0;
}
/**
* Identify device address
@@ -44,13 +141,17 @@ int util_sys_get_dev_addr(const char *dev, char *addr)
unsigned int maj, min;
struct stat s;
ssize_t len;
dev_t base;
char *path;
if (stat(dev, &s) != 0)
return -1;
maj = major(s.st_rdev);
min = minor(s.st_rdev);
if (util_sys_get_base_dev(s.st_rdev, &base))
return -1;
maj = major(base);
min = minor(base);
if (S_ISBLK(s.st_mode))
path = util_path_sysfs("dev/block/%u:%u/device", maj, min);

View File

@@ -5,21 +5,21 @@
.TH LSSTP 8 "Jul 2020" "s390-tools" "Linux Administrator's Manual"
.SH NAME
.B "lsstp "
\- tool to show STP system information
\- Show STP configuration information
.SH SYNOPSIS
.BI "lsstp "
.SH DESCRIPTION
.B lsstp
displays information about the currenta Server Time Protocol (STP) configuration
like Coordianted Timing Network (CTN) ID, Timing state and Leap seconds.
displays information about the current Server Time Protocol (STP) configuration
like coordinated time network (CTN) ID, timing state and leap seconds.
.SH OUTPUT
.TP
.B STP online
Whether the STP subsystem is online
Indication of the online state
.TP
.B CTN ID
The ID of the Coordinated Time Network. If it can be decoded as EBCDIC it will be shown as EBCDIC String, otherwise a hexadecimal representation is shown.
The ID of the coordinated time network. If it can be decoded as EBCDIC it is shown as an EBCDIC string, otherwise a hexadecimal representation is shown.
.TP
.B CTN Type
The type of timing network.
@@ -31,15 +31,15 @@ STP is not configured for attachment to a CTN.
STP is configured and attached to a CTN with only STP nodes.
.IP
.B Mixed
STP is configured and attached to a CTN which contains both STP and External Time Reference (ETR) nodes.
STP is configured and attached to a CTN with both STP and external time reference (ETR) nodes.
.TP
.B Stratum
The Stratum level of the STP clock. This indicates the number of servers in the timing path between the local STP clock and the selected primary time server.
The number of servers in the timing path between the local STP clock and the selected primary time server.
.TP
.B Timing mode
.IP
.B Local
The Time-of-day (TOD) clock is stepped to the local hardware oscillator and is not steered by the STP facility.
The Time-of-day (TOD) clock is stepped by the local hardware oscillator and is not steered by the STP facility.
.IP
.B ETR
The TOD clock is synchronized with an attached 9037 Sysplex Timer.
@@ -51,10 +51,10 @@ The TOD clock is steered by the STP facility to maintain synchronization with a
The TOD clock is not initialized. The STP facility is allowed to perform a step adjustment to the TOD clock for synchronization.
.TP
.B Timing state
The synchronization state of the STP facilty. Can be unsynchronzied, synchronized and stopped.
The synchronization state of the STP facility. Can be unsynchronized, synchronized or stopped.
.TP
.B DST offset
The Daylight savings time offset relative to UTC in minutes.
The daylight savings time offset relative to UTC in minutes.
.TP
.B Timezone offset
The offset of the local time relative to UTC in minutes.
@@ -62,11 +62,11 @@ The offset of the local time relative to UTC in minutes.
.B Time offset
The total time offset at the server. This field is only valid in mixed CTN configurations.
.TP
.B Active Leap seconds
The number of Leap seconds that are currently in effect at the STP facility.
.B Active leap seconds
The number of leap seconds that are currently in effect at the STP facility.
.TP
.B Leap second <insertion|delation> at
If a Leap second insertion or deletetion is scheduled in the STP facility, this field will show the Day and Time of the scheduled change.
.B Leap second <insertion|deletion> at
If a leap second insertion or deletion is scheduled in the STP facility, this field shows the day and time of the scheduled change.
.SH OPTIONS
.TP
.BI "-v|--version"

View File

@@ -2,15 +2,27 @@
include ../common.mak
SCRIPTS = mk-s390image mk-pxelinux-ramfs
NETBOOT_SAMPLEDIR=$(TOOLS_DATADIR)/netboot
all:
install: all
$(INSTALL) -d -m 755 $(DESTDIR)$(NETBOOT_SAMPLEDIR)
$(INSTALL) -m 755 mk-s390image mk-pxelinux-ramfs \
$(DESTDIR)$(NETBOOT_SAMPLEDIR)
$(INSTALL) -m 644 Dockerfile Makefile.pxelinux.0 README.md \
install: install-scripts
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 \
Dockerfile Makefile.pxelinux.0 README.md mk-s390image.1 \
$(DESTDIR)$(NETBOOT_SAMPLEDIR)
.PHONY: all install clean
install-scripts: $(SCRIPTS)
@if [ ! -d $(DESTDIR)$(NETBOOT_SAMPLEDIR) ]; then \
mkdir -p $(DESTDIR)$(NETBOOT_SAMPLEDIR); \
chown $(OWNER).$(GROUP) $(DESTDIR)$(NETBOOT_SAMPLEDIR); \
chmod 755 $(DESTDIR)$(NETBOOT_SAMPLEDIR); \
fi; \
for i in $^; do \
$(SED) -e 's/%S390_TOOLS_VERSION%/$(S390_TOOLS_RELEASE)/' \
< $$i >$(DESTDIR)$(NETBOOT_SAMPLEDIR)/$$i; \
chown $(OWNER).$(GROUP) $(DESTDIR)$(NETBOOT_SAMPLEDIR)/$$i; \
chmod 755 $(DESTDIR)$(NETBOOT_SAMPLEDIR)/$$i; \
done
.PHONY: all install clean install-scripts

View File

@@ -54,9 +54,18 @@ OPTIONS
-b Search installed busybox in directory BUSYBOX_DIR
-k Use KERNEL_VERSION instead of currently running kernel
-h Print this help, then exit
-v Print version information, then exit
EOF
}
printversion()
{
cat <<-EOD
$cmd: version %S390_TOOLS_VERSION%
Copyright IBM Corp. 2017
EOD
}
# Get shared objects for binary
sharedobjs()
{
@@ -64,7 +73,7 @@ sharedobjs()
}
# Check args
args=$(getopt b:k:h $*)
args=$(getopt b:k:hv $*)
if [ $? = 0 ]
then
set -- $args
@@ -74,6 +83,7 @@ then
-b) busyboxdir=$2; shift 2;;
-k) kernelversion=$2; shift 2;;
-h) usage; exit 0;;
-v) printversion; exit 0;;
--) shift; break;;
*) echo "$cmd: Unexpected argument $1, exiting..." >&2; exit 1;;
esac

View File

@@ -60,9 +60,18 @@ OPTIONS
-p Use PARMFILE with kernel parameters in the image
-r Include RAMDISK in the image
-h Print this help, then exit
-v Print version information, then exit
EOF
}
printversion()
{
cat <<-EOD
$cmd: version %S390_TOOLS_VERSION%
Copyright IBM Corp. 2017
EOD
}
# Convert decimal number to big endian doubleword
dec2be64()
{
@@ -129,6 +138,9 @@ dobuild()
parmfile_size=$(du -b $parmfile | cut -f1)
if [ $parmfile_size -le $MAX_PARMFILE_SIZE ]
then
# Clear any previous parameters
dd seek=$OFFS_COMMANDLINE_BYTES bs=1 count=$MAX_PARMFILE_SIZE \
if=/dev/zero of=$image conv=notrunc status=none
dd seek=$OFFS_COMMANDLINE_BYTES bs=1 if=$parmfile \
of=$image conv=notrunc status=none
else
@@ -142,7 +154,7 @@ dobuild()
}
# check args and build
args=$(getopt "r:p:h" $*)
args=$(getopt "r:p:hv" $*)
if [ $? = 0 ]
then
set -- $args
@@ -152,6 +164,7 @@ then
-r) ramdisk=$2; shift 2;;
-p) parmfile=$2; shift 2;;
-h) usage; exit 0;;
-v) printversion; exit 0;;
--) shift; break;;
*) echo "$cmd: Unexpected argument $1, exiting..." >&2; exit 1;;
esac

17
netboot/mk-s390image.1 Normal file
View File

@@ -0,0 +1,17 @@
.TH MK-S390IMAGE "1" "November 2020" "s390-tools" "User Commands"
.SH NAME
mk-s390image \- tool for creating bootable image
.SH SYNOPSIS
.B mk-s390image
\fI\,KERNEL BOOT_IMAGE \/\fR[\fI\,-r RAMDISK\/\fR] [\fI\,-p PARMFILE\/\fR]
.SH DESCRIPTION
Build an s390 image BOOT_IMAGE suitable for CD/tape/network boot or as a
KVM firmware image using a stripped Linux kernel file KERNEL.
.PP
.SH OPTIONS
.TP
\fB\-p\fR Use PARMFILE with kernel parameters in the image
.TP
\fB\-r\fR Include RAMDISK in the image
.TP
\fB\-h\fR Print usage message, then exit

View File

@@ -10,10 +10,11 @@ zipl-switch-to-blscfg \- Switch zipl to use BootLoaderSpec configuration
\fBzipl-switch-to-blscfg\fP {\-h|\-v}
.SH DESCRIPTION
This script switches the zipl boot-loader configuration to use BootLoaderSpec files
to define IPL sections. For each Linux kernel defined in the zipl.conf config file,
a BLS fragment is generated in the BLS directory specified. Also, the zipl.conf is
modified it only contains global configurations, all IPL sections comes from BLS.
This script switches the zipl boot-loader configuration to use BootLoaderSpec
files to define IPL sections. For each Linux kernel defined in the zipl.conf
config file, a BLS fragment is generated in the BLS directory specified. Also,
zipl.conf is modified to only contain global configuration. All IPL sections
come from BLS files.
.SH OPTIONS
.TP
@@ -30,7 +31,8 @@ The suffix used for backup files, defaults to .bak.
.TP
\fB\-\-bls-directory <DIRECTORY>\fP
The DIRECTORY where the BLS fragments will be generated. The directory is created if it doesn't exists, by default /boot/loader/entries is used.
The DIRECTORY where the BLS fragments will be stored. The directory is
created if it does not exist. By default /boot/loader/entries is used.
.TP
\fB\-\-config-file <FILE>\fP

View File

@@ -10,11 +10,12 @@
Description=Apply Control Program Identification (CPI)
DefaultDependencies=no
Conflicts=shutdown.target
After=local-fs.target
After=sysinit.target
ConditionPathIsReadWrite=/sys/firmware/cpi
[Service]
Type=oneshot
RemainAfterExit=yes
#
# Specify a file with the environment variables using the EnvironmentFile=
# service property.

View File

@@ -387,6 +387,7 @@ function extended()
read EXTSZ 2> /dev/null < $DEVPATH/extent_pool/extent_size
read CAPACITY 2> /dev/null < $DEVPATH/capacity/logical_capacity
read ALLOCATED 2> /dev/null < $DEVPATH/capacity/space_allocated
read FC_SEC 2> /dev/null < $DEVPATH/fc_security
# convert to hexadecimal values
PIM=0x$PIM
@@ -521,7 +522,7 @@ function extended()
elif [[ "$ALIAS" == 1 ]]; then
if [[ "$BASEONLY" == "false" ]]; then
ACTIVE="alias"
printf "%s:%s:%s# status:\t\t\t\t%s# type: \t\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s# hpf:\t\t\t\t\t%s # uid: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s# paths_error_threshold_exceeded: \t%s %s %s %s %s %s %s %s#\n" \
printf "%s:%s:%s# status:\t\t\t\t%s# type: \t\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s# hpf:\t\t\t\t\t%s # uid: \t\t\t\t%s# fc_security: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s# paths_error_threshold_exceeded: \t%s %s %s %s %s %s %s %s#\n" \
"$SORTKEYLEN" "$SORTKEY" \
"$BUSID" \
"$ACTIVE" \
@@ -532,6 +533,7 @@ function extended()
"$ERP" \
"$HPF" \
"$DEV_UID" \
"$FC_SEC" \
"${INSTALLED_PATHS[@]}" \
"${USED_PATHS[@]}" \
"${NP_PATHS[@]}" \
@@ -563,7 +565,7 @@ function extended()
DISCIPLINE="${DISCIPLINE} (ESE)"
fi
printf "%s:%s:%s/%s/%s%s%s# status:\t\t\t\t%s# type: \t\t\t\t%s# blksz:\t\t\t\t%s# size: \t\t\t\t%s# blocks:\t\t\t\t%s# extent_size:\t\t\t\t%s# logical_capacity:\t\t\t%s# space_allocated:\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s# hpf:\t\t\t\t\t%s# uid: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s# paths_error_threshold_exceeded: \t%s %s %s %s %s %s %s %s#\n" \
printf "%s:%s:%s/%s/%s%s%s# status:\t\t\t\t%s# type: \t\t\t\t%s# blksz:\t\t\t\t%s# size: \t\t\t\t%s# blocks:\t\t\t\t%s# extent_size:\t\t\t\t%s# logical_capacity:\t\t\t%s# space_allocated:\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s# hpf:\t\t\t\t\t%s# uid: \t\t\t\t%s# fc_security: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s# paths_error_threshold_exceeded: \t%s %s %s %s %s %s %s %s#\n" \
"$SORTKEYLEN" "$SORTKEY" \
"$BUSID" \
"$BLOCKNAME" \
@@ -584,6 +586,7 @@ function extended()
"$ERP" \
"$HPF" \
"$DEV_UID" \
"$FC_SEC" \
"${INSTALLED_PATHS[@]}" \
"${USED_PATHS[@]}" \
"${NP_PATHS[@]}" \

View File

@@ -1178,8 +1178,14 @@ static int get_apqn_measurement_data(uint8_t card)
scdmd_area.request.header.code = 0x102d;
scdmd_area.request.header.length =
sizeof(struct chsc_scdmd_request);
scdmd_area.request.first_drid.ap_index = card;
scdmd_area.request.first_drid.domain_index = g.min_domain;
if (scdmd_area.response.p) {
scdmd_area.request.first_drid =
scdmd_area.response.crid;
} else {
scdmd_area.request.first_drid.ap_index = card;
scdmd_area.request.first_drid.domain_index =
g.min_domain;
}
scdmd_area.request.last_drid.ap_index = card;
scdmd_area.request.last_drid.domain_index = g.max_domain;
scdmd_area.request.s = 1;
@@ -1217,10 +1223,6 @@ static int get_apqn_measurement_data(uint8_t card)
rc = process_apqn_measurement_data(&scdmd_area);
if (rc != 0)
break;
if (scdmd_area.response.p)
scdmd_area.request.first_drid =
scdmd_area.response.crid;
} while (scdmd_area.response.p);
return rc;

View File

@@ -313,6 +313,22 @@ static struct attrib dasd_attr_safe_offline = {
.writeonly = 1,
};
static struct attrib dasd_attr_fc_security = {
.name = "fc_security",
.title = "Show FC Endpoint Security state of DASD device",
.desc =
"This read-only attribute shows the Fibre Channel Endpoint Security\n"
"status of the connection to the DASD device:\n"
" Unsupported : The DASD device does not support Fibre Channel\n"
" Endpoint Security\n"
" Inconsistent : The operational channel paths of the DASD device\n"
" report inconsistent Fibre Channel Endpoint\n"
" Security status\n"
" Authentication: The connection has been authenticated\n"
" Encryption : The connection is encrypted\n",
.readonly = 1,
};
/*
* DASD subtype methods.
*/
@@ -617,6 +633,7 @@ struct subtype dasd_subtype_eckd = {
&dasd_attr_reservation_policy,
&dasd_attr_last_known_reservation_state,
&dasd_attr_safe_offline,
&dasd_attr_fc_security,
&internal_attr_early,
),
.unknown_dev_attribs = 1,

View File

@@ -21,6 +21,7 @@
#include <time.h>
#include <unistd.h>
#include "lib/util_file.h"
#include "lib/util_path.h"
#include "zgetdump.h"
@@ -98,6 +99,24 @@ static void em_init(struct vol *vol)
l.dump_incomplete = 1;
}
/*
* Check whether a device with a given busid is online
*/
static unsigned int dev_is_online(const char *busid)
{
unsigned int online;
char *path;
path = util_path_sysfs("%s/%s/online", SYSFS_BUSDIR, busid);
if (util_file_read_ui(&online, 10, path) != 0) {
warnx("Could not open \"%s\" (%s)", path, strerror(errno));
free(path);
exit(EXIT_FAILURE);
}
free(path);
return online;
}
/*
* Check sysfs, whether a device specified by its bus ID is defined and online.
@@ -106,67 +125,40 @@ static void em_init(struct vol *vol)
static enum dev_status dev_from_busid(char *bus_id, dev_t *dev)
{
struct dirent *direntp;
int fh, minor, major;
int minor, major;
char buf[10];
DIR *fh_dir;
char *sysfs;
sysfs = util_path_sysfs("%s/%s", SYSFS_BUSDIR, bus_id);
fh_dir = opendir(sysfs);
free(sysfs);
if (!fh_dir)
if (!util_path_is_dir(sysfs)) {
free(sysfs);
return DEV_UNDEFINED;
sysfs = util_path_sysfs("%s/%s/online", SYSFS_BUSDIR, bus_id);
fh = open(sysfs, O_RDONLY);
if (fh == -1) {
warnx("Could not open \"%s\" (%s)", sysfs, strerror(errno));
goto err;
}
free(sysfs);
if (read(fh, buf, 1) == -1)
ERR_EXIT_ERRNO("Could not read online attribute");
close(fh);
if (buf[0] != '1')
if (!dev_is_online(bus_id))
return DEV_OFFLINE;
while ((direntp = readdir(fh_dir)))
if (strncmp(direntp->d_name, "block:", 6) == 0)
break;
closedir(fh_dir);
if (direntp == NULL) {
sysfs = util_path_sysfs("%s/%s/block", SYSFS_BUSDIR, bus_id);
fh_dir = opendir(sysfs);
if (!fh_dir) {
warnx("Could not open \"%s\" (%s) ",
sysfs, strerror(errno));
goto err;
}
while ((direntp = readdir(fh_dir)))
if (strncmp(direntp->d_name, "dasd", 4) == 0)
break;
closedir(fh_dir);
if (direntp == NULL) {
warnx("Problem with contents of \"%s\"", sysfs);
goto err;
}
free(sysfs);
}
sysfs = util_path_sysfs("%s/%s/%s/dev",
SYSFS_BUSDIR, bus_id, direntp->d_name);
fh = open(sysfs, O_RDONLY);
if (fh == -1) {
warnx("Could not open \"%s\" (%s)", sysfs, strerror(errno));
sysfs = util_path_sysfs("%s/%s/block", SYSFS_BUSDIR, bus_id);
fh_dir = opendir(sysfs);
if (!fh_dir) {
warnx("Could not open \"%s\" (%s) ", sysfs, strerror(errno));
goto err;
}
if (read(fh, buf, sizeof(buf)) == -1) {
while ((direntp = readdir(fh_dir)))
if (strncmp(direntp->d_name, "dasd", 4) == 0)
break;
if (direntp == NULL) {
warnx("Problem with contents of \"%s\"", sysfs);
goto err;
}
if (util_file_read_line(buf, sizeof(buf), "%s/%s/dev", sysfs, direntp->d_name)) {
warnx("Could not read dev file (%s)", strerror(errno));
goto err;
}
close(fh);
closedir(fh_dir);
if (sscanf(buf, "%i:%i", &major, &minor) != 2) {
warnx("Malformed content of \"%s\": %s", sysfs, buf);
goto err;
@@ -178,6 +170,8 @@ static enum dev_status dev_from_busid(char *bus_id, dev_t *dev)
return DEV_ONLINE;
err:
if (fh_dir)
closedir(fh_dir);
free(sysfs);
exit(EXIT_FAILURE);
}

View File

@@ -31,7 +31,7 @@ configuration.
* Issue "make bzImage" to build the zfcpdump kernel image.
In a Linux distribution the zfcpdump enabled kernel image must be copied to
/lib/s390-tools/zfcpdump/zfcpdump_part.image, where the s390 zipl tool is
/lib/s390-tools/zfcpdump/zfcpdump-image, where the s390 zipl tool is
looking for the dump kernel when preparing a SCSI dump disk.
Create and install initrd

View File

@@ -7,7 +7,7 @@ INCLUDE_PARMS := $(addprefix -I,$(INCLUDE_PATHS))
ALL_CFLAGS = $(NO_PIE_CFLAGS) -Os -g $(INCLUDE_PARMS) \
-DS390_TOOLS_RELEASE=$(S390_TOOLS_RELEASE) \
-fno-builtin -ffreestanding -fno-asynchronous-unwind-tables \
-fno-delete-null-pointer-checks \
-fno-delete-null-pointer-checks -fno-stack-protector \
-fexec-charset=IBM1047 -m64 -mpacked-stack \
-mstack-size=4096 -mstack-guard=128 -msoft-float \
-W -Wall -Wformat-security

View File

@@ -25,6 +25,7 @@
#include <linux/fiemap.h>
#include "lib/util_proc.h"
#include "lib/util_sys.h"
#include "disk.h"
#include "error.h"
@@ -89,88 +90,6 @@ disk_determine_dasd_type(struct disk_info *data,
return 0;
}
static int blkext_get_partnum(dev_t dev)
{
char path[PATH_MAX], *buf;
int dev_major, dev_minor, partnum = -1;
dev_major = major(dev);
dev_minor = minor(dev);
snprintf(path, PATH_MAX, "/sys/dev/block/%d:%d/partition",
dev_major, dev_minor);
if (misc_read_special_file(path, &buf, NULL, 1)) {
error_text("Could not read from path '%s'", path);
return -1;
}
partnum = atoi(buf);
free(buf);
if (partnum < 0) {
error_text("Bad partition number in '%s'", path);
return -1;
}
return partnum;
}
static int blkext_is_base_device(dev_t dev)
{
int dev_major, dev_minor;
char path[PATH_MAX];
struct stat stats;
dev_major = major(dev);
dev_minor = minor(dev);
snprintf(path, PATH_MAX, "/sys/dev/block/%d:%d/partition",
dev_major, dev_minor);
return (stat(path, &stats));
}
static int blkext_get_base_dev(dev_t dev, dev_t *base_dev)
{
int base_major, base_minor;
char dev_path[PATH_MAX], base_path[PATH_MAX];
char *temp_path, *buf;
misc_asprintf(&temp_path, "/sys/dev/block/%d:%d", major(dev), minor(dev));
if (!realpath(temp_path, dev_path)) {
error_reason(strerror(errno));
error_text("Could not resolve link %s", temp_path);
free(temp_path);
return -1;
}
free(temp_path);
misc_asprintf(&temp_path, "%s/..", dev_path);
if (!realpath(temp_path, base_path)) {
error_reason(strerror(errno));
error_text("Could not resolve path %s", temp_path);
free(temp_path);
return -1;
}
free(temp_path);
misc_asprintf(&temp_path, "%s/dev", base_path);
if (misc_read_special_file(temp_path, &buf, NULL, 1)) {
error_text("Could not read from path '%s'", temp_path);
free(temp_path);
return -1;
}
free(temp_path);
if (sscanf(buf, "%i:%i", &base_major, &base_minor) != 2) {
error_text("Could not parse major:minor from string '%s'", buf);
free(buf);
return -1;
}
free(buf);
*base_dev = makedev(base_major, base_minor);
return 0;
}
/* Return non-zero for ECKD type. */
int
disk_is_eckd(disk_type_t type)
@@ -492,15 +411,15 @@ disk_get_info(const char* device, struct job_target_data* target,
data->devno = -1;
data->type = disk_type_scsi;
if (blkext_is_base_device(stats.st_rdev)) {
data->device = stats.st_rdev;
data->partnum = 0;
} else {
if (blkext_get_base_dev(stats.st_rdev, &data->device))
if (util_sys_dev_is_partition(stats.st_rdev)) {
if (util_sys_get_base_dev(stats.st_rdev, &data->device))
goto out_close;
data->partnum = blkext_get_partnum(stats.st_rdev);
data->partnum = util_sys_get_partnum(stats.st_rdev);
if (data->partnum == -1)
goto out_close;
} else {
data->device = stats.st_rdev;
data->partnum = 0;
}
} else {
/* Driver name is unknown */

View File

@@ -1,10 +1,13 @@
include ../common.mak
SUB_DIRS = ekmfweb
ifneq (${HAVE_OPENSSL},0)
BUILD_TARGETS += zkey
INSTALL_TARGETS += install-zkey
ifneq (${HAVE_JSONC},0)
ifneq (${HAVE_LIBCURL},0)
SUB_DIRS += ekmfweb
endif
endif
else
BUILD_TARGETS += zkey-skip
INSTALL_TARGETS += zkey-skip
@@ -12,9 +15,14 @@ endif
ifneq (${HAVE_CRYPTSETUP2},0)
ifneq (${HAVE_JSONC},0)
BUILD_TARGETS += zkey-cryptsetup
INSTALL_TARGETS += install-zkey-cryptsetup
CPPFLAGS += -DHAVE_LUKS2_SUPPORT
ifneq (${HAVE_OPENSSL},0)
BUILD_TARGETS += zkey-cryptsetup
INSTALL_TARGETS += install-zkey-cryptsetup
CPPFLAGS += -DHAVE_LUKS2_SUPPORT
else
BUILD_TARGETS += zkey-cryptsetup-skip-openssl
INSTALL_TARGETS += zkey-cryptsetup-skip-openssl
endif
else
BUILD_TARGETS += zkey-cryptsetup-skip-jsonc
INSTALL_TARGETS += zkey-cryptsetup-skip-jsonc
@@ -64,6 +72,9 @@ zkey-cryptsetup-skip-cryptsetup2:
zkey-cryptsetup-skip-jsonc:
echo " SKIP zkey-cryptsetup due to HAVE_JSONC=0"
zkey-cryptsetup-skip-openssl:
echo " SKIP zkey-cryptsetup due to HAVE_OPENSSL=0"
all: $(BUILD_TARGETS) $(SUB_DIRS)
zkey.o: zkey.c pkey.h cca.h ep11.h misc.h

View File

@@ -1,14 +1,15 @@
include ../../common.mak
VERSION = 1.0
VERM = $(shell echo $(VERSION) | cut -d '.' -f 1)
all: zkey-ekmfweb.so
libs = $(rootdir)/libutil/libutil.a
export LIBRARY_PATH = $(rootdir)/libekmfweb:$LIBRARY_PATH
zkey-ekmfweb.o: zkey-ekmfweb.c zkey-ekmfweb.h ../kms-plugin.h \
../cca.h ../utils.h ../pkey.h ../properties.h \
$(rootdir)include/ekmfweb/ekmfweb.h $(rootdir)/libekmfweb/libekmfweb.so
$(rootdir)include/ekmfweb/ekmfweb.h libekmfweb.dep
properties.o: ../properties.c ../properties.h
$(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) -fPIC -c $< -o $@
@@ -26,9 +27,9 @@ utils.o: ../utils.c ../utils.h ../pkey.h ../cca.h ../ep11.h
$(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) -fPIC -c $< -o $@
zkey-ekmfweb.so: ALL_CFLAGS += -fPIC
zkey-ekmfweb.so: LDLIBS = -lekmfweb -ldl -lcrypto -shared
zkey-ekmfweb.so: LDFLAGS = -shared -Wl,--version-script=zkey-ekmfweb.map \
-Wl,-z,defs,-Bsymbolic
zkey-ekmfweb.so: LDLIBS = -L$(rootdir)/libekmfweb -lekmfweb -ldl -lcrypto
zkey-ekmfweb.so: ALL_LDFLAGS += -shared -Wl,--version-script=zkey-ekmfweb.map \
-Wl,-z,defs,-Bsymbolic -Wl,-soname,zkey-ekmfweb.so.$(VERM)
zkey-ekmfweb.so: zkey-ekmfweb.o properties.o pkey.o cca.o ep11.o utils.o $(libs)
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
@@ -36,13 +37,18 @@ install-libekmfweb.dep:
$(MAKE) -C $(rootdir)/libekmfweb/ TOPDIR=$(TOPDIR) ARCH=$(ARCH) install
touch install-libekmfweb.dep
libekmfweb.dep:
$(MAKE) -C $(rootdir)/libekmfweb/ TOPDIR=$(TOPDIR) ARCH=$(ARCH) all
touch libekmfweb.dep
install: all install-libekmfweb.dep zkey-ekmfweb.so
$(INSTALL) -d -m 755 $(DESTDIR)$(MANDIR)/man1
$(INSTALL) -m 644 -c zkey-ekmfweb.1 $(DESTDIR)$(MANDIR)/man1
$(INSTALL) -d -m 755 $(DESTDIR)$(LIB64DIR)
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 -T zkey-ekmfweb.so $(DESTDIR)$(LIB64DIR)/zkey-ekmfweb.so
$(INSTALL) -d -m 755 $(DESTDIR)$(USRLIB64DIR)
$(INSTALL) -d -m 755 $(DESTDIR)$(USRLIB64DIR)/zkey
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 -T zkey-ekmfweb.so $(DESTDIR)$(USRLIB64DIR)/zkey/zkey-ekmfweb.so
clean:
rm -f *.o zkey-ekmfweb.so install-libekmfweb.dep
rm -f *.o zkey-ekmfweb.so install-libekmfweb.dep libekmfweb.dep
.PHONY: all install clean

View File

@@ -899,24 +899,24 @@ int kms_display_info(const kms_handle_t handle)
if (rc == 0) {
switch (type) {
case EVP_PKEY_EC:
printf(" EBMF Web public key: ECC (%s)\n",
printf(" EKMF Web public key: ECC (%s)\n",
OBJ_nid2sn(curve));
break;
case EVP_PKEY_RSA:
printf(" EBMF Web public key: RSA "
printf(" EKMF Web public key: RSA "
"(%d bits)\n", mod_bits);
break;
default:
printf(" EBMF Web public key: "
printf(" EKMF Web public key: "
"(unknown key type)\n");
break;
}
} else {
printf(" EBMF Web public key: (not available)\n");
printf(" EKMF Web public key: (not available)\n");
}
free(tmp);
} else {
printf(" EBMF Web public key: (configuration required)\n");
printf(" EKMF Web public key: (configuration required)\n");
}
printf(" Key templates:\n");

View File

@@ -40,13 +40,14 @@
#define ENVVAR_ZKEY_KMS_PLUGINS "ZKEY_KMS_PLUGINS"
#define DEFAULT_KMS_PLUGINS "/etc/zkey/kms-plugins.conf"
#define KMS_PLUGIN_LOCATION "/usr/lib64/zkey"
#define KMS_CONFIG_FILE "kms.conf"
#define KMS_CONFIG_PROP_KMS "kms"
#define KMS_CONFIG_PROP_KMS_CONFIG "config"
#define KMS_CONFIG_PROP_APQNS "apqns"
#define KMS_CONFIG_PROP_CCA_APQNS "ep11_apqns"
#define KMS_CONFIG_PROP_EP11_APQNS "cca_apqns"
#define KMS_CONFIG_PROP_CCA_APQNS "cca_apqns"
#define KMS_CONFIG_PROP_EP11_APQNS "ep11_apqns"
#define KMS_CONFIG_LOCAL "local"
#define KMS_KEY_PROP_NAME "zkey-name"
@@ -209,6 +210,7 @@ static int load_kms_plugin(const char *plugin,
void **plugin_lib, char **plugin_name, bool verbose)
{
kms_get_functions_t _kms_get_functions;
char load_so_name[PATH_MAX];
char *so_name = NULL;
FILE *fp = NULL;
char line[4096];
@@ -258,15 +260,26 @@ static int load_kms_plugin(const char *plugin,
goto out;
}
/* Try to load via LD_LIBRARY_PATH first */
snprintf(load_so_name, sizeof(load_so_name), "%s", so_name);
pr_verbose(verbose, "Loading KMS plugin '%s': '%s'", *plugin_name,
so_name);
*plugin_lib = dlopen(so_name, RTLD_GLOBAL | RTLD_NOW);
load_so_name);
*plugin_lib = dlopen(load_so_name, RTLD_GLOBAL | RTLD_NOW);
if (*plugin_lib == NULL) {
pr_verbose(verbose, "%s", dlerror());
warnx("Failed to load KMS plugin '%s': '%s'", *plugin_name,
so_name);
rc = -ELIBACC;
goto out;
/* Try to load from default plugin location */
snprintf(load_so_name, sizeof(load_so_name), "%s/%s",
KMS_PLUGIN_LOCATION, so_name);
pr_verbose(verbose, "Loading KMS plugin '%s': '%s'",
*plugin_name, load_so_name);
*plugin_lib = dlopen(load_so_name, RTLD_GLOBAL | RTLD_NOW);
if (*plugin_lib == NULL) {
pr_verbose(verbose, "%s", dlerror());
warnx("Failed to load KMS plugin '%s': '%s'",
*plugin_name, load_so_name);
rc = -ELIBACC;
goto out;
}
}
_kms_get_functions = (kms_get_functions_t)dlsym(*plugin_lib,
@@ -274,7 +287,7 @@ static int load_kms_plugin(const char *plugin,
if (_kms_get_functions == NULL) {
pr_verbose(verbose, "%s", dlerror());
warnx("Failed to load KMS plugin '%s': '%s'", *plugin_name,
so_name);
load_so_name);
rc = -ELIBACC;
goto out;
}
@@ -283,13 +296,13 @@ static int load_kms_plugin(const char *plugin,
if (*kms_functions == NULL) {
pr_verbose(verbose, "kms_get_functions() reutned NULL");
warnx("Failed to load KMS plugin '%s': '%s'", *plugin_name,
so_name);
load_so_name);
rc = -ELIBACC;
goto out;
}
pr_verbose(verbose, "Successfully loaded KMS plugin '%s': '%s' (API "
"version: %u)", *plugin_name, so_name,
"version: %u)", *plugin_name, load_so_name,
(*kms_functions)->api_version);
out: