[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20250822142215.2475014-7-dhowells@redhat.com>
Date: Fri, 22 Aug 2025 15:22:13 +0100
From: David Howells <dhowells@...hat.com>
To: Jarkko Sakkinen <jarkko@...nel.org>
Cc: David Howells <dhowells@...hat.com>,
keyrings@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: [PATCH 6/7] request-key: Add a simpler debug test
Add a simpler debug test to avoid the need to supply all the parameters
that don't take part in the matching. This looks like:
request-key --check <type> <desc> [<callout>] [<op>]
request-key --check user debug:bar
The unspecified parameters are just defaulted.
Signed-off-by: David Howells <dhowells@...hat.com>
---
man/request-key.8 | 38 ++++++---
request-key.c | 203 ++++++++++++++++++++++++++++++----------------
2 files changed, 161 insertions(+), 80 deletions(-)
diff --git a/man/request-key.8 b/man/request-key.8
index 15b6bb8..90121d9 100644
--- a/man/request-key.8
+++ b/man/request-key.8
@@ -14,14 +14,18 @@ request\-key \- handle key instantiation callback requests from the kernel
.nf
\fB/sbin/request\-key\fP [\fB--help\fP|\fB--version\fP]
\fB/sbin/request\-key\fP \fIop key uid gid t-ring p-ring s-ring\fP [\fIinfo\fP]
-\fB/sbin/request\-key -d [-lnv] -D\fP \fIdesc\fP \fIop key\fP...
+\fB/sbin/request\-key -d\fP [\fB-lnv\fP] [\fB-D\fP \fIdesc\fP] \fIop key\fP...
+\fB/sbin/request\-key --check\fP [\fB-lnv\fP] \fItype desc\fP [\fIinfo\fP] [\fIop\fP]
.fi
.SH DESCRIPTION
This program is invoked by the kernel when the kernel is asked for a key that
it doesn't have immediately available. The kernel creates a partially set up
-key and then calls out to this program to instantiate it. It is not intended to
-be called directly. A debugging capability is available through command line
-options, however, to aid in testing and in debugging configuration.
+key and then calls out to this program to instantiate it. It is not generally
+intended to be called directly.
+.PP
+Debugging capabilities are also available through command line options to aid
+in testing and in configuration debugging.
+.SH COMMAND-LINE OPTIONS
.PP
The normally required parameters are:
.IP \fBop\fP
@@ -39,12 +43,12 @@ The optional callout info that can be passed by \fIrequest_key(2)\fP.
.PP
The options that may also be supplied are:
.IP \fB-d\fP
-Turn on debugging mode. In this mode, no attempts are made to access any keys
+Debug the lookup. If this is supplied, no attempts are made to access any keys
and, if a handler program is selected, it won't be executed; instead, this
-program will print a message and exit 0.
-.IP \fB-D <description>\fP
-In debugging mode, use the proposed key description specified with this rather
-than the sample ("user;0;0;1f0000;debug:1234") built into the program.
+program will print a message and exit.
+.IP "\fB-D\fP \fIdescription\fP"
+Use with \fB-d\fP to provide a specific key description rather than using the
+sample ("user;0;0;1f0000;debug:1234") built into the program.
.IP \fB-l\fP
Use configuration from the current directory. The program will use
.IR request-key.d/* " and " request-key.conf
@@ -56,6 +60,9 @@ will be copied to the system log - this will prevent that.
.IP \fB-v\fP
Turn on debugging output. This may be specified multiple times to produce
increasing levels of verbosity.
+.IP \fB--check\fP
+If this is provide, then a simpler debugging mode is engaged that defaults most
+of the arguments, but otherwise operates much the same as '-d'.
.IP \fB--help\fP
Print help text and exit.
.IP \fB--version\fP
@@ -67,8 +74,19 @@ of them don't matter and can be just set to 0, e.g.:
.nf
request-key -d -D "user;0;0;0;debug:bar" create 0 0 0 0 0 0 foo
.fi
+.PP
+With the simple check mode, the parameters that aren't involved in matching
+are just defaulted and only those that are necessary are given; further, only
+the basic key description needs be supplied, e.g.:
+.PP
+.nf
+request-key --check user debug:bar
+request-key --check user debug:bar foo
+request-key --check user debug:bar foo create
+.fi
.SH ERRORS
-All errors will be logged to the syslog unless the \fB-n\fP option is given.
+All errors will be logged to the syslog unless \fB-n\fP or \fB--check\fP are
+given. Errors will also be logged to stderr if \fB-v\fP is given.
.SH FILES
.ul
/etc/request\-key.d/*.conf
diff --git a/request-key.c b/request-key.c
index 9a7d741..302d083 100644
--- a/request-key.c
+++ b/request-key.c
@@ -133,6 +133,17 @@ static void error(const char *fmt, ...)
#define file_error(FMT, ...) error("%s: "FMT, conffile, ## __VA_ARGS__)
#define line_error(FMT, ...) error("%s:%d: "FMT, conffile, confline, ## __VA_ARGS__)
+static __attribute__((noreturn, format(printf, 1, 2)))
+void cmderror(const char *fmt, ...)
+{
+ va_list va;
+
+ va_start(va, fmt);
+ vfprintf(stderr, fmt, va);
+ va_end(va);
+ exit(2);
+}
+
static void oops(int x)
{
error("Died on signal %d", x);
@@ -141,6 +152,7 @@ static void oops(int x)
static const char help_text[] =
"Usage: request-key [OPTIONS] [PARAMS]\n"
" request-key [OPTIONS] -d -D <desc> [PARAMS]\n"
+ " request-key [OPTIONS] --check <type> <desc> [<callout>] [<op>]\n"
"\n"
"Where the required parameters, [PARAMS], are, in order:\n"
" <op> : The operation type (e.g. 'create')\n"
@@ -158,22 +170,33 @@ static const char help_text[] =
" -l : Use config from local dir, not /etc\n"
" -n : Don't log to syslog\n"
" -v : Turn up verbosity (can use multiple times)\n"
- " --version: Print version and exit\n"
" --help : Print this text and exit\n"
+ " --version: Print version and exit\n"
"\n"
"Service program lookup testing can be done with the '-d' option, but\n"
- "as there is no actual key to query, the called must supply the key's\n"
- "attributes manually using '-D' in the form returned by the\n"
- "'keyctl rdescribe' command, for example:\n"
+ "as there is no actual key to query, the caller must supply the key's\n"
+ "attributes manually. For debug mode this is done using the '-D'\n"
+ "option with a parameter in the form returned by the 'keyctl rdescribe'\n"
+ "command, for example:\n"
"\n"
" ./request-key -d -D \"user;0;0;0;debug:bar\" create 0 0 0 0 0 0 foo\n"
"\n"
"where 'user' is the key type and 'debug:bar' is the key description.\n"
+ "\n"
+ "A simpler test mode is also available by specifying '--check'. In\n"
+ "this mode, most of the parameters are set to fixed values and the\n"
+ "'callout' and 'op' values may be defaulted (to \"\" and \"create\"\n"
+ "respectively), for example:\n"
+ "\n"
+ " ./request-key --check user debug:bar\n"
+ " ./request-key --check user debug:bar foo\n"
+ " ./request-key --check user debug:bar foo create\n"
;
static struct option long_options[] = {
{ .name = "help", .val = 1 },
{ .name = "version", .val = 2 },
+ { .name = "check", .val = 3 },
{}
};
@@ -183,7 +206,7 @@ static struct option long_options[] = {
*/
int main(int argc, char *argv[])
{
- struct parameters params;
+ struct parameters params = {};
char *test_desc = "user;0;0;1f0000;debug:1234";
char *buf;
int ret, ntype, dpos, n, fd, opt;
@@ -202,15 +225,23 @@ int main(int argc, char *argv[])
switch (opt) {
case 1:
fputs(help_text, stderr);
- exit(2);
+ exit(0);
case 2:
printf("request-key from %s (Built %s)\n",
keyutils_version_string, keyutils_build_string);
return 0;
+ case 3:
+ if (debug_mode)
+ cmderror("Multiple debug modes specified\n");
+ debug_mode = 2;
+ xnolog = 1;
+ break;
case 'D':
test_desc = optarg;
break;
case 'd':
+ if (debug_mode)
+ cmderror("Multiple debug modes specified\n");
debug_mode = 1;
break;
case 'l':
@@ -228,80 +259,102 @@ int main(int argc, char *argv[])
argc -= optind;
argv += optind;
- if (argc != 7 && argc != 8)
- error("Unexpected argument count: %d\n", argc);
+ switch (debug_mode) {
+ case 0:
+ /* If we were invoked directly by the kernel, make sure we have
+ * stdin, stdout and stderr set.
+ */
+ fd = open("/dev/null", O_RDWR);
+ if (fd < 0)
+ error("open");
+ if (fd > 2) {
+ close(fd);
+ }
+ else if (fd < 2) {
+ ret = dup(fd);
+ if (ret < 0)
+ error("dup failed: %m\n");
- fd = open("/dev/null", O_RDWR);
- if (fd < 0)
- error("open");
- if (fd > 2) {
- close(fd);
- }
- else if (fd < 2) {
- ret = dup(fd);
- if (ret < 0)
- error("dup failed: %m\n");
+ if (ret < 2 && dup(fd) < 0)
+ error("dup failed: %m\n");
+ }
+ /* Fallthrough. */
+
+ case 1:
+ if (argc != 7 && argc != 8)
+ cmderror("Unexpected argument count: %d\n", argc);
+
+ params.op = argv[0];
+ params.key = argv[1];
+ params.uid = argv[2];
+ params.gid = argv[3];
+ params.thread_keyring = argv[4];
+ params.process_keyring = argv[5];
+ params.session_keyring = argv[6];
+ params.callout_info = argv[7];
+
+ params.key_id = atoi(params.key);
+
+ if (!debug_mode) {
+ /* assume authority over the key
+ * - older kernel doesn't support this function
+ */
+ ret = keyctl_assume_authority(params.key_id);
+ if (ret < 0 && !(argc == 8 || errno == EOPNOTSUPP))
+ error("Failed to assume authority over key %d (%m)\n",
+ params.key_id);
- if (ret < 2 && dup(fd) < 0)
- error("dup failed: %m\n");
- }
+ /* ask the kernel to describe the key to us */
+ ret = keyctl_describe_alloc(params.key_id, &buf);
+ if (ret < 0)
+ goto inaccessible;
- params.op = argv[0];
- params.key = argv[1];
- params.uid = argv[2];
- params.gid = argv[3];
- params.thread_keyring = argv[4];
- params.process_keyring = argv[5];
- params.session_keyring = argv[6];
- params.callout_info = argv[7];
+ /* get hold of the callout info */
+ if (!params.callout_info) {
+ void *tmp;
- params.key_id = atoi(params.key);
+ if (keyctl_read_alloc(KEY_SPEC_REQKEY_AUTH_KEY, &tmp) < 0)
+ error("Failed to retrieve callout info (%m)\n");
- /* assume authority over the key
- * - older kernel doesn't support this function
- */
- if (!debug_mode) {
- ret = keyctl_assume_authority(params.key_id);
- if (ret < 0 && !(argc == 8 || errno == EOPNOTSUPP))
- error("Failed to assume authority over key %d (%m)\n",
- params.key_id);
- }
+ params.callout_info = tmp;
+ }
+ } else {
+ buf = strdup(test_desc);
+ }
- /* ask the kernel to describe the key to us */
- if (!debug_mode) {
- ret = keyctl_describe_alloc(params.key_id, &buf);
- if (ret < 0)
- goto inaccessible;
- } else {
- buf = strdup(test_desc);
+ /* extract the type and description from the key */
+ debug("Key descriptor: \"%s\"\n", buf);
+ ntype = -1;
+ dpos = -1;
+
+ n = sscanf(buf, "%*[^;]%n;%*d;%*d;%x;%n", &ntype, &n, &dpos);
+ if (n != 1)
+ error("Failed to parse key description\n");
+
+ params.key_type = buf;
+ params.key_type[ntype] = 0;
+ params.key_desc = buf + dpos;
+ break;
+
+ case 2:
+ /* request-key <type> <desc> [<callout>] [<op>] */
+ if (argc < 2 || argc > 4)
+ cmderror("Unexpected argument count: %d\n", argc);
+ params.key_type = argv[0];
+ params.key_desc = argv[1];
+ params.callout_info = argc > 2 ? argv[2] : "";
+ params.op = argc > 3 ? argv[3] : "create";
+ params.key = "undef-key";
+ params.uid = "undef-uid";
+ params.gid = "undef-gid";
+ params.thread_keyring = "undef-tring";
+ params.process_keyring = "undef-pring";
+ params.session_keyring = "undef-sring";
+ break;
}
- /* extract the type and description from the key */
- debug("Key descriptor: \"%s\"\n", buf);
- ntype = -1;
- dpos = -1;
-
- n = sscanf(buf, "%*[^;]%n;%*d;%*d;%x;%n", &ntype, &n, &dpos);
- if (n != 1)
- error("Failed to parse key description\n");
-
- params.key_type = buf;
- params.key_type[ntype] = 0;
- params.key_desc = buf + dpos;
-
debug("Key type: %s\n", params.key_type);
debug("Key desc: %s\n", params.key_desc);
-
- /* get hold of the callout info */
- if (!params.callout_info) {
- void *tmp;
-
- if (keyctl_read_alloc(KEY_SPEC_REQKEY_AUTH_KEY, &tmp) < 0)
- error("Failed to retrieve callout info (%m)\n");
-
- params.callout_info = tmp;
- }
-
debug("CALLOUT: '%s'\n", params.callout_info);
/* determine the action to perform */
@@ -734,6 +787,16 @@ static void execute_program(struct parameters *params, char *cmdline)
debug("%s %s\n", pipeit ? "PipeThru" : "Run", prog);
for (ap = argv; *ap; ap++)
debug("- argv[%td] = \"%s\"\n", ap - argv, *ap);
+ } else if (debug_mode) {
+ char **ap;
+
+ printf("Run: ");
+ if (pipeit)
+ putchar('|');
+ printf("%s", prog);
+ for (ap = argv; *ap; ap++)
+ printf(" \"%s\"", *ap);
+ printf("\n");
}
/* become the same UID/GID as the key requesting process */
Powered by blists - more mailing lists