[LTP] [PATCH v2] syscalls/add_key05: add maxbytes/maxkeys test under unprivileged user

Yang Xu xuyang2018.jy@cn.fujitsu.com
Fri Feb 28 09:47:41 CET 2020


This case is designed to test whether we can reach maxbytes/maxkeys
quota exactly under unprivileged users. It is a regression test for
commit a08bf91ce28e ("KEYS: allow reaching the keys quotas exactly").
But this kenrel commit is a incomplete fix, it still fails on 5.6.3-rc1.
Fix patch[1] is still under review.

[1]https://patchwork.kernel.org/patch/11411507/

Signed-off-by: Yang Xu <xuyang2018.jy@cn.fujitsu.com>
---
v1->v2:
1. using parse_proc_key_user
2. add some messages about delta(v1 uses data_len)
3. fix something pointed by Cyril
 runtest/syscalls                              |   1 +
 testcases/kernel/syscalls/add_key/.gitignore  |   1 +
 testcases/kernel/syscalls/add_key/add_key05.c | 211 ++++++++++++++++++
 3 files changed, 213 insertions(+)
 create mode 100644 testcases/kernel/syscalls/add_key/add_key05.c

diff --git a/runtest/syscalls b/runtest/syscalls
index a9faf1e25..0462a08ef 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -18,6 +18,7 @@ add_key01 add_key01
 add_key02 add_key02
 add_key03 add_key03
 add_key04 add_key04
+add_key05 add_key05
 
 adjtimex01 adjtimex01
 adjtimex02 adjtimex02
diff --git a/testcases/kernel/syscalls/add_key/.gitignore b/testcases/kernel/syscalls/add_key/.gitignore
index b9a04214d..f57dc2228 100644
--- a/testcases/kernel/syscalls/add_key/.gitignore
+++ b/testcases/kernel/syscalls/add_key/.gitignore
@@ -2,3 +2,4 @@
 /add_key02
 /add_key03
 /add_key04
+/add_key05
diff --git a/testcases/kernel/syscalls/add_key/add_key05.c b/testcases/kernel/syscalls/add_key/add_key05.c
new file mode 100644
index 000000000..66b303544
--- /dev/null
+++ b/testcases/kernel/syscalls/add_key/add_key05.c
@@ -0,0 +1,211 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2020 FUJITSU LIMITED. All rights reserved.
+ * Author: Yang Xu <xuyang2018.jy@cn.fujitsu.com>
+ *
+ *Description:
+ * Test unprivileged user can support the number of keys and the
+ * number of bytes consumed in payloads of the keys.The defalut value
+ * is 200 and 20000.
+ * This is also a regresstion test for
+ * commit a08bf91ce28e ("KEYS: allow reaching the keys quotas exactly")
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include "tst_test.h"
+#include "lapi/keyctl.h"
+
+static char *user_buf;
+static const char *username = "ltp_add_key05";
+static int user_added;
+struct passwd *ltpuser;
+static char fmt[1024];
+
+static void add_user(void)
+{
+	if (user_added)
+		return;
+
+	const char *const cmd_useradd[] = {"useradd", username, NULL};
+	int rc;
+
+	switch ((rc = tst_run_cmd(cmd_useradd, NULL, NULL, 1))) {
+	case 0:
+		user_added = 1;
+		ltpuser = SAFE_GETPWNAM(username);
+		break;
+	case 1:
+	case 255:
+		break;
+	default:
+		tst_brk(TBROK, "Useradd failed (%d)", rc);
+	}
+	sprintf(fmt, "%5u: %%*5d %%*d/%%*d %%d/%%d %%d/%%d", ltpuser->pw_uid);
+}
+
+static void clean_user(void)
+{
+	if (!user_added)
+		return;
+
+	const char *const cmd_userdel[] = {"userdel", "-r", username, NULL};
+
+	if (tst_run_cmd(cmd_userdel, NULL, NULL, 1))
+		tst_res(TWARN | TERRNO, "'userdel -r %s' failed", username);
+	else
+		user_added = 0;
+}
+
+static inline void parse_proc_key_users(int *used_key, int *max_key, int *used_bytes, int *max_bytes)
+{
+	unsigned int val[4];
+	SAFE_FILE_LINES_SCANF("/proc/key-users", fmt, &val[0], &val[1], &val[2], &val[3]);
+
+	if (used_key)
+		*used_key = val[0];
+	if (max_key)
+		*max_key = val[1];
+	if (used_bytes)
+		*used_bytes = val[2];
+	if (max_bytes)
+		*max_bytes = val[3];
+}
+
+static void verify_max_btyes(void)
+{
+	char *buf;
+	int plen, invalid_plen, delta;
+	int used_bytes, max_bytes, tmp_used_bytes;
+
+	tst_res(TINFO, "test max bytes under unprivileged user");
+
+	parse_proc_key_users(NULL, NULL, &tmp_used_bytes, NULL);
+	TEST(add_key("user", "test2", user_buf, 64, KEY_SPEC_THREAD_KEYRING));
+	if (TST_RET == -1) {
+		tst_res(TFAIL | TTERRNO, "add key test2 failed");
+		return;
+	}
+	parse_proc_key_users(NULL, NULL, &used_bytes, &max_bytes);
+
+	/*
+	 * Compute delta between default datalen(in key_alloc) and actual
+	 * datlen(in key_payload_reserve).
+	 * more info see kernel code: security/keys/key.c
+	 */
+	delta = used_bytes - tmp_used_bytes - strlen("test2") - 1 - 64;
+	invalid_plen = max_bytes - used_bytes - delta - strlen("test_xxx");
+	buf = tst_alloc(invalid_plen);
+
+	TEST(add_key("user", "test_inv", buf, invalid_plen, KEY_SPEC_THREAD_KEYRING));
+	if (TST_RET != -1) {
+		tst_res(TFAIL, "add_key(test_inv) succeeded unexpectedltly");
+		return;
+	}
+	if (TST_ERR == EDQUOT)
+		tst_res(TPASS | TTERRNO, "add_key(test_inv) failed as expected");
+	else
+		tst_res(TFAIL | TTERRNO, "add_key(test_inv) failed expected EDQUOT got");
+
+	/*Reset delta*/
+	TEST(add_key("user", "test3", user_buf, 64, KEY_SPEC_THREAD_KEYRING));
+	if (TST_RET == -1) {
+		tst_res(TFAIL | TTERRNO, "add key test3 failed");
+		return;
+	}
+	TEST(add_key("user", "test4", user_buf, 64, KEY_SPEC_THREAD_KEYRING));
+	if (TST_RET == -1) {
+		tst_res(TFAIL | TTERRNO, "add key test4 failed");
+		return;
+	}
+	parse_proc_key_users(NULL, NULL, &used_bytes, &max_bytes);
+	plen = max_bytes - used_bytes - delta - strlen("test_xxx") - 1;
+	TEST(add_key("user", "test_max", buf, plen, KEY_SPEC_THREAD_KEYRING));
+	if (TST_RET == -1) {
+		 tst_res(TFAIL | TTERRNO, "add_key(test_max) failed unexpectedly");
+		 return;
+	}
+
+	tst_res(TPASS, "add_key(test_max) succeeded as expected");
+	parse_proc_key_users(NULL, NULL, &tmp_used_bytes, &max_bytes);
+	if (tmp_used_bytes == max_bytes)
+		tst_res(TPASS, "allow reaching the max bytes exactly");
+	else
+		tst_res(TFAIL, "max used bytes %u, key allow max bytes %u", tmp_used_bytes, max_bytes);
+}
+
+static void verify_max_keys(void)
+{
+	int i, used_key, max_key, used_bytes, max_bytes;
+	char desc[10];
+	int plen;
+
+	tst_res(TINFO, "test max keys under unprivileged user");
+	parse_proc_key_users(&used_key, &max_key, &used_bytes, &max_bytes);
+	plen = (max_bytes - used_bytes) / (max_key - used_key);
+	if (plen > 64)
+		plen = 64;
+
+	for (i = used_key + 1; i <= max_key; i++) {
+		sprintf(desc, "abc%d", i);
+		TEST(add_key("user", desc, user_buf, 64, KEY_SPEC_THREAD_KEYRING));
+		if (TST_RET == -1) {
+			tst_res(TFAIL | TTERRNO, "add keyring key(%s) failed", desc);
+			goto count;
+		}
+	}
+
+	TEST(add_key("user", "test_invalid_key", user_buf, 64, KEY_SPEC_THREAD_KEYRING));
+	if (TST_RET != -1) {
+		tst_res(TFAIL, "add keyring key(test_invalid_key) succeeded unexpectedly");
+		goto count;
+	}
+	if (TST_ERR == EDQUOT)
+		tst_res(TPASS | TTERRNO, "add_key(test_invalid_key) failed as expected");
+	else
+		tst_res(TFAIL | TTERRNO, "add_key(test_invalid_key) failed expected EDQUOT got");
+
+count:
+	parse_proc_key_users(&used_key, &max_key, NULL, NULL);
+	if (used_key == max_key)
+		tst_res(TPASS, "allow reaching the max key(%u) exactly", max_key);
+	else
+		tst_res(TFAIL, "max used key %u, key allow max key %u", used_key, max_key);
+}
+
+static void do_test(unsigned int n)
+{
+	add_user();
+	if (!SAFE_FORK()) {
+		SAFE_SETUID(ltpuser->pw_uid);
+		TEST(add_key("user", "test1", user_buf, 64, KEY_SPEC_THREAD_KEYRING));
+		if (TST_RET == -1) {
+			tst_res(TFAIL | TTERRNO, "add key test1 failed");
+			return;
+		}
+		if (n)
+			verify_max_keys();
+		else
+			verify_max_btyes();
+		exit(0);
+	}
+	tst_reap_children();
+	clean_user();
+}
+
+static struct tst_test test = {
+	.test = do_test,
+	.tcnt = 2,
+	.needs_root = 1,
+	.forks_child = 1,
+	.cleanup = clean_user,
+	.bufs = (struct tst_buffers []) {
+		{&user_buf, .size = 64},
+		{}
+	},
+	.tags = (const struct tst_tag[]) {
+		{"linux-git", "a08bf91ce28"},
+		{}
+	}
+};
-- 
2.18.0





More information about the ltp mailing list