Currently the keyctl helper makes silent assumption that either all expected arguments are being provided or otherwise it's somewhat safe to access beyond the actual va arg list. With AAPCS64-cap this will no longer slide through, as reading more arguments than provided will trigger capability bound fault. Introduce dedicated macro to handle the variadic-ness instead, making sure that at any point all arguments are being provided, whether explicitly or through default values.
Reported-by: Kevin Brodsky kevin.brodsky@arm.com Suggested-by: Kevin Brodsky kevin.brodsky@arm.com Signed-off-by: Beata Michalska beata.michalska@arm.com --- include/lapi/keyctl.h | 22 +++++++++---------- testcases/cve/cve-2016-7042.c | 6 ++--- testcases/kernel/syscalls/add_key/add_key03.c | 2 +- testcases/kernel/syscalls/add_key/add_key04.c | 2 +- testcases/kernel/syscalls/keyctl/keyctl01.c | 6 ++--- testcases/kernel/syscalls/keyctl/keyctl02.c | 8 +++---- testcases/kernel/syscalls/keyctl/keyctl03.c | 2 +- testcases/kernel/syscalls/keyctl/keyctl04.c | 6 ++--- testcases/kernel/syscalls/keyctl/keyctl05.c | 10 ++++----- testcases/kernel/syscalls/keyctl/keyctl06.c | 2 +- testcases/kernel/syscalls/keyctl/keyctl07.c | 4 ++-- testcases/kernel/syscalls/keyctl/keyctl09.c | 4 ++-- .../syscalls/request_key/request_key02.c | 4 ++-- .../syscalls/request_key/request_key03.c | 4 ++-- .../syscalls/request_key/request_key04.c | 10 ++++----- testcases/kernel/watchqueue/common.h | 4 ++-- testcases/kernel/watchqueue/wqueue01.c | 2 +- testcases/kernel/watchqueue/wqueue02.c | 2 +- testcases/kernel/watchqueue/wqueue03.c | 2 +- testcases/kernel/watchqueue/wqueue04.c | 2 +- testcases/kernel/watchqueue/wqueue05.c | 2 +- testcases/kernel/watchqueue/wqueue06.c | 2 +- testcases/kernel/watchqueue/wqueue07.c | 2 +- testcases/kernel/watchqueue/wqueue08.c | 2 +- testcases/kernel/watchqueue/wqueue09.c | 4 ++-- 25 files changed, 57 insertions(+), 59 deletions(-)
diff --git a/include/lapi/keyctl.h b/include/lapi/keyctl.h index 9c847a429..1c7436ef6 100644 --- a/include/lapi/keyctl.h +++ b/include/lapi/keyctl.h @@ -39,23 +39,21 @@ static inline key_serial_t request_key(const char *type, type, description, callout_info, destringid); }
-static inline long keyctl(int cmd, ...) -{ - va_list va; - uintptr_t arg2, arg3, arg4, arg5; +#define __KEYCTL(cmd, arg2, arg3, arg4, arg5, ...) \ + keyctl((cmd), (arg2), (arg3), (arg4), (arg5))
- va_start(va, cmd); - arg2 = va_arg(va, uintptr_t); - arg3 = va_arg(va, uintptr_t); - arg4 = va_arg(va, uintptr_t); - arg5 = va_arg(va, uintptr_t); - va_end(va); +#define KEYCTL(cmd, ...) \ + __KEYCTL((cmd), ##__VA_ARGS__, 0, 0, 0, 0)
+static inline long keyctl(int cmd, uintptr_t arg2, uintptr_t arg3, + uintptr_t arg4, uintptr_t arg5) +{ return tst_syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5); }
-static inline key_serial_t keyctl_join_session_keyring(const char *name) { - return keyctl(KEYCTL_JOIN_SESSION_KEYRING, name); +static inline key_serial_t keyctl_join_session_keyring(const char *name) +{ + return KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, name); }
#endif /* defined(HAVE_KEYUTILS_H) && defined(HAVE_LIBKEYUTILS) */ diff --git a/testcases/cve/cve-2016-7042.c b/testcases/cve/cve-2016-7042.c index 4434265dd..91ffccf2f 100644 --- a/testcases/cve/cve-2016-7042.c +++ b/testcases/cve/cve-2016-7042.c @@ -34,7 +34,7 @@ static void do_test(void) if (key == -1) tst_brk(TBROK, "Failed to add key");
- if (keyctl(KEYCTL_UPDATE, key, "b", 1)) + if (KEYCTL(KEYCTL_UPDATE, key, "b", 1)) tst_brk(TBROK, "Failed to update key");
fd = SAFE_OPEN(PATH_KEYS, O_RDONLY); @@ -47,7 +47,7 @@ static void do_test(void)
SAFE_CLOSE(fd);
- if (keyctl(KEYCTL_UNLINK, key, KEY_SPEC_SESSION_KEYRING)) + if (KEYCTL(KEYCTL_UNLINK, key, KEY_SPEC_SESSION_KEYRING)) tst_brk(TBROK, "Failed to unlink key"); key = 0; } @@ -60,7 +60,7 @@ static void setup(void)
static void cleanup(void) { - if (key > 0 && keyctl(KEYCTL_UNLINK, key, KEY_SPEC_SESSION_KEYRING)) + if (key > 0 && KEYCTL(KEYCTL_UNLINK, key, KEY_SPEC_SESSION_KEYRING)) tst_res(TWARN, "Failed to unlink key");
if (fd > 0) diff --git a/testcases/kernel/syscalls/add_key/add_key03.c b/testcases/kernel/syscalls/add_key/add_key03.c index d26912cb7..53613fc08 100644 --- a/testcases/kernel/syscalls/add_key/add_key03.c +++ b/testcases/kernel/syscalls/add_key/add_key03.c @@ -35,7 +35,7 @@ static key_serial_t create_keyring(const char *description)
static key_serial_t get_keyring_id(key_serial_t special_id) { - TEST(keyctl(KEYCTL_GET_KEYRING_ID, special_id, 1)); + TEST(KEYCTL(KEYCTL_GET_KEYRING_ID, special_id, 1)); if (TST_RET < 0) { tst_brk(TBROK | TTERRNO, "unable to get ID of keyring %d", special_id); diff --git a/testcases/kernel/syscalls/add_key/add_key04.c b/testcases/kernel/syscalls/add_key/add_key04.c index aa02fdd1d..105135566 100644 --- a/testcases/kernel/syscalls/add_key/add_key04.c +++ b/testcases/kernel/syscalls/add_key/add_key04.c @@ -40,7 +40,7 @@ static void do_test(void) { int status;
- TEST(keyctl(KEYCTL_JOIN_SESSION_KEYRING, NULL)); + TEST(KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, NULL)); if (TST_RET < 0) tst_brk(TBROK | TTERRNO, "failed to join new session keyring");
diff --git a/testcases/kernel/syscalls/keyctl/keyctl01.c b/testcases/kernel/syscalls/keyctl/keyctl01.c index 55e069c68..2e29c8375 100644 --- a/testcases/kernel/syscalls/keyctl/keyctl01.c +++ b/testcases/kernel/syscalls/keyctl/keyctl01.c @@ -22,19 +22,19 @@ static void do_test(void) { key_serial_t key;
- TEST(keyctl(KEYCTL_GET_KEYRING_ID, KEY_SPEC_USER_SESSION_KEYRING)); + TEST(KEYCTL(KEYCTL_GET_KEYRING_ID, KEY_SPEC_USER_SESSION_KEYRING)); if (TST_RET != -1) tst_res(TPASS, "KEYCTL_GET_KEYRING_ID succeeded"); else tst_res(TFAIL | TTERRNO, "KEYCTL_GET_KEYRING_ID failed");
for (key = INT32_MAX; key > INT32_MIN; key--) { - TEST(keyctl(KEYCTL_READ, key)); + TEST(KEYCTL(KEYCTL_READ, key)); if (TST_RET == -1 && TST_ERR == ENOKEY) break; }
- TEST(keyctl(KEYCTL_REVOKE, key)); + TEST(KEYCTL(KEYCTL_REVOKE, key)); if (TST_RET != -1) { tst_res(TFAIL, "KEYCTL_REVOKE succeeded unexpectedly"); return; diff --git a/testcases/kernel/syscalls/keyctl/keyctl02.c b/testcases/kernel/syscalls/keyctl/keyctl02.c index 564aef4da..e5e1ae40c 100644 --- a/testcases/kernel/syscalls/keyctl/keyctl02.c +++ b/testcases/kernel/syscalls/keyctl/keyctl02.c @@ -42,7 +42,7 @@ static void *do_read(void *arg) key_serial_t key = (unsigned long)arg; char buffer[4] = { 0 };
- keyctl(KEYCTL_READ, key, buffer, 4); + KEYCTL(KEYCTL_READ, key, buffer, 4);
return NULL; } @@ -51,7 +51,7 @@ static void *do_revoke(void *arg) { key_serial_t key = (unsigned long)arg;
- keyctl(KEYCTL_REVOKE, key); + KEYCTL(KEYCTL_REVOKE, key);
return NULL; } @@ -100,7 +100,7 @@ static void do_test(void) * If we have invalidate, we can drop extra key immediately as well, * which also schedules gc. */ - if (keyctl(KEYCTL_INVALIDATE, key_inv) == -1 && errno != EOPNOTSUPP) + if (KEYCTL(KEYCTL_INVALIDATE, key_inv) == -1 && errno != EOPNOTSUPP) tst_brk(TBROK | TERRNO, "Failed to invalidate key");
/* @@ -108,7 +108,7 @@ static void do_test(void) * so we wait and periodically check for last test key to be removed. */ for (i = 0; i < MAX_WAIT_FOR_GC_MS; i += 100) { - ret = keyctl(KEYCTL_REVOKE, key); + ret = KEYCTL(KEYCTL_REVOKE, key); if (ret == -1 && errno == ENOKEY) break; usleep(100*1000); diff --git a/testcases/kernel/syscalls/keyctl/keyctl03.c b/testcases/kernel/syscalls/keyctl/keyctl03.c index 9d7b9a0b5..159cc7d0d 100644 --- a/testcases/kernel/syscalls/keyctl/keyctl03.c +++ b/testcases/kernel/syscalls/keyctl/keyctl03.c @@ -32,7 +32,7 @@ static void do_test(void)
request_key("keyring", "foo", "bar", KEY_SPEC_THREAD_KEYRING);
- TEST(keyctl(KEYCTL_UNLINK, key, KEY_SPEC_SESSION_KEYRING)); + TEST(KEYCTL(KEYCTL_UNLINK, key, KEY_SPEC_SESSION_KEYRING)); if (TST_RET) tst_res(TFAIL | TTERRNO, "keyctl unlink failed"); else diff --git a/testcases/kernel/syscalls/keyctl/keyctl04.c b/testcases/kernel/syscalls/keyctl/keyctl04.c index 1fed23ca6..8693099fb 100644 --- a/testcases/kernel/syscalls/keyctl/keyctl04.c +++ b/testcases/kernel/syscalls/keyctl/keyctl04.c @@ -23,16 +23,16 @@ static void do_test(void) { key_serial_t tid_keyring;
- TEST(keyctl(KEYCTL_GET_KEYRING_ID, KEY_SPEC_THREAD_KEYRING, 1)); + TEST(KEYCTL(KEYCTL_GET_KEYRING_ID, KEY_SPEC_THREAD_KEYRING, 1)); if (TST_RET < 0) tst_brk(TBROK | TTERRNO, "failed to create thread keyring"); tid_keyring = TST_RET;
- TEST(keyctl(KEYCTL_SET_REQKEY_KEYRING, KEY_REQKEY_DEFL_THREAD_KEYRING)); + TEST(KEYCTL(KEYCTL_SET_REQKEY_KEYRING, KEY_REQKEY_DEFL_THREAD_KEYRING)); if (TST_RET < 0) tst_brk(TBROK | TTERRNO, "failed to set reqkey keyring");
- TEST(keyctl(KEYCTL_GET_KEYRING_ID, KEY_SPEC_THREAD_KEYRING, 0)); + TEST(KEYCTL(KEYCTL_GET_KEYRING_ID, KEY_SPEC_THREAD_KEYRING, 0)); if (TST_RET < 0) tst_brk(TBROK | TTERRNO, "failed to get thread keyring ID"); if (TST_RET == tid_keyring) diff --git a/testcases/kernel/syscalls/keyctl/keyctl05.c b/testcases/kernel/syscalls/keyctl/keyctl05.c index 7d7c076c0..6879ab7b2 100644 --- a/testcases/kernel/syscalls/keyctl/keyctl05.c +++ b/testcases/kernel/syscalls/keyctl/keyctl05.c @@ -75,7 +75,7 @@ static const char x509_cert[] =
static void new_session_keyring(void) { - TEST(keyctl(KEYCTL_JOIN_SESSION_KEYRING, NULL)); + TEST(KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, NULL)); if (TST_RET < 0) tst_brk(TBROK | TTERRNO, "failed to join new session keyring"); } @@ -121,7 +121,7 @@ static void test_update_nonupdatable(const char *type, * Non-updatable keys don't start with write permission, so we must * explicitly grant it. */ - TEST(keyctl(KEYCTL_SETPERM, keyid, KEY_POS_ALL)); + TEST(KEYCTL(KEYCTL_SETPERM, keyid, KEY_POS_ALL)); if (TST_RET != 0) { tst_res(TFAIL | TTERRNO, "failed to grant write permission to '%s' key", type); @@ -129,7 +129,7 @@ static void test_update_nonupdatable(const char *type, }
tst_res(TINFO, "Try to update the '%s' key...", type); - TEST(keyctl(KEYCTL_UPDATE, keyid, payload, plen)); + TEST(KEYCTL(KEYCTL_UPDATE, keyid, payload, plen)); if (TST_RET == 0) { tst_res(TFAIL, "updating '%s' key unexpectedly succeeded", type); @@ -169,7 +169,7 @@ static void test_update_setperm_race(void)
for (i = 0; i < 10000; i++) { perm ^= KEY_POS_WRITE; - TEST(keyctl(KEYCTL_SETPERM, keyid, perm)); + TEST(KEYCTL(KEYCTL_SETPERM, keyid, perm)); if (TST_RET != 0) tst_brk(TBROK | TTERRNO, "setperm failed"); } @@ -178,7 +178,7 @@ static void test_update_setperm_race(void)
tst_res(TINFO, "Try to update the 'user' key..."); for (i = 0; i < 10000; i++) { - TEST(keyctl(KEYCTL_UPDATE, keyid, payload, sizeof(payload))); + TEST(KEYCTL(KEYCTL_UPDATE, keyid, payload, sizeof(payload))); if (TST_RET != 0 && TST_ERR != EACCES) { tst_res(TFAIL | TTERRNO, "failed to update 'user' key"); return; diff --git a/testcases/kernel/syscalls/keyctl/keyctl06.c b/testcases/kernel/syscalls/keyctl/keyctl06.c index f76a85ff2..97170a026 100644 --- a/testcases/kernel/syscalls/keyctl/keyctl06.c +++ b/testcases/kernel/syscalls/keyctl/keyctl06.c @@ -37,7 +37,7 @@ static void do_test(void) add_test_key("key2");
memset(key_ids, 0, sizeof(key_ids)); - TEST(keyctl(KEYCTL_READ, KEY_SPEC_PROCESS_KEYRING, + TEST(KEYCTL(KEYCTL_READ, KEY_SPEC_PROCESS_KEYRING, (char *)key_ids, sizeof(key_serial_t))); if (TST_RET < 0) tst_brk(TBROK | TTERRNO, "KEYCTL_READ failed"); diff --git a/testcases/kernel/syscalls/keyctl/keyctl07.c b/testcases/kernel/syscalls/keyctl/keyctl07.c index 875ef0bb8..20dfa8a08 100644 --- a/testcases/kernel/syscalls/keyctl/keyctl07.c +++ b/testcases/kernel/syscalls/keyctl/keyctl07.c @@ -46,7 +46,7 @@ static void try_to_read_negative_key(void) }
/* Get the ID of the negative key by reading the keyring */ - TEST(keyctl(KEYCTL_READ, KEY_SPEC_PROCESS_KEYRING, + TEST(KEYCTL(KEYCTL_READ, KEY_SPEC_PROCESS_KEYRING, &key_id, sizeof(key_id))); if (TST_RET < 0) tst_brk(TBROK | TTERRNO, "KEYCTL_READ unexpectedly failed"); @@ -60,7 +60,7 @@ static void try_to_read_negative_key(void) * to read from memory address 0x00000000ffffff92. */ tst_res(TINFO, "trying to read from the negative key..."); - TEST(keyctl(KEYCTL_READ, key_id, buffer, sizeof(buffer))); + TEST(KEYCTL(KEYCTL_READ, key_id, buffer, sizeof(buffer))); if (TST_RET != -1) { tst_brk(TFAIL, "KEYCTL_READ on negative key unexpectedly succeeded"); diff --git a/testcases/kernel/syscalls/keyctl/keyctl09.c b/testcases/kernel/syscalls/keyctl/keyctl09.c index c88c481b9..c18a3ab25 100644 --- a/testcases/kernel/syscalls/keyctl/keyctl09.c +++ b/testcases/kernel/syscalls/keyctl/keyctl09.c @@ -33,7 +33,7 @@ static void do_test(void) if (!TST_PASS) return;
- TST_EXP_POSITIVE(keyctl(KEYCTL_READ, TST_RET, buffer, sizeof(buffer))); + TST_EXP_POSITIVE(KEYCTL(KEYCTL_READ, TST_RET, buffer, sizeof(buffer)));
if (!TST_PASS) return; @@ -42,7 +42,7 @@ static void do_test(void) ENCRYPTED_KEY_INVALID_PAYLOAD, 60, KEY_SPEC_PROCESS_KEYRING), EINVAL);
- keyctl(KEYCTL_CLEAR, KEY_SPEC_PROCESS_KEYRING); + KEYCTL(KEYCTL_CLEAR, KEY_SPEC_PROCESS_KEYRING); }
static struct tst_test test = { diff --git a/testcases/kernel/syscalls/request_key/request_key02.c b/testcases/kernel/syscalls/request_key/request_key02.c index 89a78142e..3aaae41e3 100644 --- a/testcases/kernel/syscalls/request_key/request_key02.c +++ b/testcases/kernel/syscalls/request_key/request_key02.c @@ -68,13 +68,13 @@ static int init_key(char *name, int cmd) tst_brk(TBROK | TERRNO, "add_key() failed");
if (cmd == KEYCTL_REVOKE) { - if (keyctl(cmd, n) == -1) { + if (KEYCTL(cmd, n) == -1) { tst_brk(TBROK | TERRNO, "failed to revoke a key"); } }
if (cmd == KEYCTL_SET_TIMEOUT) { - if (keyctl(cmd, n, sec) == -1) { + if (KEYCTL(cmd, n, sec) == -1) { tst_brk(TBROK | TERRNO, "failed to set timeout for a key"); } diff --git a/testcases/kernel/syscalls/request_key/request_key03.c b/testcases/kernel/syscalls/request_key/request_key03.c index 3f0c093f3..177932ad9 100644 --- a/testcases/kernel/syscalls/request_key/request_key03.c +++ b/testcases/kernel/syscalls/request_key/request_key03.c @@ -48,7 +48,7 @@ static void test_with_key_type(const char *type, const char *payload, pid_t request_key_pid; bool info_only;
- TEST(keyctl(KEYCTL_JOIN_SESSION_KEYRING, NULL)); + TEST(KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, NULL)); if (TST_RET < 0) tst_brk(TBROK | TTERRNO, "failed to join new session keyring");
@@ -97,7 +97,7 @@ static void test_with_key_type(const char *type, const char *payload, "unexpected error adding key of type '%s'", type); } - TEST(keyctl(KEYCTL_CLEAR, KEY_SPEC_SESSION_KEYRING)); + TEST(KEYCTL(KEYCTL_CLEAR, KEY_SPEC_SESSION_KEYRING)); if (TST_RET < 0) { tst_brk(TBROK | TTERRNO, "unable to clear keyring"); diff --git a/testcases/kernel/syscalls/request_key/request_key04.c b/testcases/kernel/syscalls/request_key/request_key04.c index c125f4261..b049d8799 100644 --- a/testcases/kernel/syscalls/request_key/request_key04.c +++ b/testcases/kernel/syscalls/request_key/request_key04.c @@ -24,25 +24,25 @@ static void do_test(void) key_serial_t keyid; int saved_errno;
- TEST(keyctl(KEYCTL_JOIN_SESSION_KEYRING, NULL)); + TEST(KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, NULL)); if (TST_RET < 0) tst_brk(TBROK | TTERRNO, "failed to join new session keyring");
- TEST(keyctl(KEYCTL_SETPERM, KEY_SPEC_SESSION_KEYRING, + TEST(KEYCTL(KEYCTL_SETPERM, KEY_SPEC_SESSION_KEYRING, KEY_POS_SEARCH|KEY_POS_READ|KEY_POS_VIEW)); if (TST_RET < 0) { tst_brk(TBROK | TTERRNO, "failed to set permissions on session keyring"); }
- TEST(keyctl(KEYCTL_SET_REQKEY_KEYRING, + TEST(KEYCTL(KEYCTL_SET_REQKEY_KEYRING, KEY_REQKEY_DEFL_SESSION_KEYRING)); if (TST_RET < 0) { tst_brk(TBROK | TTERRNO, "failed to set request-key default keyring"); }
- TEST(keyctl(KEYCTL_READ, KEY_SPEC_SESSION_KEYRING, + TEST(KEYCTL(KEYCTL_READ, KEY_SPEC_SESSION_KEYRING, &keyid, sizeof(keyid))); if (TST_RET < 0) tst_brk(TBROK | TTERRNO, "failed to read from session keyring"); @@ -54,7 +54,7 @@ static void do_test(void) tst_brk(TBROK, "request_key() unexpectedly succeeded"); saved_errno = TST_ERR;
- TEST(keyctl(KEYCTL_READ, KEY_SPEC_SESSION_KEYRING, + TEST(KEYCTL(KEYCTL_READ, KEY_SPEC_SESSION_KEYRING, &keyid, sizeof(keyid))); if (TST_RET < 0) tst_brk(TBROK | TTERRNO, "failed to read from session keyring"); diff --git a/testcases/kernel/watchqueue/common.h b/testcases/kernel/watchqueue/common.h index 92e8f079c..ea35219e5 100644 --- a/testcases/kernel/watchqueue/common.h +++ b/testcases/kernel/watchqueue/common.h @@ -85,8 +85,8 @@ static inline key_serial_t wqueue_add_key(int fd) if (key == -1) tst_brk(TBROK, "add_key error: %s", tst_strerrno(errno));
- keyctl(KEYCTL_WATCH_KEY, key, fd, 0x01); - keyctl(KEYCTL_WATCH_KEY, KEY_SPEC_SESSION_KEYRING, fd, 0x02); + KEYCTL(KEYCTL_WATCH_KEY, key, fd, 0x01); + KEYCTL(KEYCTL_WATCH_KEY, KEY_SPEC_SESSION_KEYRING, fd, 0x02);
return key; } diff --git a/testcases/kernel/watchqueue/wqueue01.c b/testcases/kernel/watchqueue/wqueue01.c index 904e512af..dd0a68dfb 100644 --- a/testcases/kernel/watchqueue/wqueue01.c +++ b/testcases/kernel/watchqueue/wqueue01.c @@ -32,7 +32,7 @@ static void run(void) fd = wqueue_watch(256, &wqueue_filter); key = wqueue_add_key(fd);
- keyctl(KEYCTL_UPDATE, key, "b", 1); + KEYCTL(KEYCTL_UPDATE, key, "b", 1); wqueue_consumer(fd, saw_key_updated);
SAFE_CLOSE(fd); diff --git a/testcases/kernel/watchqueue/wqueue02.c b/testcases/kernel/watchqueue/wqueue02.c index 0c3e947d1..37929b9d0 100644 --- a/testcases/kernel/watchqueue/wqueue02.c +++ b/testcases/kernel/watchqueue/wqueue02.c @@ -32,7 +32,7 @@ static void run(void) fd = wqueue_watch(256, &wqueue_filter); key = wqueue_add_key(fd);
- keyctl(KEYCTL_UNLINK, key, KEY_SPEC_SESSION_KEYRING); + KEYCTL(KEYCTL_UNLINK, key, KEY_SPEC_SESSION_KEYRING); wqueue_consumer(fd, saw_key_unlinked);
SAFE_CLOSE(fd); diff --git a/testcases/kernel/watchqueue/wqueue03.c b/testcases/kernel/watchqueue/wqueue03.c index c17fc1452..8ce23b253 100644 --- a/testcases/kernel/watchqueue/wqueue03.c +++ b/testcases/kernel/watchqueue/wqueue03.c @@ -32,7 +32,7 @@ static void run(void) fd = wqueue_watch(256, &wqueue_filter); key = wqueue_add_key(fd);
- keyctl(KEYCTL_REVOKE, key); + KEYCTL(KEYCTL_REVOKE, key); wqueue_consumer(fd, saw_key_revoked);
SAFE_CLOSE(fd); diff --git a/testcases/kernel/watchqueue/wqueue04.c b/testcases/kernel/watchqueue/wqueue04.c index fc880064b..c23a75254 100644 --- a/testcases/kernel/watchqueue/wqueue04.c +++ b/testcases/kernel/watchqueue/wqueue04.c @@ -32,7 +32,7 @@ static void run(void) fd = wqueue_watch(256, &wqueue_filter); key = wqueue_add_key(fd);
- keyctl(KEYCTL_LINK, key, KEY_SPEC_SESSION_KEYRING); + KEYCTL(KEYCTL_LINK, key, KEY_SPEC_SESSION_KEYRING); wqueue_consumer(fd, saw_key_linked);
SAFE_CLOSE(fd); diff --git a/testcases/kernel/watchqueue/wqueue05.c b/testcases/kernel/watchqueue/wqueue05.c index 78a4c702e..221d95d22 100644 --- a/testcases/kernel/watchqueue/wqueue05.c +++ b/testcases/kernel/watchqueue/wqueue05.c @@ -32,7 +32,7 @@ static void run(void) fd = wqueue_watch(256, &wqueue_filter); key = wqueue_add_key(fd);
- keyctl(KEYCTL_INVALIDATE, key); + KEYCTL(KEYCTL_INVALIDATE, key); wqueue_consumer(fd, saw_key_invalidated);
SAFE_CLOSE(fd); diff --git a/testcases/kernel/watchqueue/wqueue06.c b/testcases/kernel/watchqueue/wqueue06.c index 2cb6a966d..692612255 100644 --- a/testcases/kernel/watchqueue/wqueue06.c +++ b/testcases/kernel/watchqueue/wqueue06.c @@ -31,7 +31,7 @@ static void run(void) fd = wqueue_watch(256, &wqueue_filter); wqueue_add_key(fd);
- keyctl(KEYCTL_CLEAR, KEY_SPEC_SESSION_KEYRING); + KEYCTL(KEYCTL_CLEAR, KEY_SPEC_SESSION_KEYRING); wqueue_consumer(fd, saw_key_cleared);
SAFE_CLOSE(fd); diff --git a/testcases/kernel/watchqueue/wqueue07.c b/testcases/kernel/watchqueue/wqueue07.c index 6c4d1e92a..a7daad973 100644 --- a/testcases/kernel/watchqueue/wqueue07.c +++ b/testcases/kernel/watchqueue/wqueue07.c @@ -32,7 +32,7 @@ static void run(void) fd = wqueue_watch(256, &wqueue_filter); key = wqueue_add_key(fd);
- keyctl(KEYCTL_SETPERM, key, KEY_POS_ALL | KEY_USR_ALL); + KEYCTL(KEYCTL_SETPERM, key, KEY_POS_ALL | KEY_USR_ALL); wqueue_consumer(fd, saw_key_setattr);
SAFE_CLOSE(fd); diff --git a/testcases/kernel/watchqueue/wqueue08.c b/testcases/kernel/watchqueue/wqueue08.c index 4ed9522da..bea3a6c36 100644 --- a/testcases/kernel/watchqueue/wqueue08.c +++ b/testcases/kernel/watchqueue/wqueue08.c @@ -37,7 +37,7 @@ static void run(void) key = wqueue_add_key(fd);
/* if watch_id = -1 key is removed from the watch queue */ - keyctl(KEYCTL_WATCH_KEY, key, fd, -1); + KEYCTL(KEYCTL_WATCH_KEY, key, fd, -1); wqueue_consumer(fd, saw_watch_removal);
SAFE_CLOSE(fd); diff --git a/testcases/kernel/watchqueue/wqueue09.c b/testcases/kernel/watchqueue/wqueue09.c index 9f077b35b..f19d98f09 100644 --- a/testcases/kernel/watchqueue/wqueue09.c +++ b/testcases/kernel/watchqueue/wqueue09.c @@ -44,7 +44,7 @@ static void run(void)
iterations = (getpagesize() / WATCH_QUEUE_NOTE_SIZE) * 2; for (i = 0; i < iterations; i++) - keyctl(KEYCTL_UPDATE, key, "b", 1); + KEYCTL(KEYCTL_UPDATE, key, "b", 1);
data_lost = 0; while (!data_lost) @@ -58,7 +58,7 @@ static void run(void)
static void cleanup(void) { - keyctl(KEYCTL_REVOKE, key); + KEYCTL(KEYCTL_REVOKE, key); SAFE_CLOSE(fd); }
Hi Beata,
On 25-11-2022 14:26, Beata Michalska wrote:
Currently the keyctl helper makes silent assumption that either all expected arguments are being provided or otherwise it's somewhat safe to access beyond the actual va arg list. With AAPCS64-cap this will no longer slide through, as reading more arguments than provided will trigger capability bound fault. Introduce dedicated macro to handle the variadic-ness instead, making sure that at any point all arguments are being provided, whether explicitly or through default values.
Reported-by: Kevin Brodsky kevin.brodsky@arm.com Suggested-by: Kevin Brodsky kevin.brodsky@arm.com Signed-off-by: Beata Michalska beata.michalska@arm.com
include/lapi/keyctl.h | 22 +++++++++---------- testcases/cve/cve-2016-7042.c | 6 ++--- testcases/kernel/syscalls/add_key/add_key03.c | 2 +- testcases/kernel/syscalls/add_key/add_key04.c | 2 +- testcases/kernel/syscalls/keyctl/keyctl01.c | 6 ++--- testcases/kernel/syscalls/keyctl/keyctl02.c | 8 +++---- testcases/kernel/syscalls/keyctl/keyctl03.c | 2 +- testcases/kernel/syscalls/keyctl/keyctl04.c | 6 ++--- testcases/kernel/syscalls/keyctl/keyctl05.c | 10 ++++----- testcases/kernel/syscalls/keyctl/keyctl06.c | 2 +- testcases/kernel/syscalls/keyctl/keyctl07.c | 4 ++-- testcases/kernel/syscalls/keyctl/keyctl09.c | 4 ++-- .../syscalls/request_key/request_key02.c | 4 ++-- .../syscalls/request_key/request_key03.c | 4 ++-- .../syscalls/request_key/request_key04.c | 10 ++++----- testcases/kernel/watchqueue/common.h | 4 ++-- testcases/kernel/watchqueue/wqueue01.c | 2 +- testcases/kernel/watchqueue/wqueue02.c | 2 +- testcases/kernel/watchqueue/wqueue03.c | 2 +- testcases/kernel/watchqueue/wqueue04.c | 2 +- testcases/kernel/watchqueue/wqueue05.c | 2 +- testcases/kernel/watchqueue/wqueue06.c | 2 +- testcases/kernel/watchqueue/wqueue07.c | 2 +- testcases/kernel/watchqueue/wqueue08.c | 2 +- testcases/kernel/watchqueue/wqueue09.c | 4 ++-- 25 files changed, 57 insertions(+), 59 deletions(-)
diff --git a/include/lapi/keyctl.h b/include/lapi/keyctl.h index 9c847a429..1c7436ef6 100644 --- a/include/lapi/keyctl.h +++ b/include/lapi/keyctl.h @@ -39,23 +39,21 @@ static inline key_serial_t request_key(const char *type, type, description, callout_info, destringid); } -static inline long keyctl(int cmd, ...) -{
- va_list va;
- uintptr_t arg2, arg3, arg4, arg5;
+#define __KEYCTL(cmd, arg2, arg3, arg4, arg5, ...) \
- keyctl((cmd), (arg2), (arg3), (arg4), (arg5))
- va_start(va, cmd);
- arg2 = va_arg(va, uintptr_t);
- arg3 = va_arg(va, uintptr_t);
- arg4 = va_arg(va, uintptr_t);
- arg5 = va_arg(va, uintptr_t);
- va_end(va);
+#define KEYCTL(cmd, ...) \
- __KEYCTL((cmd), ##__VA_ARGS__, 0, 0, 0, 0)
+static inline long keyctl(int cmd, uintptr_t arg2, uintptr_t arg3,
uintptr_t arg4, uintptr_t arg5)
+{
Just to note, there is no keyctl function signature standardised in Posix and libcs don't seem to typically define this wrapper. So, in my opinion, you could make "keyctl" directly a macro that calls __KEYCTL and make __KEYCTL call tst_syscall. In that way you don't need to replace keyctl with KEYCTL everywhere. I can see though why you preferred it this way and it looks as fine to me.
Great patch!
Tudor
return tst_syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5); } -static inline key_serial_t keyctl_join_session_keyring(const char *name) {
- return keyctl(KEYCTL_JOIN_SESSION_KEYRING, name);
+static inline key_serial_t keyctl_join_session_keyring(const char *name) +{
- return KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, name); }
#endif /* defined(HAVE_KEYUTILS_H) && defined(HAVE_LIBKEYUTILS) */ diff --git a/testcases/cve/cve-2016-7042.c b/testcases/cve/cve-2016-7042.c index 4434265dd..91ffccf2f 100644 --- a/testcases/cve/cve-2016-7042.c +++ b/testcases/cve/cve-2016-7042.c @@ -34,7 +34,7 @@ static void do_test(void) if (key == -1) tst_brk(TBROK, "Failed to add key");
- if (keyctl(KEYCTL_UPDATE, key, "b", 1))
- if (KEYCTL(KEYCTL_UPDATE, key, "b", 1)) tst_brk(TBROK, "Failed to update key");
fd = SAFE_OPEN(PATH_KEYS, O_RDONLY); @@ -47,7 +47,7 @@ static void do_test(void) SAFE_CLOSE(fd);
- if (keyctl(KEYCTL_UNLINK, key, KEY_SPEC_SESSION_KEYRING))
- if (KEYCTL(KEYCTL_UNLINK, key, KEY_SPEC_SESSION_KEYRING)) tst_brk(TBROK, "Failed to unlink key"); key = 0; }
@@ -60,7 +60,7 @@ static void setup(void) static void cleanup(void) {
- if (key > 0 && keyctl(KEYCTL_UNLINK, key, KEY_SPEC_SESSION_KEYRING))
- if (key > 0 && KEYCTL(KEYCTL_UNLINK, key, KEY_SPEC_SESSION_KEYRING)) tst_res(TWARN, "Failed to unlink key");
if (fd > 0) diff --git a/testcases/kernel/syscalls/add_key/add_key03.c b/testcases/kernel/syscalls/add_key/add_key03.c index d26912cb7..53613fc08 100644 --- a/testcases/kernel/syscalls/add_key/add_key03.c +++ b/testcases/kernel/syscalls/add_key/add_key03.c @@ -35,7 +35,7 @@ static key_serial_t create_keyring(const char *description) static key_serial_t get_keyring_id(key_serial_t special_id) {
- TEST(keyctl(KEYCTL_GET_KEYRING_ID, special_id, 1));
- TEST(KEYCTL(KEYCTL_GET_KEYRING_ID, special_id, 1)); if (TST_RET < 0) { tst_brk(TBROK | TTERRNO, "unable to get ID of keyring %d", special_id);
diff --git a/testcases/kernel/syscalls/add_key/add_key04.c b/testcases/kernel/syscalls/add_key/add_key04.c index aa02fdd1d..105135566 100644 --- a/testcases/kernel/syscalls/add_key/add_key04.c +++ b/testcases/kernel/syscalls/add_key/add_key04.c @@ -40,7 +40,7 @@ static void do_test(void) { int status;
- TEST(keyctl(KEYCTL_JOIN_SESSION_KEYRING, NULL));
- TEST(KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, NULL)); if (TST_RET < 0) tst_brk(TBROK | TTERRNO, "failed to join new session keyring");
diff --git a/testcases/kernel/syscalls/keyctl/keyctl01.c b/testcases/kernel/syscalls/keyctl/keyctl01.c index 55e069c68..2e29c8375 100644 --- a/testcases/kernel/syscalls/keyctl/keyctl01.c +++ b/testcases/kernel/syscalls/keyctl/keyctl01.c @@ -22,19 +22,19 @@ static void do_test(void) { key_serial_t key;
- TEST(keyctl(KEYCTL_GET_KEYRING_ID, KEY_SPEC_USER_SESSION_KEYRING));
- TEST(KEYCTL(KEYCTL_GET_KEYRING_ID, KEY_SPEC_USER_SESSION_KEYRING)); if (TST_RET != -1) tst_res(TPASS, "KEYCTL_GET_KEYRING_ID succeeded"); else tst_res(TFAIL | TTERRNO, "KEYCTL_GET_KEYRING_ID failed");
for (key = INT32_MAX; key > INT32_MIN; key--) {
TEST(keyctl(KEYCTL_READ, key));
if (TST_RET == -1 && TST_ERR == ENOKEY) break; }TEST(KEYCTL(KEYCTL_READ, key));
- TEST(keyctl(KEYCTL_REVOKE, key));
- TEST(KEYCTL(KEYCTL_REVOKE, key)); if (TST_RET != -1) { tst_res(TFAIL, "KEYCTL_REVOKE succeeded unexpectedly"); return;
diff --git a/testcases/kernel/syscalls/keyctl/keyctl02.c b/testcases/kernel/syscalls/keyctl/keyctl02.c index 564aef4da..e5e1ae40c 100644 --- a/testcases/kernel/syscalls/keyctl/keyctl02.c +++ b/testcases/kernel/syscalls/keyctl/keyctl02.c @@ -42,7 +42,7 @@ static void *do_read(void *arg) key_serial_t key = (unsigned long)arg; char buffer[4] = { 0 };
- keyctl(KEYCTL_READ, key, buffer, 4);
- KEYCTL(KEYCTL_READ, key, buffer, 4);
return NULL; } @@ -51,7 +51,7 @@ static void *do_revoke(void *arg) { key_serial_t key = (unsigned long)arg;
- keyctl(KEYCTL_REVOKE, key);
- KEYCTL(KEYCTL_REVOKE, key);
return NULL; } @@ -100,7 +100,7 @@ static void do_test(void) * If we have invalidate, we can drop extra key immediately as well, * which also schedules gc. */
- if (keyctl(KEYCTL_INVALIDATE, key_inv) == -1 && errno != EOPNOTSUPP)
- if (KEYCTL(KEYCTL_INVALIDATE, key_inv) == -1 && errno != EOPNOTSUPP) tst_brk(TBROK | TERRNO, "Failed to invalidate key");
/* @@ -108,7 +108,7 @@ static void do_test(void) * so we wait and periodically check for last test key to be removed. */ for (i = 0; i < MAX_WAIT_FOR_GC_MS; i += 100) {
ret = keyctl(KEYCTL_REVOKE, key);
if (ret == -1 && errno == ENOKEY) break; usleep(100*1000);ret = KEYCTL(KEYCTL_REVOKE, key);
diff --git a/testcases/kernel/syscalls/keyctl/keyctl03.c b/testcases/kernel/syscalls/keyctl/keyctl03.c index 9d7b9a0b5..159cc7d0d 100644 --- a/testcases/kernel/syscalls/keyctl/keyctl03.c +++ b/testcases/kernel/syscalls/keyctl/keyctl03.c @@ -32,7 +32,7 @@ static void do_test(void) request_key("keyring", "foo", "bar", KEY_SPEC_THREAD_KEYRING);
- TEST(keyctl(KEYCTL_UNLINK, key, KEY_SPEC_SESSION_KEYRING));
- TEST(KEYCTL(KEYCTL_UNLINK, key, KEY_SPEC_SESSION_KEYRING)); if (TST_RET) tst_res(TFAIL | TTERRNO, "keyctl unlink failed"); else
diff --git a/testcases/kernel/syscalls/keyctl/keyctl04.c b/testcases/kernel/syscalls/keyctl/keyctl04.c index 1fed23ca6..8693099fb 100644 --- a/testcases/kernel/syscalls/keyctl/keyctl04.c +++ b/testcases/kernel/syscalls/keyctl/keyctl04.c @@ -23,16 +23,16 @@ static void do_test(void) { key_serial_t tid_keyring;
- TEST(keyctl(KEYCTL_GET_KEYRING_ID, KEY_SPEC_THREAD_KEYRING, 1));
- TEST(KEYCTL(KEYCTL_GET_KEYRING_ID, KEY_SPEC_THREAD_KEYRING, 1)); if (TST_RET < 0) tst_brk(TBROK | TTERRNO, "failed to create thread keyring"); tid_keyring = TST_RET;
- TEST(keyctl(KEYCTL_SET_REQKEY_KEYRING, KEY_REQKEY_DEFL_THREAD_KEYRING));
- TEST(KEYCTL(KEYCTL_SET_REQKEY_KEYRING, KEY_REQKEY_DEFL_THREAD_KEYRING)); if (TST_RET < 0) tst_brk(TBROK | TTERRNO, "failed to set reqkey keyring");
- TEST(keyctl(KEYCTL_GET_KEYRING_ID, KEY_SPEC_THREAD_KEYRING, 0));
- TEST(KEYCTL(KEYCTL_GET_KEYRING_ID, KEY_SPEC_THREAD_KEYRING, 0)); if (TST_RET < 0) tst_brk(TBROK | TTERRNO, "failed to get thread keyring ID"); if (TST_RET == tid_keyring)
diff --git a/testcases/kernel/syscalls/keyctl/keyctl05.c b/testcases/kernel/syscalls/keyctl/keyctl05.c index 7d7c076c0..6879ab7b2 100644 --- a/testcases/kernel/syscalls/keyctl/keyctl05.c +++ b/testcases/kernel/syscalls/keyctl/keyctl05.c @@ -75,7 +75,7 @@ static const char x509_cert[] = static void new_session_keyring(void) {
- TEST(keyctl(KEYCTL_JOIN_SESSION_KEYRING, NULL));
- TEST(KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, NULL)); if (TST_RET < 0) tst_brk(TBROK | TTERRNO, "failed to join new session keyring"); }
@@ -121,7 +121,7 @@ static void test_update_nonupdatable(const char *type, * Non-updatable keys don't start with write permission, so we must * explicitly grant it. */
- TEST(keyctl(KEYCTL_SETPERM, keyid, KEY_POS_ALL));
- TEST(KEYCTL(KEYCTL_SETPERM, keyid, KEY_POS_ALL)); if (TST_RET != 0) { tst_res(TFAIL | TTERRNO, "failed to grant write permission to '%s' key", type);
@@ -129,7 +129,7 @@ static void test_update_nonupdatable(const char *type, } tst_res(TINFO, "Try to update the '%s' key...", type);
- TEST(keyctl(KEYCTL_UPDATE, keyid, payload, plen));
- TEST(KEYCTL(KEYCTL_UPDATE, keyid, payload, plen)); if (TST_RET == 0) { tst_res(TFAIL, "updating '%s' key unexpectedly succeeded", type);
@@ -169,7 +169,7 @@ static void test_update_setperm_race(void) for (i = 0; i < 10000; i++) { perm ^= KEY_POS_WRITE;
TEST(keyctl(KEYCTL_SETPERM, keyid, perm));
}TEST(KEYCTL(KEYCTL_SETPERM, keyid, perm)); if (TST_RET != 0) tst_brk(TBROK | TTERRNO, "setperm failed");
@@ -178,7 +178,7 @@ static void test_update_setperm_race(void) tst_res(TINFO, "Try to update the 'user' key..."); for (i = 0; i < 10000; i++) {
TEST(keyctl(KEYCTL_UPDATE, keyid, payload, sizeof(payload)));
if (TST_RET != 0 && TST_ERR != EACCES) { tst_res(TFAIL | TTERRNO, "failed to update 'user' key"); return;TEST(KEYCTL(KEYCTL_UPDATE, keyid, payload, sizeof(payload)));
diff --git a/testcases/kernel/syscalls/keyctl/keyctl06.c b/testcases/kernel/syscalls/keyctl/keyctl06.c index f76a85ff2..97170a026 100644 --- a/testcases/kernel/syscalls/keyctl/keyctl06.c +++ b/testcases/kernel/syscalls/keyctl/keyctl06.c @@ -37,7 +37,7 @@ static void do_test(void) add_test_key("key2"); memset(key_ids, 0, sizeof(key_ids));
- TEST(keyctl(KEYCTL_READ, KEY_SPEC_PROCESS_KEYRING,
- TEST(KEYCTL(KEYCTL_READ, KEY_SPEC_PROCESS_KEYRING, (char *)key_ids, sizeof(key_serial_t))); if (TST_RET < 0) tst_brk(TBROK | TTERRNO, "KEYCTL_READ failed");
diff --git a/testcases/kernel/syscalls/keyctl/keyctl07.c b/testcases/kernel/syscalls/keyctl/keyctl07.c index 875ef0bb8..20dfa8a08 100644 --- a/testcases/kernel/syscalls/keyctl/keyctl07.c +++ b/testcases/kernel/syscalls/keyctl/keyctl07.c @@ -46,7 +46,7 @@ static void try_to_read_negative_key(void) } /* Get the ID of the negative key by reading the keyring */
- TEST(keyctl(KEYCTL_READ, KEY_SPEC_PROCESS_KEYRING,
- TEST(KEYCTL(KEYCTL_READ, KEY_SPEC_PROCESS_KEYRING, &key_id, sizeof(key_id))); if (TST_RET < 0) tst_brk(TBROK | TTERRNO, "KEYCTL_READ unexpectedly failed");
@@ -60,7 +60,7 @@ static void try_to_read_negative_key(void) * to read from memory address 0x00000000ffffff92. */ tst_res(TINFO, "trying to read from the negative key...");
- TEST(keyctl(KEYCTL_READ, key_id, buffer, sizeof(buffer)));
- TEST(KEYCTL(KEYCTL_READ, key_id, buffer, sizeof(buffer))); if (TST_RET != -1) { tst_brk(TFAIL, "KEYCTL_READ on negative key unexpectedly succeeded");
diff --git a/testcases/kernel/syscalls/keyctl/keyctl09.c b/testcases/kernel/syscalls/keyctl/keyctl09.c index c88c481b9..c18a3ab25 100644 --- a/testcases/kernel/syscalls/keyctl/keyctl09.c +++ b/testcases/kernel/syscalls/keyctl/keyctl09.c @@ -33,7 +33,7 @@ static void do_test(void) if (!TST_PASS) return;
- TST_EXP_POSITIVE(keyctl(KEYCTL_READ, TST_RET, buffer, sizeof(buffer)));
- TST_EXP_POSITIVE(KEYCTL(KEYCTL_READ, TST_RET, buffer, sizeof(buffer)));
if (!TST_PASS) return; @@ -42,7 +42,7 @@ static void do_test(void) ENCRYPTED_KEY_INVALID_PAYLOAD, 60, KEY_SPEC_PROCESS_KEYRING), EINVAL);
- keyctl(KEYCTL_CLEAR, KEY_SPEC_PROCESS_KEYRING);
- KEYCTL(KEYCTL_CLEAR, KEY_SPEC_PROCESS_KEYRING); }
static struct tst_test test = { diff --git a/testcases/kernel/syscalls/request_key/request_key02.c b/testcases/kernel/syscalls/request_key/request_key02.c index 89a78142e..3aaae41e3 100644 --- a/testcases/kernel/syscalls/request_key/request_key02.c +++ b/testcases/kernel/syscalls/request_key/request_key02.c @@ -68,13 +68,13 @@ static int init_key(char *name, int cmd) tst_brk(TBROK | TERRNO, "add_key() failed"); if (cmd == KEYCTL_REVOKE) {
if (keyctl(cmd, n) == -1) {
} }if (KEYCTL(cmd, n) == -1) { tst_brk(TBROK | TERRNO, "failed to revoke a key");
if (cmd == KEYCTL_SET_TIMEOUT) {
if (keyctl(cmd, n, sec) == -1) {
}if (KEYCTL(cmd, n, sec) == -1) { tst_brk(TBROK | TERRNO, "failed to set timeout for a key");
diff --git a/testcases/kernel/syscalls/request_key/request_key03.c b/testcases/kernel/syscalls/request_key/request_key03.c index 3f0c093f3..177932ad9 100644 --- a/testcases/kernel/syscalls/request_key/request_key03.c +++ b/testcases/kernel/syscalls/request_key/request_key03.c @@ -48,7 +48,7 @@ static void test_with_key_type(const char *type, const char *payload, pid_t request_key_pid; bool info_only;
- TEST(keyctl(KEYCTL_JOIN_SESSION_KEYRING, NULL));
- TEST(KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, NULL)); if (TST_RET < 0) tst_brk(TBROK | TTERRNO, "failed to join new session keyring");
@@ -97,7 +97,7 @@ static void test_with_key_type(const char *type, const char *payload, "unexpected error adding key of type '%s'", type); }
TEST(keyctl(KEYCTL_CLEAR, KEY_SPEC_SESSION_KEYRING));
TEST(KEYCTL(KEYCTL_CLEAR, KEY_SPEC_SESSION_KEYRING)); if (TST_RET < 0) { tst_brk(TBROK | TTERRNO, "unable to clear keyring");
diff --git a/testcases/kernel/syscalls/request_key/request_key04.c b/testcases/kernel/syscalls/request_key/request_key04.c index c125f4261..b049d8799 100644 --- a/testcases/kernel/syscalls/request_key/request_key04.c +++ b/testcases/kernel/syscalls/request_key/request_key04.c @@ -24,25 +24,25 @@ static void do_test(void) key_serial_t keyid; int saved_errno;
- TEST(keyctl(KEYCTL_JOIN_SESSION_KEYRING, NULL));
- TEST(KEYCTL(KEYCTL_JOIN_SESSION_KEYRING, NULL)); if (TST_RET < 0) tst_brk(TBROK | TTERRNO, "failed to join new session keyring");
- TEST(keyctl(KEYCTL_SETPERM, KEY_SPEC_SESSION_KEYRING,
- TEST(KEYCTL(KEYCTL_SETPERM, KEY_SPEC_SESSION_KEYRING, KEY_POS_SEARCH|KEY_POS_READ|KEY_POS_VIEW)); if (TST_RET < 0) { tst_brk(TBROK | TTERRNO, "failed to set permissions on session keyring"); }
- TEST(keyctl(KEYCTL_SET_REQKEY_KEYRING,
- TEST(KEYCTL(KEYCTL_SET_REQKEY_KEYRING, KEY_REQKEY_DEFL_SESSION_KEYRING)); if (TST_RET < 0) { tst_brk(TBROK | TTERRNO, "failed to set request-key default keyring"); }
- TEST(keyctl(KEYCTL_READ, KEY_SPEC_SESSION_KEYRING,
- TEST(KEYCTL(KEYCTL_READ, KEY_SPEC_SESSION_KEYRING, &keyid, sizeof(keyid))); if (TST_RET < 0) tst_brk(TBROK | TTERRNO, "failed to read from session keyring");
@@ -54,7 +54,7 @@ static void do_test(void) tst_brk(TBROK, "request_key() unexpectedly succeeded"); saved_errno = TST_ERR;
- TEST(keyctl(KEYCTL_READ, KEY_SPEC_SESSION_KEYRING,
- TEST(KEYCTL(KEYCTL_READ, KEY_SPEC_SESSION_KEYRING, &keyid, sizeof(keyid))); if (TST_RET < 0) tst_brk(TBROK | TTERRNO, "failed to read from session keyring");
diff --git a/testcases/kernel/watchqueue/common.h b/testcases/kernel/watchqueue/common.h index 92e8f079c..ea35219e5 100644 --- a/testcases/kernel/watchqueue/common.h +++ b/testcases/kernel/watchqueue/common.h @@ -85,8 +85,8 @@ static inline key_serial_t wqueue_add_key(int fd) if (key == -1) tst_brk(TBROK, "add_key error: %s", tst_strerrno(errno));
- keyctl(KEYCTL_WATCH_KEY, key, fd, 0x01);
- keyctl(KEYCTL_WATCH_KEY, KEY_SPEC_SESSION_KEYRING, fd, 0x02);
- KEYCTL(KEYCTL_WATCH_KEY, key, fd, 0x01);
- KEYCTL(KEYCTL_WATCH_KEY, KEY_SPEC_SESSION_KEYRING, fd, 0x02);
return key; } diff --git a/testcases/kernel/watchqueue/wqueue01.c b/testcases/kernel/watchqueue/wqueue01.c index 904e512af..dd0a68dfb 100644 --- a/testcases/kernel/watchqueue/wqueue01.c +++ b/testcases/kernel/watchqueue/wqueue01.c @@ -32,7 +32,7 @@ static void run(void) fd = wqueue_watch(256, &wqueue_filter); key = wqueue_add_key(fd);
- keyctl(KEYCTL_UPDATE, key, "b", 1);
- KEYCTL(KEYCTL_UPDATE, key, "b", 1); wqueue_consumer(fd, saw_key_updated);
SAFE_CLOSE(fd); diff --git a/testcases/kernel/watchqueue/wqueue02.c b/testcases/kernel/watchqueue/wqueue02.c index 0c3e947d1..37929b9d0 100644 --- a/testcases/kernel/watchqueue/wqueue02.c +++ b/testcases/kernel/watchqueue/wqueue02.c @@ -32,7 +32,7 @@ static void run(void) fd = wqueue_watch(256, &wqueue_filter); key = wqueue_add_key(fd);
- keyctl(KEYCTL_UNLINK, key, KEY_SPEC_SESSION_KEYRING);
- KEYCTL(KEYCTL_UNLINK, key, KEY_SPEC_SESSION_KEYRING); wqueue_consumer(fd, saw_key_unlinked);
SAFE_CLOSE(fd); diff --git a/testcases/kernel/watchqueue/wqueue03.c b/testcases/kernel/watchqueue/wqueue03.c index c17fc1452..8ce23b253 100644 --- a/testcases/kernel/watchqueue/wqueue03.c +++ b/testcases/kernel/watchqueue/wqueue03.c @@ -32,7 +32,7 @@ static void run(void) fd = wqueue_watch(256, &wqueue_filter); key = wqueue_add_key(fd);
- keyctl(KEYCTL_REVOKE, key);
- KEYCTL(KEYCTL_REVOKE, key); wqueue_consumer(fd, saw_key_revoked);
SAFE_CLOSE(fd); diff --git a/testcases/kernel/watchqueue/wqueue04.c b/testcases/kernel/watchqueue/wqueue04.c index fc880064b..c23a75254 100644 --- a/testcases/kernel/watchqueue/wqueue04.c +++ b/testcases/kernel/watchqueue/wqueue04.c @@ -32,7 +32,7 @@ static void run(void) fd = wqueue_watch(256, &wqueue_filter); key = wqueue_add_key(fd);
- keyctl(KEYCTL_LINK, key, KEY_SPEC_SESSION_KEYRING);
- KEYCTL(KEYCTL_LINK, key, KEY_SPEC_SESSION_KEYRING); wqueue_consumer(fd, saw_key_linked);
SAFE_CLOSE(fd); diff --git a/testcases/kernel/watchqueue/wqueue05.c b/testcases/kernel/watchqueue/wqueue05.c index 78a4c702e..221d95d22 100644 --- a/testcases/kernel/watchqueue/wqueue05.c +++ b/testcases/kernel/watchqueue/wqueue05.c @@ -32,7 +32,7 @@ static void run(void) fd = wqueue_watch(256, &wqueue_filter); key = wqueue_add_key(fd);
- keyctl(KEYCTL_INVALIDATE, key);
- KEYCTL(KEYCTL_INVALIDATE, key); wqueue_consumer(fd, saw_key_invalidated);
SAFE_CLOSE(fd); diff --git a/testcases/kernel/watchqueue/wqueue06.c b/testcases/kernel/watchqueue/wqueue06.c index 2cb6a966d..692612255 100644 --- a/testcases/kernel/watchqueue/wqueue06.c +++ b/testcases/kernel/watchqueue/wqueue06.c @@ -31,7 +31,7 @@ static void run(void) fd = wqueue_watch(256, &wqueue_filter); wqueue_add_key(fd);
- keyctl(KEYCTL_CLEAR, KEY_SPEC_SESSION_KEYRING);
- KEYCTL(KEYCTL_CLEAR, KEY_SPEC_SESSION_KEYRING); wqueue_consumer(fd, saw_key_cleared);
SAFE_CLOSE(fd); diff --git a/testcases/kernel/watchqueue/wqueue07.c b/testcases/kernel/watchqueue/wqueue07.c index 6c4d1e92a..a7daad973 100644 --- a/testcases/kernel/watchqueue/wqueue07.c +++ b/testcases/kernel/watchqueue/wqueue07.c @@ -32,7 +32,7 @@ static void run(void) fd = wqueue_watch(256, &wqueue_filter); key = wqueue_add_key(fd);
- keyctl(KEYCTL_SETPERM, key, KEY_POS_ALL | KEY_USR_ALL);
- KEYCTL(KEYCTL_SETPERM, key, KEY_POS_ALL | KEY_USR_ALL); wqueue_consumer(fd, saw_key_setattr);
SAFE_CLOSE(fd); diff --git a/testcases/kernel/watchqueue/wqueue08.c b/testcases/kernel/watchqueue/wqueue08.c index 4ed9522da..bea3a6c36 100644 --- a/testcases/kernel/watchqueue/wqueue08.c +++ b/testcases/kernel/watchqueue/wqueue08.c @@ -37,7 +37,7 @@ static void run(void) key = wqueue_add_key(fd); /* if watch_id = -1 key is removed from the watch queue */
- keyctl(KEYCTL_WATCH_KEY, key, fd, -1);
- KEYCTL(KEYCTL_WATCH_KEY, key, fd, -1); wqueue_consumer(fd, saw_watch_removal);
SAFE_CLOSE(fd); diff --git a/testcases/kernel/watchqueue/wqueue09.c b/testcases/kernel/watchqueue/wqueue09.c index 9f077b35b..f19d98f09 100644 --- a/testcases/kernel/watchqueue/wqueue09.c +++ b/testcases/kernel/watchqueue/wqueue09.c @@ -44,7 +44,7 @@ static void run(void) iterations = (getpagesize() / WATCH_QUEUE_NOTE_SIZE) * 2; for (i = 0; i < iterations; i++)
keyctl(KEYCTL_UPDATE, key, "b", 1);
KEYCTL(KEYCTL_UPDATE, key, "b", 1);
data_lost = 0; while (!data_lost) @@ -58,7 +58,7 @@ static void run(void) static void cleanup(void) {
- keyctl(KEYCTL_REVOKE, key);
- KEYCTL(KEYCTL_REVOKE, key); SAFE_CLOSE(fd); }
On Fri, Nov 25, 2022 at 03:34:36PM +0000, Tudor Cretu wrote:
Hi Beata,
On 25-11-2022 14:26, Beata Michalska wrote:
Currently the keyctl helper makes silent assumption that either all expected arguments are being provided or otherwise it's somewhat safe to access beyond the actual va arg list. With AAPCS64-cap this will no longer slide through, as reading more arguments than provided will trigger capability bound fault. Introduce dedicated macro to handle the variadic-ness instead, making sure that at any point all arguments are being provided, whether explicitly or through default values.
Reported-by: Kevin Brodsky kevin.brodsky@arm.com Suggested-by: Kevin Brodsky kevin.brodsky@arm.com Signed-off-by: Beata Michalska beata.michalska@arm.com
include/lapi/keyctl.h | 22 +++++++++---------- testcases/cve/cve-2016-7042.c | 6 ++--- testcases/kernel/syscalls/add_key/add_key03.c | 2 +- testcases/kernel/syscalls/add_key/add_key04.c | 2 +- testcases/kernel/syscalls/keyctl/keyctl01.c | 6 ++--- testcases/kernel/syscalls/keyctl/keyctl02.c | 8 +++---- testcases/kernel/syscalls/keyctl/keyctl03.c | 2 +- testcases/kernel/syscalls/keyctl/keyctl04.c | 6 ++--- testcases/kernel/syscalls/keyctl/keyctl05.c | 10 ++++----- testcases/kernel/syscalls/keyctl/keyctl06.c | 2 +- testcases/kernel/syscalls/keyctl/keyctl07.c | 4 ++-- testcases/kernel/syscalls/keyctl/keyctl09.c | 4 ++-- .../syscalls/request_key/request_key02.c | 4 ++-- .../syscalls/request_key/request_key03.c | 4 ++-- .../syscalls/request_key/request_key04.c | 10 ++++----- testcases/kernel/watchqueue/common.h | 4 ++-- testcases/kernel/watchqueue/wqueue01.c | 2 +- testcases/kernel/watchqueue/wqueue02.c | 2 +- testcases/kernel/watchqueue/wqueue03.c | 2 +- testcases/kernel/watchqueue/wqueue04.c | 2 +- testcases/kernel/watchqueue/wqueue05.c | 2 +- testcases/kernel/watchqueue/wqueue06.c | 2 +- testcases/kernel/watchqueue/wqueue07.c | 2 +- testcases/kernel/watchqueue/wqueue08.c | 2 +- testcases/kernel/watchqueue/wqueue09.c | 4 ++-- 25 files changed, 57 insertions(+), 59 deletions(-)
diff --git a/include/lapi/keyctl.h b/include/lapi/keyctl.h index 9c847a429..1c7436ef6 100644 --- a/include/lapi/keyctl.h +++ b/include/lapi/keyctl.h @@ -39,23 +39,21 @@ static inline key_serial_t request_key(const char *type, type, description, callout_info, destringid); } -static inline long keyctl(int cmd, ...) -{
- va_list va;
- uintptr_t arg2, arg3, arg4, arg5;
+#define __KEYCTL(cmd, arg2, arg3, arg4, arg5, ...) \
- keyctl((cmd), (arg2), (arg3), (arg4), (arg5))
- va_start(va, cmd);
- arg2 = va_arg(va, uintptr_t);
- arg3 = va_arg(va, uintptr_t);
- arg4 = va_arg(va, uintptr_t);
- arg5 = va_arg(va, uintptr_t);
- va_end(va);
+#define KEYCTL(cmd, ...) \
- __KEYCTL((cmd), ##__VA_ARGS__, 0, 0, 0, 0)
+static inline long keyctl(int cmd, uintptr_t arg2, uintptr_t arg3,
uintptr_t arg4, uintptr_t arg5)
+{
Just to note, there is no keyctl function signature standardised in Posix and libcs don't seem to typically define this wrapper. So, in my opinion, you could make "keyctl" directly a macro that calls __KEYCTL and make __KEYCTL call tst_syscall. In that way you don't need to replace keyctl with KEYCTL everywhere. I can see though why you preferred it this way and it looks as fine to me.
That's actually good idea- will bake v2 (slightly tweaked). Thanks for the suggestion!
--- BR B.
Great patch!
Tudor
[...]
linux-morello-ltp@op-lists.linaro.org