[PATCH v2 2/2] keys: Add KUnit coverage for KEYCTL_MOVE keep guard
Liu Mingyu <[email protected]> Sun, 31 May 2026 20:51:51 +0000
| Newsgroups | org.kernel.vger.keyrings,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
Add keyring KUnit tests that exercise successful key_move(), rejection of moving a protected key out of a protected source keyring, and the same-keyring no-op path. Keep the test-only infrastructure separate from the KEYCTL_MOVE fix so the fix can be backported without pulling in the KUnit module. Signed-off-by: Mingyu Liu <[email protected]> --- security/keys/Kconfig | 13 ++++ security/keys/Makefile | 1 + security/keys/keyring_test.c | 121 +++++++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+) create mode 100644 security/keys/keyring_test.c diff --git a/security/keys/Kconfig b/security/keys/Kconfig index 84f39e50ca36..acffb5f7385c 100644 --- a/security/keys/Kconfig +++ b/security/keys/Kconfig @@ -129,4 +129,17 @@ config KEY_NOTIFICATIONS This makes use of pipes to handle the notification buffer and provides KEYCTL_WATCH_KEY to enable/disable watches. +config KEYS_KUNIT_TEST + tristate "KUnit tests for keyrings" if !KUNIT_ALL_TESTS + depends on KUNIT + default KUNIT_ALL_TESTS + help + Build KUnit tests for keyring operations. + These tests exercise keyring link and move behavior, including + protection of KEY_FLAG_KEEP entries. + They are intended for KUnit runs on developer kernels and are not + needed for normal systems. + + If you are unsure how to answer this question, answer N. + endif # KEYS diff --git a/security/keys/Makefile b/security/keys/Makefile index 5f40807f05b3..fa583a4ea945 100644 --- a/security/keys/Makefile +++ b/security/keys/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_SYSCTL) += sysctl.o obj-$(CONFIG_PERSISTENT_KEYRINGS) += persistent.o obj-$(CONFIG_KEY_DH_OPERATIONS) += dh.o obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += keyctl_pkey.o +obj-$(CONFIG_KEYS_KUNIT_TEST) += keyring_test.o # # Key types diff --git a/security/keys/keyring_test.c b/security/keys/keyring_test.c new file mode 100644 index 000000000000..0055b50224e9 --- /dev/null +++ b/security/keys/keyring_test.c @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * KUnit tests for keyring operations. + */ + +#include <keys/user-type.h> +#include <kunit/test.h> +#include <linux/cred.h> +#include <linux/err.h> +#include <linux/key.h> +#include <linux/key-type.h> +#include <linux/keyctl.h> +#include <linux/module.h> +#include <linux/uidgid.h> + +static void keyring_test_key_put(void *data) +{ + key_put(data); +} + +static struct key *test_keyring_alloc(struct kunit *test, const char *desc, + unsigned long flags) +{ + struct key *keyring; + + keyring = keyring_alloc(desc, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, + current_cred(), KEY_POS_ALL | KEY_USR_ALL, + KEY_ALLOC_NOT_IN_QUOTA | flags, NULL, NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, keyring); + KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, + keyring_test_key_put, + keyring), 0); + + return keyring; +} + +static struct key *test_user_key_alloc(struct kunit *test, const char *desc, + struct key *keyring, + unsigned long flags) +{ + static const char payload[] = "payload"; + struct key *key; + int ret; + + key = key_alloc(&key_type_user, desc, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, + current_cred(), KEY_POS_ALL | KEY_USR_ALL, + KEY_ALLOC_NOT_IN_QUOTA | flags, NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, key); + KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, + keyring_test_key_put, + key), 0); + + ret = key_instantiate_and_link(key, payload, sizeof(payload), + keyring, NULL); + KUNIT_ASSERT_EQ(test, ret, 0); + + return key; +} + +static void keyring_move_user_key(struct kunit *test) +{ + struct key *from, *to, *key; + int ret; + + from = test_keyring_alloc(test, "move-from", 0); + to = test_keyring_alloc(test, "move-to", 0); + key = test_user_key_alloc(test, "move-key", from, 0); + + ret = key_move(key, from, to, 0); + KUNIT_EXPECT_EQ(test, ret, 0); + + ret = key_move(key, to, from, 0); + KUNIT_EXPECT_EQ(test, ret, 0); +} + +static void keyring_move_keep_key_fails(struct kunit *test) +{ + struct key *from, *to, *key; + int ret; + + from = test_keyring_alloc(test, "keep-from", KEY_ALLOC_SET_KEEP); + to = test_keyring_alloc(test, "keep-to", 0); + key = test_user_key_alloc(test, "keep-key", from, 0); + + KUNIT_ASSERT_TRUE(test, test_bit(KEY_FLAG_KEEP, &from->flags)); + KUNIT_ASSERT_TRUE(test, test_bit(KEY_FLAG_KEEP, &key->flags)); + + ret = key_move(key, from, to, 0); + KUNIT_EXPECT_EQ(test, ret, -EPERM); + + ret = key_move(key, to, from, 0); + KUNIT_EXPECT_EQ(test, ret, -ENOENT); +} + +static void keyring_move_keep_same_keyring(struct kunit *test) +{ + struct key *keyring, *key; + int ret; + + keyring = test_keyring_alloc(test, "keep-same", KEY_ALLOC_SET_KEEP); + key = test_user_key_alloc(test, "keep-same-key", keyring, 0); + + ret = key_move(key, keyring, keyring, 0); + KUNIT_EXPECT_EQ(test, ret, 0); +} + +static struct kunit_case keyring_test_cases[] = { + KUNIT_CASE(keyring_move_user_key), + KUNIT_CASE(keyring_move_keep_key_fails), + KUNIT_CASE(keyring_move_keep_same_keyring), + {} +}; + +static struct kunit_suite keyring_test_suite = { + .name = "keyring", + .test_cases = keyring_test_cases, +}; + +kunit_test_suite(keyring_test_suite); + +MODULE_LICENSE("GPL"); -- 2.51.2.windows.1