From c22d282e67c5c8e88a86a148c5c21c3f435b4312 Mon Sep 17 00:00:00 2001 From: Juergen Christ Date: Fri, 11 Mar 2022 14:19:50 +0100 Subject: [PATCH] zcryptctl: Add control domain handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support control domain handling for custom zcrypt device nodes. Signed-off-by: Juergen Christ Reviewed-by: Harald Freudenberger Signed-off-by: Jan Höppner --- zconf/zcrypt/zcryptctl.8 | 40 ++++++++++--- zconf/zcrypt/zcryptctl.c | 121 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 152 insertions(+), 9 deletions(-) diff --git a/zconf/zcrypt/zcryptctl.8 b/zconf/zcrypt/zcryptctl.8 index 5d098da3..e46bb734 100644 --- a/zconf/zcrypt/zcryptctl.8 +++ b/zconf/zcrypt/zcryptctl.8 @@ -1,6 +1,6 @@ .\" zcryptctl.8 .\" -.\" Copyright 2018 IBM Corp. +.\" Copyright 2018, 2022 IBM Corp. .\" s390-tools is free software; you can redistribute it and/or modify .\" it under the terms of the MIT license. See LICENSE for details. .\" @@ -10,7 +10,7 @@ .\" nroff -man zcryptctl.8 .\" to process this source .\" -.TH ZCRYPTCTL 8 "AUG 2018" "s390-tools" +.TH ZCRYPTCTL 8 "JAN 2022" "s390-tools" .SH NAME zcryptctl \- display information and administrate zcrypt multiple device nodes .SH SYNOPSIS @@ -35,6 +35,11 @@ zcryptctl \- display information and administrate zcrypt multiple device nodes .B deldom .I node-name domain-nr .TP +.B zcryptctl addctrl +.R | +.B delctrl +.I node-name domain-nr +.TP .B zcryptctl addioctl .R | .B delioctl @@ -57,6 +62,7 @@ driver. Each zcrypt device node can be restricted in terms of crypto cards, domains, and available ioctls. Such a device node can be used as a base for container solutions like Docker to control and restrict the access to crypto resources. +See the NOTES section below for information on control domains. .SH COMMANDS .TP 8 .B zcryptctl list @@ -96,6 +102,14 @@ Update the filter for the specified zcrypt device node and add or delete a domain to be accessible through this node. The symbol \fBALL\fP can be used to enable or disable all domains. .TP +.B zcryptctl addctrl +.R | +.B delctrl +.I node-name domain-nr +Update the filter for the specified zcrypt device node and add or +delete a control domain to be accessible through this node. The symbol +\fBALL\fP can be used to enable or disable all domains. +.TP .B zcryptctl addioctl .R | .B delioctl @@ -116,19 +130,20 @@ line and the settings are applied. Syntax is simple: .IP "node=" .IP "aps=" .IP "doms=" +.IP "ctrls=" .IP "ioctls=" .LP Empty lines are ignored and the '#' marks the rest of the line as comment. .LP The \fBnode=\fP line creates a new zcrypt device node, the \fBaps=\fP, -\fBdoms=\fP and \fBioctls=\fP lines customize the previously created -node. The symbol \fBALL\fP is also recognized for aps, doms, and -ioctls. +\fBdoms=\fP, \fBctrls=\fP and \fBioctls=\fP lines customize the +previously created node. The symbol \fBALL\fP is also recognized for +aps, doms, and ioctls. .LP Each action must fit into one line, spreading over multiple lines is -not supported. But you can use more than one \fBaps=\fP, \fBdoms=\fP -and \fBioctls=\fP lines to customize the very same node. +not supported. But you can use more than one \fBaps=\fP, \fBdoms=\fP, +\fBctrls=\fP and \fBioctls=\fP lines to customize the very same node. .LP Processing stops when a line cannot be parsed or the current action fails. In this case the exit status is non zero but the successful @@ -139,6 +154,17 @@ actions until the failure occurs are not rolled back. List the current configuration in a form suitable for input to the \fBzcryptctl config\fP command. .LP +.SH NOTES + +Control domain filtering is only supported for custom device + if the \fBadmask\fP file in sysfs under +/sys/class/zcrypt//admask exists. If this file does not +exist, the kernel is too old and does not support control command +filtering. This is the same effect as setting the control domain mask +to ALL. Note that, even though you can allow more than available to +the system, you can only send control commands to control domains +available to the system. + .SH EXIT STATUS On successful completion of the command the exit status is 0. A non zero return code (and some kind of failure message) is emitted if the diff --git a/zconf/zcrypt/zcryptctl.c b/zconf/zcrypt/zcryptctl.c index 8326a087..a6189f50 100644 --- a/zconf/zcrypt/zcryptctl.c +++ b/zconf/zcrypt/zcryptctl.c @@ -2,7 +2,7 @@ * zcryptctl - Maintain zcrypt multi device nodes. * * by Harald Freudenberger - * Copyright IBM Corp. 2018 + * Copyright IBM Corp. 2018, 2022 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -58,6 +58,8 @@ #define CMD_DEL_IOCTL 0x0009 #define CMD_CONFIG 0x000A #define CMD_LISTCONFIG 0x000B +#define CMD_ADD_CTRL 0x000C +#define CMD_DEL_CTRL 0x000D /* * Program configuration @@ -70,7 +72,7 @@ static const struct util_prg prg = { { .owner = "IBM Corp.", .pub_first = 2018, - .pub_last = 2018, + .pub_last = 2022, }, UTIL_PRG_COPYRIGHT_END } @@ -345,6 +347,18 @@ static int cmd_list(int cmd, if (test_bit(i, buf)) printf("%c%d", n++ == 0 ? tab : ',', i); putchar('\n'); + if (cmd == CMD_LISTCONFIG) + printf(" ctrls ="); + else + printf(" control domains:"); + if (read_dn_attr(de->d_name, "admask", buf, sizeof(buf)) != 0) + errx(EXIT_FAILURE, + "Could not fetch admask attribute from sysfs for zcrypt node '%s'", + de->d_name); + for (i = n = 0; i < MAX_ZDEV_DOMAINS_EXT; i++) + if (test_bit(i, buf)) + printf("%c%d", n++ == 0 ? tab : ',', i); + putchar('\n'); if (cmd == CMD_LISTCONFIG) printf(" ioctls ="); else @@ -526,6 +540,52 @@ static int cmd_add_del_dom(int cmd, const char *node, const char *arg) return 0; } +static void add_del_ctrl(int cmd, const char *node, int dom) +{ + int rc; + char buf[PATH_MAX]; + + if (cmd == CMD_ADD_CTRL) + sprintf(buf, "+%d", dom); + else + sprintf(buf, "-%d", dom); + rc = write_dn_attr(node, "admask", buf); + if (rc != 0) + errx(EXIT_FAILURE, + "Could not write into sysfs entry to %s domain %d for zdev node '%s'", + cmd == CMD_ADD_CTRL ? "add" : "remove", dom, node); +} + +static int cmd_add_del_ctrl(int cmd, const char *node, const char *arg) +{ + int dom, all = 0; + + if (strcasecmp(arg, "ALL") == 0) { + all = 1; + } else { + if (sscanf(arg, "%i", &dom) != 1) + errx(EXIT_FAILURE, + "Invalid domain argument '%s'", arg); + if (dom < 0 || dom >= MAX_ZDEV_DOMAINS_EXT) + errx(EXIT_FAILURE, + "Domain argument '%s' out of range [0..%d]", + arg, MAX_ZDEV_DOMAINS_EXT - 1); + } + + if (!all) { + add_del_ctrl(cmd, node, dom); + printf("Control domain %d %s\n", dom, + (cmd == CMD_ADD_CTRL ? "added" : "removed")); + } else { + for (dom = 0; dom < MAX_ZDEV_DOMAINS_EXT; dom++) + add_del_ctrl(cmd, node, dom); + printf("All control domains %s\n", + (cmd == CMD_ADD_CTRL ? "added" : "removed")); + } + + return 0; +} + static void add_del_ioctl(int cmd, const char *node, int ioctlnr) { int rc; @@ -700,6 +760,28 @@ static int cmd_config(int cmd _UNUSED_, while (isblank(*p) || *p == ',') p++; } + } else if (_match_keyword(&p, "ctrls")) { + if (!havenode) + errx(EXIT_FAILURE, + "Missing node=... before processing any ctrls=... statements in line %d '%s'", + nr, line); + if (!_match_character(&p, '=')) + errx(EXIT_FAILURE, + "Missing '=' at '%-8.8s...' in line %d '%s'", + p, nr, line); + while (1) { + while (isspace(*p)) + p++; + if (*p == '\0' || *p == '#') + break; + if (!_match_string(&p, buf)) + errx(EXIT_FAILURE, + "Missing argument(s) for ctrls=... at '%-8.8s...' in line %d '%s'", + p, nr, line); + cmd_add_del_ctrl(CMD_ADD_CTRL, node, buf); + while (isblank(*p) || *p == ',') + p++; + } } else if (_match_keyword(&p, "ioctls")) { if (!havenode) errx(EXIT_FAILURE, @@ -817,6 +899,28 @@ static struct zcryptctl_cmds_s { "domain argument may be a number in the range 0-255 or the\n" "symbol ALL.", }, + { + .cmd = CMD_ADD_CTRL, + .command = "addctrl", + .function = cmd_add_del_ctrl, + .usage = "zcryptctl addctrl ", + .description = + "Update the filter for the specified zcrypt device node and\n" + "add a crypto control domain to be accessible via this node.\n" + "The domain argument may be a number in the range 0-255 or\n" + "the symbol ALL.", + }, + { + .cmd = CMD_DEL_CTRL, + .command = "delctrl", + .function = cmd_add_del_ctrl, + .usage = "zcryptctl delctrl ", + .description = + "Update the filter for the specified zcrypt device node and\n" + "remove a crypto control domain from the allowed domains list.\n" + "The domain argument may be a number in the range 0-255 or\n" + "the symbol ALL.", + }, { .cmd = CMD_ADD_IOCTL, .command = "addioctl", @@ -1003,6 +1107,19 @@ int main(int argc, char *argv[]) argv[optind + 1], argv[optind + 2]); break; + case CMD_ADD_CTRL: + case CMD_DEL_CTRL: + if (optind + 1 >= argc) + errx(EXIT_FAILURE, "Missing node name argument"); + if (optind + 2 >= argc) + errx(EXIT_FAILURE, "Missing domain argument"); + if (check_nodename(argv[optind + 1]) != 0) + errx(EXIT_FAILURE, "Invalid or unknown nodename '%s'", + argv[optind + 1]); + rc = zcryptctl_cmds[cmdindex].function(c, + argv[optind + 1], + argv[optind + 2]); + break; case CMD_ADD_IOCTL: case CMD_DEL_IOCTL: if (optind + 1 >= argc)