* [PATCH 1/7] lib: Fix a couple of potential signed oveflows
2025-08-22 14:22 [PATCH 0/7] keyutils: Add some fixes and updates David Howells
@ 2025-08-22 14:22 ` David Howells
2025-08-23 23:25 ` Jarkko Sakkinen
2025-08-22 14:22 ` [PATCH 2/7] request-key: Fix mishandling of last line of config file David Howells
` (5 subsequent siblings)
6 siblings, 1 reply; 13+ messages in thread
From: David Howells @ 2025-08-22 14:22 UTC (permalink / raw)
To: Jarkko Sakkinen; +Cc: David Howells, keyrings, linux-kernel
Fix keyctl_read_alloc() to check for a potential unsigned overflow when we
allocate a buffer with an extra byte added on the end for a NUL.
Fix keyctl_dh_compute_alloc() for the same thing.
Signed-off-by: David Howells <dhowells@redhat.com>
---
keyutils.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/keyutils.c b/keyutils.c
index 37b6cc3..fd02cda 100644
--- a/keyutils.c
+++ b/keyutils.c
@@ -18,6 +18,7 @@
#include <dlfcn.h>
#include <sys/uio.h>
#include <errno.h>
+#include <limits.h>
#include <asm/unistd.h>
#include "keyutils.h"
@@ -442,6 +443,8 @@ int keyctl_read_alloc(key_serial_t id, void **_buffer)
return -1;
for (;;) {
+ if (ret == LONG_MAX)
+ return -EFBIG; /* Don't let buflen+1 overflow. */
buflen = ret;
buf = malloc(buflen + 1);
if (!buf)
@@ -515,6 +518,8 @@ int keyctl_dh_compute_alloc(key_serial_t priv, key_serial_t prime,
if (ret < 0)
return -1;
+ if (ret == LONG_MAX)
+ return -EFBIG; /* Don't let buflen+1 overflow. */
buflen = ret;
buf = malloc(buflen + 1);
if (!buf)
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 1/7] lib: Fix a couple of potential signed oveflows
2025-08-22 14:22 ` [PATCH 1/7] lib: Fix a couple of potential signed oveflows David Howells
@ 2025-08-23 23:25 ` Jarkko Sakkinen
0 siblings, 0 replies; 13+ messages in thread
From: Jarkko Sakkinen @ 2025-08-23 23:25 UTC (permalink / raw)
To: David Howells; +Cc: keyrings, linux-kernel
On Fri, Aug 22, 2025 at 03:22:08PM +0100, David Howells wrote:
> Fix keyctl_read_alloc() to check for a potential unsigned overflow when we
> allocate a buffer with an extra byte added on the end for a NUL.
>
> Fix keyctl_dh_compute_alloc() for the same thing.
>
> Signed-off-by: David Howells <dhowells@redhat.com>
> ---
> keyutils.c | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/keyutils.c b/keyutils.c
> index 37b6cc3..fd02cda 100644
> --- a/keyutils.c
> +++ b/keyutils.c
> @@ -18,6 +18,7 @@
> #include <dlfcn.h>
> #include <sys/uio.h>
> #include <errno.h>
> +#include <limits.h>
> #include <asm/unistd.h>
> #include "keyutils.h"
>
> @@ -442,6 +443,8 @@ int keyctl_read_alloc(key_serial_t id, void **_buffer)
> return -1;
>
> for (;;) {
> + if (ret == LONG_MAX)
> + return -EFBIG; /* Don't let buflen+1 overflow. */
> buflen = ret;
> buf = malloc(buflen + 1);
> if (!buf)
> @@ -515,6 +518,8 @@ int keyctl_dh_compute_alloc(key_serial_t priv, key_serial_t prime,
> if (ret < 0)
> return -1;
>
> + if (ret == LONG_MAX)
> + return -EFBIG; /* Don't let buflen+1 overflow. */
> buflen = ret;
> buf = malloc(buflen + 1);
> if (!buf)
>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
BR, Jarkko
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 2/7] request-key: Fix mishandling of last line of config file
2025-08-22 14:22 [PATCH 0/7] keyutils: Add some fixes and updates David Howells
2025-08-22 14:22 ` [PATCH 1/7] lib: Fix a couple of potential signed oveflows David Howells
@ 2025-08-22 14:22 ` David Howells
2025-08-23 23:59 ` Jarkko Sakkinen
2025-08-22 14:22 ` [PATCH 3/7] test: Hide endianness David Howells
` (4 subsequent siblings)
6 siblings, 1 reply; 13+ messages in thread
From: David Howells @ 2025-08-22 14:22 UTC (permalink / raw)
To: Jarkko Sakkinen; +Cc: David Howells, keyrings, linux-kernel
Fix mishandling of the config file by /sbin/request-key whereby the last
line of a file, if it is lacking a newline, will trim off the last
character and then try and use that. Return an error instead if we find a
line without a newline char at the end.
Signed-off-by: David Howells <dhowells@redhat.com>
---
request-key.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/request-key.c b/request-key.c
index bf47c0a..d1feec3 100644
--- a/request-key.c
+++ b/request-key.c
@@ -367,6 +367,8 @@ static void scan_conf_file(struct parameters *params, int dirfd, const char *con
/* ignore blank lines and comments */
if (len == 1 || buf[0] == '#' || isspace(buf[0]))
continue;
+ if (len == 0 || buf[len - 1] != '\n')
+ line_error("Line missing newline\n");
buf[--len] = 0;
p = buf;
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 2/7] request-key: Fix mishandling of last line of config file
2025-08-22 14:22 ` [PATCH 2/7] request-key: Fix mishandling of last line of config file David Howells
@ 2025-08-23 23:59 ` Jarkko Sakkinen
0 siblings, 0 replies; 13+ messages in thread
From: Jarkko Sakkinen @ 2025-08-23 23:59 UTC (permalink / raw)
To: David Howells; +Cc: keyrings, linux-kernel
On Fri, Aug 22, 2025 at 03:22:09PM +0100, David Howells wrote:
> Fix mishandling of the config file by /sbin/request-key whereby the last
> line of a file, if it is lacking a newline, will trim off the last
> character and then try and use that. Return an error instead if we find a
> line without a newline char at the end.
>
> Signed-off-by: David Howells <dhowells@redhat.com>
> ---
> request-key.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/request-key.c b/request-key.c
> index bf47c0a..d1feec3 100644
> --- a/request-key.c
> +++ b/request-key.c
> @@ -367,6 +367,8 @@ static void scan_conf_file(struct parameters *params, int dirfd, const char *con
> /* ignore blank lines and comments */
> if (len == 1 || buf[0] == '#' || isspace(buf[0]))
> continue;
> + if (len == 0 || buf[len - 1] != '\n')
> + line_error("Line missing newline\n");
>
> buf[--len] = 0;
> p = buf;
>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Looks good to me. And the next question is not directly related to
this patch per se.
Just a hypothetical question. What if for spurious reasons the config
file would have carriage returns?
BR, Jarkko
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 3/7] test: Hide endianness
2025-08-22 14:22 [PATCH 0/7] keyutils: Add some fixes and updates David Howells
2025-08-22 14:22 ` [PATCH 1/7] lib: Fix a couple of potential signed oveflows David Howells
2025-08-22 14:22 ` [PATCH 2/7] request-key: Fix mishandling of last line of config file David Howells
@ 2025-08-22 14:22 ` David Howells
2025-08-22 14:22 ` [PATCH 4/7] tests: Add skips for testing of unsupported features David Howells
` (3 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: David Howells @ 2025-08-22 14:22 UTC (permalink / raw)
To: Jarkko Sakkinen; +Cc: David Howells, keyrings, linux-kernel
Hide the endianness of the raw binary contents of a keyring by passing it
through /usr/bin/od which will automatically byteswap it in 4-byte chunks
rather than trying to detect the endianness by examining what may be a
binary file to obtain a string the format of which changes over time.
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Link: https://lore.kernel.org/keyrings/2813085.1745332819@warthog.procyon.org.uk/
---
tests/keyctl/reading/valid/runtest.sh | 9 ++-----
tests/toolbox.inc.sh | 36 +++++++++++++++++----------
2 files changed, 25 insertions(+), 20 deletions(-)
diff --git a/tests/keyctl/reading/valid/runtest.sh b/tests/keyctl/reading/valid/runtest.sh
index 2fb88b9..2527f13 100644
--- a/tests/keyctl/reading/valid/runtest.sh
+++ b/tests/keyctl/reading/valid/runtest.sh
@@ -40,13 +40,8 @@ expect_payload payload "67697a7a 617264"
# read the contents of the keyring as hex and match it to the key ID
marker "READ KEYRING"
-read_key $keyringid
-tmp=`printf %08x $keyid`
-if [ "$endian" = "LE" ]
-then
- tmp=`echo $tmp | sed 's/\(..\)\(..\)\(..\)\(..\)/\4\3\2\1/'`
-fi
-expect_payload payload $tmp
+pipe_key_int32 $keyringid
+expect_payload payload $keyid
# remove read permission from the key and try reading it again
# - we should still have read permission because it's searchable in our
diff --git a/tests/toolbox.inc.sh b/tests/toolbox.inc.sh
index 609a6c7..6f4fb18 100644
--- a/tests/toolbox.inc.sh
+++ b/tests/toolbox.inc.sh
@@ -12,19 +12,6 @@
echo === $OUTPUTFILE ===
-endian=`file -L /proc/$$/exe`
-if expr "$endian" : '.* MSB \+\(pie executable\|executable\|shared object\).*' >&/dev/null
-then
- endian=BE
-elif expr "$endian" : '.* LSB \+\(pie executable\|executable\|shared object\).*' >&/dev/null
-then
- endian=LE
-else
- echo -e "+++ \e[31;1mCan't Determine Endianness\e[0m"
- echo "+++ Can't Determine Endianness" >>$OUTPUTFILE
- exit 2
-fi
-
maxtypelen=31
maxtype=`for ((i=0; i<$((maxtypelen)); i++)); do echo -n a; done`
@@ -1055,6 +1042,29 @@ function pipe_key ()
fi
}
+###############################################################################
+#
+# pipe a key's raw payload to od to stdout, displaying it as a sequence of
+# 32-bit numbers, appropriately byteswapped.
+#
+###############################################################################
+function pipe_key_int32 ()
+{
+ my_exitval=0
+ if [ "x$1" = "x--fail" ]
+ then
+ my_exitval=1
+ shift
+ fi
+
+ echo keyctl pipe $1 \| od -t u4 -A none >>$OUTPUTFILE
+ echo `keyctl pipe $1 | od -t u4 -A none` >>$OUTPUTFILE 2>&1
+ if [ $? != $my_exitval ]
+ then
+ failed
+ fi
+}
+
###############################################################################
#
# pipe a key's raw payload through md5sum
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 4/7] tests: Add skips for testing of unsupported features
2025-08-22 14:22 [PATCH 0/7] keyutils: Add some fixes and updates David Howells
` (2 preceding siblings ...)
2025-08-22 14:22 ` [PATCH 3/7] test: Hide endianness David Howells
@ 2025-08-22 14:22 ` David Howells
2025-08-22 14:22 ` [PATCH 5/7] request-key: Add help text David Howells
` (2 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: David Howells @ 2025-08-22 14:22 UTC (permalink / raw)
To: Jarkko Sakkinen; +Cc: David Howells, keyrings, linux-kernel
Add skips for features that are either unsupported by the kernel or by the
keyutils package.
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Link: https://lore.kernel.org/keyrings/3089643.1745491480@warthog.procyon.org.uk/
---
tests/features/limits/runtest.sh | 6 +++++
tests/hex2bin.pl | 21 +++++++++++++++
tests/keyctl/id/bad-args/runtest.sh | 6 +++++
tests/keyctl/id/noargs/runtest.sh | 6 +++++
tests/keyctl/id/valid/runtest.sh | 6 +++++
tests/keyctl/move/bad-args/runtest.sh | 6 +++++
tests/keyctl/move/noargs/runtest.sh | 6 +++++
tests/keyctl/move/recursion/runtest.sh | 6 +++++
tests/keyctl/move/valid/runtest.sh | 6 +++++
tests/keyctl/session/valid2/runtest.sh | 6 +++++
tests/keyctl/supports/bad-args/runtest.sh | 6 +++++
tests/keyctl/supports/valid/runtest.sh | 6 +++++
tests/prepare.inc.sh | 23 +++++++++++++++-
tests/toolbox.inc.sh | 33 ++++++++++++++++++-----
14 files changed, 136 insertions(+), 7 deletions(-)
create mode 100644 tests/hex2bin.pl
diff --git a/tests/features/limits/runtest.sh b/tests/features/limits/runtest.sh
index 3af2f5a..7642071 100644
--- a/tests/features/limits/runtest.sh
+++ b/tests/features/limits/runtest.sh
@@ -9,6 +9,12 @@
result=PASS
echo "++++ BEGINNING TEST" >$OUTPUTFILE
+if ! keyutils_at_or_later_than 1.6.2
+then
+ toolbox_skip_test $TEST "SKIPPING DUE TO LACK OF 'keyctl --test'"
+ exit 0
+fi
+
# This doesn't work on MIPS earler than 3.19 because of a kernel bug
kver=`uname -r`
kmch=`uname -m`
diff --git a/tests/hex2bin.pl b/tests/hex2bin.pl
new file mode 100644
index 0000000..4f0f27a
--- /dev/null
+++ b/tests/hex2bin.pl
@@ -0,0 +1,21 @@
+#!/usr/bin/perl -w
+use strict;
+
+die "Format:\n\t$0 <hex> [<hex>]*\n\t$0 -\n" unless (@ARGV);
+
+my $str = "";
+
+if ($ARGV[0] eq "-") {
+ shift(@ARGV);
+ $str .= $_ while (<STDIN>);
+} else {
+ $str = join("", @ARGV);
+}
+
+$str =~ s/[ \t\n]//g;
+die "odd length string\n" if (length($str) & 1);
+
+for (; $str; $str = substr($str, 2)) {
+ my $pair = hex(substr($str, 0, 2));
+ print pack("C", $pair);
+}
diff --git a/tests/keyctl/id/bad-args/runtest.sh b/tests/keyctl/id/bad-args/runtest.sh
index 957d1a5..bba62c6 100644
--- a/tests/keyctl/id/bad-args/runtest.sh
+++ b/tests/keyctl/id/bad-args/runtest.sh
@@ -6,6 +6,12 @@
# ---- do the actual testing ----
+if [ $have_id_command = 0 ]
+then
+ toolbox_skip_test $TEST "SKIPPING DUE TO LACK OF 'keyctl id'"
+ exit 0
+fi
+
result=PASS
echo "++++ BEGINNING TEST" >$OUTPUTFILE
diff --git a/tests/keyctl/id/noargs/runtest.sh b/tests/keyctl/id/noargs/runtest.sh
index aff9de6..b95c596 100644
--- a/tests/keyctl/id/noargs/runtest.sh
+++ b/tests/keyctl/id/noargs/runtest.sh
@@ -6,6 +6,12 @@
# ---- do the actual testing ----
+if [ $have_id_command = 0 ]
+then
+ toolbox_skip_test $TEST "SKIPPING DUE TO LACK OF 'keyctl id'"
+ exit 0
+fi
+
result=PASS
echo "++++ BEGINNING TEST" >$OUTPUTFILE
diff --git a/tests/keyctl/id/valid/runtest.sh b/tests/keyctl/id/valid/runtest.sh
index ffed995..2c06b3d 100644
--- a/tests/keyctl/id/valid/runtest.sh
+++ b/tests/keyctl/id/valid/runtest.sh
@@ -6,6 +6,12 @@
# ---- do the actual testing ----
+if [ $have_id_command = 0 ]
+then
+ toolbox_skip_test $TEST "SKIPPING DUE TO LACK OF 'keyctl id'"
+ exit 0
+fi
+
result=PASS
echo "++++ BEGINNING TEST" >$OUTPUTFILE
diff --git a/tests/keyctl/move/bad-args/runtest.sh b/tests/keyctl/move/bad-args/runtest.sh
index b1c7e66..9410941 100644
--- a/tests/keyctl/move/bad-args/runtest.sh
+++ b/tests/keyctl/move/bad-args/runtest.sh
@@ -6,6 +6,12 @@
# ---- do the actual testing ----
+if [ $have_move_key = 0 ]
+then
+ toolbox_skip_test $TEST "SKIPPING DUE TO LACK OF 'keyctl move'"
+ exit 0
+fi
+
result=PASS
echo "++++ BEGINNING TEST" >$OUTPUTFILE
diff --git a/tests/keyctl/move/noargs/runtest.sh b/tests/keyctl/move/noargs/runtest.sh
index 29a91f1..8ad91e9 100644
--- a/tests/keyctl/move/noargs/runtest.sh
+++ b/tests/keyctl/move/noargs/runtest.sh
@@ -6,6 +6,12 @@
# ---- do the actual testing ----
+if [ $have_move_key = 0 ]
+then
+ toolbox_skip_test $TEST "SKIPPING DUE TO LACK OF 'keyctl move'"
+ exit 0
+fi
+
result=PASS
echo "++++ BEGINNING TEST" >$OUTPUTFILE
diff --git a/tests/keyctl/move/recursion/runtest.sh b/tests/keyctl/move/recursion/runtest.sh
index 36cd5cb..8b90be8 100644
--- a/tests/keyctl/move/recursion/runtest.sh
+++ b/tests/keyctl/move/recursion/runtest.sh
@@ -6,6 +6,12 @@
# ---- do the actual testing ----
+if [ $have_move_key = 0 ]
+then
+ toolbox_skip_test $TEST "SKIPPING DUE TO LACK OF 'keyctl move'"
+ exit 0
+fi
+
result=PASS
echo "++++ BEGINNING TEST" >$OUTPUTFILE
diff --git a/tests/keyctl/move/valid/runtest.sh b/tests/keyctl/move/valid/runtest.sh
index 31b51d7..20ccff2 100644
--- a/tests/keyctl/move/valid/runtest.sh
+++ b/tests/keyctl/move/valid/runtest.sh
@@ -6,6 +6,12 @@
# ---- do the actual testing ----
+if [ $have_move_key = 0 ]
+then
+ toolbox_skip_test $TEST "SKIPPING DUE TO LACK OF 'keyctl move'"
+ exit 0
+fi
+
result=PASS
echo "++++ BEGINNING TEST" >$OUTPUTFILE
diff --git a/tests/keyctl/session/valid2/runtest.sh b/tests/keyctl/session/valid2/runtest.sh
index 12ad234..1642395 100644
--- a/tests/keyctl/session/valid2/runtest.sh
+++ b/tests/keyctl/session/valid2/runtest.sh
@@ -6,6 +6,12 @@
# ---- do the actual testing ----
+if [ $have_id_command = 0 ]
+then
+ toolbox_skip_test $TEST "SKIPPING DUE TO LACK OF 'keyctl id'"
+ exit 0
+fi
+
result=PASS
echo "++++ BEGINNING TEST" >$OUTPUTFILE
diff --git a/tests/keyctl/supports/bad-args/runtest.sh b/tests/keyctl/supports/bad-args/runtest.sh
index 05581a4..f87f517 100644
--- a/tests/keyctl/supports/bad-args/runtest.sh
+++ b/tests/keyctl/supports/bad-args/runtest.sh
@@ -6,6 +6,12 @@
# ---- do the actual testing ----
+if [ $have_capabilities = 0 ]
+then
+ toolbox_skip_test $TEST "SKIPPING DUE TO LACK OF 'keyctl supports'"
+ exit 0
+fi
+
result=PASS
echo "++++ BEGINNING TEST" >$OUTPUTFILE
diff --git a/tests/keyctl/supports/valid/runtest.sh b/tests/keyctl/supports/valid/runtest.sh
index 2c62ef2..4e41200 100644
--- a/tests/keyctl/supports/valid/runtest.sh
+++ b/tests/keyctl/supports/valid/runtest.sh
@@ -6,6 +6,12 @@
# ---- do the actual testing ----
+if [ $have_capabilities = 0 ]
+then
+ toolbox_skip_test $TEST "SKIPPING DUE TO LACK OF 'keyctl supports'"
+ exit 0
+fi
+
result=PASS
echo "++++ BEGINNING TEST" >$OUTPUTFILE
diff --git a/tests/prepare.inc.sh b/tests/prepare.inc.sh
index 4033d69..be134da 100644
--- a/tests/prepare.inc.sh
+++ b/tests/prepare.inc.sh
@@ -112,11 +112,14 @@ then
esac
fi
+have_capabilities=0
have_key_invalidate=0
have_big_key_type=0
have_dh_compute=0
-have_restrict_keyring=0
+have_move_key=0
have_notify=0
+have_public_key=0
+have_restrict_keyring=0
if keyctl supports capabilities >&/dev/null
then
@@ -179,3 +182,21 @@ if [ "$SKIPINSTALLREQ" = "yes" ]
then
skip_install_required=1
fi
+
+#
+# Check if "keyctl id" is supported
+#
+have_id_command=0
+if keyutils_at_or_later_than 1.6.2
+then
+ have_id_command=1
+fi
+
+#
+# Check if "keyctl pkey_*" are supported
+#
+have_pkey_commands=0
+if keyutils_at_or_later_than 1.6
+then
+ have_pkey_commands=1
+fi
diff --git a/tests/toolbox.inc.sh b/tests/toolbox.inc.sh
index 6f4fb18..212b353 100644
--- a/tests/toolbox.inc.sh
+++ b/tests/toolbox.inc.sh
@@ -613,8 +613,15 @@ function create_key ()
my_keyring=$4
fi
- echo keyctl add "$@" >>$OUTPUTFILE
- keyctl add "$@" >>$OUTPUTFILE 2>&1
+ if [ "$1" = "-x" ] && version_less_than $OSRELEASE 9
+ then
+ shift
+ echo perl ../../../hex2bin.pl "$3" "|" keyctl padd "$1 $2 $4" >>$OUTPUTFILE
+ perl ../../../hex2bin.pl "$3" | keyctl padd "$1" "$2" "$4" >>$OUTPUTFILE
+ else
+ echo keyctl add "$@" >>$OUTPUTFILE
+ keyctl add "$@" >>$OUTPUTFILE 2>&1
+ fi
e=$?
if [ $e == $my_exitval ]
then
@@ -682,8 +689,15 @@ function pcreate_key ()
my_keyring=$3
fi
- echo echo -n $data \| keyctl padd "$@" >>$OUTPUTFILE
- echo -n $data | keyctl padd "$@" >>$OUTPUTFILE 2>&1
+ if [ "$1" = "-x" ] && version_less_than $OSRELEASE 9
+ then
+ shift
+ echo echo -n $data \| perl ../../../hex2bin.pl "|" keyctl padd "$@" >>$OUTPUTFILE
+ echo -n $data | perl ../../../hex2bin.pl - | keyctl padd "$@" >>$OUTPUTFILE
+ else
+ echo echo -n $data \| keyctl padd "$@" >>$OUTPUTFILE
+ echo -n $data | keyctl padd "$@" >>$OUTPUTFILE 2>&1
+ fi
e=$?
if [ $e == $my_exitval ]
then
@@ -1232,8 +1246,15 @@ function update_key ()
shift
fi
- echo keyctl update "$@" >>$OUTPUTFILE
- keyctl update "$@" >>$OUTPUTFILE 2>&1
+ if [ "x$1" = "x-x" ] && version_less_than $OSRELEASE 9
+ then
+ shift
+ echo perl ../../../hex2bin.pl "$2" "|" keyctl pupdate "$1" >>$OUTPUTFILE
+ perl ../../../hex2bin.pl "$2" | keyctl pupdate "$1" >>$OUTPUTFILE
+ else
+ echo keyctl update "$@" >>$OUTPUTFILE
+ keyctl update "$@" >>$OUTPUTFILE 2>&1
+ fi
e=$?
if [ $e == $my_exitval ]
then
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 5/7] request-key: Add help text
2025-08-22 14:22 [PATCH 0/7] keyutils: Add some fixes and updates David Howells
` (3 preceding siblings ...)
2025-08-22 14:22 ` [PATCH 4/7] tests: Add skips for testing of unsupported features David Howells
@ 2025-08-22 14:22 ` David Howells
2025-08-24 0:03 ` Jarkko Sakkinen
2025-08-22 14:22 ` [PATCH 6/7] request-key: Add a simpler debug test David Howells
2025-08-22 14:22 ` [PATCH 7/7] request-key: Support the promised multiwildcard matching David Howells
6 siblings, 1 reply; 13+ messages in thread
From: David Howells @ 2025-08-22 14:22 UTC (permalink / raw)
To: Jarkko Sakkinen; +Cc: David Howells, keyrings, linux-kernel
Add --help text to /sbin/request-key.
Signed-off-by: David Howells <dhowells@redhat.com>
---
man/request-key.8 | 42 +++++++++++++++++++++++++++-------
request-key.c | 57 ++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 85 insertions(+), 14 deletions(-)
diff --git a/man/request-key.8 b/man/request-key.8
index 50a7506..15b6bb8 100644
--- a/man/request-key.8
+++ b/man/request-key.8
@@ -7,20 +7,37 @@
.\" as published by the Free Software Foundation; either version
.\" 2 of the License, or (at your option) any later version.
.\"
-.TH REQUEST-KEY 8 "15 Nov 2011" Linux "Linux Key Management Utilities"
+.TH REQUEST-KEY 8 "22 Aug 2025" Linux "Linux Key Management Utilities"
.SH NAME
request\-key \- handle key instantiation callback requests from the kernel
.SH SYNOPSIS
-\fB/sbin/request\-key \fR<op> <key> <uid> <gid> <threadring> <processring>
- <sessionring> [<info>]
+.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...
+.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.
+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.
.PP
-However, for debugging purposes, it can be given some options on the command
-line:
+The normally required parameters are:
+.IP \fBop\fP
+The operation being done, such as "create" if a key is being instantiated for
+creation.
+.IP \fBkey\fP
+The ID of the key being operated upon.
+.IP "\fBuid\fP, \fBgid\fP"
+The ownership of the task that caused the key to be created.
+.IP "\fBt-ring\fP, \fBp-ring\fP, \fBs-ring\fP"
+The thread, process and session keyrings of the task that caused the key to be
+created.
+.IP \fBinfo\fP
+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
and, if a handler program is selected, it won't be executed; instead, this
@@ -39,10 +56,19 @@ 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--help\fP
+Print help text and exit.
.IP \fB--version\fP
Print the program version and exit.
+.SH EXAMPLES
+When using the debugging mode, all the parameters must be given, though a lot
+of them don't matter and can be just set to 0, e.g.:
+.PP
+.nf
+request-key -d -D "user;0;0;0;debug:bar" create 0 0 0 0 0 0 foo
+.fi
.SH ERRORS
-All errors will be logged to the syslog.
+All errors will be logged to the syslog unless the \fB-n\fP option is given.
.SH FILES
.ul
/etc/request\-key.d/*.conf
diff --git a/request-key.c b/request-key.c
index d1feec3..9a7d741 100644
--- a/request-key.c
+++ b/request-key.c
@@ -111,7 +111,7 @@ static void error(const char *fmt, ...)
{
va_list va;
- if (verbosity) {
+ if (verbosity || debug_mode) {
va_start(va, fmt);
vfprintf(stderr, fmt, va);
va_end(va);
@@ -138,6 +138,45 @@ static void oops(int x)
error("Died on signal %d", x);
}
+static const char help_text[] =
+ "Usage: request-key [OPTIONS] [PARAMS]\n"
+ " request-key [OPTIONS] -d -D <desc> [PARAMS]\n"
+ "\n"
+ "Where the required parameters, [PARAMS], are, in order:\n"
+ " <op> : The operation type (e.g. 'create')\n"
+ " <key> : The ID of the key to be operated upon\n"
+ " <uid> : The UID of the requesting process\n"
+ " <gid> : The GID of the requesting process\n"
+ " <t-ring> : The thread keyring of the requesting process (or 0)\n"
+ " <p-ring> : The process keyring of the requesting process (or 0)\n"
+ " <s-ring> : The session keyring of the requesting process (or 0)\n"
+ " <callout>: The callout data supplied to the request\n"
+ "\n"
+ "and [OPTIONS] are none or more of\n"
+ " -d : Debug mode for direct cmdline testing\n"
+ " -D <desc>: Description for debug mode\n"
+ " -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"
+ "\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"
+ "\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"
+ ;
+
+static struct option long_options[] = {
+ { .name = "help", .val = 1 },
+ { .name = "version", .val = 2 },
+ {}
+};
+
/*****************************************************************************/
/*
*
@@ -149,19 +188,25 @@ int main(int argc, char *argv[])
char *buf;
int ret, ntype, dpos, n, fd, opt;
- if (argc == 2 && strcmp(argv[1], "--version") == 0) {
- printf("request-key from %s (Built %s)\n",
- keyutils_version_string, keyutils_build_string);
- return 0;
+ if (argc == 1) {
+ fputs(help_text, stderr);
+ exit(2);
}
signal(SIGSEGV, oops);
signal(SIGBUS, oops);
signal(SIGPIPE, SIG_IGN);
- while (opt = getopt(argc, argv, "D:dlnv"),
+ while (opt = getopt_long(argc, argv, "D:dlnv", long_options, NULL),
opt != -1) {
switch (opt) {
+ case 1:
+ fputs(help_text, stderr);
+ exit(2);
+ case 2:
+ printf("request-key from %s (Built %s)\n",
+ keyutils_version_string, keyutils_build_string);
+ return 0;
case 'D':
test_desc = optarg;
break;
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 5/7] request-key: Add help text
2025-08-22 14:22 ` [PATCH 5/7] request-key: Add help text David Howells
@ 2025-08-24 0:03 ` Jarkko Sakkinen
0 siblings, 0 replies; 13+ messages in thread
From: Jarkko Sakkinen @ 2025-08-24 0:03 UTC (permalink / raw)
To: David Howells; +Cc: keyrings, linux-kernel
On Fri, Aug 22, 2025 at 03:22:12PM +0100, David Howells wrote:
> Add --help text to /sbin/request-key.
>
> Signed-off-by: David Howells <dhowells@redhat.com>
> ---
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
> man/request-key.8 | 42 +++++++++++++++++++++++++++-------
> request-key.c | 57 ++++++++++++++++++++++++++++++++++++++++++-----
> 2 files changed, 85 insertions(+), 14 deletions(-)
>
> diff --git a/man/request-key.8 b/man/request-key.8
> index 50a7506..15b6bb8 100644
> --- a/man/request-key.8
> +++ b/man/request-key.8
> @@ -7,20 +7,37 @@
> .\" as published by the Free Software Foundation; either version
> .\" 2 of the License, or (at your option) any later version.
> .\"
> -.TH REQUEST-KEY 8 "15 Nov 2011" Linux "Linux Key Management Utilities"
> +.TH REQUEST-KEY 8 "22 Aug 2025" Linux "Linux Key Management Utilities"
> .SH NAME
> request\-key \- handle key instantiation callback requests from the kernel
> .SH SYNOPSIS
> -\fB/sbin/request\-key \fR<op> <key> <uid> <gid> <threadring> <processring>
> - <sessionring> [<info>]
> +.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...
> +.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.
> +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.
> .PP
> -However, for debugging purposes, it can be given some options on the command
> -line:
> +The normally required parameters are:
> +.IP \fBop\fP
> +The operation being done, such as "create" if a key is being instantiated for
> +creation.
> +.IP \fBkey\fP
> +The ID of the key being operated upon.
> +.IP "\fBuid\fP, \fBgid\fP"
> +The ownership of the task that caused the key to be created.
> +.IP "\fBt-ring\fP, \fBp-ring\fP, \fBs-ring\fP"
> +The thread, process and session keyrings of the task that caused the key to be
> +created.
> +.IP \fBinfo\fP
> +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
> and, if a handler program is selected, it won't be executed; instead, this
> @@ -39,10 +56,19 @@ 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--help\fP
> +Print help text and exit.
> .IP \fB--version\fP
> Print the program version and exit.
> +.SH EXAMPLES
> +When using the debugging mode, all the parameters must be given, though a lot
> +of them don't matter and can be just set to 0, e.g.:
> +.PP
> +.nf
> +request-key -d -D "user;0;0;0;debug:bar" create 0 0 0 0 0 0 foo
> +.fi
> .SH ERRORS
> -All errors will be logged to the syslog.
> +All errors will be logged to the syslog unless the \fB-n\fP option is given.
> .SH FILES
> .ul
> /etc/request\-key.d/*.conf
> diff --git a/request-key.c b/request-key.c
> index d1feec3..9a7d741 100644
> --- a/request-key.c
> +++ b/request-key.c
> @@ -111,7 +111,7 @@ static void error(const char *fmt, ...)
> {
> va_list va;
>
> - if (verbosity) {
> + if (verbosity || debug_mode) {
> va_start(va, fmt);
> vfprintf(stderr, fmt, va);
> va_end(va);
> @@ -138,6 +138,45 @@ static void oops(int x)
> error("Died on signal %d", x);
> }
>
> +static const char help_text[] =
> + "Usage: request-key [OPTIONS] [PARAMS]\n"
> + " request-key [OPTIONS] -d -D <desc> [PARAMS]\n"
> + "\n"
> + "Where the required parameters, [PARAMS], are, in order:\n"
> + " <op> : The operation type (e.g. 'create')\n"
> + " <key> : The ID of the key to be operated upon\n"
> + " <uid> : The UID of the requesting process\n"
> + " <gid> : The GID of the requesting process\n"
> + " <t-ring> : The thread keyring of the requesting process (or 0)\n"
> + " <p-ring> : The process keyring of the requesting process (or 0)\n"
> + " <s-ring> : The session keyring of the requesting process (or 0)\n"
> + " <callout>: The callout data supplied to the request\n"
> + "\n"
> + "and [OPTIONS] are none or more of\n"
> + " -d : Debug mode for direct cmdline testing\n"
> + " -D <desc>: Description for debug mode\n"
> + " -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"
> + "\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"
> + "\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"
> + ;
> +
> +static struct option long_options[] = {
> + { .name = "help", .val = 1 },
> + { .name = "version", .val = 2 },
> + {}
> +};
> +
> /*****************************************************************************/
> /*
> *
> @@ -149,19 +188,25 @@ int main(int argc, char *argv[])
> char *buf;
> int ret, ntype, dpos, n, fd, opt;
>
> - if (argc == 2 && strcmp(argv[1], "--version") == 0) {
> - printf("request-key from %s (Built %s)\n",
> - keyutils_version_string, keyutils_build_string);
> - return 0;
> + if (argc == 1) {
> + fputs(help_text, stderr);
> + exit(2);
> }
>
> signal(SIGSEGV, oops);
> signal(SIGBUS, oops);
> signal(SIGPIPE, SIG_IGN);
>
> - while (opt = getopt(argc, argv, "D:dlnv"),
> + while (opt = getopt_long(argc, argv, "D:dlnv", long_options, NULL),
> opt != -1) {
> switch (opt) {
> + case 1:
> + fputs(help_text, stderr);
> + exit(2);
> + case 2:
> + printf("request-key from %s (Built %s)\n",
> + keyutils_version_string, keyutils_build_string);
> + return 0;
> case 'D':
> test_desc = optarg;
> break;
>
BR, Jarkko
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 6/7] request-key: Add a simpler debug test
2025-08-22 14:22 [PATCH 0/7] keyutils: Add some fixes and updates David Howells
` (4 preceding siblings ...)
2025-08-22 14:22 ` [PATCH 5/7] request-key: Add help text David Howells
@ 2025-08-22 14:22 ` David Howells
2025-08-24 0:04 ` Jarkko Sakkinen
2025-08-22 14:22 ` [PATCH 7/7] request-key: Support the promised multiwildcard matching David Howells
6 siblings, 1 reply; 13+ messages in thread
From: David Howells @ 2025-08-22 14:22 UTC (permalink / raw)
To: Jarkko Sakkinen; +Cc: David Howells, keyrings, linux-kernel
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@redhat.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 */
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 6/7] request-key: Add a simpler debug test
2025-08-22 14:22 ` [PATCH 6/7] request-key: Add a simpler debug test David Howells
@ 2025-08-24 0:04 ` Jarkko Sakkinen
0 siblings, 0 replies; 13+ messages in thread
From: Jarkko Sakkinen @ 2025-08-24 0:04 UTC (permalink / raw)
To: David Howells; +Cc: keyrings, linux-kernel
On Fri, Aug 22, 2025 at 03:22:13PM +0100, David Howells wrote:
> 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@redhat.com>
Tested-by: Jarkko Sakkinen <jarkko@kernel.org>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
BR, Jarkko
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 7/7] request-key: Support the promised multiwildcard matching
2025-08-22 14:22 [PATCH 0/7] keyutils: Add some fixes and updates David Howells
` (5 preceding siblings ...)
2025-08-22 14:22 ` [PATCH 6/7] request-key: Add a simpler debug test David Howells
@ 2025-08-22 14:22 ` David Howells
2025-08-24 0:05 ` Jarkko Sakkinen
6 siblings, 1 reply; 13+ messages in thread
From: David Howells @ 2025-08-22 14:22 UTC (permalink / raw)
To: Jarkko Sakkinen; +Cc: David Howells, keyrings, linux-kernel
The manual page for request-key.conf says that multiple wildcards can be
used in match elements in the config files, so implement this feature.
Also add a flag, "--test-match", to allow that match function to be tested
directly, e.g.:
request-key --test-match "**a*a***i**a**a**" antidisestablishmentarianism
Signed-off-by: David Howells <dhowells@redhat.com>
---
man/request-key.8 | 19 +++-
request-key.c | 252 ++++++++++++++++++++++++++++++++++++----------
2 files changed, 217 insertions(+), 54 deletions(-)
diff --git a/man/request-key.8 b/man/request-key.8
index 90121d9..7cec6e8 100644
--- a/man/request-key.8
+++ b/man/request-key.8
@@ -16,6 +16,7 @@ request\-key \- handle key instantiation callback requests from the kernel
\fB/sbin/request\-key\fP \fIop key uid gid t-ring p-ring s-ring\fP [\fIinfo\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]
+\fB/sbin/request\-key --match\fP [\fB-v\fP] \fIpattern datum\fP [\fIdatum...\fP]
.fi
.SH DESCRIPTION
This program is invoked by the kernel when the kernel is asked for a key that
@@ -65,6 +66,10 @@ 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--match\fP
+Test the pattern matcher. The first parameter is the pattern and all
+subsequent parameters are strings to try matching against that. The program
+exits 1 if any match failure occurs, 0 if all succeed.
.IP \fB--version\fP
Print the program version and exit.
.SH EXAMPLES
@@ -84,9 +89,19 @@ request-key --check user debug:bar
request-key --check user debug:bar foo
request-key --check user debug:bar foo create
.fi
+.PP
+Pattern match testing can be done directly without invoking any of the lookup
+code and without reference to the configuration, e.g.:
+.PP
+.nf
+request-key --match "debug:*" debug:a user:b user:debug:c
+request-key --match -v "*a*a***a*a**a**" antidisestablishmentarianism
+.fi
+.PP
.SH ERRORS
-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.
+All errors will be logged to the syslog unless one of \fB-n\fP, \fB--check\fP
+or \fB--match\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 302d083..97afeee 100644
--- a/request-key.c
+++ b/request-key.c
@@ -16,6 +16,7 @@
* data: command name, e.g.: "/home/dhowells/request-key-create.sh"
*/
+#define _GNU_SOURCE
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
@@ -56,6 +57,7 @@ struct parameters {
};
static int verbosity;
+static int match_debug;
static int xlocaldirs;
static int xnolog;
static int debug_mode;
@@ -81,8 +83,8 @@ static void pipe_to_program(struct parameters *params,
char **argv)
__attribute__((noreturn));
-static int match(const char *pattern, int plen, const char *datum, int dlen,
- unsigned int *wildness);
+static int match(const char *pattern, unsigned int plen,
+ const char *datum, unsigned int dlen);
static void debug(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
static void debug(const char *fmt, ...)
@@ -153,6 +155,7 @@ 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"
+ " request-key [OPTIONS] --match <pattern> <datum> [datum ...]\n"
"\n"
"Where the required parameters, [PARAMS], are, in order:\n"
" <op> : The operation type (e.g. 'create')\n"
@@ -168,6 +171,7 @@ static const char help_text[] =
" -d : Debug mode for direct cmdline testing\n"
" -D <desc>: Description for debug mode\n"
" -l : Use config from local dir, not /etc\n"
+ " -M : Enable string-matching algorithm debugging\n"
" -n : Don't log to syslog\n"
" -v : Turn up verbosity (can use multiple times)\n"
" --help : Print this text and exit\n"
@@ -191,12 +195,20 @@ static const char help_text[] =
" ./request-key --check user debug:bar\n"
" ./request-key --check user debug:bar foo\n"
" ./request-key --check user debug:bar foo create\n"
+ "\n"
+ "Another test mode is available ('--match') that allows the\n"
+ "pattern match evaluator to be tested against a bunch of sample\n"
+ "strings. For each string, either 'No' or 'Yes(n)' is printed,\n"
+ "where 'n' is the number of wild-matched characters. For example:\n"
+ "\n"
+ " ./request-key --match \"**foo**bar*\" \"foobar\"\n"
;
static struct option long_options[] = {
{ .name = "help", .val = 1 },
{ .name = "version", .val = 2 },
{ .name = "check", .val = 3 },
+ { .name = "match", .val = 4 },
{}
};
@@ -236,6 +248,12 @@ int main(int argc, char *argv[])
debug_mode = 2;
xnolog = 1;
break;
+ case 4:
+ if (debug_mode)
+ cmderror("Multiple debug modes specified\n");
+ debug_mode = 3;
+ xnolog = 1;
+ break;
case 'D':
test_desc = optarg;
break;
@@ -351,6 +369,30 @@ int main(int argc, char *argv[])
params.process_keyring = "undef-pring";
params.session_keyring = "undef-sring";
break;
+
+ case 3:
+ const char *pattern;
+ int e = 0;
+
+ if (verbosity)
+ match_debug = 1;
+ if (argc < 2)
+ cmderror("Insufficient arguments\n");
+ pattern = argv[0];
+ argv++;
+ argc--;
+ for (; argc; argc--) {
+ int m = match(pattern, strlen(pattern),
+ argv[0], strlen(argv[0]));
+ if (m >= 0) {
+ printf("Yes(%d)\n", m);
+ } else {
+ printf("No\n");
+ e = 3;
+ }
+ argv++;
+ }
+ exit(e);
}
debug("Key type: %s\n", params.key_type);
@@ -450,6 +492,7 @@ static void scan_conf_file(struct parameters *params, int dirfd, const char *con
for (confline = 1;; confline++) {
unsigned int wildness[4] = {};
unsigned int len;
+ int m;
/* read the file line-by-line */
if (!fgets(buf, sizeof(buf), conf)) {
@@ -478,9 +521,10 @@ static void scan_conf_file(struct parameters *params, int dirfd, const char *con
goto syntax_error;
*p = 0;
- if (!match(q, p - q, params->op, params->oplen, &wildness[0]))
+ m = match(q, p - q, params->op, params->oplen);
+ if (m < 0)
continue;
-
+ wildness[0] += m;
p++;
/* attempt to match the type */
@@ -494,8 +538,10 @@ static void scan_conf_file(struct parameters *params, int dirfd, const char *con
goto syntax_error;
*p = 0;
- if (!match(q, p - q, params->key_type, params->ktlen, &wildness[1]))
+ m = match(q, p - q, params->key_type, params->ktlen);
+ if (m < 0)
continue;
+ wildness[1] += m;
p++;
@@ -510,9 +556,10 @@ static void scan_conf_file(struct parameters *params, int dirfd, const char *con
goto syntax_error;
*p = 0;
- if (!match(q, p - q, params->key_desc, params->kdlen, &wildness[2]))
+ m = match(q, p - q, params->key_desc, params->kdlen);
+ if (m < 0)
continue;
-
+ wildness[2] += m;
p++;
/* attempt to match the callout info */
@@ -526,8 +573,10 @@ static void scan_conf_file(struct parameters *params, int dirfd, const char *con
goto syntax_error;
*p = 0;
- if (!match(q, p - q, params->callout_info, params->cilen, &wildness[3]))
+ m = match(q, p - q, params->callout_info, params->cilen);
+ if (m < 0)
continue;
+ wildness[3] += m;
p++;
@@ -569,75 +618,174 @@ syntax_error:
line_error("Syntax error\n");
}
+static void mdebug(const char *msg,
+ const char *pattern, unsigned int plen,
+ const char *datum, unsigned int dlen)
+{
+ if (match_debug)
+ printf("- %s(%*.*s,%*.*s)\n",
+ msg, plen, plen, pattern, dlen, dlen, datum);
+}
+
+static void mdebug2(const char *msg)
+{
+ if (match_debug)
+ printf("- %s\n", msg);
+}
+
/*****************************************************************************/
/*
* attempt to match a datum to a pattern
* - one asterisk is allowed anywhere in the pattern to indicate a wildcard
- * - returns true if matched, false if not
- * - adds the total number of chars skipped by wildcard to *_wildness
+ * - returns -1 if not matched or the number of chars skipped by wildcard
*/
-static int match(const char *pattern, int plen, const char *datum, int dlen,
- unsigned int *_wildness)
+static int match(const char *pattern, unsigned int plen,
+ const char *datum, unsigned int dlen)
{
- const char *asterisk;
- int n;
+ const char *left, *right;
+ unsigned int wild = 0, n;
if (verbosity >= 2)
debug("match(%*.*s,%*.*s)", plen, plen, pattern, dlen, dlen, datum);
+ mdebug("match", pattern, plen, datum, dlen);
- asterisk = memchr(pattern, '*', plen);
- if (!asterisk) {
- /* exact match only if no wildcard */
- if (plen == dlen && memcmp(pattern, datum, dlen) == 0)
- goto yes;
+ if (plen <= 0)
goto no;
+
+ /* Special case "*" matches everything */
+ if (plen == 1 && pattern[0] == '*') {
+ wild = dlen;
+ goto yes;
}
- /* the datum mustn't be shorter than the pattern without the asterisk */
- if (dlen < plen - 1)
+ left = memchr(pattern, '*', plen);
+ if (!left) {
+ /* No wildcard: exact match only. */
+ mdebug2("exact-only");
+ if (plen == dlen && memcmp(pattern, datum, dlen) == 0) {
+ wild = 0;
+ goto yes;
+ }
goto no;
+ }
- n = asterisk - pattern;
- if (n == 0) {
- /* wildcard at beginning of pattern */
- pattern++;
- if (!*pattern)
- goto yes_wildcard; /* "*" matches everything */
+ if (left > pattern) {
+ /* Check prefix matches. */
+ mdebug("prefix", pattern, left - pattern, datum, dlen);
+ if (dlen < left - pattern ||
+ memcmp(pattern, datum, left - pattern) != 0) {
+ mdebug2("prefix-x");
+ goto no;
+ }
+ n = left - pattern;
+ datum += n;
+ dlen -= n;
+ pattern += n + 1;
+ plen -= n + 1;
+ while (plen > 0 && *pattern == '*') {
+ pattern++;
+ plen--;
+ }
+ if (!plen) {
+ /* Simple prefix match. */
+ mdebug2("simple-prefix");
+ wild = dlen;
+ goto yes;
+ }
+ } else {
+ while (plen > 0 && *pattern == '*') {
+ pattern++;
+ plen--;
+ }
+ }
- /* match the end of the datum */
- if (memcmp(pattern, datum + (dlen - (plen - 1)), plen - 1) == 0)
- goto yes_wildcard;
- goto no;
+ right = memrchr(pattern, '*', plen);
+ if (right != pattern + plen - 1) {
+ /* Check suffix matches */
+ const char *suffix = right ? right + 1 : pattern;
+ const char *p_end = pattern + plen;
+ const char *d_end = datum + dlen;
+ int slen = p_end - suffix;
+
+ mdebug("suffix", suffix, slen, datum, dlen);
+ if (slen > dlen ||
+ memcmp(suffix, d_end - slen, slen) != 0) {
+ mdebug2("suffix-x");
+ goto no;
+ }
+ dlen -= slen;
+ plen -= slen;
+ while (plen > 0 && pattern[plen - 1] == '*')
+ plen--;
+ if (!plen) {
+ /* Simple prefix+suffix match. */
+ wild = dlen;
+ goto yes;
+ }
+ } else {
+ while (plen > 0 && pattern[plen - 1] == '*')
+ plen--;
}
- /* need to match beginning of datum for "abc*" and "abc*def" */
- if (memcmp(pattern, datum, n) != 0)
- goto no;
+ /* We now have a remnant part of the pattern bounded by a pair of
+ * wildcards (e.g.: [aa**]bb*cc*dd[**ee]) and we need to find the
+ * middle substrings in order in the remnant part of the datum. The
+ * remnant pattern fragment may also contain further wildcards.
+ */
+ for (;;) {
+ mdebug("middle", pattern, plen, datum, dlen);
+ const char *sub = pattern, *p;
+ int slen, skip;
+
+ left = memchr(pattern, '*', plen);
+ if (!left) {
+ /* No further wildcard */
+ mdebug2("middle-1");
+ if (plen > dlen)
+ goto no;
+ p = memmem(datum, dlen, pattern, plen);
+ if (!p) {
+ mdebug2("middle-1-x");
+ goto no;
+ }
+ wild += dlen - plen;
+ goto yes;
+ }
- if (!asterisk[1])
- goto yes_wildcard; /* "abc*" matches */
+ slen = left - pattern;
+ pattern = left + 1;
+ plen -= slen + 1;
- /* match the end of the datum */
- asterisk++;
- n = plen - n - 1;
- if (memcmp(pattern, datum + (dlen - n), n) == 0)
- goto yes_wildcard;
+ p = memmem(datum, dlen, sub, slen);
+ if (!p) {
+ mdebug2("middle-x");
+ goto no;
+ }
+ skip = p - datum;
+ wild += skip;
+ datum += skip + slen;
+ dlen -= skip + slen;
+
+ while (plen && *pattern == '*') {
+ pattern++;
+ plen--;
+ }
-no:
- if (verbosity >= 2)
- debug(" = no\n");
- return 0;
+ /* plen really shouldn't be 0 here. */
+ if (plen <= 0) {
+ error("plen unexpectedly 0\n");
+ goto no;
+ }
+ }
yes:
if (verbosity >= 2)
- debug(" = yes (w=0)\n");
- return 1;
-
-yes_wildcard:
- *_wildness += dlen - (plen - 1);
+ debug(" = yes (w=%u)\n", wild);
+ return wild;
+no:
if (verbosity >= 2)
- debug(" = yes (w=%u)\n", dlen - (plen - 1));
- return 1;
+ debug(" = no\n");
+ return -1;
} /* end match() */
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 7/7] request-key: Support the promised multiwildcard matching
2025-08-22 14:22 ` [PATCH 7/7] request-key: Support the promised multiwildcard matching David Howells
@ 2025-08-24 0:05 ` Jarkko Sakkinen
0 siblings, 0 replies; 13+ messages in thread
From: Jarkko Sakkinen @ 2025-08-24 0:05 UTC (permalink / raw)
To: David Howells; +Cc: keyrings, linux-kernel
On Fri, Aug 22, 2025 at 03:22:14PM +0100, David Howells wrote:
> The manual page for request-key.conf says that multiple wildcards can be
> used in match elements in the config files, so implement this feature.
>
> Also add a flag, "--test-match", to allow that match function to be tested
> directly, e.g.:
>
> request-key --test-match "**a*a***i**a**a**" antidisestablishmentarianism
>
> Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
BR, Jarkko
^ permalink raw reply [flat|nested] 13+ messages in thread