* [LTP] [PATCH 01/33] lapi/keyctl.h: Add fallback definitions for extended ops
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 02/33] keyctl10: Test KEYCTL_DESCRIBE format parsing Andrea Cervesato
` (31 subsequent siblings)
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Add fallback definitions for KEYCTL_LINK, KEYCTL_RESTRICT_KEYRING,
KEYCTL_MOVE, and KEYCTL_MOVE_EXCL, as well as fallback definitions
for struct keyctl_dh_params and struct keyctl_kdf_params when built
without keyutils.h or linux/keyctl.h.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
include/lapi/keyctl.h | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/include/lapi/keyctl.h b/include/lapi/keyctl.h
index 83fa09303..a056ddaad 100644
--- a/include/lapi/keyctl.h
+++ b/include/lapi/keyctl.h
@@ -20,6 +20,21 @@
# include "lapi/syscalls.h"
typedef int32_t key_serial_t;
+#if !defined(HAVE_KEYUTILS_H) && !defined(HAVE_LINUX_KEYCTL_H)
+struct keyctl_dh_params {
+ int32_t priv;
+ int32_t prime;
+ int32_t base;
+};
+
+struct keyctl_kdf_params {
+ char *hashname;
+ char *otherinfo;
+ uint32_t otherinfolen;
+ uint32_t __spare[8];
+};
+#endif
+
static inline key_serial_t add_key(const char *type,
const char *description,
const void *payload,
@@ -124,6 +139,10 @@ static inline key_serial_t keyctl_join_session_keyring(const char *name) {
# define KEYCTL_CLEAR 7
#endif
+#ifndef KEYCTL_LINK
+# define KEYCTL_LINK 8
+#endif
+
#ifndef KEYCTL_UNLINK
# define KEYCTL_UNLINK 9
#endif
@@ -168,6 +187,18 @@ static inline key_serial_t keyctl_join_session_keyring(const char *name) {
# define KEYCTL_WATCH_KEY 32
#endif
+#ifndef KEYCTL_RESTRICT_KEYRING
+# define KEYCTL_RESTRICT_KEYRING 29
+#endif
+
+#ifndef KEYCTL_MOVE
+# define KEYCTL_MOVE 30
+#endif
+
+#ifndef KEYCTL_MOVE_EXCL
+# define KEYCTL_MOVE_EXCL 0x00000001 /* do not displace from the to-keyring */
+#endif
+
/* key permissions */
#ifndef KEY_POS_VIEW
# define KEY_POS_VIEW 0x01000000
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 02/33] keyctl10: Test KEYCTL_DESCRIBE format parsing
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 01/33] lapi/keyctl.h: Add fallback definitions for extended ops Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 14:07 ` [LTP] lapi/keyctl.h: Add fallback definitions for extended ops linuxtestproject.agent
2026-09-02 11:04 ` [LTP] [PATCH 03/33] keyctl11: Test KEYCTL_DESCRIBE with exact buffer size Andrea Cervesato
` (30 subsequent siblings)
32 siblings, 1 reply; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Test the format parsing of KEYCTL_DESCRIBE: verify that describing
a valid key returns a string formatted as "type;uid;gid;perm;description"
and that all five fields match the key's attributes.
Also add keyctl_common.h helper header for shared test definitions.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl10.c | 99 ++++++++++++++++++++++++
testcases/kernel/syscalls/keyctl/keyctl_common.h | 53 +++++++++++++
4 files changed, 154 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index 737c63e31..bf4c0d46e 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -727,6 +727,7 @@ keyctl06 keyctl06
keyctl07 keyctl07
keyctl08 keyctl08
keyctl09 keyctl09
+keyctl10 keyctl10
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index f9948c176..08b2d101d 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -7,3 +7,4 @@
/keyctl07
/keyctl08
/keyctl09
+/keyctl10
diff --git a/testcases/kernel/syscalls/keyctl/keyctl10.c b/testcases/kernel/syscalls/keyctl/keyctl10.c
new file mode 100644
index 000000000..105daa63d
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl10.c
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Test the format parsing of ``KEYCTL_DESCRIBE`` of :manpage:`keyctl(2)`.
+ *
+ * ``KEYCTL_DESCRIBE`` formats a key description as
+ * "type;uid;gid;perm;description" and returns the full length of the
+ * string including the terminating NUL byte.
+ *
+ * [Algorithm]
+ *
+ * - describe a valid key and verify all five fields of the description
+ * match the key's attributes
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include "keyctl_common.h"
+
+#define KEY_DESC "ltpkeyctl10"
+#define PAYLOAD "payload"
+#define BUF_SIZE 64
+
+static key_serial_t key;
+static long desc_len;
+static char buf[BUF_SIZE];
+
+static void setup(void)
+{
+ SAFE_KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
+
+ key = new_user_key(KEY_DESC, PAYLOAD, sizeof(PAYLOAD),
+ KEY_SPEC_PROCESS_KEYRING);
+ SAFE_KEYCTL(KEYCTL_SETPERM, key, KEY_PERM_SET, 0, 0);
+
+ TEST(keyctl(KEYCTL_DESCRIBE, key, (unsigned long)NULL, 0, 0));
+ if (TST_RET < 0)
+ tst_brk(TBROK | TTERRNO, "KEYCTL_DESCRIBE failed");
+
+ desc_len = TST_RET;
+}
+
+static void run(void)
+{
+ char type[32], desc[BUF_SIZE];
+ unsigned int uid, gid, perm;
+
+ memset(buf, 0, sizeof(buf));
+ TST_EXP_EQ_LI_SILENT(keyctl(KEYCTL_DESCRIBE, key, (unsigned long)buf,
+ sizeof(buf), 0), desc_len);
+ if (!TST_PASS)
+ return;
+
+ TST_EXP_EQ_SZ_SILENT((size_t)desc_len, strlen(buf) + 1);
+ if (!TST_PASS) {
+ tst_res(TINFO, "unexpected description '%s'", buf);
+ return;
+ }
+
+ if (sscanf(buf, "%31[^;];%u;%u;%x;%63[^\n]",
+ type, &uid, &gid, &perm, desc) != 5) {
+ tst_res(TFAIL, "malformed description '%s'", buf);
+ return;
+ }
+
+ if (strcmp(type, "user")) {
+ tst_res(TFAIL, "wrong key type '%s', expected 'user'", type);
+ return;
+ }
+
+ if (uid != getuid() || gid != getgid()) {
+ tst_res(TFAIL, "wrong owner uid %u gid %u, expected %u %u",
+ uid, gid, getuid(), getgid());
+ return;
+ }
+
+ if (perm != KEY_PERM_SET) {
+ tst_res(TFAIL, "wrong permissions %08x, expected %08x",
+ perm, KEY_PERM_SET);
+ return;
+ }
+
+ if (strcmp(desc, KEY_DESC)) {
+ tst_res(TFAIL, "wrong description '%s', expected '%s'",
+ desc, KEY_DESC);
+ return;
+ }
+
+ tst_res(TPASS, "described the key correctly");
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test_all = run,
+};
diff --git a/testcases/kernel/syscalls/keyctl/keyctl_common.h b/testcases/kernel/syscalls/keyctl/keyctl_common.h
new file mode 100644
index 000000000..c7290cc6e
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl_common.h
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+#ifndef KEYCTL_COMMON_H__
+#define KEYCTL_COMMON_H__
+
+#include <stdint.h>
+#include <string.h>
+
+#include "tst_test.h"
+#include "lapi/keyctl.h"
+
+#define KEY_PERM_ALL (KEY_POS_ALL | KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL)
+#define KEY_PERM_SET (KEY_POS_ALL | KEY_USR_ALL)
+
+#define KEY_VIEW_BITS (KEY_POS_VIEW | KEY_USR_VIEW | KEY_GRP_VIEW | KEY_OTH_VIEW)
+#define KEY_PERM_NO_VIEW (KEY_PERM_ALL & ~KEY_VIEW_BITS)
+
+#define KEY_WRITE_BITS (KEY_POS_WRITE | KEY_USR_WRITE | KEY_GRP_WRITE | KEY_OTH_WRITE)
+#define KEY_PERM_NO_WRITE (KEY_PERM_ALL & ~KEY_WRITE_BITS)
+
+#define KEY_SETATTR_BITS (KEY_POS_SETATTR | KEY_USR_SETATTR | KEY_GRP_SETATTR | KEY_OTH_SETATTR)
+#define KEY_PERM_NO_SETATTR (KEY_PERM_ALL & ~KEY_SETATTR_BITS)
+
+static inline key_serial_t new_ring(const char *desc)
+{
+ TEST(add_key("keyring", desc, NULL, 0, KEY_SPEC_PROCESS_KEYRING));
+ if (TST_RET < 0)
+ tst_brk(TBROK | TTERRNO, "failed to create keyring '%s'", desc);
+
+ return TST_RET;
+}
+
+static inline key_serial_t new_user_key(const char *desc, const void *payload,
+ size_t plen, key_serial_t ring)
+{
+ TEST(add_key("user", desc, payload, plen, ring));
+ if (TST_RET < 0)
+ tst_brk(TBROK | TTERRNO, "failed to add user key '%s'", desc);
+
+ return TST_RET;
+}
+
+static inline key_serial_t search_ring(key_serial_t ring, const char *type,
+ const char *desc)
+{
+ return keyctl(KEYCTL_SEARCH, ring, (unsigned long)type,
+ (unsigned long)desc, 0);
+}
+
+#endif /* KEYCTL_COMMON_H__ */
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* Re: [LTP] lapi/keyctl.h: Add fallback definitions for extended ops
2026-09-02 11:04 ` [LTP] [PATCH 02/33] keyctl10: Test KEYCTL_DESCRIBE format parsing Andrea Cervesato
@ 2026-09-02 14:07 ` linuxtestproject.agent
0 siblings, 0 replies; 35+ messages in thread
From: linuxtestproject.agent @ 2026-09-02 14:07 UTC (permalink / raw)
To: Andrea Cervesato; +Cc: ltp
Hi Andrea,
On Wed, 02 Sep 2026 13:04:16 +0200, Andrea Cervesato wrote:
> lapi/keyctl.h: Add fallback definitions for extended ops
--- [PATCH 1/33] ---
> +#if !defined(HAVE_KEYUTILS_H) && !defined(HAVE_LINUX_KEYCTL_H)
> +struct keyctl_dh_params {
This block sits in the #else branch of
"defined(HAVE_KEYUTILS_H) && defined(HAVE_LIBKEYUTILS)", so <keyutils.h>
is never included on this path and only <linux/keyctl.h> can declare the
structs. With keyutils.h present (HAVE_KEYUTILS_H, configure.ac:59) but
libkeyutils not linkable (m4/ltp-keyutils.m4) and linux/keyctl.h absent,
the guard is false and nothing declares keyctl_dh_params /
keyctl_kdf_params, breaking keyctl25..keyctl28. Use
"#ifndef HAVE_LINUX_KEYCTL_H". The same guard is reused for
keyctl_pkey_query / keyctl_pkey_params in patch 21/33.
> +#ifndef KEYCTL_RESTRICT_KEYRING
> +# define KEYCTL_RESTRICT_KEYRING 29
> +#endif
Commands 29 and 30 are appended after KEYCTL_WATCH_KEY (32), and patches
21/33 and 27/33 then insert 24..28 and 31 after those. The rest of the
list is in ascending command order.
--- [PATCH 2/33] ---
> + TEST(keyctl(KEYCTL_DESCRIBE, key, (unsigned long)NULL, 0, 0));
> + if (TST_RET < 0)
> + tst_brk(TBROK | TTERRNO, "KEYCTL_DESCRIBE failed");
> +
> + desc_len = TST_RET;
safe_keyctl() already treats a negative KEYCTL_DESCRIBE return as a
failure, and the previous line in the same function uses SAFE_KEYCTL().
This is a setup precondition, not the tested call, so the "subject
syscall" exception does not apply:
desc_len = SAFE_KEYCTL(KEYCTL_DESCRIBE, key, 0, 0, 0);
Same in keyctl11, keyctl12, keyctl16, keyctl34, keyctl35 and keyctl36.
> + if (strcmp(type, "user")) {
> + tst_res(TFAIL, "wrong key type '%s', expected 'user'", type);
> + return;
> + }
Use TST_EXP_EQ_STR(type, "user") instead of strcmp() + tst_res(). Same
for the strcmp() against KEY_DESC below.
--- [PATCH 3/33] ---
> + memset(buf, 0, desc_len);
> + TST_EXP_EQ_LI_SILENT(keyctl(KEYCTL_DESCRIBE, key, (unsigned long)buf,
> + desc_len, 0), desc_len);
> + if (!TST_PASS)
> + return;
> +
> + if (buf[desc_len - 1] != '\0') {
> + tst_res(TFAIL, "description is not NUL terminated");
buf is zeroed immediately before the call, so buf[desc_len - 1] is
already '\0' and this check cannot fail even if the kernel copied
nothing. Nothing verifies the content either. Poison the buffer
(memset(buf, 'x', desc_len)) and assert
strlen(buf) + 1 == (size_t)desc_len, as keyctl12 already does with 0xAA.
> + TST_EXP_EQ_LI_SILENT(keyctl(KEYCTL_DESCRIBE, key, (unsigned long)buf,
> + desc_len, 0), desc_len);
TST_EXP_EQ_*() compare two plain values and do not go through TEST(), so
errno is lost on failure. For syscall return values use
TST_EXP_VAL()/TST_EXP_VAL_SILENT(), or TST_EXP_PASS()/
TST_EXP_PASS_SILENT() when 0 is expected. Recurs in keyctl12, keyctl16,
keyctl18, keyctl19, keyctl20, keyctl25, keyctl27 and keyctl29..keyctl36.
--- [PATCH 7/33] ---
> + memset(buf, 0, sizeof(buf));
> +
> + TEST(keyctl(KEYCTL_GET_SECURITY, key, (unsigned long)buf, sizeof(buf), 0));
...
> + if (TST_RET == 1) {
> + if (buf[0] != '\0') {
> + tst_res(TFAIL, "empty label is not NUL terminated");
...
> + tst_res(TPASS, "security label returned, full length %ld", TST_RET);
Same tautology as keyctl11: buf is zeroed first, so buf[0] == '\0'
always holds. The TST_RET > 1 branch reports TPASS without inspecting
buf at all. Poison buf and assert strlen(buf) + 1 == (size_t)TST_RET
whenever TST_RET <= sizeof(buf); that covers both branches.
--- [PATCH 14/33] ---
> + TEST(keyctl(KEYCTL_RESTRICT_KEYRING, ring_reject, 0, 0, 0));
> + if (TST_RET == 0)
> + tst_res(TPASS, "KEYCTL_RESTRICT_KEYRING with NULL type and restriction passed");
> + else if (TST_RET == -1 && TST_ERR == EEXIST)
> + tst_res(TPASS, "KEYCTL_RESTRICT_KEYRING reject-all already active");
Restricting a keyring is one-shot (keyring_restrict() returns -EEXIST
once restrict_link is set), so this branch only exists to survive -i N,
but it also accepts EEXIST on the first iteration where the keyring has
never been restricted. Move the restriction into setup(), which the
framework calls once, and keep run() to the EPERM assertions. Same
pattern in keyctl23.
--- [PATCH 15/33] ---
> + TST_EXP_FAIL(keyctl(KEYCTL_LINK, user_key, ring_builtin, 0, 0),
> + EOPNOTSUPP,
> + "KEYCTL_LINK of non-asymmetric key on builtin_trusted restricted keyring");
> +
> + TST_EXP_FAIL2(add_key("asymmetric", "cert", untrusted_cert,
> + sizeof(untrusted_cert), ring_builtin), ENOKEY,
EOPNOTSUPP and ENOKEY come from restrict_link_by_signature(), which is
only reachable with CONFIG_SYSTEM_TRUSTED_KEYRING=y. Without it,
include/keys/system_keyring.h does
"#define restrict_link_by_builtin_trusted restrict_link_reject", both
calls return EPERM and the test reports two TFAILs instead of skipping.
The restriction still installs in that configuration, so the existing
EOPNOTSUPP TCONF branch never fires. Add:
.needs_kconfigs = (const char *[]) {
"CONFIG_SYSTEM_TRUSTED_KEYRING=y",
NULL
},
Note certs/Kconfig makes SYSTEM_TRUSTED_KEYRING depend on
X509_CERTIFICATE_PARSER=y, so whenever modprobe actually loads
x509_key_parser as a module the option is off and the test always fails.
> + TEST(keyctl(KEYCTL_RESTRICT_KEYRING, ring_builtin,
> + (unsigned long)"asymmetric", (unsigned long)"bogus", 0));
> + asym_supported = (TST_RET != -1 || TST_ERR != ENODEV);
KEYCTL_RESTRICT_KEYRING resolves the type through keyring_restrict() ->
key_type_lookup(), which returns ENOKEY for an unregistered type; ENODEV
is what add_key() returns (security/keys/key.c:830), as
add_asymmetric_key_or_tconf() correctly assumes in patch 22/33. With a
registered type the probe gets EINVAL from "bogus", so asym_supported is
always 1 and the TCONF branch is dead code. Compare against ENOKEY.
--- [PATCH 16/33] ---
> + asym_supported = (TST_RET != -1 || TST_ERR != ENODEV);
Same wrong errno as keyctl23. Here the dead TCONF branch also turns two
tcases into spurious TFAILs on a kernel without CONFIG_ASYMMETRIC_KEY_TYPE:
"asymmetric with invalid restriction string" expects EINVAL and
"self-referencing key_or_keyring chain" expects EDEADLK, but both receive
ENOKEY.
> + keyctl(KEYCTL_UNLINK, probe_ring, KEY_SPEC_PROCESS_KEYRING, 0, 0);
These housekeeping unlinks are not the tested call and must succeed. Use
SAFE_KEYCTL(); as written a failure is silently discarded. Same for the
fresh_ring unlink in verify_negative().
--- [PATCH 17/33] ---
> +/* RFC 7919 2048-bit FFDHE Group parameters (ffdhe2048) */
> +static const unsigned char dh_prime[] = {
> + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc9, 0x0f, 0xda, 0xa2, 0x21, 0x68, 0xc2, 0x34,
This prime is the RFC 3526 2048-bit MODP group (Group 14 / modp2048),
not RFC 7919 ffdhe2048 - ffdhe2048 continues 0xad 0xf8 0x54 0x58 after
the leading 0xff bytes. The commit message repeats the claim. The vector
itself is correct: pow(dh_base, dh_priv, dh_prime) reproduces
dh_expected_secret byte for byte. The header is reused by
keyctl26..keyctl28, so fix the comment and the commit message.
--- [PATCH 28/33] ---
> + TEST(keyctl(KEYCTL_CAPABILITIES, (unsigned long)caps, sizeof(caps), 0, 0));
> + if (TST_RET < 0)
> + tst_brk(TBROK | TTERRNO, "KEYCTL_CAPABILITIES failed");
Patch 27/33 adds "case KEYCTL_CAPABILITIES" to safe_keyctl(), and patch
21/33 adds the five KEYCTL_PKEY_* cases, but no test in the series ever
calls SAFE_KEYCTL() with any of them. Either use SAFE_KEYCTL() here and
in keyctl35/keyctl36, or drop the unused cases.
--- [PATCH 32/33] ---
> + .ulimit = (const struct tst_ulimit_val []) {
> + {RLIMIT_NOFILE, 524288},
> + {}
> + },
set_ulimit_() (lib/tst_test.c:1330) raises rlim_max when rlim_cur exceeds
it, which needs CAP_SYS_RESOURCE, and safe_setrlimit() aborts with
TBROK | TERRNO on failure. The test does not set .needs_root, so on any
host whose hard RLIMIT_NOFILE is below 524288 an unprivileged run ends in
TBROK before a single assertion runs - reproduced here with a hard limit
of 65536, where the same getrlimit/setrlimit sequence returns EPERM. The
test holds one watch at a time, so the default soft limit already
suffices; keyctl39 exercises the same code with no .ulimit at all.
> + TST_EXP_PASS(keyctl(KEYCTL_WATCH_KEY, key, pipefd[0], 1),
> + "KEYCTL_WATCH_KEY add watch on key");
The keyctl() helper in lapi/keyctl.h unconditionally reads four variadic
arguments (arg2..arg5); only three are passed here, which is undefined
behaviour. Append an explicit 0, as every other call site in this series
does. Same in keyctl39.
> + TEST(pipe2(pipefd, O_NOTIFICATION_PIPE));
> + if (TST_RET < 0) {
> + if (TST_ERR == ENOPKG)
> + tst_brk(TCONF | TTERRNO, "CONFIG_WATCH_QUEUE is not set");
This block plus the IOC_WATCH_QUEUE_SET_SIZE call duplicates
wqueue_watch() in testcases/kernel/watchqueue/common.h:100-116.
Verdict - Needs revision
Pre-existing issues:
include/lapi/keyctl.h already fails checkpatch on master with one ERROR
("open brace '{' following function definitions go on the next line",
keyctl_join_session_keyring()) and two CHECKs (multiple blank lines,
missing blank line after a declaration).
---
Note:
The agent can sometimes produce false positives although often its
findings are genuine. If you find issues with the review, please
comment this email or ignore the suggestions.
Regards,
LTP AI Reviewer
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 35+ messages in thread
* [LTP] [PATCH 03/33] keyctl11: Test KEYCTL_DESCRIBE with exact buffer size
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 01/33] lapi/keyctl.h: Add fallback definitions for extended ops Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 02/33] keyctl10: Test KEYCTL_DESCRIBE format parsing Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 04/33] keyctl12: Test KEYCTL_DESCRIBE with too small buffer Andrea Cervesato
` (29 subsequent siblings)
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Test KEYCTL_DESCRIBE when called with a buffer sized exactly to the
full description length: verify the string is copied completely
including the terminating NUL byte.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl11.c | 62 +++++++++++++++++++++++++++++
3 files changed, 64 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index bf4c0d46e..7c9042471 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -728,6 +728,7 @@ keyctl07 keyctl07
keyctl08 keyctl08
keyctl09 keyctl09
keyctl10 keyctl10
+keyctl11 keyctl11
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index 08b2d101d..4974fe48d 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -8,3 +8,4 @@
/keyctl08
/keyctl09
/keyctl10
+/keyctl11
diff --git a/testcases/kernel/syscalls/keyctl/keyctl11.c b/testcases/kernel/syscalls/keyctl/keyctl11.c
new file mode 100644
index 000000000..4dd0be7ca
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl11.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Test ``KEYCTL_DESCRIBE`` of :manpage:`keyctl(2)` with exact buffer size.
+ *
+ * [Algorithm]
+ *
+ * - describe a key into a buffer sized exactly to the full string length,
+ * verify full string copy including terminating NUL byte
+ */
+
+#include "keyctl_common.h"
+
+static key_serial_t key;
+static long desc_len;
+static char *buf;
+
+static void setup(void)
+{
+ SAFE_KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
+
+ key = new_user_key("k", "payload", 7, KEY_SPEC_PROCESS_KEYRING);
+ SAFE_KEYCTL(KEYCTL_SETPERM, key, KEY_PERM_SET, 0, 0);
+
+ TEST(keyctl(KEYCTL_DESCRIBE, key, (unsigned long)NULL, 0, 0));
+ if (TST_RET < 0)
+ tst_brk(TBROK | TTERRNO, "KEYCTL_DESCRIBE failed");
+
+ desc_len = TST_RET;
+ buf = SAFE_MALLOC(desc_len);
+}
+
+static void cleanup(void)
+{
+ free(buf);
+}
+
+static void run(void)
+{
+ memset(buf, 0, desc_len);
+ TST_EXP_EQ_LI_SILENT(keyctl(KEYCTL_DESCRIBE, key, (unsigned long)buf,
+ desc_len, 0), desc_len);
+ if (!TST_PASS)
+ return;
+
+ if (buf[desc_len - 1] != '\0') {
+ tst_res(TFAIL, "description is not NUL terminated");
+ return;
+ }
+
+ tst_res(TPASS, "full description including NUL fits exact %ld byte buffer",
+ desc_len);
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = run,
+};
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 04/33] keyctl12: Test KEYCTL_DESCRIBE with too small buffer
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (2 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 03/33] keyctl11: Test KEYCTL_DESCRIBE with exact buffer size Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 05/33] keyctl13: Test KEYCTL_DESCRIBE size query Andrea Cervesato
` (28 subsequent siblings)
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Test KEYCTL_DESCRIBE when called with a buffer smaller than the
full description length: verify the buffer is left untouched and the
return value still reports the full length.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl12.c | 62 +++++++++++++++++++++++++++++
3 files changed, 64 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index 7c9042471..d8e846e65 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -729,6 +729,7 @@ keyctl08 keyctl08
keyctl09 keyctl09
keyctl10 keyctl10
keyctl11 keyctl11
+keyctl12 keyctl12
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index 4974fe48d..9ce6e2250 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -9,3 +9,4 @@
/keyctl09
/keyctl10
/keyctl11
+/keyctl12
diff --git a/testcases/kernel/syscalls/keyctl/keyctl12.c b/testcases/kernel/syscalls/keyctl/keyctl12.c
new file mode 100644
index 000000000..b135fbe49
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl12.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Test ``KEYCTL_DESCRIBE`` of :manpage:`keyctl(2)` with too small buffer.
+ *
+ * [Algorithm]
+ *
+ * - describe a key with buffer smaller than full length, verify the buffer
+ * remains untouched and the return value is unchanged
+ */
+
+#include "keyctl_common.h"
+
+#define BUF_SIZE 64
+
+static key_serial_t key;
+static long desc_len;
+static char buf[BUF_SIZE];
+
+static void setup(void)
+{
+ SAFE_KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
+
+ key = new_user_key("k", "payload", 7, KEY_SPEC_PROCESS_KEYRING);
+ SAFE_KEYCTL(KEYCTL_SETPERM, key, KEY_PERM_SET, 0, 0);
+
+ TEST(keyctl(KEYCTL_DESCRIBE, key, (unsigned long)NULL, 0, 0));
+ if (TST_RET < 0)
+ tst_brk(TBROK | TTERRNO, "KEYCTL_DESCRIBE failed");
+
+ desc_len = TST_RET;
+}
+
+static void run(void)
+{
+ size_t i;
+
+ memset(buf, 0xAA, sizeof(buf));
+ TST_EXP_EQ_LI_SILENT(keyctl(KEYCTL_DESCRIBE, key, (unsigned long)buf,
+ desc_len - 1, 0), desc_len);
+ if (!TST_PASS)
+ return;
+
+ for (i = 0; i < sizeof(buf); i++) {
+ if (buf[i] != (char)0xAA) {
+ tst_res(TFAIL,
+ "too small buffer was written to at offset %zu",
+ i);
+ return;
+ }
+ }
+
+ tst_res(TPASS, "too small buffer was left untouched");
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test_all = run,
+};
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 05/33] keyctl13: Test KEYCTL_DESCRIBE size query
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (3 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 04/33] keyctl12: Test KEYCTL_DESCRIBE with too small buffer Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 06/33] keyctl14: Negative tests for KEYCTL_DESCRIBE Andrea Cervesato
` (27 subsequent siblings)
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Test KEYCTL_DESCRIBE when called with a NULL buffer and buflen 0:
verify the call succeeds and returns the full description length
without writing to userspace memory.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl13.c | 46 +++++++++++++++++++++++++++++
3 files changed, 48 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index d8e846e65..25367084d 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -730,6 +730,7 @@ keyctl09 keyctl09
keyctl10 keyctl10
keyctl11 keyctl11
keyctl12 keyctl12
+keyctl13 keyctl13
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index 9ce6e2250..d4ce61a6e 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -10,3 +10,4 @@
/keyctl10
/keyctl11
/keyctl12
+/keyctl13
diff --git a/testcases/kernel/syscalls/keyctl/keyctl13.c b/testcases/kernel/syscalls/keyctl/keyctl13.c
new file mode 100644
index 000000000..ebdb3cf32
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl13.c
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Test ``KEYCTL_DESCRIBE`` of :manpage:`keyctl(2)` with NULL buffer and buflen 0.
+ *
+ * [Algorithm]
+ *
+ * - describe a key with NULL buffer and ``buflen = 0``, verify the full length
+ * is returned without writing
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include "keyctl_common.h"
+
+static key_serial_t key;
+
+static void setup(void)
+{
+ SAFE_KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
+
+ key = new_user_key("k", "payload", 7, KEY_SPEC_PROCESS_KEYRING);
+ SAFE_KEYCTL(KEYCTL_SETPERM, key, KEY_PERM_SET, 0, 0);
+}
+
+static void run(void)
+{
+ char expected[64];
+ long expected_len;
+
+ expected_len = snprintf(expected, sizeof(expected),
+ "user;%u;%u;%08x;k",
+ getuid(), getgid(), KEY_PERM_SET) + 1;
+
+ TST_EXP_VAL(keyctl(KEYCTL_DESCRIBE, key, (unsigned long)NULL, 0, 0),
+ expected_len);
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test_all = run,
+};
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 06/33] keyctl14: Negative tests for KEYCTL_DESCRIBE
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (4 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 05/33] keyctl13: Test KEYCTL_DESCRIBE size query Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 07/33] keyctl15: Test KEYCTL_GET_SECURITY label retrieval Andrea Cervesato
` (26 subsequent siblings)
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Test error conditions of KEYCTL_DESCRIBE using a parameterized
tcase table: verify ENOKEY on a bogus key id and EACCES when View
permission is missing.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl14.c | 54 +++++++++++++++++++++++++++++
3 files changed, 56 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index 25367084d..160d2f798 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -731,6 +731,7 @@ keyctl10 keyctl10
keyctl11 keyctl11
keyctl12 keyctl12
keyctl13 keyctl13
+keyctl14 keyctl14
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index d4ce61a6e..8120454d8 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -11,3 +11,4 @@
/keyctl11
/keyctl12
/keyctl13
+/keyctl14
diff --git a/testcases/kernel/syscalls/keyctl/keyctl14.c b/testcases/kernel/syscalls/keyctl/keyctl14.c
new file mode 100644
index 000000000..e98dde40f
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl14.c
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Negative test cases for ``KEYCTL_DESCRIBE`` of :manpage:`keyctl(2)`.
+ *
+ * [Algorithm]
+ *
+ * - describe with bogus key id fails with ``ENOKEY``
+ * - describe without View permission fails with ``EACCES``
+ */
+
+#include "keyctl_common.h"
+
+#define BUF_SIZE 64
+
+static key_serial_t key_no_view;
+static key_serial_t bogus_id = INT32_MAX;
+static char buf[BUF_SIZE];
+
+static struct tcase {
+ key_serial_t *keyid;
+ int exp_errno;
+ const char *desc;
+} tcases[] = {
+ { &bogus_id, ENOKEY, "bogus key id" },
+ { &key_no_view, EACCES, "key without View permission" },
+};
+
+static void setup(void)
+{
+ SAFE_KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
+
+ key_no_view = new_user_key("k_no_view", "payload", 7, KEY_SPEC_PROCESS_KEYRING);
+ SAFE_KEYCTL(KEYCTL_SETPERM, key_no_view, KEY_PERM_NO_VIEW, 0, 0);
+}
+
+static void verify_negative(unsigned int n)
+{
+ struct tcase *tc = &tcases[n];
+
+ TST_EXP_FAIL2(keyctl(KEYCTL_DESCRIBE, (unsigned long)*tc->keyid,
+ (unsigned long)buf, sizeof(buf), 0),
+ tc->exp_errno,
+ "KEYCTL_DESCRIBE with %s", tc->desc);
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test = verify_negative,
+ .tcnt = ARRAY_SIZE(tcases),
+};
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 07/33] keyctl15: Test KEYCTL_GET_SECURITY label retrieval
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (5 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 06/33] keyctl14: Negative tests for KEYCTL_DESCRIBE Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 08/33] keyctl16: Test KEYCTL_GET_SECURITY truncated copy Andrea Cervesato
` (25 subsequent siblings)
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Test KEYCTL_GET_SECURITY label retrieval: verify reading the security
label of a valid key into a large buffer returns a positive length
and an empty string when no LSM label is set.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl15.c | 66 +++++++++++++++++++++++++++++
3 files changed, 68 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index 160d2f798..da901baae 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -732,6 +732,7 @@ keyctl11 keyctl11
keyctl12 keyctl12
keyctl13 keyctl13
keyctl14 keyctl14
+keyctl15 keyctl15
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index 8120454d8..852fee4ea 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -12,3 +12,4 @@
/keyctl12
/keyctl13
/keyctl14
+/keyctl15
diff --git a/testcases/kernel/syscalls/keyctl/keyctl15.c b/testcases/kernel/syscalls/keyctl/keyctl15.c
new file mode 100644
index 000000000..c281e9c69
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl15.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Test ``KEYCTL_GET_SECURITY`` label retrieval of :manpage:`keyctl(2)`.
+ *
+ * ``KEYCTL_GET_SECURITY`` reads the LSM security label of a key.
+ * When no label is set (no LSM enabled or the LSM does not label keys)
+ * the operation returns 1 and an empty string.
+ *
+ * [Algorithm]
+ *
+ * - read the label of a valid key into a large buffer, verify the return
+ * value is at least 1 and an empty string is returned when no label is set
+ */
+
+#include "keyctl_common.h"
+
+#define KEY_DESC "ltpkeyctl15"
+#define PAYLOAD "payload"
+#define BUF_SIZE 128
+
+static key_serial_t key;
+static char buf[BUF_SIZE];
+
+static void setup(void)
+{
+ SAFE_KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
+
+ key = new_user_key(KEY_DESC, PAYLOAD, sizeof(PAYLOAD),
+ KEY_SPEC_PROCESS_KEYRING);
+ SAFE_KEYCTL(KEYCTL_SETPERM, key, KEY_PERM_SET, 0, 0);
+}
+
+static void run(void)
+{
+ memset(buf, 0, sizeof(buf));
+
+ TEST(keyctl(KEYCTL_GET_SECURITY, key, (unsigned long)buf, sizeof(buf), 0));
+ if (TST_RET < 0)
+ tst_brk(TBROK | TTERRNO, "KEYCTL_GET_SECURITY failed");
+
+ if (TST_RET < 1) {
+ tst_res(TFAIL, "returned %ld, expected at least 1", TST_RET);
+ return;
+ }
+
+ if (TST_RET == 1) {
+ if (buf[0] != '\0') {
+ tst_res(TFAIL, "empty label is not NUL terminated");
+ return;
+ }
+
+ tst_res(TPASS, "no label set, empty string returned");
+ return;
+ }
+
+ tst_res(TPASS, "security label returned, full length %ld", TST_RET);
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test_all = run,
+};
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 08/33] keyctl16: Test KEYCTL_GET_SECURITY truncated copy
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (6 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 07/33] keyctl15: Test KEYCTL_GET_SECURITY label retrieval Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 09/33] keyctl17: Negative tests for KEYCTL_GET_SECURITY Andrea Cervesato
` (24 subsequent siblings)
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Test KEYCTL_GET_SECURITY truncated copy behavior: verify that calling
with a 1-byte buffer receives exactly one byte while the return value
still reports the full label length.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl16.c | 74 +++++++++++++++++++++++++++++
3 files changed, 76 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index da901baae..89c8a95af 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -733,6 +733,7 @@ keyctl12 keyctl12
keyctl13 keyctl13
keyctl14 keyctl14
keyctl15 keyctl15
+keyctl16 keyctl16
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index 852fee4ea..c351716d0 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -13,3 +13,4 @@
/keyctl13
/keyctl14
/keyctl15
+/keyctl16
diff --git a/testcases/kernel/syscalls/keyctl/keyctl16.c b/testcases/kernel/syscalls/keyctl/keyctl16.c
new file mode 100644
index 000000000..f5662e326
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl16.c
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Test ``KEYCTL_GET_SECURITY`` truncated copy of :manpage:`keyctl(2)`.
+ *
+ * ``KEYCTL_GET_SECURITY`` returns the full length of the label, but unlike
+ * ``KEYCTL_DESCRIBE`` the kernel performs a truncated copy when the user
+ * buffer is too small.
+ *
+ * [Algorithm]
+ *
+ * - verify a one byte buffer receives exactly one byte while the full
+ * length is still returned
+ */
+
+#include "keyctl_common.h"
+
+#define KEY_DESC "ltpkeyctl16"
+#define PAYLOAD "payload"
+#define BUF_SIZE 128
+
+static key_serial_t key;
+static long sec_len;
+static char buf[BUF_SIZE];
+
+static void setup(void)
+{
+ SAFE_KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
+
+ key = new_user_key(KEY_DESC, PAYLOAD, sizeof(PAYLOAD),
+ KEY_SPEC_PROCESS_KEYRING);
+ SAFE_KEYCTL(KEYCTL_SETPERM, key, KEY_PERM_SET, 0, 0);
+
+ TEST(keyctl(KEYCTL_GET_SECURITY, key, (unsigned long)NULL, 0, 0));
+ if (TST_RET < 0)
+ tst_brk(TBROK | TTERRNO, "KEYCTL_GET_SECURITY failed");
+
+ sec_len = TST_RET;
+}
+
+static void run(void)
+{
+ size_t i;
+
+ memset(buf, 0xAA, sizeof(buf));
+ TST_EXP_EQ_LI_SILENT(keyctl(KEYCTL_GET_SECURITY, key,
+ (unsigned long)buf, 1, 0), sec_len);
+ if (!TST_PASS)
+ return;
+
+ if (buf[0] == (char)0xAA) {
+ tst_res(TFAIL, "nothing was copied into the buffer");
+ return;
+ }
+
+ for (i = 1; i < sizeof(buf); i++) {
+ if (buf[i] != (char)0xAA) {
+ tst_res(TFAIL, "copy overran the buffer at offset %zu",
+ i);
+ return;
+ }
+ }
+
+ tst_res(TPASS, "exactly one byte copied, full length %ld returned",
+ sec_len);
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test_all = run,
+};
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 09/33] keyctl17: Negative tests for KEYCTL_GET_SECURITY
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (7 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 08/33] keyctl16: Test KEYCTL_GET_SECURITY truncated copy Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 10/33] keyctl18: Test basic KEYCTL_MOVE Andrea Cervesato
` (23 subsequent siblings)
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Test error conditions of KEYCTL_GET_SECURITY using a parameterized
tcase table: verify ENOKEY on a bogus key id and ENOKEY when View
permission is missing (due to the kernel request-key auth token
fallback path).
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl17.c | 55 +++++++++++++++++++++++++++++
3 files changed, 57 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index 89c8a95af..fcc1d58a8 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -734,6 +734,7 @@ keyctl13 keyctl13
keyctl14 keyctl14
keyctl15 keyctl15
keyctl16 keyctl16
+keyctl17 keyctl17
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index c351716d0..dddb45f85 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -14,3 +14,4 @@
/keyctl14
/keyctl15
/keyctl16
+/keyctl17
diff --git a/testcases/kernel/syscalls/keyctl/keyctl17.c b/testcases/kernel/syscalls/keyctl/keyctl17.c
new file mode 100644
index 000000000..216152f1d
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl17.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Negative test cases for ``KEYCTL_GET_SECURITY`` of :manpage:`keyctl(2)`.
+ *
+ * [Algorithm]
+ *
+ * - get_security with bogus key id fails with ``ENOKEY``
+ * - get_security without View permission fails with ``ENOKEY`` (the kernel
+ * falls back to looking for an auth token and returns its ``ENOKEY``)
+ */
+
+#include "keyctl_common.h"
+
+#define BUF_SIZE 128
+
+static key_serial_t key_no_view;
+static key_serial_t bogus_id = INT32_MAX;
+static char buf[BUF_SIZE];
+
+static struct tcase {
+ key_serial_t *keyid;
+ int exp_errno;
+ const char *desc;
+} tcases[] = {
+ { &bogus_id, ENOKEY, "bogus key id" },
+ { &key_no_view, ENOKEY, "key without View permission" },
+};
+
+static void setup(void)
+{
+ SAFE_KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
+
+ key_no_view = new_user_key("k_no_view", "payload", 7, KEY_SPEC_PROCESS_KEYRING);
+ SAFE_KEYCTL(KEYCTL_SETPERM, key_no_view, KEY_PERM_NO_VIEW, 0, 0);
+}
+
+static void verify_negative(unsigned int n)
+{
+ struct tcase *tc = &tcases[n];
+
+ TST_EXP_FAIL2(keyctl(KEYCTL_GET_SECURITY, (unsigned long)*tc->keyid,
+ (unsigned long)buf, sizeof(buf), 0),
+ tc->exp_errno,
+ "KEYCTL_GET_SECURITY with %s", tc->desc);
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test = verify_negative,
+ .tcnt = ARRAY_SIZE(tcases),
+};
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 10/33] keyctl18: Test basic KEYCTL_MOVE
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (8 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 09/33] keyctl17: Negative tests for KEYCTL_GET_SECURITY Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 11/33] keyctl19: Test KEYCTL_MOVE with same source and destination Andrea Cervesato
` (22 subsequent siblings)
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Test basic moving of a key between two keyrings with KEYCTL_MOVE:
verify the key is moved to the destination and no longer found in
the source keyring.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl18.c | 60 +++++++++++++++++++++++++++++
3 files changed, 62 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index fcc1d58a8..895dd0fc4 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -735,6 +735,7 @@ keyctl14 keyctl14
keyctl15 keyctl15
keyctl16 keyctl16
keyctl17 keyctl17
+keyctl18 keyctl18
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index dddb45f85..808cd2d23 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -15,3 +15,4 @@
/keyctl15
/keyctl16
/keyctl17
+/keyctl18
diff --git a/testcases/kernel/syscalls/keyctl/keyctl18.c b/testcases/kernel/syscalls/keyctl/keyctl18.c
new file mode 100644
index 000000000..2b87e65d4
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl18.c
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Test basic ``KEYCTL_MOVE`` of :manpage:`keyctl(2)`, added in Linux 5.3.
+ *
+ * [Algorithm]
+ *
+ * - move a key between two keyrings, verify it can be found only in the
+ * destination afterwards
+ */
+
+#include "keyctl_common.h"
+
+#define RING_A_DESC "ltpkeyctl18_a"
+#define RING_B_DESC "ltpkeyctl18_b"
+#define KEY_DESC "k"
+#define PAYLOAD "payload"
+
+static key_serial_t ring_a, ring_b;
+static key_serial_t key;
+
+static void setup(void)
+{
+ SAFE_KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
+
+ ring_a = new_ring(RING_A_DESC);
+ ring_b = new_ring(RING_B_DESC);
+ key = new_user_key(KEY_DESC, PAYLOAD, sizeof(PAYLOAD), ring_a);
+}
+
+static void reset_state(void)
+{
+ SAFE_KEYCTL(KEYCTL_LINK, key, ring_a, 0, 0);
+ TEST(keyctl(KEYCTL_UNLINK, key, ring_b, 0, 0));
+ if (TST_RET == -1 && TST_ERR != ENOENT)
+ tst_brk(TBROK | TTERRNO, "failed to unlink key from ring_b");
+}
+
+static void run(void)
+{
+ reset_state();
+
+ TST_EXP_PASS(keyctl(KEYCTL_MOVE, key, ring_a, ring_b, 0));
+ if (!TST_PASS)
+ return;
+
+ TST_EXP_EQ_LI(search_ring(ring_b, "user", KEY_DESC), key);
+
+ TST_EXP_FAIL2(search_ring(ring_a, "user", KEY_DESC), ENOKEY,
+ "key no longer found in the source keyring");
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test_all = run,
+ .min_kver = "5.3",
+};
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 11/33] keyctl19: Test KEYCTL_MOVE with same source and destination
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (9 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 10/33] keyctl18: Test basic KEYCTL_MOVE Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 12/33] keyctl20: Test KEYCTL_MOVE displacement Andrea Cervesato
` (21 subsequent siblings)
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Test KEYCTL_MOVE when the source keyring equals the destination
keyring: verify the operation succeeds as a no-op and the key
remains linked in the keyring.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl19.c | 43 +++++++++++++++++++++++++++++
3 files changed, 45 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index 895dd0fc4..1935bee31 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -736,6 +736,7 @@ keyctl15 keyctl15
keyctl16 keyctl16
keyctl17 keyctl17
keyctl18 keyctl18
+keyctl19 keyctl19
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index 808cd2d23..f32107923 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -16,3 +16,4 @@
/keyctl16
/keyctl17
/keyctl18
+/keyctl19
diff --git a/testcases/kernel/syscalls/keyctl/keyctl19.c b/testcases/kernel/syscalls/keyctl/keyctl19.c
new file mode 100644
index 000000000..389ad7603
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl19.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Test ``KEYCTL_MOVE`` of :manpage:`keyctl(2)` with same source and destination.
+ *
+ * [Algorithm]
+ *
+ * - move a key where the source keyring equals the destination keyring,
+ * verify it is a successful no-op
+ */
+
+#include "keyctl_common.h"
+
+#define RING_DESC "ltpkeyctl19"
+#define KEY_DESC "k"
+#define PAYLOAD "payload"
+
+static key_serial_t ring;
+static key_serial_t key;
+
+static void setup(void)
+{
+ SAFE_KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
+
+ ring = new_ring(RING_DESC);
+ key = new_user_key(KEY_DESC, PAYLOAD, sizeof(PAYLOAD), ring);
+}
+
+static void run(void)
+{
+ TST_EXP_PASS(keyctl(KEYCTL_MOVE, key, ring, ring, 0));
+
+ TST_EXP_EQ_LI(search_ring(ring, "user", KEY_DESC), key);
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test_all = run,
+ .min_kver = "5.3",
+};
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 12/33] keyctl20: Test KEYCTL_MOVE displacement
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (10 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 11/33] keyctl19: Test KEYCTL_MOVE with same source and destination Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 13/33] keyctl21: Negative and boundary tests for KEYCTL_MOVE Andrea Cervesato
` (20 subsequent siblings)
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Test KEYCTL_MOVE displacement behavior: verify moving a key without
KEYCTL_MOVE_EXCL into a destination holding a matching key displaces
the existing key.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl20.c | 62 +++++++++++++++++++++++++++++
3 files changed, 64 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index 1935bee31..bfe4090a0 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -737,6 +737,7 @@ keyctl16 keyctl16
keyctl17 keyctl17
keyctl18 keyctl18
keyctl19 keyctl19
+keyctl20 keyctl20
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index f32107923..acddfa79e 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -17,3 +17,4 @@
/keyctl17
/keyctl18
/keyctl19
+/keyctl20
diff --git a/testcases/kernel/syscalls/keyctl/keyctl20.c b/testcases/kernel/syscalls/keyctl/keyctl20.c
new file mode 100644
index 000000000..6da36fe32
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl20.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Test ``KEYCTL_MOVE`` displacement of :manpage:`keyctl(2)`.
+ *
+ * [Algorithm]
+ *
+ * - move a key without ``KEYCTL_MOVE_EXCL`` into a destination keyring that
+ * already contains a matching key, verify it displaces the existing key
+ */
+
+#include "keyctl_common.h"
+
+#define RING_A_DESC "ltpkeyctl20_a"
+#define RING_B_DESC "ltpkeyctl20_b"
+#define KEY_DESC "k"
+#define PAYLOAD "payload"
+
+static key_serial_t ring_a, ring_b;
+static key_serial_t key_a, key_excl;
+
+static void setup(void)
+{
+ SAFE_KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
+
+ ring_a = new_ring(RING_A_DESC);
+ ring_b = new_ring(RING_B_DESC);
+
+ key_a = new_user_key(KEY_DESC, PAYLOAD, sizeof(PAYLOAD), ring_a);
+ key_excl = new_user_key(KEY_DESC, PAYLOAD, sizeof(PAYLOAD), ring_b);
+
+ /* Keep key_excl in session keyring so displacement does not destroy it */
+ SAFE_KEYCTL(KEYCTL_LINK, key_excl, KEY_SPEC_SESSION_KEYRING, 0, 0);
+}
+
+static void reset_state(void)
+{
+ SAFE_KEYCTL(KEYCTL_LINK, key_a, ring_a, 0, 0);
+ TEST(keyctl(KEYCTL_UNLINK, key_a, ring_b, 0, 0));
+ if (TST_RET == -1 && TST_ERR != ENOENT)
+ tst_brk(TBROK | TTERRNO, "failed to unlink key_a from ring_b");
+
+ SAFE_KEYCTL(KEYCTL_LINK, key_excl, ring_b, 0, 0);
+}
+
+static void run(void)
+{
+ reset_state();
+
+ TST_EXP_PASS(keyctl(KEYCTL_MOVE, key_a, ring_a, ring_b, 0));
+
+ TST_EXP_EQ_LI(search_ring(ring_b, "user", KEY_DESC), key_a);
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test_all = run,
+ .min_kver = "5.3",
+};
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 13/33] keyctl21: Negative and boundary tests for KEYCTL_MOVE
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (11 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 12/33] keyctl20: Test KEYCTL_MOVE displacement Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 14/33] keyctl22: Test KEYCTL_RESTRICT_KEYRING reject-all Andrea Cervesato
` (19 subsequent siblings)
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Test error and boundary conditions of KEYCTL_MOVE using a
parameterized tcase table: KEYCTL_MOVE_EXCL (EEXIST), unknown flag
bits (EINVAL), bogus IDs (ENOKEY), non-keyrings (ENOTDIR), unlinked
key (ENOENT), keyring cycle (EDEADLK), and destination without
Write permission (EACCES).
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl21.c | 111 ++++++++++++++++++++++++++++
3 files changed, 113 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index bfe4090a0..b95264564 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -738,6 +738,7 @@ keyctl17 keyctl17
keyctl18 keyctl18
keyctl19 keyctl19
keyctl20 keyctl20
+keyctl21 keyctl21
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index acddfa79e..e8c71e79e 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -18,3 +18,4 @@
/keyctl18
/keyctl19
/keyctl20
+/keyctl21
diff --git a/testcases/kernel/syscalls/keyctl/keyctl21.c b/testcases/kernel/syscalls/keyctl/keyctl21.c
new file mode 100644
index 000000000..a2db5a406
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl21.c
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Negative and boundary test cases for ``KEYCTL_MOVE`` of :manpage:`keyctl(2)`.
+ *
+ * [Algorithm]
+ *
+ * - ``KEYCTL_MOVE_EXCL`` fails with ``EEXIST`` when the destination already
+ * holds a matching key
+ * - unknown flag bits are rejected with ``EINVAL``
+ * - bogus key or keyring ids fail with ``ENOKEY``
+ * - a plain key used as source or destination keyring fails with ``ENOTDIR``
+ * - moving a key that is not linked in the source fails with ``ENOENT``
+ * - moving a keyring into itself fails with ``EDEADLK`` from the keyring
+ * cycle detection
+ * - moving into a keyring without Write permission fails with ``EACCES``
+ */
+
+#include "keyctl_common.h"
+
+#define RING_A_DESC "ltpkeyctl21_a"
+#define RING_B_DESC "ltpkeyctl21_b"
+#define RING_C_DESC "ltpkeyctl21_c"
+#define KEY_A_DESC "ka"
+#define KEY_B_DESC "kb"
+#define PAYLOAD "payload"
+
+static key_serial_t ring_a, ring_b, ring_c, ring_no_write;
+static key_serial_t key_a, key_b, key_excl;
+static key_serial_t bogus_id = INT32_MAX;
+
+static struct tcase {
+ key_serial_t *keyid;
+ key_serial_t *from;
+ key_serial_t *to;
+ unsigned int flags;
+ int exp_errno;
+ const char *desc;
+} tcases[] = {
+ { &key_a, &ring_a, &ring_b, KEYCTL_MOVE_EXCL,
+ EEXIST, "KEYCTL_MOVE_EXCL on existing key" },
+
+ { &key_a, &ring_a, &ring_b, 0x2,
+ EINVAL, "unknown flag bits" },
+
+ { &bogus_id, &ring_a, &ring_b, 0,
+ ENOKEY, "bogus key id" },
+
+ { &key_a, &bogus_id, &ring_b, 0,
+ ENOKEY, "bogus source keyring" },
+
+ { &key_a, &ring_a, &bogus_id, 0,
+ ENOKEY, "bogus destination keyring" },
+
+ { &key_a, &key_b, &ring_b, 0,
+ ENOTDIR, "plain key as source keyring" },
+
+ { &key_a, &ring_a, &key_b, 0,
+ ENOTDIR, "plain key as destination keyring" },
+
+ { &key_b, &ring_a, &ring_b, 0,
+ ENOENT, "key not linked in the source keyring" },
+
+ { &ring_c, &ring_b, &ring_c, 0,
+ EDEADLK, "keyring into itself" },
+
+ { &key_a, &ring_a, &ring_no_write, 0,
+ EACCES, "destination without Write permission" },
+};
+
+static void setup(void)
+{
+ SAFE_KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
+
+ ring_a = new_ring(RING_A_DESC);
+ ring_b = new_ring(RING_B_DESC);
+ ring_c = new_ring(RING_C_DESC);
+ ring_no_write = new_ring("ltpkeyctl21_nowrite");
+ SAFE_KEYCTL(KEYCTL_SETPERM, ring_no_write, KEY_PERM_NO_WRITE, 0, 0);
+
+ key_a = new_user_key(KEY_A_DESC, PAYLOAD, sizeof(PAYLOAD), ring_a);
+ key_b = new_user_key(KEY_B_DESC, PAYLOAD, sizeof(PAYLOAD), ring_b);
+ key_excl = new_user_key(KEY_A_DESC, PAYLOAD, sizeof(PAYLOAD), ring_b);
+
+ /* Keep key_excl in session keyring */
+ SAFE_KEYCTL(KEYCTL_LINK, key_excl, KEY_SPEC_SESSION_KEYRING, 0, 0);
+
+ /* Link ring_c into ring_b for cycle test */
+ SAFE_KEYCTL(KEYCTL_LINK, ring_c, ring_b, 0, 0);
+}
+
+static void verify_negative(unsigned int n)
+{
+ struct tcase *tc = &tcases[n];
+
+ TST_EXP_FAIL(keyctl(KEYCTL_MOVE, (unsigned long)*tc->keyid,
+ (unsigned long)*tc->from, (unsigned long)*tc->to,
+ tc->flags),
+ tc->exp_errno,
+ "KEYCTL_MOVE with %s", tc->desc);
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test = verify_negative,
+ .tcnt = ARRAY_SIZE(tcases),
+ .min_kver = "5.3",
+};
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 14/33] keyctl22: Test KEYCTL_RESTRICT_KEYRING reject-all
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (12 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 13/33] keyctl21: Negative and boundary tests for KEYCTL_MOVE Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 15/33] keyctl23: Test KEYCTL_RESTRICT_KEYRING builtin_trusted Andrea Cervesato
` (18 subsequent siblings)
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Test KEYCTL_RESTRICT_KEYRING reject-all restriction: verify that
restricting a keyring with NULL type and NULL restriction succeeds,
and subsequent link and add_key attempts fail with EPERM.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl22.c | 54 +++++++++++++++++++++++++++++
3 files changed, 56 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index b95264564..262ef967d 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -739,6 +739,7 @@ keyctl18 keyctl18
keyctl19 keyctl19
keyctl20 keyctl20
keyctl21 keyctl21
+keyctl22 keyctl22
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index e8c71e79e..82a74e4a3 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -19,3 +19,4 @@
/keyctl19
/keyctl20
/keyctl21
+/keyctl22
diff --git a/testcases/kernel/syscalls/keyctl/keyctl22.c b/testcases/kernel/syscalls/keyctl/keyctl22.c
new file mode 100644
index 000000000..c4410e3dc
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl22.c
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Test ``KEYCTL_RESTRICT_KEYRING`` reject-all of :manpage:`keyctl(2)`,
+ * added in Linux 4.12.
+ *
+ * [Algorithm]
+ *
+ * - restrict a keyring with ``NULL`` type and ``NULL`` restriction (reject all links),
+ * verify subsequent links and add_key fail with ``EPERM``
+ */
+
+#include "keyctl_common.h"
+
+#define PAYLOAD "payload"
+
+static key_serial_t ring_reject;
+static key_serial_t user_key;
+
+static void setup(void)
+{
+ SAFE_KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
+
+ ring_reject = new_ring("ltpkeyctl22_reject");
+ user_key = new_user_key("k", PAYLOAD, sizeof(PAYLOAD),
+ KEY_SPEC_PROCESS_KEYRING);
+}
+
+static void run(void)
+{
+ TEST(keyctl(KEYCTL_RESTRICT_KEYRING, ring_reject, 0, 0, 0));
+ if (TST_RET == 0)
+ tst_res(TPASS, "KEYCTL_RESTRICT_KEYRING with NULL type and restriction passed");
+ else if (TST_RET == -1 && TST_ERR == EEXIST)
+ tst_res(TPASS, "KEYCTL_RESTRICT_KEYRING reject-all already active");
+ else
+ tst_res(TFAIL | TTERRNO, "KEYCTL_RESTRICT_KEYRING reject-all failed");
+
+ TST_EXP_FAIL(keyctl(KEYCTL_LINK, user_key, ring_reject, 0, 0), EPERM,
+ "KEYCTL_LINK on reject-all restricted keyring");
+
+ TST_EXP_FAIL2(add_key("user", "k_rej", PAYLOAD, sizeof(PAYLOAD),
+ ring_reject), EPERM,
+ "add_key on reject-all restricted keyring");
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test_all = run,
+ .min_kver = "4.12",
+};
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 15/33] keyctl23: Test KEYCTL_RESTRICT_KEYRING builtin_trusted
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (13 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 14/33] keyctl22: Test KEYCTL_RESTRICT_KEYRING reject-all Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 16/33] keyctl24: Negative tests for KEYCTL_RESTRICT_KEYRING Andrea Cervesato
` (17 subsequent siblings)
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Test KEYCTL_RESTRICT_KEYRING builtin_trusted restriction: verify that
restricting a keyring with asymmetric builtin_trusted allows only
trusted asymmetric keys, rejecting user keys with EOPNOTSUPP and
untrusted certs with ENOKEY.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl23.c | 142 ++++++++++++++++++++++++++++
3 files changed, 144 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index 262ef967d..f7c4830a9 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -740,6 +740,7 @@ keyctl19 keyctl19
keyctl20 keyctl20
keyctl21 keyctl21
keyctl22 keyctl22
+keyctl23 keyctl23
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index 82a74e4a3..803e4e94c 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -20,3 +20,4 @@
/keyctl20
/keyctl21
/keyctl22
+/keyctl23
diff --git a/testcases/kernel/syscalls/keyctl/keyctl23.c b/testcases/kernel/syscalls/keyctl/keyctl23.c
new file mode 100644
index 000000000..76e0f8954
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl23.c
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Test ``KEYCTL_RESTRICT_KEYRING`` builtin_trusted of :manpage:`keyctl(2)`.
+ *
+ * Requires root (CAP_SYS_MODULE) to load the ``x509_key_parser`` module.
+ *
+ * [Algorithm]
+ *
+ * - restrict a keyring with ``asymmetric`` and ``builtin_trusted``, verify
+ * linking a user key fails with ``EOPNOTSUPP`` and adding an untrusted
+ * cert fails with ``ENOKEY``
+ */
+
+#include "keyctl_common.h"
+#include "tst_module.h"
+
+#define PAYLOAD "payload"
+
+/*
+ * Self-signed RSA-2048 X.509 certificate in DER format generated using:
+ * openssl req -x509 -newkey rsa:2048 -subj "/CN=ltp-keyctl23-untrusted" \
+ * -days 36500 -nodes -batch -outform der
+ *
+ * Used only as an untrusted certificate to verify that add_key() on a
+ * keyring restricted with builtin_trusted rejects it with ENOKEY.
+ */
+static const unsigned char untrusted_cert[] = {
+ 0x30, 0x82, 0x03, 0x25, 0x30, 0x82, 0x02, 0x0d, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x14, 0x52,
+ 0xad, 0xef, 0x01, 0xca, 0xbb, 0x64, 0x17, 0xa7, 0x1a, 0xa7, 0xcb, 0x2f, 0x82, 0x44, 0x6e, 0xec,
+ 0x5a, 0x2e, 0x2c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
+ 0x05, 0x00, 0x30, 0x21, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x6c,
+ 0x74, 0x70, 0x2d, 0x6b, 0x65, 0x79, 0x63, 0x74, 0x6c, 0x32, 0x33, 0x2d, 0x75, 0x6e, 0x74, 0x72,
+ 0x75, 0x73, 0x74, 0x65, 0x64, 0x30, 0x20, 0x17, 0x0d, 0x32, 0x36, 0x30, 0x39, 0x30, 0x32, 0x30,
+ 0x39, 0x32, 0x33, 0x34, 0x39, 0x5a, 0x18, 0x0f, 0x32, 0x31, 0x32, 0x36, 0x30, 0x38, 0x30, 0x39,
+ 0x30, 0x39, 0x32, 0x33, 0x34, 0x39, 0x5a, 0x30, 0x21, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x0c, 0x16, 0x6c, 0x74, 0x70, 0x2d, 0x6b, 0x65, 0x79, 0x63, 0x74, 0x6c, 0x32, 0x33,
+ 0x2d, 0x75, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01,
+ 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xd5, 0xee, 0x8d, 0xec, 0x85,
+ 0x8e, 0x29, 0xc7, 0xe7, 0xf8, 0x3f, 0xed, 0xc8, 0x82, 0xb2, 0x17, 0x95, 0xf4, 0xe0, 0x99, 0x02,
+ 0x84, 0xc5, 0xb3, 0x46, 0x62, 0x8c, 0x8a, 0xd3, 0x89, 0xd5, 0x62, 0x25, 0xa7, 0xc8, 0x92, 0xcc,
+ 0xc5, 0x64, 0x20, 0x80, 0xb7, 0xf3, 0xc2, 0x40, 0xdc, 0xf0, 0xf0, 0xd8, 0x85, 0x5f, 0x58, 0x61,
+ 0x77, 0xd6, 0xd5, 0x3a, 0x32, 0xec, 0x81, 0x15, 0x25, 0xb4, 0x08, 0x21, 0x6d, 0xf3, 0xd6, 0x80,
+ 0xa6, 0x91, 0x5a, 0x53, 0x9e, 0x54, 0x49, 0x5b, 0x91, 0x6b, 0x74, 0x0b, 0xb5, 0x99, 0xd5, 0x49,
+ 0x46, 0x41, 0x56, 0x67, 0xb4, 0xed, 0x17, 0x82, 0x96, 0x03, 0x40, 0xd7, 0x0d, 0x0a, 0x00, 0x95,
+ 0x3c, 0xb7, 0x75, 0x9e, 0x61, 0xab, 0xe9, 0x10, 0x4a, 0xa9, 0x90, 0x21, 0xd2, 0xb4, 0x3d, 0xd0,
+ 0x83, 0x48, 0x0c, 0x59, 0xa9, 0xd7, 0xbe, 0x7b, 0x4c, 0x75, 0xf0, 0xd1, 0x8a, 0x29, 0x1c, 0x06,
+ 0x35, 0x29, 0x6d, 0x3c, 0x6e, 0xb9, 0xce, 0x11, 0xa9, 0x1b, 0x4d, 0xf7, 0xfd, 0x6d, 0x2e, 0x02,
+ 0x7f, 0xbe, 0x45, 0xb7, 0x11, 0xae, 0x1d, 0xbb, 0x70, 0x02, 0xae, 0xc1, 0xb3, 0x31, 0x3d, 0x99,
+ 0xd9, 0x70, 0x01, 0xbd, 0xea, 0xd3, 0x0d, 0x04, 0xe0, 0x2f, 0xac, 0x79, 0xe4, 0xb2, 0x0c, 0x96,
+ 0xba, 0x66, 0x9e, 0xcf, 0x72, 0x13, 0xa3, 0x37, 0x44, 0x03, 0x2d, 0xe9, 0x5c, 0x71, 0x6f, 0x35,
+ 0x71, 0xf8, 0xdc, 0x58, 0xa3, 0x1f, 0x57, 0x88, 0x59, 0x79, 0xe6, 0x7e, 0x37, 0x9b, 0xc9, 0xa3,
+ 0x36, 0x03, 0x5c, 0xcb, 0x30, 0x92, 0x5e, 0x9e, 0x43, 0x48, 0xa2, 0x3e, 0x7f, 0xdc, 0xb8, 0xe3,
+ 0x6a, 0xe6, 0x8c, 0x18, 0xb2, 0x42, 0x4c, 0xbb, 0x2d, 0x6a, 0x6c, 0x5f, 0xd1, 0xc1, 0xd5, 0x33,
+ 0x3b, 0xdb, 0x8c, 0x3c, 0xa2, 0xec, 0xaa, 0xed, 0xce, 0xe1, 0xd1, 0x02, 0x03, 0x01, 0x00, 0x01,
+ 0xa3, 0x53, 0x30, 0x51, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xd3,
+ 0x8d, 0xd1, 0xe4, 0x77, 0x4e, 0xe2, 0xb2, 0xb6, 0xab, 0x31, 0x58, 0x69, 0x7b, 0x27, 0x31, 0xce,
+ 0x00, 0xcd, 0x60, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14,
+ 0xd3, 0x8d, 0xd1, 0xe4, 0x77, 0x4e, 0xe2, 0xb2, 0xb6, 0xab, 0x31, 0x58, 0x69, 0x7b, 0x27, 0x31,
+ 0xce, 0x00, 0xcd, 0x60, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05,
+ 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x1e, 0xb9, 0x52, 0x16, 0xf2, 0xef, 0xca,
+ 0xbc, 0x35, 0x93, 0xb4, 0x38, 0xb8, 0xab, 0xfe, 0x73, 0x1a, 0x06, 0x50, 0x99, 0x58, 0xc4, 0xa8,
+ 0xf4, 0x26, 0xb1, 0xe1, 0x8e, 0x0b, 0xd3, 0xe7, 0xa8, 0x8d, 0x1f, 0xa0, 0x79, 0x4c, 0x9f, 0xdd,
+ 0x3a, 0xf0, 0xb7, 0xf2, 0x18, 0xfc, 0x99, 0x11, 0x45, 0x8f, 0xeb, 0xc9, 0xf2, 0x48, 0x2e, 0x4a,
+ 0x7b, 0x24, 0x37, 0xa4, 0xbc, 0x52, 0x96, 0x80, 0x76, 0x46, 0x59, 0x27, 0xb5, 0xa0, 0x07, 0x5b,
+ 0x6c, 0x38, 0x5c, 0xde, 0x95, 0x76, 0xfc, 0x21, 0xb8, 0x1e, 0x7e, 0x13, 0x3e, 0x59, 0x95, 0xf9,
+ 0x39, 0xdb, 0xd5, 0x41, 0x3d, 0x8d, 0xfd, 0x4c, 0x1a, 0x4b, 0xdd, 0x41, 0x3b, 0x27, 0x58, 0xf8,
+ 0x72, 0xa3, 0x70, 0x97, 0xc6, 0xb9, 0x0e, 0x4e, 0x3c, 0x08, 0xba, 0x2f, 0xa9, 0x55, 0x6d, 0x23,
+ 0xdd, 0xc4, 0x0a, 0x43, 0xad, 0x20, 0x75, 0x0d, 0xea, 0xbc, 0x49, 0x6c, 0xd2, 0x87, 0x59, 0x46,
+ 0x72, 0x3e, 0x77, 0x9b, 0x29, 0x63, 0x38, 0x0a, 0x2f, 0x61, 0xcc, 0xda, 0xd0, 0x21, 0x47, 0x6f,
+ 0x9f, 0x19, 0x26, 0x0c, 0xbb, 0x77, 0x22, 0x8d, 0xc7, 0x65, 0x01, 0x25, 0x4b, 0x69, 0x38, 0xae,
+ 0x6e, 0x16, 0x4f, 0x70, 0x35, 0xab, 0xea, 0x76, 0xe4, 0x37, 0xe4, 0x92, 0x6b, 0xf0, 0x6e, 0xc5,
+ 0x4c, 0xc1, 0x37, 0xc1, 0x28, 0xa6, 0x78, 0xc7, 0x90, 0xb4, 0xea, 0xbb, 0x8d, 0x12, 0xe1, 0x30,
+ 0xe1, 0x7b, 0x76, 0xc3, 0x65, 0xc3, 0x99, 0x7b, 0xb3, 0xb1, 0x9a, 0xe9, 0x73, 0xb2, 0x4d, 0x08,
+ 0x2a, 0xa4, 0x67, 0x42, 0xef, 0x7c, 0xf5, 0x67, 0x3e, 0xa4, 0x78, 0xe1, 0x04, 0x93, 0x5e, 0x1b,
+ 0xf9, 0xae, 0xe1, 0x5a, 0x7f, 0x42, 0x38, 0xb7, 0x93, 0xfb, 0x27, 0xff, 0x1c, 0x7e, 0xdd, 0x8a,
+ 0x71, 0x10, 0xcb, 0x65, 0xc9, 0xf2, 0x0f, 0x9e, 0x7d,
+};
+
+static key_serial_t ring_builtin;
+static key_serial_t user_key;
+static int asym_supported;
+
+static void setup(void)
+{
+ SAFE_KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
+
+ tst_modprobe("x509_key_parser", NULL);
+
+ ring_builtin = new_ring("ltpkeyctl23_builtin");
+
+ user_key = new_user_key("k", PAYLOAD, sizeof(PAYLOAD),
+ KEY_SPEC_PROCESS_KEYRING);
+
+ /* Probe if asymmetric key type is supported */
+ TEST(keyctl(KEYCTL_RESTRICT_KEYRING, ring_builtin,
+ (unsigned long)"asymmetric", (unsigned long)"bogus", 0));
+ asym_supported = (TST_RET != -1 || TST_ERR != ENODEV);
+}
+
+static void run(void)
+{
+ if (!asym_supported) {
+ tst_res(TCONF, "asymmetric key type not supported");
+ return;
+ }
+
+ TEST(keyctl(KEYCTL_RESTRICT_KEYRING, ring_builtin,
+ (unsigned long)"asymmetric",
+ (unsigned long)"builtin_trusted", 0));
+ if (TST_RET == -1 && TST_ERR == EOPNOTSUPP) {
+ tst_res(TCONF, "builtin_trusted restriction not supported");
+ return;
+ }
+
+ if (TST_RET == 0)
+ tst_res(TPASS, "KEYCTL_RESTRICT_KEYRING builtin_trusted passed");
+ else if (TST_RET == -1 && TST_ERR == EEXIST)
+ tst_res(TPASS, "KEYCTL_RESTRICT_KEYRING builtin_trusted already active");
+ else
+ tst_res(TFAIL | TTERRNO, "KEYCTL_RESTRICT_KEYRING builtin_trusted failed");
+
+ TST_EXP_FAIL(keyctl(KEYCTL_LINK, user_key, ring_builtin, 0, 0),
+ EOPNOTSUPP,
+ "KEYCTL_LINK of non-asymmetric key on builtin_trusted restricted keyring");
+
+ TST_EXP_FAIL2(add_key("asymmetric", "cert", untrusted_cert,
+ sizeof(untrusted_cert), ring_builtin), ENOKEY,
+ "add_key of untrusted cert on builtin_trusted restricted keyring");
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test_all = run,
+ .min_kver = "4.12",
+ .needs_root = 1,
+};
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 16/33] keyctl24: Negative tests for KEYCTL_RESTRICT_KEYRING
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (14 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 15/33] keyctl23: Test KEYCTL_RESTRICT_KEYRING builtin_trusted Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 17/33] keyctl25: Test KEYCTL_DH_COMPUTE shared secret computation Andrea Cervesato
` (16 subsequent siblings)
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Test error conditions of KEYCTL_RESTRICT_KEYRING using a parameterized
tcase table: invalid type/restriction combinations (EINVAL), non-keyrings
(ENOTDIR), unknown key type (ENOKEY), key type without lookup (ENOENT),
invalid restriction string (EINVAL), bogus key serial (ENOKEY), already
restricted (EEXIST), self-chain cycle (EDEADLK), and missing Setattr
(EACCES).
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl24.c | 173 ++++++++++++++++++++++++++++
3 files changed, 175 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index f7c4830a9..be35e9f93 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -741,6 +741,7 @@ keyctl20 keyctl20
keyctl21 keyctl21
keyctl22 keyctl22
keyctl23 keyctl23
+keyctl24 keyctl24
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index 803e4e94c..767ccf61a 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -21,3 +21,4 @@
/keyctl21
/keyctl22
/keyctl23
+/keyctl24
diff --git a/testcases/kernel/syscalls/keyctl/keyctl24.c b/testcases/kernel/syscalls/keyctl/keyctl24.c
new file mode 100644
index 000000000..2ec78e720
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl24.c
@@ -0,0 +1,173 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Negative test cases for ``KEYCTL_RESTRICT_KEYRING`` of :manpage:`keyctl(2)`.
+ *
+ * [Algorithm]
+ *
+ * - restrict with ``NULL`` type and non-NULL restriction fails with ``EINVAL``
+ * - restrict with non-NULL type and ``NULL`` restriction fails with ``EINVAL``
+ * - restrict on a non-keyring key fails with ``ENOTDIR``
+ * - restrict with unknown key type fails with ``ENOKEY``
+ * - restrict with key type having no restriction lookup fails with ``ENOENT``
+ * - restrict with asymmetric type and invalid restriction string fails with
+ * ``EINVAL``
+ * - restrict with asymmetric type and bogus key serial fails with ``ENOKEY``
+ * - restrict an already restricted keyring fails with ``EEXIST``
+ * - restrict with self-referencing key_or_keyring chain fails with ``EDEADLK``
+ * - restrict without Setattr permission fails with ``EACCES``
+ */
+
+#include <stdio.h>
+
+#include "keyctl_common.h"
+
+static key_serial_t ring_reject, ring_no_setattr;
+static key_serial_t user_key;
+static int asym_supported;
+
+/*
+ * A tcase with .id = NULL asks verify_negative() to allocate a fresh
+ * unrestricted keyring for the case and unlink it afterwards, so that a
+ * false-positive result cannot restrict a ring shared with later cases.
+ * .self_cycle asks for a "key_or_keyring:<fresh>:chain" restriction string
+ * pointing back at that fresh ring, needed for the EDEADLK check.
+ */
+static struct tcase {
+ key_serial_t *id;
+ int self_cycle;
+ const char *type;
+ const char *restriction;
+ int exp_errno;
+ int needs_asym;
+ const char *desc;
+} tcases[] = {
+ {
+ .restriction = "builtin_trusted",
+ .exp_errno = EINVAL,
+ .desc = "NULL type and non-NULL restriction",
+ },
+ {
+ .type = "asymmetric",
+ .exp_errno = EINVAL,
+ .desc = "non-NULL type and NULL restriction",
+ },
+ {
+ .id = &user_key,
+ .exp_errno = ENOTDIR,
+ .desc = "non-keyring key",
+ },
+ {
+ .type = "nosuchtype",
+ .restriction = "builtin_trusted",
+ .exp_errno = ENOKEY,
+ .desc = "unknown key type",
+ },
+ {
+ .type = "user",
+ .restriction = "builtin_trusted",
+ .exp_errno = ENOENT,
+ .desc = "key type having no lookup_restriction",
+ },
+ {
+ .type = "asymmetric",
+ .restriction = "bogus",
+ .exp_errno = EINVAL,
+ .needs_asym = 1,
+ .desc = "asymmetric with invalid restriction string",
+ },
+ {
+ .type = "asymmetric",
+ .restriction = "key_or_keyring:2147483647",
+ .exp_errno = ENOKEY,
+ .needs_asym = 1,
+ .desc = "asymmetric with bogus key serial",
+ },
+ {
+ .id = &ring_reject,
+ .exp_errno = EEXIST,
+ .desc = "already restricted keyring",
+ },
+ {
+ .self_cycle = 1,
+ .type = "asymmetric",
+ .exp_errno = EDEADLK,
+ .needs_asym = 1,
+ .desc = "self-referencing key_or_keyring chain",
+ },
+ {
+ .id = &ring_no_setattr,
+ .exp_errno = EACCES,
+ .desc = "keyring without Setattr permission",
+ },
+};
+
+static void setup(void)
+{
+ key_serial_t probe_ring;
+
+ SAFE_KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
+
+ ring_reject = new_ring("ltpkeyctl24_reject");
+ ring_no_setattr = new_ring("ltpkeyctl24_no_setattr");
+ SAFE_KEYCTL(KEYCTL_SETPERM, ring_no_setattr, KEY_PERM_NO_SETATTR, 0, 0);
+
+ /* Permanently restrict ring_reject with reject-all for EEXIST test */
+ SAFE_KEYCTL(KEYCTL_RESTRICT_KEYRING, ring_reject, 0, 0, 0);
+
+ user_key = new_user_key("k", "payload", 7, KEY_SPEC_PROCESS_KEYRING);
+
+ /* Probe asymmetric support on a throwaway ring so we cannot poison
+ * any ring reused later by the tcase table.
+ */
+ probe_ring = new_ring("ltpkeyctl24_probe");
+ TEST(keyctl(KEYCTL_RESTRICT_KEYRING, probe_ring,
+ (unsigned long)"asymmetric", (unsigned long)"bogus", 0));
+ asym_supported = (TST_RET != -1 || TST_ERR != ENODEV);
+ keyctl(KEYCTL_UNLINK, probe_ring, KEY_SPEC_PROCESS_KEYRING, 0, 0);
+}
+
+static void verify_negative(unsigned int n)
+{
+ struct tcase *tc = &tcases[n];
+ key_serial_t id, fresh_ring = 0;
+ const char *restriction = tc->restriction;
+ char cycle_buf[64];
+
+ if (tc->needs_asym && !asym_supported) {
+ tst_res(TCONF, "asymmetric key type not supported");
+ return;
+ }
+
+ if (tc->id) {
+ id = *tc->id;
+ } else {
+ fresh_ring = new_ring("ltpkeyctl24_fresh");
+ id = fresh_ring;
+ if (tc->self_cycle) {
+ snprintf(cycle_buf, sizeof(cycle_buf),
+ "key_or_keyring:%d:chain", fresh_ring);
+ restriction = cycle_buf;
+ }
+ }
+
+ TST_EXP_FAIL(keyctl(KEYCTL_RESTRICT_KEYRING, (unsigned long)id,
+ (unsigned long)tc->type,
+ (unsigned long)restriction, 0),
+ tc->exp_errno,
+ "KEYCTL_RESTRICT_KEYRING with %s", tc->desc);
+
+ if (fresh_ring)
+ keyctl(KEYCTL_UNLINK, fresh_ring, KEY_SPEC_PROCESS_KEYRING,
+ 0, 0);
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test = verify_negative,
+ .tcnt = ARRAY_SIZE(tcases),
+ .min_kver = "4.12",
+};
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 17/33] keyctl25: Test KEYCTL_DH_COMPUTE shared secret computation
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (15 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 16/33] keyctl24: Negative tests for KEYCTL_RESTRICT_KEYRING Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 18/33] keyctl26: Test KEYCTL_DH_COMPUTE size query Andrea Cervesato
` (15 subsequent siblings)
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Test KEYCTL_DH_COMPUTE shared secret computation: verify that
computing a 256-byte DH shared secret with RFC 7919 FFDHE-2048
parameters matches the precomputed mathematical value.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl25.c | 66 ++++++++++++++++++++
testcases/kernel/syscalls/keyctl/keyctl_dh_data.h | 74 +++++++++++++++++++++++
4 files changed, 142 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index be35e9f93..1b059f652 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -742,6 +742,7 @@ keyctl21 keyctl21
keyctl22 keyctl22
keyctl23 keyctl23
keyctl24 keyctl24
+keyctl25 keyctl25
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index 767ccf61a..4cf772558 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -22,3 +22,4 @@
/keyctl22
/keyctl23
/keyctl24
+/keyctl25
diff --git a/testcases/kernel/syscalls/keyctl/keyctl25.c b/testcases/kernel/syscalls/keyctl/keyctl25.c
new file mode 100644
index 000000000..f2d94a9f0
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl25.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Test ``KEYCTL_DH_COMPUTE`` shared secret computation of :manpage:`keyctl(2)`.
+ *
+ * [Algorithm]
+ *
+ * - compute DH shared secret using RFC 7919 FFDHE-2048 parameters and
+ * verify the 256-byte result matches the expected secret
+ */
+
+#include "keyctl_common.h"
+#include "keyctl_dh_data.h"
+
+static struct keyctl_dh_params *dh_params;
+static unsigned char out_buf[256];
+
+static void setup(void)
+{
+ SAFE_KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
+
+ dh_params->priv = new_user_key("dh_priv", dh_priv, sizeof(dh_priv),
+ KEY_SPEC_PROCESS_KEYRING);
+ dh_params->prime = new_user_key("dh_prime", dh_prime, sizeof(dh_prime),
+ KEY_SPEC_PROCESS_KEYRING);
+ dh_params->base = new_user_key("dh_base", dh_base, sizeof(dh_base),
+ KEY_SPEC_PROCESS_KEYRING);
+}
+
+static void run(void)
+{
+ memset(out_buf, 0, sizeof(out_buf));
+
+ TST_EXP_EQ_LI_SILENT(keyctl(KEYCTL_DH_COMPUTE, (unsigned long)dh_params,
+ (unsigned long)out_buf,
+ sizeof(dh_expected_secret), 0),
+ (long)sizeof(dh_expected_secret));
+ if (!TST_PASS)
+ return;
+
+ if (memcmp(out_buf, dh_expected_secret, sizeof(dh_expected_secret))) {
+ tst_res(TFAIL, "computed secret does not match expected value");
+ return;
+ }
+
+ tst_res(TPASS, "KEYCTL_DH_COMPUTE computed expected shared secret");
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test_all = run,
+ .min_kver = "4.7",
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_KEYS=y",
+ "CONFIG_KEY_DH_OPERATIONS=y",
+ "CONFIG_CRYPTO_DH",
+ NULL
+ },
+ .bufs = (struct tst_buffers []) {
+ {&dh_params, .size = sizeof(*dh_params)},
+ {},
+ },
+};
diff --git a/testcases/kernel/syscalls/keyctl/keyctl_dh_data.h b/testcases/kernel/syscalls/keyctl/keyctl_dh_data.h
new file mode 100644
index 000000000..bc1432dc3
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl_dh_data.h
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ *
+ * Static test vectors for KEYCTL_DH_COMPUTE tests (keyctl25..keyctl28).
+ */
+
+#ifndef KEYCTL_DH_DATA_H__
+#define KEYCTL_DH_DATA_H__
+
+/* RFC 7919 2048-bit FFDHE Group parameters (ffdhe2048) */
+static const unsigned char dh_prime[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc9, 0x0f, 0xda, 0xa2, 0x21, 0x68, 0xc2, 0x34,
+ 0xc4, 0xc6, 0x62, 0x8b, 0x80, 0xdc, 0x1c, 0xd1, 0x29, 0x02, 0x4e, 0x08, 0x8a, 0x67, 0xcc, 0x74,
+ 0x02, 0x0b, 0xbe, 0xa6, 0x3b, 0x13, 0x9b, 0x22, 0x51, 0x4a, 0x08, 0x79, 0x8e, 0x34, 0x04, 0xdd,
+ 0xef, 0x95, 0x19, 0xb3, 0xcd, 0x3a, 0x43, 0x1b, 0x30, 0x2b, 0x0a, 0x6d, 0xf2, 0x5f, 0x14, 0x37,
+ 0x4f, 0xe1, 0x35, 0x6d, 0x6d, 0x51, 0xc2, 0x45, 0xe4, 0x85, 0xb5, 0x76, 0x62, 0x5e, 0x7e, 0xc6,
+ 0xf4, 0x4c, 0x42, 0xe9, 0xa6, 0x37, 0xed, 0x6b, 0x0b, 0xff, 0x5c, 0xb6, 0xf4, 0x06, 0xb7, 0xed,
+ 0xee, 0x38, 0x6b, 0xfb, 0x5a, 0x89, 0x9f, 0xa5, 0xae, 0x9f, 0x24, 0x11, 0x7c, 0x4b, 0x1f, 0xe6,
+ 0x49, 0x28, 0x66, 0x51, 0xec, 0xe4, 0x5b, 0x3d, 0xc2, 0x00, 0x7c, 0xb8, 0xa1, 0x63, 0xbf, 0x05,
+ 0x98, 0xda, 0x48, 0x36, 0x1c, 0x55, 0xd3, 0x9a, 0x69, 0x16, 0x3f, 0xa8, 0xfd, 0x24, 0xcf, 0x5f,
+ 0x83, 0x65, 0x5d, 0x23, 0xdc, 0xa3, 0xad, 0x96, 0x1c, 0x62, 0xf3, 0x56, 0x20, 0x85, 0x52, 0xbb,
+ 0x9e, 0xd5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6d, 0x67, 0x0c, 0x35, 0x4e, 0x4a, 0xbc, 0x98, 0x04,
+ 0xf1, 0x74, 0x6c, 0x08, 0xca, 0x18, 0x21, 0x7c, 0x32, 0x90, 0x5e, 0x46, 0x2e, 0x36, 0xce, 0x3b,
+ 0xe3, 0x9e, 0x77, 0x2c, 0x18, 0x0e, 0x86, 0x03, 0x9b, 0x27, 0x83, 0xa2, 0xec, 0x07, 0xa2, 0x8f,
+ 0xb5, 0xc5, 0x5d, 0xf0, 0x6f, 0x4c, 0x52, 0xc9, 0xde, 0x2b, 0xcb, 0xf6, 0x95, 0x58, 0x17, 0x18,
+ 0x39, 0x95, 0x49, 0x7c, 0xea, 0x95, 0x6a, 0xe5, 0x15, 0xd2, 0x26, 0x18, 0x98, 0xfa, 0x05, 0x10,
+ 0x15, 0x72, 0x8e, 0x5a, 0x8a, 0xac, 0xaa, 0x68, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+};
+
+static const unsigned char dh_priv[] = {
+ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+};
+
+static const unsigned char dh_base[] = {
+ 0xdd, 0x5d, 0x87, 0xa6, 0xf9, 0xdf, 0x57, 0xf1, 0x3d, 0xf2, 0xc6, 0x58, 0xe5, 0x01, 0xab, 0xd7,
+ 0x2a, 0xdb, 0xa3, 0x48, 0x63, 0x61, 0x3b, 0xd1, 0x67, 0x69, 0xee, 0xf9, 0x55, 0x25, 0x8e, 0x36,
+ 0x11, 0xee, 0x8e, 0xc5, 0x42, 0xa4, 0x26, 0xe3, 0x75, 0xc6, 0xb4, 0xd8, 0x3b, 0x71, 0x7c, 0x97,
+ 0xf8, 0x85, 0x04, 0xb4, 0x3a, 0xcc, 0x5d, 0xf0, 0x3a, 0x49, 0x04, 0xe8, 0x8d, 0x26, 0x19, 0xdf,
+ 0xb7, 0xfb, 0x3c, 0xda, 0x68, 0xbc, 0x13, 0x6c, 0x46, 0x8d, 0xfe, 0xdf, 0x1c, 0x5a, 0x5b, 0x73,
+ 0x04, 0x64, 0x08, 0x86, 0x6f, 0xec, 0x89, 0x49, 0xbe, 0xb5, 0x87, 0xa0, 0xa4, 0xb6, 0xe6, 0xc0,
+ 0xde, 0xf5, 0xf2, 0x44, 0x05, 0x38, 0x51, 0x84, 0xa6, 0x9e, 0x9d, 0xce, 0x42, 0x08, 0xf3, 0x63,
+ 0xad, 0xb0, 0xe1, 0xce, 0x88, 0x18, 0x63, 0xeb, 0x8d, 0x82, 0xd4, 0xae, 0xad, 0x5e, 0x1c, 0x19,
+ 0x50, 0x47, 0xd7, 0x0d, 0x9b, 0xdc, 0x44, 0x7b, 0xda, 0x02, 0x76, 0x84, 0xb4, 0x35, 0x1d, 0x98,
+ 0x50, 0x3f, 0xee, 0x1b, 0xcf, 0x82, 0x7f, 0xfd, 0x07, 0x50, 0x17, 0x01, 0xc7, 0xf3, 0x91, 0x24,
+ 0x22, 0xdd, 0x2f, 0x42, 0xb2, 0x6c, 0xf4, 0x0a, 0xdd, 0xe0, 0x7d, 0x63, 0xe2, 0x35, 0xf4, 0x2f,
+ 0x65, 0x21, 0x40, 0x2a, 0x90, 0xdd, 0x2c, 0xea, 0x4a, 0x2e, 0x17, 0x76, 0x40, 0x74, 0x2d, 0x3c,
+ 0xac, 0x85, 0x3e, 0x96, 0xfa, 0x49, 0x44, 0x13, 0xfe, 0xe9, 0x45, 0x97, 0x2b, 0x24, 0x23, 0xa0,
+ 0xf5, 0x1b, 0xec, 0xf2, 0x85, 0x28, 0xc9, 0xdb, 0x92, 0x60, 0x02, 0xc5, 0x0f, 0xfe, 0x2b, 0x1a,
+ 0x97, 0xc9, 0x78, 0xcf, 0x48, 0x8b, 0xa2, 0x9b, 0xbb, 0x47, 0x2e, 0x7e, 0x63, 0x28, 0x2d, 0xdd,
+ 0x32, 0x0a, 0x15, 0xa0, 0x72, 0xd8, 0x17, 0x60, 0x75, 0x20, 0x4f, 0x7d, 0xed, 0x29, 0x35, 0x61,
+};
+
+static const unsigned char dh_expected_secret[] = {
+ 0x61, 0xfc, 0x0d, 0x4d, 0x01, 0xce, 0xe1, 0x52, 0x34, 0x0f, 0x52, 0xb4, 0x53, 0x28, 0xaa, 0x11,
+ 0xd8, 0x6e, 0x92, 0xce, 0x8e, 0x8f, 0x7b, 0xa2, 0x91, 0x80, 0xf6, 0x2d, 0x99, 0x9b, 0xc7, 0x71,
+ 0x4c, 0xbb, 0x05, 0xef, 0xde, 0x22, 0xbd, 0xdf, 0x6f, 0x8d, 0xbb, 0x00, 0xdf, 0x4e, 0xfa, 0x1c,
+ 0x14, 0xea, 0x54, 0x20, 0xac, 0xec, 0x51, 0xcd, 0xbd, 0xd0, 0x63, 0xfc, 0x35, 0x7b, 0xd9, 0xab,
+ 0x36, 0x7f, 0x1b, 0x67, 0xc3, 0xb1, 0x51, 0x4e, 0x2d, 0x19, 0x05, 0x50, 0xbe, 0x1d, 0x44, 0x51,
+ 0x5f, 0xfe, 0x65, 0xf8, 0xf6, 0x12, 0xad, 0x6c, 0xc5, 0x84, 0x96, 0xd9, 0xc3, 0xc9, 0x39, 0x7d,
+ 0x87, 0x98, 0xa7, 0x8e, 0x52, 0x4d, 0x1f, 0x26, 0xbe, 0x62, 0x14, 0xf4, 0x66, 0xcf, 0x9a, 0x90,
+ 0x4d, 0x28, 0xdd, 0x29, 0x11, 0x6e, 0x51, 0x0c, 0x7b, 0x18, 0x1e, 0xac, 0x55, 0x49, 0xce, 0x1d,
+ 0xef, 0xcc, 0x6c, 0xa2, 0x0e, 0x80, 0xd3, 0x0d, 0x24, 0xc0, 0x77, 0x68, 0x87, 0xf8, 0xa3, 0x05,
+ 0x0f, 0x8d, 0xaa, 0x58, 0x6b, 0xbb, 0x6b, 0xd0, 0x76, 0xea, 0x87, 0x5c, 0xc3, 0x3e, 0xef, 0x19,
+ 0x66, 0x9e, 0xc7, 0xd4, 0x4e, 0x85, 0xdf, 0x06, 0x61, 0x0b, 0x94, 0x9c, 0xd3, 0x58, 0x23, 0xa7,
+ 0xb1, 0xf6, 0x36, 0xaf, 0x6b, 0x4c, 0xf1, 0x88, 0x40, 0xd4, 0x5f, 0x6e, 0x9d, 0x1f, 0xa7, 0x3c,
+ 0x8b, 0xc2, 0x71, 0xba, 0x87, 0xcd, 0xc2, 0x9b, 0x33, 0xcf, 0x18, 0xee, 0x59, 0x8e, 0xf6, 0x6c,
+ 0x76, 0xcc, 0xed, 0xcc, 0x09, 0xfe, 0xe1, 0xf8, 0xce, 0x5c, 0x78, 0xb3, 0xb9, 0xe3, 0xf5, 0x29,
+ 0x14, 0xaa, 0x67, 0xd0, 0xb5, 0xcb, 0x7a, 0x7e, 0xd1, 0x2e, 0x83, 0x97, 0xf1, 0x6b, 0xfb, 0xe4,
+ 0xfb, 0xeb, 0xdd, 0x18, 0x54, 0x0d, 0x4c, 0xa7, 0x65, 0xc1, 0x0c, 0x11, 0xad, 0xea, 0x83, 0x9f,
+};
+
+#endif /* KEYCTL_DH_DATA_H__ */
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 18/33] keyctl26: Test KEYCTL_DH_COMPUTE size query
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (16 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 17/33] keyctl25: Test KEYCTL_DH_COMPUTE shared secret computation Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 19/33] keyctl27: Test KEYCTL_DH_COMPUTE KDF key derivation Andrea Cervesato
` (14 subsequent siblings)
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Test KEYCTL_DH_COMPUTE buffer size query: verify that calling
with buflen 0 returns the required output buffer size (256)
without writing to userspace.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl26.c | 53 +++++++++++++++++++++++++++++
3 files changed, 55 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index 1b059f652..108efa4a8 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -743,6 +743,7 @@ keyctl22 keyctl22
keyctl23 keyctl23
keyctl24 keyctl24
keyctl25 keyctl25
+keyctl26 keyctl26
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index 4cf772558..dd282b7ce 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -23,3 +23,4 @@
/keyctl23
/keyctl24
/keyctl25
+/keyctl26
diff --git a/testcases/kernel/syscalls/keyctl/keyctl26.c b/testcases/kernel/syscalls/keyctl/keyctl26.c
new file mode 100644
index 000000000..32bc5f393
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl26.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Test ``KEYCTL_DH_COMPUTE`` size query of :manpage:`keyctl(2)`.
+ *
+ * [Algorithm]
+ *
+ * - verify calling ``KEYCTL_DH_COMPUTE`` with ``buflen = 0`` returns required
+ * buffer size (256) without writing
+ */
+
+#include "keyctl_common.h"
+#include "keyctl_dh_data.h"
+
+static struct keyctl_dh_params *dh_params;
+
+static void setup(void)
+{
+ SAFE_KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
+
+ dh_params->priv = new_user_key("dh_priv", dh_priv, sizeof(dh_priv),
+ KEY_SPEC_PROCESS_KEYRING);
+ dh_params->prime = new_user_key("dh_prime", dh_prime, sizeof(dh_prime),
+ KEY_SPEC_PROCESS_KEYRING);
+ dh_params->base = new_user_key("dh_base", dh_base, sizeof(dh_base),
+ KEY_SPEC_PROCESS_KEYRING);
+}
+
+static void run(void)
+{
+ TST_EXP_VAL(keyctl(KEYCTL_DH_COMPUTE, (unsigned long)dh_params,
+ (unsigned long)NULL, 0, 0),
+ (long)sizeof(dh_expected_secret));
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test_all = run,
+ .min_kver = "4.7",
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_KEYS=y",
+ "CONFIG_KEY_DH_OPERATIONS=y",
+ "CONFIG_CRYPTO_DH",
+ NULL
+ },
+ .bufs = (struct tst_buffers []) {
+ {&dh_params, .size = sizeof(*dh_params)},
+ {},
+ },
+};
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 19/33] keyctl27: Test KEYCTL_DH_COMPUTE KDF key derivation
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (17 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 18/33] keyctl26: Test KEYCTL_DH_COMPUTE size query Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 20/33] keyctl28: Negative and boundary tests for KEYCTL_DH_COMPUTE Andrea Cervesato
` (13 subsequent siblings)
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Test KEYCTL_DH_COMPUTE SP800-56A KDF key derivation: verify that
deriving a key using SHA-256 and otherinfo matches the precomputed
mathematical test vector.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl27.c | 78 +++++++++++++++++++++++
testcases/kernel/syscalls/keyctl/keyctl_dh_data.h | 5 ++
4 files changed, 85 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index 108efa4a8..d23461c4b 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -744,6 +744,7 @@ keyctl23 keyctl23
keyctl24 keyctl24
keyctl25 keyctl25
keyctl26 keyctl26
+keyctl27 keyctl27
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index dd282b7ce..720ba1de6 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -24,3 +24,4 @@
/keyctl24
/keyctl25
/keyctl26
+/keyctl27
diff --git a/testcases/kernel/syscalls/keyctl/keyctl27.c b/testcases/kernel/syscalls/keyctl/keyctl27.c
new file mode 100644
index 000000000..288bd0f37
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl27.c
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Test ``KEYCTL_DH_COMPUTE`` KDF key derivation of :manpage:`keyctl(2)`.
+ *
+ * The KDF extension to ``KEYCTL_DH_COMPUTE`` (SP800-56A) landed in Linux 4.12.
+ *
+ * [Algorithm]
+ *
+ * - derive key with SP800-56A KDF (SHA-256 + otherinfo), verify derived
+ * key matches expected 32-byte value
+ */
+
+#include "keyctl_common.h"
+#include "keyctl_dh_data.h"
+
+#define KDF_OTHERINFO "LTP-KDF-TEST-INFO"
+
+static struct keyctl_dh_params *dh_params;
+static struct keyctl_kdf_params *kdf_params;
+static unsigned char out_buf[32];
+
+static void setup(void)
+{
+ SAFE_KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
+
+ dh_params->priv = new_user_key("dh_priv", dh_priv, sizeof(dh_priv),
+ KEY_SPEC_PROCESS_KEYRING);
+ dh_params->prime = new_user_key("dh_prime", dh_prime, sizeof(dh_prime),
+ KEY_SPEC_PROCESS_KEYRING);
+ dh_params->base = new_user_key("dh_base", dh_base, sizeof(dh_base),
+ KEY_SPEC_PROCESS_KEYRING);
+}
+
+static void run(void)
+{
+ memset(kdf_params, 0, sizeof(*kdf_params));
+ kdf_params->hashname = "sha256";
+ kdf_params->otherinfo = (char *)KDF_OTHERINFO;
+ kdf_params->otherinfolen = strlen(KDF_OTHERINFO);
+
+ memset(out_buf, 0, sizeof(out_buf));
+ TST_EXP_EQ_LI_SILENT(keyctl(KEYCTL_DH_COMPUTE, (unsigned long)dh_params,
+ (unsigned long)out_buf,
+ sizeof(dh_kdf_expected),
+ (unsigned long)kdf_params),
+ (long)sizeof(dh_kdf_expected));
+ if (!TST_PASS)
+ return;
+
+ if (memcmp(out_buf, dh_kdf_expected, sizeof(dh_kdf_expected))) {
+ tst_res(TFAIL, "derived KDF key does not match expected value");
+ return;
+ }
+
+ tst_res(TPASS, "KEYCTL_DH_COMPUTE with KDF derived expected key");
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test_all = run,
+ .min_kver = "4.12",
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_KEYS=y",
+ "CONFIG_KEY_DH_OPERATIONS=y",
+ "CONFIG_CRYPTO_DH",
+ "CONFIG_CRYPTO_SHA256",
+ NULL
+ },
+ .bufs = (struct tst_buffers []) {
+ {&dh_params, .size = sizeof(*dh_params)},
+ {&kdf_params, .size = sizeof(*kdf_params)},
+ {},
+ },
+};
diff --git a/testcases/kernel/syscalls/keyctl/keyctl_dh_data.h b/testcases/kernel/syscalls/keyctl/keyctl_dh_data.h
index bc1432dc3..7ac7876a0 100644
--- a/testcases/kernel/syscalls/keyctl/keyctl_dh_data.h
+++ b/testcases/kernel/syscalls/keyctl/keyctl_dh_data.h
@@ -71,4 +71,9 @@ static const unsigned char dh_expected_secret[] = {
0xfb, 0xeb, 0xdd, 0x18, 0x54, 0x0d, 0x4c, 0xa7, 0x65, 0xc1, 0x0c, 0x11, 0xad, 0xea, 0x83, 0x9f,
};
+static const unsigned char dh_kdf_expected[] = {
+ 0x66, 0x39, 0xec, 0x41, 0x31, 0x33, 0xe6, 0xc0, 0x61, 0x67, 0x28, 0x51, 0x61, 0xf7, 0x8c, 0xd7,
+ 0xc0, 0x55, 0xc9, 0xcc, 0x83, 0x46, 0xf3, 0xaa, 0x62, 0xed, 0xca, 0x90, 0x99, 0x2d, 0xc4, 0x07,
+};
+
#endif /* KEYCTL_DH_DATA_H__ */
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 20/33] keyctl28: Negative and boundary tests for KEYCTL_DH_COMPUTE
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (18 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 19/33] keyctl27: Test KEYCTL_DH_COMPUTE KDF key derivation Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 21/33] lapi/keyctl.h: Add fallback definitions for public key ops Andrea Cervesato
` (12 subsequent siblings)
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Test error and boundary conditions of KEYCTL_DH_COMPUTE using a
parameterized tcase table: buffer smaller than secret (EOVERFLOW),
bogus prime key (ENOKEY), non-user key (EOPNOTSUPP), NULL buffer
(EINVAL), non-zero __spare (EINVAL), buflen > 1024 (EMSGSIZE),
otherinfolen > 64 (EMSGSIZE), and unknown KDF hash name (ENOENT).
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl28.c | 140 ++++++++++++++++++++++++++++
3 files changed, 142 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index d23461c4b..6fdbbea17 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -745,6 +745,7 @@ keyctl24 keyctl24
keyctl25 keyctl25
keyctl26 keyctl26
keyctl27 keyctl27
+keyctl28 keyctl28
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index 720ba1de6..139e480b3 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -25,3 +25,4 @@
/keyctl25
/keyctl26
/keyctl27
+/keyctl28
diff --git a/testcases/kernel/syscalls/keyctl/keyctl28.c b/testcases/kernel/syscalls/keyctl/keyctl28.c
new file mode 100644
index 000000000..f62aeb582
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl28.c
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Negative and boundary test cases for ``KEYCTL_DH_COMPUTE`` of :manpage:`keyctl(2)`.
+ *
+ * [Algorithm]
+ *
+ * - verify ``EOVERFLOW`` when buffer is smaller than secret size (255 < 256)
+ * - verify ``ENOKEY`` when prime key id does not exist
+ * - verify ``EOPNOTSUPP`` when prime key is not of "user" type
+ * - verify ``EINVAL`` when buffer is ``NULL`` with non-zero buflen
+ * - verify ``EINVAL`` when KDF ``__spare`` field contains non-zero data
+ * - verify ``EMSGSIZE`` when KDF requested output length exceeds 1024
+ * - verify ``EMSGSIZE`` when KDF otherinfo length exceeds 64
+ * - verify ``ENOENT`` when KDF hash algorithm name is unknown
+ */
+
+#include "keyctl_common.h"
+#include "keyctl_dh_data.h"
+
+static struct keyctl_dh_params *dh_params;
+static struct keyctl_dh_params *dh_bogus_prime;
+static struct keyctl_dh_params *dh_nonuser_prime;
+
+static struct keyctl_kdf_params *kdf_valid;
+static struct keyctl_kdf_params *kdf_spare_nonzero;
+static struct keyctl_kdf_params *kdf_oi_toolarge;
+static struct keyctl_kdf_params *kdf_unknown_hash;
+
+static unsigned char out_buf[1025];
+
+static struct tcase {
+ struct keyctl_dh_params **params;
+ void *buffer;
+ size_t buflen;
+ struct keyctl_kdf_params **kdf;
+ int exp_errno;
+ const char *desc;
+} tcases[] = {
+ { &dh_params, out_buf, 255, NULL,
+ EOVERFLOW, "buffer smaller than secret size (255 < 256)" },
+
+ { &dh_bogus_prime, out_buf, 256, NULL,
+ ENOKEY, "bogus prime key ID" },
+
+ { &dh_nonuser_prime, out_buf, 256, NULL,
+ EOPNOTSUPP, "non-user key as prime parameter" },
+
+ { &dh_params, NULL, 256, NULL,
+ EINVAL, "NULL buffer with non-zero buflen" },
+
+ { &dh_params, out_buf, 32, &kdf_spare_nonzero,
+ EINVAL, "KDF non-zero __spare field" },
+
+ { &dh_params, out_buf, 1025, &kdf_valid,
+ EMSGSIZE, "KDF output length > 1024" },
+
+ { &dh_params, out_buf, 32, &kdf_oi_toolarge,
+ EMSGSIZE, "KDF otherinfolen > 64" },
+
+ { &dh_params, out_buf, 32, &kdf_unknown_hash,
+ ENOENT, "unknown KDF hash algorithm name" },
+};
+
+static void setup(void)
+{
+ key_serial_t key_priv, key_prime, key_base;
+
+ SAFE_KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
+
+ key_priv = new_user_key("dh_priv", dh_priv, sizeof(dh_priv),
+ KEY_SPEC_PROCESS_KEYRING);
+ key_prime = new_user_key("dh_prime", dh_prime, sizeof(dh_prime),
+ KEY_SPEC_PROCESS_KEYRING);
+ key_base = new_user_key("dh_base", dh_base, sizeof(dh_base),
+ KEY_SPEC_PROCESS_KEYRING);
+
+ dh_params->priv = key_priv;
+ dh_params->prime = key_prime;
+ dh_params->base = key_base;
+
+ *dh_bogus_prime = *dh_params;
+ dh_bogus_prime->prime = INT32_MAX;
+
+ *dh_nonuser_prime = *dh_params;
+ dh_nonuser_prime->prime = KEY_SPEC_PROCESS_KEYRING;
+
+ kdf_valid->hashname = "sha256";
+ kdf_valid->otherinfo = "info";
+ kdf_valid->otherinfolen = 4;
+
+ *kdf_spare_nonzero = *kdf_valid;
+ kdf_spare_nonzero->__spare[0] = 1;
+
+ *kdf_oi_toolarge = *kdf_valid;
+ kdf_oi_toolarge->otherinfolen = 65;
+
+ *kdf_unknown_hash = *kdf_valid;
+ kdf_unknown_hash->hashname = "sha9000";
+}
+
+static void verify_negative(unsigned int n)
+{
+ struct tcase *tc = &tcases[n];
+ struct keyctl_dh_params *p = *tc->params;
+ struct keyctl_kdf_params *kdf = tc->kdf ? *tc->kdf : NULL;
+
+ TST_EXP_FAIL2(keyctl(KEYCTL_DH_COMPUTE, (unsigned long)p,
+ (unsigned long)tc->buffer, tc->buflen,
+ (unsigned long)kdf),
+ tc->exp_errno,
+ "KEYCTL_DH_COMPUTE with %s", tc->desc);
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test = verify_negative,
+ .tcnt = ARRAY_SIZE(tcases),
+ .min_kver = "4.12",
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_KEYS=y",
+ "CONFIG_KEY_DH_OPERATIONS=y",
+ "CONFIG_CRYPTO_DH",
+ "CONFIG_CRYPTO_SHA256",
+ NULL
+ },
+ .bufs = (struct tst_buffers []) {
+ {&dh_params, .size = sizeof(*dh_params)},
+ {&dh_bogus_prime, .size = sizeof(*dh_bogus_prime)},
+ {&dh_nonuser_prime, .size = sizeof(*dh_nonuser_prime)},
+ {&kdf_valid, .size = sizeof(*kdf_valid)},
+ {&kdf_spare_nonzero, .size = sizeof(*kdf_spare_nonzero)},
+ {&kdf_oi_toolarge, .size = sizeof(*kdf_oi_toolarge)},
+ {&kdf_unknown_hash, .size = sizeof(*kdf_unknown_hash)},
+ {},
+ },
+};
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 21/33] lapi/keyctl.h: Add fallback definitions for public key ops
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (19 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 20/33] keyctl28: Negative and boundary tests for KEYCTL_DH_COMPUTE Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 22/33] keyctl29: Test KEYCTL_PKEY_QUERY on public key Andrea Cervesato
` (11 subsequent siblings)
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Add fallback definitions for KEYCTL_PKEY_QUERY, KEYCTL_PKEY_ENCRYPT,
KEYCTL_PKEY_DECRYPT, KEYCTL_PKEY_SIGN, KEYCTL_PKEY_VERIFY, and
KEYCTL_SUPPORTS_*, as well as fallback structs keyctl_pkey_query
and keyctl_pkey_params when built without keyutils.h or linux/keyctl.h.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
include/lapi/keyctl.h | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 52 insertions(+)
diff --git a/include/lapi/keyctl.h b/include/lapi/keyctl.h
index a056ddaad..8820c3ddb 100644
--- a/include/lapi/keyctl.h
+++ b/include/lapi/keyctl.h
@@ -33,6 +33,26 @@ struct keyctl_kdf_params {
uint32_t otherinfolen;
uint32_t __spare[8];
};
+
+struct keyctl_pkey_query {
+ uint32_t supported_ops;
+ uint32_t key_size;
+ uint16_t max_data_size;
+ uint16_t max_sig_size;
+ uint16_t max_enc_size;
+ uint16_t max_dec_size;
+ uint32_t __spare[10];
+};
+
+struct keyctl_pkey_params {
+ int32_t key_id;
+ uint32_t in_len;
+ union {
+ uint32_t out_len;
+ uint32_t in2_len;
+ };
+ uint32_t __spare[7];
+};
#endif
static inline key_serial_t add_key(const char *type,
@@ -199,6 +219,33 @@ static inline key_serial_t keyctl_join_session_keyring(const char *name) {
# define KEYCTL_MOVE_EXCL 0x00000001 /* do not displace from the to-keyring */
#endif
+#ifndef KEYCTL_PKEY_QUERY
+# define KEYCTL_PKEY_QUERY 24
+#endif
+
+#ifndef KEYCTL_PKEY_ENCRYPT
+# define KEYCTL_PKEY_ENCRYPT 25
+#endif
+
+#ifndef KEYCTL_PKEY_DECRYPT
+# define KEYCTL_PKEY_DECRYPT 26
+#endif
+
+#ifndef KEYCTL_PKEY_SIGN
+# define KEYCTL_PKEY_SIGN 27
+#endif
+
+#ifndef KEYCTL_PKEY_VERIFY
+# define KEYCTL_PKEY_VERIFY 28
+#endif
+
+#ifndef KEYCTL_SUPPORTS_ENCRYPT
+# define KEYCTL_SUPPORTS_ENCRYPT 0x01
+# define KEYCTL_SUPPORTS_DECRYPT 0x02
+# define KEYCTL_SUPPORTS_SIGN 0x04
+# define KEYCTL_SUPPORTS_VERIFY 0x08
+#endif
+
/* key permissions */
#ifndef KEY_POS_VIEW
# define KEY_POS_VIEW 0x01000000
@@ -259,6 +306,11 @@ static inline long safe_keyctl(const char *file, const int lineno,
case KEYCTL_GET_SECURITY:
case KEYCTL_GET_PERSISTENT:
case KEYCTL_DH_COMPUTE:
+ case KEYCTL_PKEY_QUERY:
+ case KEYCTL_PKEY_ENCRYPT:
+ case KEYCTL_PKEY_DECRYPT:
+ case KEYCTL_PKEY_SIGN:
+ case KEYCTL_PKEY_VERIFY:
if (rval < 0)
failure = 1;
break;
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 22/33] keyctl29: Test KEYCTL_PKEY_QUERY on public key
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (20 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 21/33] lapi/keyctl.h: Add fallback definitions for public key ops Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 23/33] keyctl30: Test KEYCTL_PKEY_QUERY on private key Andrea Cervesato
` (10 subsequent siblings)
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Test KEYCTL_PKEY_QUERY operation on an RSA-2048 X.509 public key
certificate: verify key_size is 2048, supported_ops contains
ENCRYPT and VERIFY, and max_enc_size/max_sig_size are 256.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl29.c | 90 ++++++++++++++++++++++
testcases/kernel/syscalls/keyctl/keyctl_common.h | 20 +++++
.../kernel/syscalls/keyctl/keyctl_pkey_data.h | 68 ++++++++++++++++
5 files changed, 180 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index 6fdbbea17..432369e63 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -746,6 +746,7 @@ keyctl25 keyctl25
keyctl26 keyctl26
keyctl27 keyctl27
keyctl28 keyctl28
+keyctl29 keyctl29
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index 139e480b3..91310b001 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -26,3 +26,4 @@
/keyctl26
/keyctl27
/keyctl28
+/keyctl29
diff --git a/testcases/kernel/syscalls/keyctl/keyctl29.c b/testcases/kernel/syscalls/keyctl/keyctl29.c
new file mode 100644
index 000000000..8fee5fb08
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl29.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Test ``KEYCTL_PKEY_QUERY`` on public key of :manpage:`keyctl(2)`.
+ *
+ * ``KEYCTL_PKEY_QUERY`` queries the parameters, operations, and buffer
+ * size limits of an asymmetric public or private key.
+ *
+ * Requires root (CAP_SYS_MODULE) to load the ``x509_key_parser`` module.
+ *
+ * [Algorithm]
+ *
+ * - query an RSA-2048 X.509 public key certificate
+ * - verify ``key_size`` is 2048 bits
+ * - verify ``supported_ops`` contains ``KEYCTL_SUPPORTS_ENCRYPT`` and
+ * ``KEYCTL_SUPPORTS_VERIFY``
+ * - verify ``max_enc_size`` is 256 bytes
+ * - verify ``max_sig_size`` is 256 bytes
+ */
+
+#include "keyctl_common.h"
+#include "keyctl_pkey_data.h"
+#include "tst_module.h"
+
+static key_serial_t cert_key;
+static struct keyctl_pkey_query *query_buf;
+
+static void setup(void)
+{
+ SAFE_KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
+
+ tst_modprobe("x509_key_parser", NULL);
+
+ cert_key = add_asymmetric_key_or_tconf("cert", rsa2048_cert,
+ sizeof(rsa2048_cert),
+ "CONFIG_X509_CERTIFICATE_PARSER");
+}
+
+static void run(void)
+{
+ memset(query_buf, 0, sizeof(*query_buf));
+
+ TST_EXP_EQ_LI_SILENT(keyctl(KEYCTL_PKEY_QUERY, (unsigned long)cert_key,
+ 0, (unsigned long)"enc=pkcs1",
+ (unsigned long)query_buf), 0);
+ if (!TST_PASS)
+ return;
+
+ TST_EXP_EQ_LU_SILENT(query_buf->key_size, 2048);
+ if (!TST_PASS)
+ return;
+
+ TST_EXP_EXPR(query_buf->supported_ops & KEYCTL_SUPPORTS_ENCRYPT,
+ "KEYCTL_PKEY_QUERY supports ENCRYPT");
+
+ TST_EXP_EXPR(query_buf->supported_ops & KEYCTL_SUPPORTS_VERIFY,
+ "KEYCTL_PKEY_QUERY supports VERIFY");
+
+ TST_EXP_EQ_LU_SILENT(query_buf->max_enc_size, 256);
+ if (!TST_PASS)
+ return;
+
+ TST_EXP_EQ_LU_SILENT(query_buf->max_sig_size, 256);
+ if (!TST_PASS)
+ return;
+
+ tst_res(TPASS, "KEYCTL_PKEY_QUERY on X.509 cert returned valid parameters");
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test_all = run,
+ .min_kver = "4.20",
+ .needs_root = 1,
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_KEYS=y",
+ "CONFIG_ASYMMETRIC_KEY_TYPE=y",
+ "CONFIG_X509_CERTIFICATE_PARSER",
+ "CONFIG_CRYPTO_RSA",
+ "CONFIG_CRYPTO_SHA256",
+ NULL
+ },
+ .bufs = (struct tst_buffers []) {
+ {&query_buf, .size = sizeof(*query_buf)},
+ {},
+ },
+};
diff --git a/testcases/kernel/syscalls/keyctl/keyctl_common.h b/testcases/kernel/syscalls/keyctl/keyctl_common.h
index c7290cc6e..723fe228b 100644
--- a/testcases/kernel/syscalls/keyctl/keyctl_common.h
+++ b/testcases/kernel/syscalls/keyctl/keyctl_common.h
@@ -50,4 +50,24 @@ static inline key_serial_t search_ring(key_serial_t ring, const char *type,
(unsigned long)desc, 0);
}
+static inline key_serial_t add_asymmetric_key_or_tconf(const char *desc,
+ const void *payload,
+ size_t plen,
+ const char *parser_kconfig)
+{
+ TEST(add_key("asymmetric", desc, payload, plen, KEY_SPEC_PROCESS_KEYRING));
+ if (TST_RET >= 0)
+ return TST_RET;
+
+ if (TST_ERR == ENODEV)
+ tst_brk(TCONF, "kernel does not support asymmetric keys");
+ if (TST_ERR == EBADMSG)
+ tst_brk(TCONF, "missing asymmetric parser (%s)", parser_kconfig);
+ if (TST_ERR == ENOENT)
+ tst_brk(TCONF, "missing crypto RSA / SHA256 algorithms");
+
+ tst_brk(TBROK | TTERRNO, "failed to add asymmetric key '%s'", desc);
+ return -1;
+}
+
#endif /* KEYCTL_COMMON_H__ */
diff --git a/testcases/kernel/syscalls/keyctl/keyctl_pkey_data.h b/testcases/kernel/syscalls/keyctl/keyctl_pkey_data.h
new file mode 100644
index 000000000..f5e55d94e
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl_pkey_data.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ *
+ * Static test vectors for KEYCTL_PKEY_* tests (keyctl29..keyctl33).
+ */
+
+#ifndef KEYCTL_PKEY_DATA_H__
+#define KEYCTL_PKEY_DATA_H__
+
+/*
+ * RSA-2048 self-signed X.509 certificate in DER format generated using:
+ * openssl req -x509 -newkey rsa:2048 -subj "/CN=ltp-keyctl-pkey" -days 36500 -nodes -batch -outform der
+ */
+static const unsigned char rsa2048_cert[] = {
+ 0x30, 0x82, 0x03, 0x17, 0x30, 0x82, 0x01, 0xff, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x14, 0x52,
+ 0xd4, 0x3e, 0xcb, 0x8a, 0x14, 0xa8, 0x5b, 0x02, 0x72, 0x3b, 0x64, 0xf9, 0x9d, 0x52, 0xa3, 0xca,
+ 0x61, 0x08, 0x78, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
+ 0x05, 0x00, 0x30, 0x1a, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x6c,
+ 0x74, 0x70, 0x2d, 0x6b, 0x65, 0x79, 0x63, 0x74, 0x6c, 0x2d, 0x70, 0x6b, 0x65, 0x79, 0x30, 0x20,
+ 0x17, 0x0d, 0x32, 0x36, 0x30, 0x39, 0x30, 0x31, 0x30, 0x39, 0x31, 0x31, 0x32, 0x36, 0x5a, 0x18,
+ 0x0f, 0x32, 0x31, 0x32, 0x36, 0x30, 0x38, 0x30, 0x38, 0x30, 0x39, 0x31, 0x31, 0x32, 0x36, 0x5a,
+ 0x30, 0x1a, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x6c, 0x74, 0x70,
+ 0x2d, 0x6b, 0x65, 0x79, 0x63, 0x74, 0x6c, 0x2d, 0x70, 0x6b, 0x65, 0x79, 0x30, 0x82, 0x01, 0x22,
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03,
+ 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xd3, 0x97, 0x61,
+ 0x14, 0x08, 0xb7, 0xca, 0x73, 0x54, 0xd0, 0x39, 0xb9, 0xaf, 0x62, 0x12, 0xcc, 0x90, 0xde, 0x86,
+ 0xeb, 0x13, 0x91, 0x06, 0x83, 0xf3, 0x41, 0x48, 0xd7, 0xf7, 0xc5, 0x50, 0x26, 0x1f, 0x2d, 0x53,
+ 0x09, 0x43, 0x59, 0x25, 0x81, 0x04, 0x98, 0x84, 0x4c, 0x10, 0x32, 0xee, 0x63, 0x60, 0xde, 0x1a,
+ 0x76, 0x63, 0xc3, 0x5d, 0x79, 0x12, 0xf2, 0xbf, 0x33, 0xd6, 0x4c, 0xf2, 0x47, 0x56, 0x03, 0x41,
+ 0x51, 0x74, 0x7f, 0x7d, 0x80, 0x64, 0x32, 0x1c, 0x1c, 0x19, 0xac, 0x12, 0x08, 0xd6, 0xd2, 0x27,
+ 0x21, 0x6c, 0xda, 0x40, 0xea, 0x3b, 0x9c, 0x7f, 0xa8, 0xee, 0x86, 0x0a, 0x18, 0xca, 0xc3, 0xb6,
+ 0x6a, 0xe8, 0x90, 0xcc, 0xaf, 0x44, 0x1c, 0x03, 0xdd, 0x57, 0xfc, 0x67, 0xba, 0xae, 0x5b, 0x7b,
+ 0x3e, 0xc3, 0xda, 0xcc, 0xcf, 0x96, 0x90, 0xad, 0x72, 0x4d, 0x44, 0x7d, 0x46, 0xa5, 0x7c, 0x83,
+ 0x4b, 0x74, 0x5d, 0x16, 0x20, 0x33, 0x4b, 0x8a, 0xdf, 0x8b, 0x14, 0x21, 0x6f, 0xbb, 0xb3, 0xd9,
+ 0x97, 0xef, 0xd2, 0xbf, 0x4f, 0x41, 0x01, 0x86, 0x69, 0xa0, 0xe6, 0xce, 0x7b, 0xdd, 0xb9, 0x5c,
+ 0x35, 0xce, 0x2f, 0x0c, 0x5d, 0x23, 0x60, 0x71, 0xd7, 0x09, 0x05, 0x1c, 0x70, 0xb4, 0x02, 0xaf,
+ 0x75, 0xb6, 0xcd, 0x2f, 0xbf, 0xba, 0xd0, 0x35, 0xc6, 0xd0, 0x09, 0x50, 0xcf, 0xf9, 0xd9, 0xe8,
+ 0xdc, 0x3b, 0xca, 0x19, 0x45, 0x63, 0x1c, 0x88, 0xc9, 0x4c, 0xa7, 0x09, 0xe6, 0x2c, 0x7e, 0x81,
+ 0xd0, 0x06, 0xe4, 0x37, 0xb9, 0x42, 0xc9, 0x3b, 0x5c, 0xb5, 0x70, 0xc4, 0xb5, 0x20, 0x14, 0xa1,
+ 0x51, 0x37, 0xf2, 0x58, 0xa8, 0x9c, 0x11, 0xc1, 0x70, 0xe6, 0xb0, 0x45, 0xf3, 0xc5, 0x23, 0xe7,
+ 0xee, 0xa7, 0x9d, 0x9b, 0x2b, 0x81, 0xef, 0xeb, 0x63, 0xf2, 0x93, 0x15, 0x21, 0x02, 0x03, 0x01,
+ 0x00, 0x01, 0xa3, 0x53, 0x30, 0x51, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04,
+ 0x14, 0x19, 0x69, 0xa7, 0x0c, 0x58, 0xc5, 0xd7, 0xb3, 0x0b, 0x26, 0xce, 0x2a, 0x34, 0x65, 0xae,
+ 0xa7, 0xad, 0xf6, 0xab, 0x74, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16,
+ 0x80, 0x14, 0x19, 0x69, 0xa7, 0x0c, 0x58, 0xc5, 0xd7, 0xb3, 0x0b, 0x26, 0xce, 0x2a, 0x34, 0x65,
+ 0xae, 0xa7, 0xad, 0xf6, 0xab, 0x74, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
+ 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x01, 0x8a, 0x1b, 0x54, 0x91,
+ 0xbb, 0xf6, 0xd9, 0xc5, 0x09, 0x4c, 0x9f, 0xd2, 0x64, 0xaf, 0xcf, 0x4e, 0x45, 0xda, 0xc6, 0x31,
+ 0x0f, 0x55, 0x7d, 0xe7, 0x83, 0xa1, 0xfe, 0x51, 0x42, 0xda, 0xb4, 0x8b, 0xba, 0xf7, 0x15, 0xae,
+ 0xde, 0xf3, 0x05, 0x44, 0xb7, 0xc2, 0x40, 0x03, 0x33, 0x88, 0x2b, 0x32, 0xee, 0x13, 0x3b, 0x50,
+ 0xb4, 0x38, 0x32, 0x3b, 0xa6, 0xdf, 0x58, 0x6a, 0x46, 0x48, 0x0d, 0xbc, 0x4a, 0xbf, 0xce, 0xb5,
+ 0x98, 0x7f, 0x5c, 0xcb, 0x04, 0xa8, 0xbf, 0x7b, 0x28, 0x04, 0xcf, 0x3b, 0xaa, 0x4d, 0x16, 0xb8,
+ 0x5f, 0x0a, 0x60, 0xca, 0xde, 0xe1, 0x87, 0x1a, 0x40, 0xc1, 0x2c, 0x93, 0x29, 0x30, 0x79, 0x21,
+ 0xca, 0xa3, 0x58, 0xea, 0x8d, 0x93, 0x96, 0x17, 0x69, 0xa9, 0xaf, 0x16, 0xaf, 0x6f, 0x44, 0x6a,
+ 0x4e, 0x59, 0x9d, 0x4d, 0x8e, 0x69, 0x7a, 0x11, 0x62, 0xbc, 0x99, 0x7e, 0x8e, 0xa6, 0x70, 0x2a,
+ 0x7b, 0xbb, 0x33, 0xde, 0x81, 0x22, 0x6d, 0x7f, 0x18, 0xa6, 0x25, 0x1f, 0x84, 0x03, 0x9b, 0x8e,
+ 0x88, 0x1b, 0x5c, 0x08, 0xf8, 0xb1, 0xf1, 0x27, 0x39, 0xbb, 0x06, 0x6c, 0x54, 0xfa, 0xb9, 0x9c,
+ 0xe1, 0x5b, 0xff, 0xc1, 0xf2, 0x24, 0xf0, 0x79, 0xbd, 0xb1, 0x9f, 0xa5, 0xb8, 0x9c, 0x11, 0x96,
+ 0x6b, 0xa1, 0x05, 0x64, 0x41, 0x45, 0x56, 0xf3, 0x5b, 0x51, 0x5d, 0x7f, 0x5d, 0x50, 0x15, 0x48,
+ 0xd0, 0x68, 0x87, 0x8a, 0x39, 0x86, 0xae, 0x03, 0xdd, 0x2a, 0x7f, 0x48, 0x25, 0x7b, 0xde, 0xd4,
+ 0x8b, 0x3c, 0xba, 0x07, 0xc6, 0x53, 0xbb, 0x2b, 0x67, 0x98, 0x00, 0xc5, 0x5d, 0x38, 0xc0, 0xc4,
+ 0x51, 0x8e, 0x24, 0xc9, 0x85, 0x83, 0xb3, 0x16, 0x79, 0x7c, 0xcc, 0x76, 0xed, 0x02, 0x1f, 0x91,
+ 0x2c, 0xa7, 0x23, 0xae, 0x7b, 0xfd, 0xd5, 0x09, 0x09, 0x70, 0x28,
+};
+
+#endif /* KEYCTL_PKEY_DATA_H__ */
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 23/33] keyctl30: Test KEYCTL_PKEY_QUERY on private key
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (21 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 22/33] keyctl29: Test KEYCTL_PKEY_QUERY on public key Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 24/33] keyctl31: Test KEYCTL_PKEY_ENCRYPT and KEYCTL_PKEY_DECRYPT Andrea Cervesato
` (9 subsequent siblings)
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Test KEYCTL_PKEY_QUERY operation on an RSA-2048 PKCS#8 private key:
verify key_size is 2048, supported_ops contains DECRYPT and SIGN,
and max_dec_size/max_sig_size are 256.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl30.c | 86 ++++++++++++++++++++++
.../kernel/syscalls/keyctl/keyctl_pkey_data.h | 84 +++++++++++++++++++++
4 files changed, 172 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index 432369e63..15f8c892c 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -747,6 +747,7 @@ keyctl26 keyctl26
keyctl27 keyctl27
keyctl28 keyctl28
keyctl29 keyctl29
+keyctl30 keyctl30
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index 91310b001..d5b6955f3 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -27,3 +27,4 @@
/keyctl27
/keyctl28
/keyctl29
+/keyctl30
diff --git a/testcases/kernel/syscalls/keyctl/keyctl30.c b/testcases/kernel/syscalls/keyctl/keyctl30.c
new file mode 100644
index 000000000..e46206ca9
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl30.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Test ``KEYCTL_PKEY_QUERY`` on private key of :manpage:`keyctl(2)`.
+ *
+ * Requires root (CAP_SYS_MODULE) to load the ``pkcs8_key_parser`` module.
+ *
+ * [Algorithm]
+ *
+ * - query an RSA-2048 PKCS#8 private key
+ * - verify ``key_size`` is 2048 bits
+ * - verify ``supported_ops`` contains ``KEYCTL_SUPPORTS_DECRYPT`` and
+ * ``KEYCTL_SUPPORTS_SIGN``
+ * - verify ``max_dec_size`` is 256 bytes
+ * - verify ``max_sig_size`` is 256 bytes
+ */
+
+#include "keyctl_common.h"
+#include "keyctl_pkey_data.h"
+#include "tst_module.h"
+
+static key_serial_t priv_key;
+static struct keyctl_pkey_query *query_buf;
+
+static void setup(void)
+{
+ SAFE_KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
+
+ tst_modprobe("pkcs8_key_parser", NULL);
+
+ priv_key = add_asymmetric_key_or_tconf("priv", rsa2048_pkcs8,
+ sizeof(rsa2048_pkcs8),
+ "CONFIG_PKCS8_PRIVATE_KEY_PARSER");
+}
+
+static void run(void)
+{
+ memset(query_buf, 0, sizeof(*query_buf));
+
+ TST_EXP_EQ_LI_SILENT(keyctl(KEYCTL_PKEY_QUERY, (unsigned long)priv_key,
+ 0, (unsigned long)"enc=pkcs1",
+ (unsigned long)query_buf), 0);
+ if (!TST_PASS)
+ return;
+
+ TST_EXP_EQ_LU_SILENT(query_buf->key_size, 2048);
+ if (!TST_PASS)
+ return;
+
+ TST_EXP_EXPR(query_buf->supported_ops & KEYCTL_SUPPORTS_DECRYPT,
+ "KEYCTL_PKEY_QUERY supports DECRYPT");
+
+ TST_EXP_EXPR(query_buf->supported_ops & KEYCTL_SUPPORTS_SIGN,
+ "KEYCTL_PKEY_QUERY supports SIGN");
+
+ TST_EXP_EQ_LU_SILENT(query_buf->max_dec_size, 256);
+ if (!TST_PASS)
+ return;
+
+ TST_EXP_EQ_LU_SILENT(query_buf->max_sig_size, 256);
+ if (!TST_PASS)
+ return;
+
+ tst_res(TPASS, "KEYCTL_PKEY_QUERY on PKCS#8 private key returned valid parameters");
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test_all = run,
+ .min_kver = "4.20",
+ .needs_root = 1,
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_KEYS=y",
+ "CONFIG_ASYMMETRIC_KEY_TYPE=y",
+ "CONFIG_PKCS8_PRIVATE_KEY_PARSER",
+ "CONFIG_CRYPTO_RSA",
+ NULL
+ },
+ .bufs = (struct tst_buffers []) {
+ {&query_buf, .size = sizeof(*query_buf)},
+ {},
+ },
+};
diff --git a/testcases/kernel/syscalls/keyctl/keyctl_pkey_data.h b/testcases/kernel/syscalls/keyctl/keyctl_pkey_data.h
index f5e55d94e..75481b89a 100644
--- a/testcases/kernel/syscalls/keyctl/keyctl_pkey_data.h
+++ b/testcases/kernel/syscalls/keyctl/keyctl_pkey_data.h
@@ -65,4 +65,88 @@ static const unsigned char rsa2048_cert[] = {
0x2c, 0xa7, 0x23, 0xae, 0x7b, 0xfd, 0xd5, 0x09, 0x09, 0x70, 0x28,
};
+/*
+ * RSA-2048 unencrypted PKCS#8 private key in DER format generated using:
+ * openssl pkcs8 -topk8 -nocrypt -outform der
+ */
+static const unsigned char rsa2048_pkcs8[] = {
+ 0x30, 0x82, 0x04, 0xbe, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x04, 0xa8, 0x30, 0x82, 0x04, 0xa4, 0x02, 0x01,
+ 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xd3, 0x97, 0x61, 0x14, 0x08, 0xb7, 0xca, 0x73, 0x54, 0xd0,
+ 0x39, 0xb9, 0xaf, 0x62, 0x12, 0xcc, 0x90, 0xde, 0x86, 0xeb, 0x13, 0x91, 0x06, 0x83, 0xf3, 0x41,
+ 0x48, 0xd7, 0xf7, 0xc5, 0x50, 0x26, 0x1f, 0x2d, 0x53, 0x09, 0x43, 0x59, 0x25, 0x81, 0x04, 0x98,
+ 0x84, 0x4c, 0x10, 0x32, 0xee, 0x63, 0x60, 0xde, 0x1a, 0x76, 0x63, 0xc3, 0x5d, 0x79, 0x12, 0xf2,
+ 0xbf, 0x33, 0xd6, 0x4c, 0xf2, 0x47, 0x56, 0x03, 0x41, 0x51, 0x74, 0x7f, 0x7d, 0x80, 0x64, 0x32,
+ 0x1c, 0x1c, 0x19, 0xac, 0x12, 0x08, 0xd6, 0xd2, 0x27, 0x21, 0x6c, 0xda, 0x40, 0xea, 0x3b, 0x9c,
+ 0x7f, 0xa8, 0xee, 0x86, 0x0a, 0x18, 0xca, 0xc3, 0xb6, 0x6a, 0xe8, 0x90, 0xcc, 0xaf, 0x44, 0x1c,
+ 0x03, 0xdd, 0x57, 0xfc, 0x67, 0xba, 0xae, 0x5b, 0x7b, 0x3e, 0xc3, 0xda, 0xcc, 0xcf, 0x96, 0x90,
+ 0xad, 0x72, 0x4d, 0x44, 0x7d, 0x46, 0xa5, 0x7c, 0x83, 0x4b, 0x74, 0x5d, 0x16, 0x20, 0x33, 0x4b,
+ 0x8a, 0xdf, 0x8b, 0x14, 0x21, 0x6f, 0xbb, 0xb3, 0xd9, 0x97, 0xef, 0xd2, 0xbf, 0x4f, 0x41, 0x01,
+ 0x86, 0x69, 0xa0, 0xe6, 0xce, 0x7b, 0xdd, 0xb9, 0x5c, 0x35, 0xce, 0x2f, 0x0c, 0x5d, 0x23, 0x60,
+ 0x71, 0xd7, 0x09, 0x05, 0x1c, 0x70, 0xb4, 0x02, 0xaf, 0x75, 0xb6, 0xcd, 0x2f, 0xbf, 0xba, 0xd0,
+ 0x35, 0xc6, 0xd0, 0x09, 0x50, 0xcf, 0xf9, 0xd9, 0xe8, 0xdc, 0x3b, 0xca, 0x19, 0x45, 0x63, 0x1c,
+ 0x88, 0xc9, 0x4c, 0xa7, 0x09, 0xe6, 0x2c, 0x7e, 0x81, 0xd0, 0x06, 0xe4, 0x37, 0xb9, 0x42, 0xc9,
+ 0x3b, 0x5c, 0xb5, 0x70, 0xc4, 0xb5, 0x20, 0x14, 0xa1, 0x51, 0x37, 0xf2, 0x58, 0xa8, 0x9c, 0x11,
+ 0xc1, 0x70, 0xe6, 0xb0, 0x45, 0xf3, 0xc5, 0x23, 0xe7, 0xee, 0xa7, 0x9d, 0x9b, 0x2b, 0x81, 0xef,
+ 0xeb, 0x63, 0xf2, 0x93, 0x15, 0x21, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x00, 0x52,
+ 0xb0, 0xba, 0x53, 0xa6, 0x04, 0x8d, 0xad, 0xfc, 0xdb, 0x53, 0x73, 0xe9, 0xc2, 0x9e, 0x2e, 0x2b,
+ 0xff, 0x8b, 0x22, 0x9b, 0x86, 0xf5, 0xd0, 0xe3, 0x64, 0x04, 0x1f, 0xc2, 0xc8, 0xed, 0xc5, 0xb8,
+ 0x31, 0x72, 0x5e, 0x10, 0x5f, 0xea, 0x74, 0x3d, 0x63, 0x8d, 0x70, 0x5c, 0x74, 0x4b, 0x0d, 0xb3,
+ 0x71, 0x99, 0x4d, 0xe3, 0x37, 0x1a, 0x74, 0x92, 0x9f, 0x23, 0x72, 0x12, 0xb2, 0x07, 0x8d, 0x31,
+ 0x64, 0x1c, 0x46, 0xc5, 0x0c, 0x7d, 0xf3, 0x8b, 0x34, 0xba, 0x1f, 0x91, 0x38, 0xd9, 0xe3, 0x72,
+ 0x70, 0xb6, 0xb2, 0x2d, 0x64, 0x2e, 0x32, 0x5c, 0x11, 0x91, 0x22, 0x67, 0xf5, 0x22, 0x45, 0x06,
+ 0x18, 0xee, 0x55, 0x61, 0x86, 0x15, 0x37, 0xf9, 0x9a, 0x29, 0x38, 0x7b, 0x86, 0x3c, 0xd3, 0x8c,
+ 0x08, 0x5c, 0x65, 0xef, 0x0c, 0xb7, 0x35, 0xf9, 0x55, 0x99, 0x33, 0x2e, 0x57, 0x31, 0xcd, 0x90,
+ 0x0e, 0x99, 0xcd, 0xb3, 0x5f, 0xb5, 0x7e, 0x16, 0x86, 0x73, 0x47, 0xc0, 0xab, 0x6b, 0x53, 0xa1,
+ 0x8f, 0x35, 0x34, 0xd3, 0x82, 0x28, 0x7c, 0x65, 0x8e, 0xa8, 0x02, 0xe2, 0xf3, 0x83, 0x6d, 0x54,
+ 0x43, 0x23, 0x45, 0x95, 0xf1, 0x74, 0xbc, 0xf1, 0x7d, 0x64, 0x16, 0xe5, 0x01, 0xc6, 0x5a, 0xbb,
+ 0x19, 0xfa, 0x54, 0x01, 0xa4, 0x26, 0x5a, 0x2f, 0xa4, 0x20, 0xb7, 0x4c, 0x61, 0x2c, 0x2a, 0x78,
+ 0xed, 0x2f, 0xcb, 0x67, 0x26, 0xf1, 0x6b, 0x0c, 0xe3, 0x8a, 0x27, 0x9e, 0x4f, 0x00, 0x06, 0x4e,
+ 0x1d, 0x58, 0x07, 0x0e, 0x1c, 0x0d, 0x0c, 0x8c, 0x3a, 0xa7, 0x1d, 0xbe, 0xb8, 0x16, 0xdf, 0xe1,
+ 0xb3, 0x13, 0x09, 0x6a, 0xe7, 0x50, 0x80, 0x2f, 0xa1, 0x38, 0x22, 0xae, 0x2d, 0x58, 0x52, 0x07,
+ 0x96, 0x10, 0x98, 0x71, 0xe1, 0xce, 0x26, 0x88, 0x4c, 0x5e, 0x11, 0x5f, 0x6c, 0xd2, 0x31, 0x02,
+ 0x81, 0x81, 0x00, 0xf3, 0x64, 0x07, 0x8c, 0x91, 0x3c, 0x5a, 0x48, 0x14, 0x4a, 0xc1, 0x4a, 0x1a,
+ 0x93, 0xe5, 0xb8, 0x3a, 0x3c, 0xfe, 0x41, 0x60, 0x49, 0x71, 0xcc, 0xee, 0xaf, 0x0e, 0xac, 0x0c,
+ 0x85, 0x51, 0x48, 0xf9, 0x36, 0xcf, 0x8c, 0xc5, 0x58, 0x48, 0xa2, 0x49, 0x46, 0xd1, 0x33, 0x92,
+ 0x8c, 0x40, 0xfa, 0xf0, 0x76, 0xc1, 0x88, 0x8f, 0x23, 0x06, 0x8b, 0x76, 0x15, 0x89, 0xc0, 0xcd,
+ 0x4b, 0x61, 0xd8, 0xc6, 0xa2, 0xcf, 0x9c, 0x04, 0x40, 0x3b, 0x7a, 0x24, 0xc1, 0x97, 0xb9, 0x36,
+ 0xa6, 0x8b, 0xff, 0xe7, 0xef, 0xa5, 0x56, 0x3c, 0x55, 0xbf, 0x6d, 0x74, 0x33, 0xeb, 0x67, 0xb3,
+ 0x4a, 0xfe, 0x81, 0xaa, 0xad, 0xd9, 0x43, 0x23, 0x59, 0xef, 0x51, 0x99, 0x2b, 0x58, 0xa6, 0xc1,
+ 0x9c, 0x09, 0x5c, 0x88, 0xa0, 0x71, 0x1c, 0x1e, 0x94, 0x39, 0xcd, 0x82, 0x7d, 0xea, 0x41, 0xa8,
+ 0x9e, 0x05, 0x17, 0x02, 0x81, 0x81, 0x00, 0xde, 0x8d, 0x9c, 0x20, 0xa1, 0x2f, 0x47, 0x3d, 0xac,
+ 0x5f, 0x15, 0xce, 0x55, 0x52, 0x6a, 0x2f, 0x3d, 0xa0, 0xb0, 0x84, 0x92, 0x6c, 0xd6, 0x0f, 0x3c,
+ 0x2e, 0x96, 0xc0, 0x26, 0x16, 0xa9, 0x0c, 0xc0, 0xec, 0x06, 0x50, 0xe7, 0x58, 0x1d, 0xfb, 0xcc,
+ 0x9a, 0x64, 0x2f, 0x1b, 0x3a, 0x69, 0xb5, 0x51, 0xca, 0xf7, 0x2e, 0xa5, 0x01, 0x1e, 0xc9, 0x23,
+ 0x85, 0x88, 0x86, 0x9e, 0x95, 0x8c, 0x03, 0xfb, 0xaf, 0x46, 0x6c, 0x7c, 0x9a, 0x4b, 0x00, 0xb7,
+ 0x27, 0x18, 0x73, 0xea, 0x1d, 0xc6, 0x55, 0x1d, 0x4c, 0xca, 0x70, 0xb1, 0xb2, 0x76, 0x21, 0x92,
+ 0xf0, 0x6f, 0xa8, 0x81, 0x82, 0x6f, 0x52, 0x70, 0x36, 0xe0, 0x66, 0x0f, 0x4f, 0x7d, 0xda, 0xf2,
+ 0xbb, 0xca, 0xaa, 0x2d, 0x3c, 0x27, 0x2a, 0xc4, 0xa6, 0x16, 0x0a, 0xec, 0x91, 0x46, 0xbc, 0x7d,
+ 0x32, 0x87, 0xd0, 0x3b, 0x80, 0x8a, 0x87, 0x02, 0x81, 0x81, 0x00, 0xcf, 0x07, 0x6d, 0x2c, 0x72,
+ 0x75, 0xc5, 0xcd, 0xbe, 0x05, 0x00, 0x79, 0x4a, 0x36, 0x37, 0x97, 0x07, 0x62, 0xce, 0x5b, 0x49,
+ 0xcd, 0xef, 0x51, 0x04, 0x4e, 0x3f, 0xca, 0xb5, 0x33, 0xc9, 0xba, 0xaa, 0xd1, 0xa6, 0xa5, 0xf5,
+ 0x4f, 0x6d, 0x29, 0x2d, 0xef, 0x61, 0x0f, 0xdf, 0x3e, 0x12, 0x1f, 0xe1, 0xdf, 0x02, 0x2c, 0x68,
+ 0xa4, 0xc0, 0x72, 0x6c, 0x55, 0x51, 0xc1, 0x80, 0x5e, 0xf8, 0xb1, 0xed, 0xf4, 0x9b, 0x67, 0xf8,
+ 0x6d, 0xb2, 0xa9, 0xe9, 0x0e, 0x0b, 0x42, 0xee, 0x6b, 0xa8, 0x76, 0x5b, 0x11, 0x8b, 0xaf, 0xd8,
+ 0xce, 0x8f, 0x70, 0x49, 0x01, 0xc8, 0xe1, 0x82, 0xae, 0xed, 0xe1, 0xda, 0x0e, 0xda, 0xd9, 0xb2,
+ 0xfe, 0x53, 0x05, 0x33, 0xa6, 0x9d, 0x57, 0xeb, 0x24, 0x11, 0x0a, 0x76, 0xe5, 0x12, 0x91, 0x7a,
+ 0xa9, 0x56, 0xa9, 0xaa, 0xaf, 0xf4, 0x4d, 0x39, 0x62, 0x80, 0xad, 0x02, 0x81, 0x81, 0x00, 0xc6,
+ 0x20, 0x7b, 0xa5, 0xf0, 0xd9, 0x0e, 0x2b, 0x31, 0x91, 0x54, 0xf0, 0x63, 0xb5, 0x03, 0x23, 0x1b,
+ 0x52, 0x3a, 0xd3, 0x4b, 0x27, 0xe9, 0x49, 0x96, 0xe2, 0x43, 0x02, 0xbc, 0xe5, 0xdf, 0x89, 0xa3,
+ 0x16, 0x7c, 0x68, 0xfa, 0x0b, 0xd0, 0x65, 0xa2, 0x38, 0xb0, 0x87, 0xdf, 0x4d, 0x99, 0x5d, 0xfa,
+ 0x7b, 0x1e, 0xa3, 0x3f, 0xf2, 0x47, 0x5d, 0xf9, 0x69, 0x9f, 0xa9, 0x78, 0xf4, 0xd9, 0xb9, 0x92,
+ 0x0e, 0xf0, 0x3b, 0x14, 0x92, 0xa7, 0xc2, 0xf3, 0x4a, 0xb2, 0xd2, 0x3e, 0xd2, 0x53, 0x06, 0xe3,
+ 0x16, 0xc2, 0x02, 0xa1, 0xaf, 0xa6, 0xcb, 0x2c, 0xed, 0x2f, 0xfa, 0x6b, 0x91, 0x9b, 0x59, 0x60,
+ 0xdc, 0xf9, 0xd8, 0xe2, 0x38, 0x7a, 0x6a, 0xb9, 0x3d, 0xc5, 0xa6, 0xca, 0xae, 0x8a, 0x8f, 0xe0,
+ 0x91, 0x9b, 0x7e, 0x0e, 0x2d, 0x27, 0x34, 0x16, 0xa1, 0x2d, 0x97, 0x8b, 0xe1, 0x5b, 0x71, 0x02,
+ 0x81, 0x80, 0x34, 0xb5, 0x23, 0xd0, 0x7f, 0xa5, 0x1f, 0x3f, 0xa2, 0xfc, 0xb8, 0x50, 0x5f, 0x16,
+ 0x76, 0x65, 0x67, 0x48, 0x62, 0xbe, 0xf8, 0x98, 0x07, 0x5c, 0xa9, 0xc2, 0x79, 0x59, 0xda, 0xa0,
+ 0xb8, 0x1b, 0x50, 0x73, 0xd6, 0x74, 0x17, 0xba, 0x09, 0xdb, 0x08, 0xc9, 0xfb, 0xe5, 0x2c, 0xe5,
+ 0xea, 0xde, 0x32, 0x1a, 0x51, 0xdf, 0xb4, 0xa8, 0x4e, 0xb5, 0x93, 0x2d, 0x58, 0x90, 0x36, 0xaa,
+ 0xa4, 0x12, 0x53, 0x54, 0x3d, 0xb0, 0xbc, 0x52, 0xb3, 0x9a, 0x0b, 0x6e, 0x73, 0xb2, 0x57, 0x58,
+ 0xbe, 0xb8, 0xfc, 0xa0, 0xaa, 0x02, 0x69, 0xea, 0xc4, 0x1b, 0xe4, 0x3e, 0x42, 0xf0, 0xf8, 0x2d,
+ 0xa2, 0xb3, 0xa9, 0x3e, 0x57, 0xfe, 0x1a, 0xe9, 0xa6, 0xca, 0x05, 0x7f, 0x9b, 0x60, 0xd7, 0x28,
+ 0x4a, 0x6a, 0xd7, 0xf4, 0xe4, 0xa1, 0x5d, 0x5c, 0x4f, 0xed, 0xd3, 0xaa, 0xb7, 0xb9, 0xfc, 0x87,
+ 0xcd, 0xc5,
+};
+
#endif /* KEYCTL_PKEY_DATA_H__ */
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 24/33] keyctl31: Test KEYCTL_PKEY_ENCRYPT and KEYCTL_PKEY_DECRYPT
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (22 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 23/33] keyctl30: Test KEYCTL_PKEY_QUERY on private key Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 25/33] keyctl32: Test KEYCTL_PKEY_SIGN and VERIFY Andrea Cervesato
` (8 subsequent siblings)
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Test public key encryption and private key decryption with
KEYCTL_PKEY_ENCRYPT and KEYCTL_PKEY_DECRYPT: encrypt a 32-byte
plaintext using an RSA-2048 X.509 public key with enc=pkcs1,
decrypt with the matching PKCS#8 private key, and verify the
decrypted output matches the original plaintext.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl31.c | 110 ++++++++++++++++++++++++++++
3 files changed, 112 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index 15f8c892c..e43dd02ab 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -748,6 +748,7 @@ keyctl27 keyctl27
keyctl28 keyctl28
keyctl29 keyctl29
keyctl30 keyctl30
+keyctl31 keyctl31
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index d5b6955f3..025dc27fc 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -28,3 +28,4 @@
/keyctl28
/keyctl29
/keyctl30
+/keyctl31
diff --git a/testcases/kernel/syscalls/keyctl/keyctl31.c b/testcases/kernel/syscalls/keyctl/keyctl31.c
new file mode 100644
index 000000000..c1e6723ac
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl31.c
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Test ``KEYCTL_PKEY_ENCRYPT`` and ``KEYCTL_PKEY_DECRYPT`` of :manpage:`keyctl(2)`.
+ *
+ * ``KEYCTL_PKEY_ENCRYPT`` encrypts a data blob using an asymmetric public key
+ * and ``KEYCTL_PKEY_DECRYPT`` decrypts the encrypted blob using the matching
+ * private key.
+ *
+ * Requires root (CAP_SYS_MODULE) to load the ``x509_key_parser`` and
+ * ``pkcs8_key_parser`` modules.
+ *
+ * [Algorithm]
+ *
+ * - encrypt a 32-byte plaintext using an RSA-2048 X.509 public key with ``enc=pkcs1``
+ * - decrypt the 256-byte ciphertext using the matching PKCS#8 private key
+ * - verify the decrypted output matches the original 32-byte plaintext
+ */
+
+#include "keyctl_common.h"
+#include "keyctl_pkey_data.h"
+#include "tst_module.h"
+
+#define CIPHERTEXT_SIZE 256
+
+static const char plaintext[] = "LTP_PKEY_ENCRYPT_DECRYPT_TEST_32";
+#define PLAINTEXT_SIZE (sizeof(plaintext) - 1)
+static unsigned char ciphertext[CIPHERTEXT_SIZE];
+static unsigned char decrypted[CIPHERTEXT_SIZE];
+
+static key_serial_t cert_key, priv_key;
+static struct keyctl_pkey_params *enc_params;
+static struct keyctl_pkey_params *dec_params;
+
+static void setup(void)
+{
+ SAFE_KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
+
+ tst_modprobe("x509_key_parser", NULL);
+ tst_modprobe("pkcs8_key_parser", NULL);
+
+ cert_key = add_asymmetric_key_or_tconf("cert", rsa2048_cert,
+ sizeof(rsa2048_cert),
+ "CONFIG_X509_CERTIFICATE_PARSER");
+ priv_key = add_asymmetric_key_or_tconf("priv", rsa2048_pkcs8,
+ sizeof(rsa2048_pkcs8),
+ "CONFIG_PKCS8_PRIVATE_KEY_PARSER");
+}
+
+static void run(void)
+{
+ memset(ciphertext, 0, sizeof(ciphertext));
+ memset(decrypted, 0, sizeof(decrypted));
+
+ memset(enc_params, 0, sizeof(*enc_params));
+ enc_params->key_id = cert_key;
+ enc_params->in_len = PLAINTEXT_SIZE;
+ enc_params->out_len = CIPHERTEXT_SIZE;
+
+ TST_EXP_EQ_LI_SILENT(keyctl(KEYCTL_PKEY_ENCRYPT, (unsigned long)enc_params,
+ (unsigned long)"enc=pkcs1",
+ (unsigned long)plaintext,
+ (unsigned long)ciphertext),
+ CIPHERTEXT_SIZE);
+ if (!TST_PASS)
+ return;
+
+ memset(dec_params, 0, sizeof(*dec_params));
+ dec_params->key_id = priv_key;
+ dec_params->in_len = CIPHERTEXT_SIZE;
+ dec_params->out_len = CIPHERTEXT_SIZE;
+
+ TST_EXP_EQ_LI_SILENT(keyctl(KEYCTL_PKEY_DECRYPT, (unsigned long)dec_params,
+ (unsigned long)"enc=pkcs1",
+ (unsigned long)ciphertext,
+ (unsigned long)decrypted),
+ PLAINTEXT_SIZE);
+ if (!TST_PASS)
+ return;
+
+ if (memcmp(plaintext, decrypted, PLAINTEXT_SIZE)) {
+ tst_res(TFAIL, "decrypted text does not match original plaintext");
+ return;
+ }
+
+ tst_res(TPASS, "KEYCTL_PKEY_ENCRYPT and KEYCTL_PKEY_DECRYPT roundtrip succeeded");
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test_all = run,
+ .min_kver = "4.20",
+ .needs_root = 1,
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_KEYS=y",
+ "CONFIG_ASYMMETRIC_KEY_TYPE=y",
+ "CONFIG_X509_CERTIFICATE_PARSER",
+ "CONFIG_PKCS8_PRIVATE_KEY_PARSER",
+ "CONFIG_CRYPTO_RSA",
+ NULL
+ },
+ .bufs = (struct tst_buffers []) {
+ {&enc_params, .size = sizeof(*enc_params)},
+ {&dec_params, .size = sizeof(*dec_params)},
+ {},
+ },
+};
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 25/33] keyctl32: Test KEYCTL_PKEY_SIGN and VERIFY
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (23 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 24/33] keyctl31: Test KEYCTL_PKEY_ENCRYPT and KEYCTL_PKEY_DECRYPT Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 26/33] keyctl33: Negative tests for KEYCTL_PKEY_* Andrea Cervesato
` (7 subsequent siblings)
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Test public key signature creation and verification with
KEYCTL_PKEY_SIGN and KEYCTL_PKEY_VERIFY: sign a 32-byte digest
using an RSA-2048 PKCS#8 private key with enc=pkcs1, verify
the 256-byte signature with the matching X.509 public key,
and verify that a mismatched digest fails with EKEYREJECTED.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl32.c | 121 ++++++++++++++++++++++++++++
3 files changed, 123 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index e43dd02ab..d4007f7a6 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -749,6 +749,7 @@ keyctl28 keyctl28
keyctl29 keyctl29
keyctl30 keyctl30
keyctl31 keyctl31
+keyctl32 keyctl32
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index 025dc27fc..8b1627bee 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -29,3 +29,4 @@
/keyctl29
/keyctl30
/keyctl31
+/keyctl32
diff --git a/testcases/kernel/syscalls/keyctl/keyctl32.c b/testcases/kernel/syscalls/keyctl/keyctl32.c
new file mode 100644
index 000000000..4a00225f6
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl32.c
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Test ``KEYCTL_PKEY_SIGN`` and ``KEYCTL_PKEY_VERIFY`` of :manpage:`keyctl(2)`.
+ *
+ * ``KEYCTL_PKEY_SIGN`` signs a digest using an asymmetric private key and
+ * ``KEYCTL_PKEY_VERIFY`` verifies the signature using the matching public key.
+ *
+ * Requires root (CAP_SYS_MODULE) to load the ``x509_key_parser`` and
+ * ``pkcs8_key_parser`` modules.
+ *
+ * [Algorithm]
+ *
+ * - sign a 32-byte digest using an RSA-2048 PKCS#8 private key with
+ * ``enc=pkcs1 hash=sha256``
+ * - verify the 256-byte signature using the matching X.509 public key
+ * - verify a mismatched digest fails verification with ``EKEYREJECTED``
+ */
+
+#include "keyctl_common.h"
+#include "keyctl_pkey_data.h"
+#include "tst_module.h"
+
+#define DIGEST_SIZE 32
+#define SIG_SIZE 256
+
+static const unsigned char digest[DIGEST_SIZE] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+};
+
+static unsigned char sig[SIG_SIZE];
+static unsigned char wrong_digest[DIGEST_SIZE];
+
+static key_serial_t cert_key, priv_key;
+static struct keyctl_pkey_params *sign_params;
+static struct keyctl_pkey_params *verify_params;
+
+static void setup(void)
+{
+ SAFE_KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
+
+ tst_modprobe("x509_key_parser", NULL);
+ tst_modprobe("pkcs8_key_parser", NULL);
+
+ cert_key = add_asymmetric_key_or_tconf("cert", rsa2048_cert,
+ sizeof(rsa2048_cert),
+ "CONFIG_X509_CERTIFICATE_PARSER");
+ priv_key = add_asymmetric_key_or_tconf("priv", rsa2048_pkcs8,
+ sizeof(rsa2048_pkcs8),
+ "CONFIG_PKCS8_PRIVATE_KEY_PARSER");
+}
+
+static void run(void)
+{
+ memset(sig, 0, sizeof(sig));
+
+ memset(sign_params, 0, sizeof(*sign_params));
+ sign_params->key_id = priv_key;
+ sign_params->in_len = DIGEST_SIZE;
+ sign_params->out_len = SIG_SIZE;
+
+ TST_EXP_EQ_LI_SILENT(keyctl(KEYCTL_PKEY_SIGN, (unsigned long)sign_params,
+ (unsigned long)"enc=pkcs1 hash=sha256",
+ (unsigned long)digest,
+ (unsigned long)sig),
+ SIG_SIZE);
+ if (!TST_PASS)
+ return;
+
+ memset(verify_params, 0, sizeof(*verify_params));
+ verify_params->key_id = cert_key;
+ verify_params->in_len = DIGEST_SIZE;
+ verify_params->in2_len = SIG_SIZE;
+
+ TST_EXP_EQ_LI_SILENT(keyctl(KEYCTL_PKEY_VERIFY, (unsigned long)verify_params,
+ (unsigned long)"enc=pkcs1 hash=sha256",
+ (unsigned long)digest,
+ (unsigned long)sig),
+ 0);
+ if (!TST_PASS)
+ return;
+
+ tst_res(TPASS, "KEYCTL_PKEY_SIGN and KEYCTL_PKEY_VERIFY roundtrip succeeded");
+
+ memcpy(wrong_digest, digest, sizeof(wrong_digest));
+ wrong_digest[0] ^= 0xff;
+
+ TST_EXP_FAIL(keyctl(KEYCTL_PKEY_VERIFY, (unsigned long)verify_params,
+ (unsigned long)"enc=pkcs1 hash=sha256",
+ (unsigned long)wrong_digest,
+ (unsigned long)sig),
+ EKEYREJECTED,
+ "KEYCTL_PKEY_VERIFY with mismatched digest");
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test_all = run,
+ .min_kver = "4.20",
+ .needs_root = 1,
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_KEYS=y",
+ "CONFIG_ASYMMETRIC_KEY_TYPE=y",
+ "CONFIG_X509_CERTIFICATE_PARSER",
+ "CONFIG_PKCS8_PRIVATE_KEY_PARSER",
+ "CONFIG_CRYPTO_RSA",
+ "CONFIG_CRYPTO_SHA256",
+ NULL
+ },
+ .bufs = (struct tst_buffers []) {
+ {&sign_params, .size = sizeof(*sign_params)},
+ {&verify_params, .size = sizeof(*verify_params)},
+ {},
+ },
+};
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 26/33] keyctl33: Negative tests for KEYCTL_PKEY_*
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (24 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 25/33] keyctl32: Test KEYCTL_PKEY_SIGN and VERIFY Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 27/33] lapi/keyctl.h: Add capability fallback defines Andrea Cervesato
` (6 subsequent siblings)
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Add negative and boundary test cases for KEYCTL_PKEY_* operations
(QUERY, ENCRYPT, DECRYPT, SIGN, VERIFY), testing invalid key serials,
unsupported key types, invalid info strings, and buffer size limits.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl33.c | 247 ++++++++++++++++++++++++++++
3 files changed, 249 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index d4007f7a6..7658ac859 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -750,6 +750,7 @@ keyctl29 keyctl29
keyctl30 keyctl30
keyctl31 keyctl31
keyctl32 keyctl32
+keyctl33 keyctl33
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index 8b1627bee..0f209d7e0 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -30,3 +30,4 @@
/keyctl30
/keyctl31
/keyctl32
+/keyctl33
diff --git a/testcases/kernel/syscalls/keyctl/keyctl33.c b/testcases/kernel/syscalls/keyctl/keyctl33.c
new file mode 100644
index 000000000..5e9418f50
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl33.c
@@ -0,0 +1,247 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Negative and boundary test cases for ``KEYCTL_PKEY_*`` of :manpage:`keyctl(2)`.
+ *
+ * Requires root (CAP_SYS_MODULE) to load the ``x509_key_parser`` and
+ * ``pkcs8_key_parser`` modules.
+ *
+ * [Algorithm]
+ *
+ * - verify ``KEYCTL_PKEY_QUERY`` with non-zero ``arg3`` fails with ``EINVAL``
+ * - verify ``KEYCTL_PKEY_QUERY`` with bogus key serial fails with ``ENOKEY``
+ * - verify ``KEYCTL_PKEY_QUERY`` with non-asymmetric key fails with ``EOPNOTSUPP``
+ * - verify ``KEYCTL_PKEY_QUERY`` with invalid info string fails with ``EINVAL``
+ * - verify ``KEYCTL_PKEY_ENCRYPT`` with bogus key serial fails with ``ENOKEY``
+ * - verify ``KEYCTL_PKEY_ENCRYPT`` with non-asymmetric key fails with ``EOPNOTSUPP``
+ * - verify ``KEYCTL_PKEY_ENCRYPT`` with invalid info string fails with ``EINVAL``
+ * - verify ``KEYCTL_PKEY_ENCRYPT`` with ``in_len`` exceeding limit fails with ``EINVAL``
+ * - verify ``KEYCTL_PKEY_DECRYPT`` on public key certificate fails with ``EINVAL``
+ * - verify ``KEYCTL_PKEY_DECRYPT`` with ``in_len`` exceeding limit fails with ``EINVAL``
+ * - verify ``KEYCTL_PKEY_SIGN`` on public key certificate fails with ``EINVAL``
+ * - verify ``KEYCTL_PKEY_SIGN`` with ``in_len`` exceeding limit fails with ``EINVAL``
+ * - verify ``KEYCTL_PKEY_VERIFY`` with non-asymmetric key fails with ``EOPNOTSUPP``
+ * - verify ``KEYCTL_PKEY_VERIFY`` with ``in2_len`` exceeding limit fails with ``EINVAL``
+ */
+
+#include "keyctl_common.h"
+#include "keyctl_pkey_data.h"
+#include "tst_module.h"
+
+static key_serial_t cert_key, priv_key, user_key;
+static key_serial_t bogus_key = INT32_MAX;
+
+static struct keyctl_pkey_query *query_buf;
+static struct keyctl_pkey_params *params;
+
+static unsigned char in_buf[512];
+static unsigned char out_buf[512];
+
+static struct tcase {
+ int op;
+ key_serial_t *key;
+ unsigned long arg3;
+ const char *info;
+ uint32_t in_len;
+ uint32_t out_in2_len;
+ int exp_errno;
+ const char *desc;
+} tcases[] = {
+ {
+ .op = KEYCTL_PKEY_QUERY,
+ .key = &cert_key,
+ .arg3 = 1,
+ .info = "enc=pkcs1",
+ .exp_errno = EINVAL,
+ .desc = "PKEY_QUERY with non-zero arg3",
+ },
+ {
+ .op = KEYCTL_PKEY_QUERY,
+ .key = &bogus_key,
+ .info = "enc=pkcs1",
+ .exp_errno = ENOKEY,
+ .desc = "PKEY_QUERY with bogus key serial",
+ },
+ {
+ .op = KEYCTL_PKEY_QUERY,
+ .key = &user_key,
+ .info = "enc=pkcs1",
+ .exp_errno = EOPNOTSUPP,
+ .desc = "PKEY_QUERY with non-asymmetric key",
+ },
+ {
+ .op = KEYCTL_PKEY_QUERY,
+ .key = &cert_key,
+ .info = "bogus_opt",
+ .exp_errno = EINVAL,
+ .desc = "PKEY_QUERY with invalid info string",
+ },
+ {
+ .op = KEYCTL_PKEY_ENCRYPT,
+ .key = &bogus_key,
+ .info = "enc=pkcs1",
+ .in_len = 32,
+ .out_in2_len = 256,
+ .exp_errno = ENOKEY,
+ .desc = "PKEY_ENCRYPT with bogus key serial",
+ },
+ {
+ .op = KEYCTL_PKEY_ENCRYPT,
+ .key = &user_key,
+ .info = "enc=pkcs1",
+ .in_len = 32,
+ .out_in2_len = 256,
+ .exp_errno = EOPNOTSUPP,
+ .desc = "PKEY_ENCRYPT with non-asymmetric key",
+ },
+ {
+ .op = KEYCTL_PKEY_ENCRYPT,
+ .key = &cert_key,
+ .info = "invalid_info",
+ .in_len = 32,
+ .out_in2_len = 256,
+ .exp_errno = EINVAL,
+ .desc = "PKEY_ENCRYPT with invalid info string",
+ },
+ {
+ .op = KEYCTL_PKEY_ENCRYPT,
+ .key = &cert_key,
+ .info = "enc=pkcs1",
+ .in_len = 500,
+ .out_in2_len = 256,
+ .exp_errno = EINVAL,
+ .desc = "PKEY_ENCRYPT with in_len exceeding limit",
+ },
+ {
+ .op = KEYCTL_PKEY_DECRYPT,
+ .key = &cert_key,
+ .info = "enc=pkcs1",
+ .in_len = 256,
+ .out_in2_len = 256,
+ .exp_errno = EINVAL,
+ .desc = "PKEY_DECRYPT on public key certificate",
+ },
+ {
+ .op = KEYCTL_PKEY_DECRYPT,
+ .key = &priv_key,
+ .info = "enc=pkcs1",
+ .in_len = 500,
+ .out_in2_len = 256,
+ .exp_errno = EINVAL,
+ .desc = "PKEY_DECRYPT with in_len exceeding limit",
+ },
+ {
+ .op = KEYCTL_PKEY_SIGN,
+ .key = &cert_key,
+ .info = "enc=pkcs1 hash=sha256",
+ .in_len = 32,
+ .out_in2_len = 256,
+ .exp_errno = EINVAL,
+ .desc = "PKEY_SIGN on public key certificate",
+ },
+ {
+ .op = KEYCTL_PKEY_SIGN,
+ .key = &priv_key,
+ .info = "enc=pkcs1 hash=sha256",
+ .in_len = 500,
+ .out_in2_len = 256,
+ .exp_errno = EINVAL,
+ .desc = "PKEY_SIGN with in_len exceeding limit",
+ },
+ {
+ .op = KEYCTL_PKEY_VERIFY,
+ .key = &user_key,
+ .info = "enc=pkcs1 hash=sha256",
+ .in_len = 32,
+ .out_in2_len = 256,
+ .exp_errno = EOPNOTSUPP,
+ .desc = "PKEY_VERIFY with non-asymmetric key",
+ },
+ {
+ .op = KEYCTL_PKEY_VERIFY,
+ .key = &cert_key,
+ .info = "enc=pkcs1 hash=sha256",
+ .in_len = 32,
+ .out_in2_len = 500,
+ .exp_errno = EINVAL,
+ .desc = "PKEY_VERIFY with in2_len exceeding limit",
+ },
+};
+
+static void setup(void)
+{
+ SAFE_KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
+
+ tst_modprobe("x509_key_parser", NULL);
+ tst_modprobe("pkcs8_key_parser", NULL);
+
+ user_key = new_user_key("ltp_user", "data", 4,
+ KEY_SPEC_PROCESS_KEYRING);
+
+ cert_key = add_asymmetric_key_or_tconf("cert", rsa2048_cert,
+ sizeof(rsa2048_cert),
+ "CONFIG_X509_CERTIFICATE_PARSER");
+ priv_key = add_asymmetric_key_or_tconf("priv", rsa2048_pkcs8,
+ sizeof(rsa2048_pkcs8),
+ "CONFIG_PKCS8_PRIVATE_KEY_PARSER");
+}
+
+static void run(unsigned int n)
+{
+ struct tcase *tc = &tcases[n];
+
+ if (tc->op == KEYCTL_PKEY_QUERY) {
+ TST_EXP_FAIL(keyctl(KEYCTL_PKEY_QUERY, (unsigned long)*tc->key,
+ tc->arg3, (unsigned long)tc->info,
+ (unsigned long)query_buf),
+ tc->exp_errno,
+ "%s", tc->desc);
+ return;
+ }
+
+ memset(params, 0, sizeof(*params));
+ params->key_id = *tc->key;
+ params->in_len = tc->in_len;
+ params->out_len = tc->out_in2_len;
+
+ if (tc->op == KEYCTL_PKEY_VERIFY) {
+ TST_EXP_FAIL(keyctl(tc->op, (unsigned long)params,
+ (unsigned long)tc->info,
+ (unsigned long)in_buf,
+ (unsigned long)out_buf),
+ tc->exp_errno,
+ "%s", tc->desc);
+ } else {
+ TST_EXP_FAIL2(keyctl(tc->op, (unsigned long)params,
+ (unsigned long)tc->info,
+ (unsigned long)in_buf,
+ (unsigned long)out_buf),
+ tc->exp_errno,
+ "%s", tc->desc);
+ }
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test = run,
+ .tcnt = ARRAY_SIZE(tcases),
+ .min_kver = "4.20",
+ .needs_root = 1,
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_KEYS=y",
+ "CONFIG_ASYMMETRIC_KEY_TYPE=y",
+ "CONFIG_X509_CERTIFICATE_PARSER",
+ "CONFIG_PKCS8_PRIVATE_KEY_PARSER",
+ "CONFIG_CRYPTO_RSA",
+ "CONFIG_CRYPTO_SHA256",
+ NULL
+ },
+ .bufs = (struct tst_buffers []) {
+ {&query_buf, .size = sizeof(*query_buf)},
+ {¶ms, .size = sizeof(*params)},
+ {},
+ },
+};
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 27/33] lapi/keyctl.h: Add capability fallback defines
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (25 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 26/33] keyctl33: Negative tests for KEYCTL_PKEY_* Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 28/33] keyctl34: Test KEYCTL_CAPABILITIES flag retrieval Andrea Cervesato
` (5 subsequent siblings)
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Add fallback definitions for KEYCTL_CAPABILITIES, KEYCTL_CAPS0_*,
and KEYCTL_CAPS1_* constants, and update safe_keyctl to handle
KEYCTL_CAPABILITIES.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
include/lapi/keyctl.h | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/include/lapi/keyctl.h b/include/lapi/keyctl.h
index 8820c3ddb..27b0f8dd2 100644
--- a/include/lapi/keyctl.h
+++ b/include/lapi/keyctl.h
@@ -219,6 +219,10 @@ static inline key_serial_t keyctl_join_session_keyring(const char *name) {
# define KEYCTL_MOVE_EXCL 0x00000001 /* do not displace from the to-keyring */
#endif
+#ifndef KEYCTL_CAPABILITIES
+# define KEYCTL_CAPABILITIES 31
+#endif
+
#ifndef KEYCTL_PKEY_QUERY
# define KEYCTL_PKEY_QUERY 24
#endif
@@ -246,6 +250,20 @@ static inline key_serial_t keyctl_join_session_keyring(const char *name) {
# define KEYCTL_SUPPORTS_VERIFY 0x08
#endif
+#ifndef KEYCTL_CAPS0_CAPABILITIES
+# define KEYCTL_CAPS0_CAPABILITIES 0x01
+# define KEYCTL_CAPS0_PERSISTENT_KEYRINGS 0x02
+# define KEYCTL_CAPS0_DIFFIE_HELLMAN 0x04
+# define KEYCTL_CAPS0_PUBLIC_KEY 0x08
+# define KEYCTL_CAPS0_BIG_KEY 0x10
+# define KEYCTL_CAPS0_INVALIDATE 0x20
+# define KEYCTL_CAPS0_RESTRICT_KEYRING 0x40
+# define KEYCTL_CAPS0_MOVE 0x80
+# define KEYCTL_CAPS1_NS_KEYRING_NAME 0x01
+# define KEYCTL_CAPS1_NS_KEY_TAG 0x02
+# define KEYCTL_CAPS1_NOTIFICATIONS 0x04
+#endif
+
/* key permissions */
#ifndef KEY_POS_VIEW
# define KEY_POS_VIEW 0x01000000
@@ -311,6 +329,7 @@ static inline long safe_keyctl(const char *file, const int lineno,
case KEYCTL_PKEY_DECRYPT:
case KEYCTL_PKEY_SIGN:
case KEYCTL_PKEY_VERIFY:
+ case KEYCTL_CAPABILITIES:
if (rval < 0)
failure = 1;
break;
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 28/33] keyctl34: Test KEYCTL_CAPABILITIES flag retrieval
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (26 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 27/33] lapi/keyctl.h: Add capability fallback defines Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 29/33] keyctl35: Test KEYCTL_CAPABILITIES size query Andrea Cervesato
` (4 subsequent siblings)
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Test keyrings subsystem capabilities retrieval with KEYCTL_CAPABILITIES
and verify standard capability bits (CAPABILITIES, INVALIDATE,
RESTRICT_KEYRING, MOVE, NS_KEYRING_NAME, NS_KEY_TAG).
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl34.c | 62 +++++++++++++++++++++++++++++
3 files changed, 64 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index 7658ac859..08877ff49 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -751,6 +751,7 @@ keyctl30 keyctl30
keyctl31 keyctl31
keyctl32 keyctl32
keyctl33 keyctl33
+keyctl34 keyctl34
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index 0f209d7e0..f2ce330d7 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -31,3 +31,4 @@
/keyctl31
/keyctl32
/keyctl33
+/keyctl34
diff --git a/testcases/kernel/syscalls/keyctl/keyctl34.c b/testcases/kernel/syscalls/keyctl/keyctl34.c
new file mode 100644
index 000000000..bfe15a6ed
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl34.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Test ``KEYCTL_CAPABILITIES`` of :manpage:`keyctl(2)`, added in Linux 5.3.
+ *
+ * ``KEYCTL_CAPABILITIES`` retrieves the bitmask of features and capabilities
+ * supported by the keyrings subsystem in the running kernel.
+ *
+ * [Algorithm]
+ *
+ * - retrieve keyrings subsystem capabilities into a buffer
+ * - verify return value is at least 2 bytes
+ * - verify standard capability bits ``KEYCTL_CAPS0_CAPABILITIES``,
+ * ``KEYCTL_CAPS0_INVALIDATE``, ``KEYCTL_CAPS0_RESTRICT_KEYRING``,
+ * ``KEYCTL_CAPS0_MOVE``, ``KEYCTL_CAPS1_NS_KEYRING_NAME``, and
+ * ``KEYCTL_CAPS1_NS_KEY_TAG`` are set
+ */
+
+#include "keyctl_common.h"
+
+static unsigned char caps[8];
+
+static void run(void)
+{
+ memset(caps, 0, sizeof(caps));
+
+ TEST(keyctl(KEYCTL_CAPABILITIES, (unsigned long)caps, sizeof(caps), 0, 0));
+ if (TST_RET < 0)
+ tst_brk(TBROK | TTERRNO, "KEYCTL_CAPABILITIES failed");
+
+ if (TST_RET < 2) {
+ tst_res(TFAIL, "KEYCTL_CAPABILITIES returned %ld, expected at least 2",
+ TST_RET);
+ return;
+ }
+
+ TST_EXP_EXPR(caps[0] & KEYCTL_CAPS0_CAPABILITIES,
+ "KEYCTL_CAPS0_CAPABILITIES is set");
+ TST_EXP_EXPR(caps[0] & KEYCTL_CAPS0_INVALIDATE,
+ "KEYCTL_CAPS0_INVALIDATE is set");
+ TST_EXP_EXPR(caps[0] & KEYCTL_CAPS0_RESTRICT_KEYRING,
+ "KEYCTL_CAPS0_RESTRICT_KEYRING is set");
+ TST_EXP_EXPR(caps[0] & KEYCTL_CAPS0_MOVE,
+ "KEYCTL_CAPS0_MOVE is set");
+
+ TST_EXP_EXPR(caps[1] & KEYCTL_CAPS1_NS_KEYRING_NAME,
+ "KEYCTL_CAPS1_NS_KEYRING_NAME is set");
+ TST_EXP_EXPR(caps[1] & KEYCTL_CAPS1_NS_KEY_TAG,
+ "KEYCTL_CAPS1_NS_KEY_TAG is set");
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .min_kver = "5.3",
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_KEYS=y",
+ NULL
+ },
+};
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 29/33] keyctl35: Test KEYCTL_CAPABILITIES size query
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (27 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 28/33] keyctl34: Test KEYCTL_CAPABILITIES flag retrieval Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 30/33] keyctl36: Test KEYCTL_CAPABILITIES buffer sizing Andrea Cervesato
` (3 subsequent siblings)
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Test that calling KEYCTL_CAPABILITIES with a NULL buffer and
buflen of 0 returns the total size in bytes of the keyrings
subsystem capability array without faulting.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl35.c | 49 +++++++++++++++++++++++++++++
3 files changed, 51 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index 08877ff49..67d626c22 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -752,6 +752,7 @@ keyctl31 keyctl31
keyctl32 keyctl32
keyctl33 keyctl33
keyctl34 keyctl34
+keyctl35 keyctl35
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index f2ce330d7..58ebb452f 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -32,3 +32,4 @@
/keyctl32
/keyctl33
/keyctl34
+/keyctl35
diff --git a/testcases/kernel/syscalls/keyctl/keyctl35.c b/testcases/kernel/syscalls/keyctl/keyctl35.c
new file mode 100644
index 000000000..43a8e2c7b
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl35.c
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Test ``KEYCTL_CAPABILITIES`` size query of :manpage:`keyctl(2)`, added in Linux 5.3.
+ *
+ * [Algorithm]
+ *
+ * - call ``KEYCTL_CAPABILITIES`` with NULL buffer and ``buflen = 0``
+ * - verify the return value is at least 2 bytes
+ * - verify calling ``KEYCTL_CAPABILITIES`` with a valid buffer returns the
+ * same size
+ */
+
+#include "keyctl_common.h"
+
+static unsigned char buf[8];
+
+static void run(void)
+{
+ long size;
+
+ TEST(keyctl(KEYCTL_CAPABILITIES, (unsigned long)NULL, 0, 0, 0));
+ if (TST_RET < 0)
+ tst_brk(TBROK | TTERRNO, "KEYCTL_CAPABILITIES size query failed");
+
+ size = TST_RET;
+ if (size < 2) {
+ tst_res(TFAIL, "KEYCTL_CAPABILITIES size query returned %ld, expected >= 2",
+ size);
+ return;
+ }
+
+ tst_res(TPASS, "KEYCTL_CAPABILITIES size query returned %ld", size);
+
+ TST_EXP_VAL(keyctl(KEYCTL_CAPABILITIES, (unsigned long)buf, sizeof(buf), 0, 0),
+ size);
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .min_kver = "5.3",
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_KEYS=y",
+ NULL
+ },
+};
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 30/33] keyctl36: Test KEYCTL_CAPABILITIES buffer sizing
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (28 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 29/33] keyctl35: Test KEYCTL_CAPABILITIES size query Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 31/33] keyctl37: Negative tests for KEYCTL_CAPABILITIES Andrea Cervesato
` (2 subsequent siblings)
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Test KEYCTL_CAPABILITIES with short buffer (verifying partial copy
without overrun) and oversized buffer (verifying trailing space is
zero-filled while returning the full capability length).
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl36.c | 88 +++++++++++++++++++++++++++++
3 files changed, 90 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index 67d626c22..8ad8f0fe5 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -753,6 +753,7 @@ keyctl32 keyctl32
keyctl33 keyctl33
keyctl34 keyctl34
keyctl35 keyctl35
+keyctl36 keyctl36
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index 58ebb452f..a4da8ae80 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -33,3 +33,4 @@
/keyctl33
/keyctl34
/keyctl35
+/keyctl36
diff --git a/testcases/kernel/syscalls/keyctl/keyctl36.c b/testcases/kernel/syscalls/keyctl/keyctl36.c
new file mode 100644
index 000000000..58fa56a07
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl36.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Test ``KEYCTL_CAPABILITIES`` buffer sizing and padding of :manpage:`keyctl(2)`.
+ *
+ * [Algorithm]
+ *
+ * - verify a 1-byte buffer receives 1 byte while the full size is returned
+ * and canary bytes beyond 1 byte remain untouched
+ * - verify an oversized buffer is zero-filled beyond the capability size
+ */
+
+#include "keyctl_common.h"
+
+#define CANARY 0xaa
+#define OVERSIZE 16
+
+static long caps_len;
+static unsigned char short_buf[4];
+static unsigned char large_buf[OVERSIZE];
+
+static void setup(void)
+{
+ TEST(keyctl(KEYCTL_CAPABILITIES, (unsigned long)NULL, 0, 0, 0));
+ if (TST_RET < 0)
+ tst_brk(TBROK | TTERRNO, "KEYCTL_CAPABILITIES size query failed");
+
+ caps_len = TST_RET;
+}
+
+static void run(void)
+{
+ size_t i;
+ int zero_padded = 1;
+
+ memset(short_buf, CANARY, sizeof(short_buf));
+ TST_EXP_EQ_LI_SILENT(keyctl(KEYCTL_CAPABILITIES,
+ (unsigned long)short_buf, 1, 0, 0),
+ caps_len);
+ if (!TST_PASS)
+ return;
+
+ if (short_buf[0] == CANARY) {
+ tst_res(TFAIL, "short buffer was not populated");
+ return;
+ }
+
+ for (i = 1; i < sizeof(short_buf); i++) {
+ if (short_buf[i] != CANARY) {
+ tst_res(TFAIL, "copy overran short buffer at offset %zu", i);
+ return;
+ }
+ }
+
+ tst_res(TPASS, "short buffer copied 1 byte without overrun");
+
+ memset(large_buf, CANARY, sizeof(large_buf));
+ TST_EXP_EQ_LI_SILENT(keyctl(KEYCTL_CAPABILITIES,
+ (unsigned long)large_buf, sizeof(large_buf), 0, 0),
+ caps_len);
+ if (!TST_PASS)
+ return;
+
+ for (i = caps_len; i < sizeof(large_buf); i++) {
+ if (large_buf[i] != 0) {
+ zero_padded = 0;
+ break;
+ }
+ }
+
+ if (!zero_padded)
+ tst_res(TFAIL, "oversized buffer was not zero-filled at offset %zu", i);
+ else
+ tst_res(TPASS, "oversized buffer zero-filled trailing space");
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test_all = run,
+ .min_kver = "5.3",
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_KEYS=y",
+ NULL
+ },
+};
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 31/33] keyctl37: Negative tests for KEYCTL_CAPABILITIES
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (29 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 30/33] keyctl36: Test KEYCTL_CAPABILITIES buffer sizing Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 32/33] keyctl38: Test KEYCTL_WATCH_KEY add and remove Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 33/33] keyctl39: Negative tests for KEYCTL_WATCH_KEY Andrea Cervesato
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Add negative test cases for KEYCTL_CAPABILITIES verifying that
passing a NULL buffer with a non-zero length or an invalid buffer
pointer fails with EFAULT.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl37.c | 63 +++++++++++++++++++++++++++++
3 files changed, 65 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index 8ad8f0fe5..66215afd7 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -754,6 +754,7 @@ keyctl33 keyctl33
keyctl34 keyctl34
keyctl35 keyctl35
keyctl36 keyctl36
+keyctl37 keyctl37
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index a4da8ae80..7ee6b9098 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -34,3 +34,4 @@
/keyctl34
/keyctl35
/keyctl36
+/keyctl37
diff --git a/testcases/kernel/syscalls/keyctl/keyctl37.c b/testcases/kernel/syscalls/keyctl/keyctl37.c
new file mode 100644
index 000000000..08d1db03b
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl37.c
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Negative test cases for ``KEYCTL_CAPABILITIES`` of :manpage:`keyctl(2)`.
+ *
+ * [Algorithm]
+ *
+ * - verify ``KEYCTL_CAPABILITIES`` with NULL buffer and ``buflen > 0`` fails with ``EFAULT``
+ * - verify ``KEYCTL_CAPABILITIES`` with invalid pointer fails with ``EFAULT``
+ */
+
+#include "keyctl_common.h"
+
+static void *bad_addr;
+
+static struct tcase {
+ void **buf;
+ size_t buflen;
+ int exp_errno;
+ const char *desc;
+} tcases[] = {
+ {
+ .buf = NULL,
+ .buflen = 1,
+ .exp_errno = EFAULT,
+ .desc = "NULL buffer with non-zero buflen",
+ },
+ {
+ .buf = &bad_addr,
+ .buflen = 1,
+ .exp_errno = EFAULT,
+ .desc = "invalid buffer pointer",
+ },
+};
+
+static void setup(void)
+{
+ bad_addr = tst_get_bad_addr(NULL);
+}
+
+static void run(unsigned int n)
+{
+ struct tcase *tc = &tcases[n];
+ void *p = tc->buf ? *tc->buf : NULL;
+
+ TST_EXP_FAIL2(keyctl(KEYCTL_CAPABILITIES, (unsigned long)p, tc->buflen, 0, 0),
+ tc->exp_errno,
+ "%s", tc->desc);
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test = run,
+ .tcnt = ARRAY_SIZE(tcases),
+ .min_kver = "5.3",
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_KEYS=y",
+ NULL
+ },
+};
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 32/33] keyctl38: Test KEYCTL_WATCH_KEY add and remove
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (30 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 31/33] keyctl37: Negative tests for KEYCTL_CAPABILITIES Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
2026-09-02 11:04 ` [LTP] [PATCH 33/33] keyctl39: Negative tests for KEYCTL_WATCH_KEY Andrea Cervesato
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Test KEYCTL_WATCH_KEY by opening a watch queue notification pipe
and adding then removing watches on both a user key and the
session keyring.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl38.c | 91 +++++++++++++++++++++++++++++
3 files changed, 93 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index 66215afd7..e9d47b5c4 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -755,6 +755,7 @@ keyctl34 keyctl34
keyctl35 keyctl35
keyctl36 keyctl36
keyctl37 keyctl37
+keyctl38 keyctl38
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index 7ee6b9098..c0a18dd77 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -35,3 +35,4 @@
/keyctl35
/keyctl36
/keyctl37
+/keyctl38
diff --git a/testcases/kernel/syscalls/keyctl/keyctl38.c b/testcases/kernel/syscalls/keyctl/keyctl38.c
new file mode 100644
index 000000000..26475c7de
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl38.c
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Test ``KEYCTL_WATCH_KEY`` of :manpage:`keyctl(2)`, added in Linux 5.8.
+ *
+ * ``KEYCTL_WATCH_KEY`` adds or removes a watch on a key or keyring to/from
+ * a watch queue notification pipe.
+ *
+ * [Algorithm]
+ *
+ * - open a notification pipe via :manpage:`pipe2()` with
+ * ``O_NOTIFICATION_PIPE``
+ * - add a watch on a key with ``watch_id = 1`` and verify success
+ * - remove the watch on the key with ``watch_id = -1`` and verify success
+ * - add a watch on a keyring with ``watch_id = 2`` and verify success
+ * - remove the watch on the keyring with ``watch_id = -1`` and verify success
+ */
+
+#define _GNU_SOURCE
+
+#include <sys/resource.h>
+#include <unistd.h>
+#include "keyctl_common.h"
+#include "lapi/watch_queue.h"
+
+static key_serial_t key;
+
+static void setup(void)
+{
+ SAFE_KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
+
+ key = new_user_key("ltpkeyctl38", "payload", 7,
+ KEY_SPEC_PROCESS_KEYRING);
+}
+
+static void run(void)
+{
+ int pipefd[2];
+
+ TEST(pipe2(pipefd, O_NOTIFICATION_PIPE));
+ if (TST_RET < 0) {
+ if (TST_ERR == ENOPKG)
+ tst_brk(TCONF | TTERRNO, "CONFIG_WATCH_QUEUE is not set");
+ if (TST_ERR == EINVAL)
+ tst_brk(TCONF | TTERRNO, "O_NOTIFICATION_PIPE is not supported");
+ tst_brk(TBROK | TTERRNO, "pipe2(O_NOTIFICATION_PIPE) failed");
+ }
+
+ SAFE_IOCTL(pipefd[0], IOC_WATCH_QUEUE_SET_SIZE, 256);
+
+ TST_EXP_PASS(keyctl(KEYCTL_WATCH_KEY, key, pipefd[0], 1),
+ "KEYCTL_WATCH_KEY add watch on key");
+
+ TST_EXP_PASS(keyctl(KEYCTL_WATCH_KEY, key, pipefd[0], -1),
+ "KEYCTL_WATCH_KEY remove watch on key");
+
+ TST_EXP_PASS(keyctl(KEYCTL_WATCH_KEY, KEY_SPEC_SESSION_KEYRING,
+ pipefd[0], 2),
+ "KEYCTL_WATCH_KEY add watch on session keyring");
+
+ TST_EXP_PASS(keyctl(KEYCTL_WATCH_KEY, KEY_SPEC_SESSION_KEYRING,
+ pipefd[0], -1),
+ "KEYCTL_WATCH_KEY remove watch on session keyring");
+
+ SAFE_CLOSE(pipefd[0]);
+ SAFE_CLOSE(pipefd[1]);
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test_all = run,
+ .min_kver = "5.8",
+ /*
+ * add_one_watch() charges per-user watches against RLIMIT_NOFILE,
+ * so raise the limit high enough to accommodate pre-existing
+ * watches on the calling user.
+ */
+ .ulimit = (const struct tst_ulimit_val []) {
+ {RLIMIT_NOFILE, 524288},
+ {}
+ },
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_KEYS=y",
+ "CONFIG_KEY_NOTIFICATIONS=y",
+ "CONFIG_WATCH_QUEUE=y",
+ NULL
+ },
+};
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread* [LTP] [PATCH 33/33] keyctl39: Negative tests for KEYCTL_WATCH_KEY
2026-09-02 11:04 [LTP] [PATCH 00/33] Improve coverage for keyctl() syscall Andrea Cervesato
` (31 preceding siblings ...)
2026-09-02 11:04 ` [LTP] [PATCH 32/33] keyctl38: Test KEYCTL_WATCH_KEY add and remove Andrea Cervesato
@ 2026-09-02 11:04 ` Andrea Cervesato
32 siblings, 0 replies; 35+ messages in thread
From: Andrea Cervesato @ 2026-09-02 11:04 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Add negative test cases for KEYCTL_WATCH_KEY verifying invalid
watch_id values, bogus key ids, missing View permission, invalid
file descriptors, non-watch-queue pipes, and removal of watches
on unwatched keys.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/keyctl/.gitignore | 1 +
testcases/kernel/syscalls/keyctl/keyctl39.c | 149 ++++++++++++++++++++++++++++
3 files changed, 151 insertions(+)
diff --git a/runtest/syscalls b/runtest/syscalls
index e9d47b5c4..538449a81 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -756,6 +756,7 @@ keyctl35 keyctl35
keyctl36 keyctl36
keyctl37 keyctl37
keyctl38 keyctl38
+keyctl39 keyctl39
kcmp01 kcmp01
kcmp02 kcmp02
diff --git a/testcases/kernel/syscalls/keyctl/.gitignore b/testcases/kernel/syscalls/keyctl/.gitignore
index c0a18dd77..8de3d46c2 100644
--- a/testcases/kernel/syscalls/keyctl/.gitignore
+++ b/testcases/kernel/syscalls/keyctl/.gitignore
@@ -36,3 +36,4 @@
/keyctl36
/keyctl37
/keyctl38
+/keyctl39
diff --git a/testcases/kernel/syscalls/keyctl/keyctl39.c b/testcases/kernel/syscalls/keyctl/keyctl39.c
new file mode 100644
index 000000000..4a0cf5efb
--- /dev/null
+++ b/testcases/kernel/syscalls/keyctl/keyctl39.c
@@ -0,0 +1,149 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Negative test cases for ``KEYCTL_WATCH_KEY`` of :manpage:`keyctl(2)`.
+ *
+ * [Algorithm]
+ *
+ * - verify ``KEYCTL_WATCH_KEY`` with ``watch_id < -1`` fails with ``EINVAL``
+ * - verify ``KEYCTL_WATCH_KEY`` with ``watch_id > 255`` fails with ``EINVAL``
+ * - verify ``KEYCTL_WATCH_KEY`` with bogus key id fails with ``ENOKEY``
+ * - verify ``KEYCTL_WATCH_KEY`` without View permission fails with ``EACCES``
+ * - verify ``KEYCTL_WATCH_KEY`` with invalid fd fails with ``EINVAL``
+ * - verify ``KEYCTL_WATCH_KEY`` with non-watch-queue fd fails with ``EINVAL``
+ * - verify ``KEYCTL_WATCH_KEY`` remove on unwatched key fails with ``EBADSLT``
+ */
+
+#define _GNU_SOURCE
+
+#include <unistd.h>
+#include "keyctl_common.h"
+#include "lapi/watch_queue.h"
+
+static key_serial_t key_valid;
+static key_serial_t key_no_view;
+static key_serial_t bogus_key = INT32_MAX;
+static int wqueue_pipefd[2] = {-1, -1};
+static int plain_pipefd[2] = {-1, -1};
+static int bad_fd = -1;
+
+static struct tcase {
+ key_serial_t *key;
+ int *fd;
+ int watch_id;
+ int exp_errno;
+ const char *desc;
+} tcases[] = {
+ {
+ .key = &key_valid,
+ .fd = &wqueue_pipefd[0],
+ .watch_id = -2,
+ .exp_errno = EINVAL,
+ .desc = "watch_id < -1",
+ },
+ {
+ .key = &key_valid,
+ .fd = &wqueue_pipefd[0],
+ .watch_id = 256,
+ .exp_errno = EINVAL,
+ .desc = "watch_id > 255",
+ },
+ {
+ .key = &bogus_key,
+ .fd = &wqueue_pipefd[0],
+ .watch_id = 1,
+ .exp_errno = ENOKEY,
+ .desc = "bogus key id",
+ },
+ {
+ .key = &key_no_view,
+ .fd = &wqueue_pipefd[0],
+ .watch_id = 1,
+ .exp_errno = EACCES,
+ .desc = "key without View permission",
+ },
+ {
+ .key = &key_valid,
+ .fd = &bad_fd,
+ .watch_id = 1,
+ .exp_errno = EINVAL,
+ .desc = "invalid fd",
+ },
+ {
+ .key = &key_valid,
+ .fd = &plain_pipefd[0],
+ .watch_id = 1,
+ .exp_errno = EINVAL,
+ .desc = "non-watch-queue fd",
+ },
+ {
+ .key = &key_valid,
+ .fd = &wqueue_pipefd[0],
+ .watch_id = -1,
+ .exp_errno = EBADSLT,
+ .desc = "remove watch on unwatched key",
+ },
+};
+
+static void setup(void)
+{
+ SAFE_KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
+
+ key_valid = new_user_key("ltpkeyctl39_valid", "data", 4,
+ KEY_SPEC_PROCESS_KEYRING);
+
+ key_no_view = new_user_key("ltpkeyctl39_noview", "data", 4,
+ KEY_SPEC_PROCESS_KEYRING);
+ SAFE_KEYCTL(KEYCTL_SETPERM, key_no_view, KEY_PERM_NO_VIEW, 0, 0);
+
+ TEST(pipe2(wqueue_pipefd, O_NOTIFICATION_PIPE));
+ if (TST_RET < 0) {
+ if (TST_ERR == ENOPKG)
+ tst_brk(TCONF | TTERRNO, "CONFIG_WATCH_QUEUE is not set");
+ if (TST_ERR == EINVAL)
+ tst_brk(TCONF | TTERRNO, "O_NOTIFICATION_PIPE is not supported");
+ tst_brk(TBROK | TTERRNO, "pipe2(O_NOTIFICATION_PIPE) failed");
+ }
+
+ SAFE_IOCTL(wqueue_pipefd[0], IOC_WATCH_QUEUE_SET_SIZE, 256);
+
+ SAFE_PIPE(plain_pipefd);
+}
+
+static void cleanup(void)
+{
+ if (wqueue_pipefd[0] != -1)
+ SAFE_CLOSE(wqueue_pipefd[0]);
+ if (wqueue_pipefd[1] != -1)
+ SAFE_CLOSE(wqueue_pipefd[1]);
+ if (plain_pipefd[0] != -1)
+ SAFE_CLOSE(plain_pipefd[0]);
+ if (plain_pipefd[1] != -1)
+ SAFE_CLOSE(plain_pipefd[1]);
+}
+
+static void run(unsigned int n)
+{
+ struct tcase *tc = &tcases[n];
+
+ TST_EXP_FAIL(keyctl(KEYCTL_WATCH_KEY, *tc->key, *tc->fd, tc->watch_id),
+ tc->exp_errno,
+ "%s", tc->desc);
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .cleanup = cleanup,
+ .test = run,
+ .tcnt = ARRAY_SIZE(tcases),
+ .min_kver = "5.8",
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_KEYS=y",
+ "CONFIG_KEY_NOTIFICATIONS=y",
+ "CONFIG_WATCH_QUEUE=y",
+ NULL
+ },
+};
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 35+ messages in thread