You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
112 lines
3.2 KiB
112 lines
3.2 KiB
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* Copyright (c) 2017 Google, Inc.
|
|
*/
|
|
|
|
/*
|
|
* Regression test for commit 37863c43b2c6 ("KEYS: prevent KEYCTL_READ on
|
|
* negative key"). This is CVE-2017-12192.
|
|
*/
|
|
|
|
#include <errno.h>
|
|
#include <stdlib.h>
|
|
#include <sys/wait.h>
|
|
|
|
#include "tst_test.h"
|
|
#include "lapi/keyctl.h"
|
|
|
|
static void try_to_read_negative_key(void)
|
|
{
|
|
key_serial_t key_id;
|
|
char buffer[128];
|
|
|
|
/*
|
|
* Create a negatively instantiated key of the "user" key type. This
|
|
* key type is chosen because it has a ->read() method (which makes the
|
|
* bug reachable) and is available whenever CONFIG_KEYS is enabled.
|
|
*
|
|
* request_key() will result in the creation of a negative key provided
|
|
* that /sbin/request-key isn't configured to positively instantiate the
|
|
* key, based on the provided type, description, and callout_info. If
|
|
* /sbin/request-key doesn't exist, errno will be ENOENT; while if it
|
|
* does exist and we specify some random unprefixed description, errno
|
|
* should be ENOKEY (since /sbin/request-key should not be configured to
|
|
* instantiate random user keys). In either case a negative key should
|
|
* be created and we can continue on with the test. Negative keys last
|
|
* for 60 seconds so there should be plenty of time for the test.
|
|
*/
|
|
TEST(request_key("user", "description", "callout_info",
|
|
KEY_SPEC_PROCESS_KEYRING));
|
|
if (TST_RET != -1)
|
|
tst_brk(TBROK, "request_key() unexpectedly succeeded");
|
|
|
|
if (TST_ERR != ENOKEY && TST_ERR != ENOENT) {
|
|
tst_brk(TBROK | TTERRNO,
|
|
"request_key() failed with unexpected error");
|
|
}
|
|
|
|
/* Get the ID of the negative key by reading the 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");
|
|
if (TST_RET != sizeof(key_id)) {
|
|
tst_brk(TBROK, "KEYCTL_READ returned %ld but expected %zu",
|
|
TST_RET, sizeof(key_id));
|
|
}
|
|
|
|
/*
|
|
* Now try to read the negative key. Unpatched kernels will oops trying
|
|
* 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)));
|
|
if (TST_RET != -1) {
|
|
tst_brk(TFAIL,
|
|
"KEYCTL_READ on negative key unexpectedly succeeded");
|
|
}
|
|
if (TST_ERR != ENOKEY) {
|
|
tst_brk(TFAIL | TTERRNO,
|
|
"KEYCTL_READ on negative key failed with unexpected error");
|
|
}
|
|
tst_res(TPASS,
|
|
"KEYCTL_READ on negative key expectedly failed with ENOKEY");
|
|
}
|
|
|
|
static void do_test(void)
|
|
{
|
|
int status;
|
|
|
|
if (SAFE_FORK() == 0) {
|
|
try_to_read_negative_key();
|
|
return;
|
|
}
|
|
|
|
SAFE_WAIT(&status);
|
|
|
|
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
|
|
tst_res(TPASS, "didn't crash while reading from negative key");
|
|
return;
|
|
}
|
|
|
|
if (WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL) {
|
|
tst_res(TFAIL, "reading from negative key caused kernel oops");
|
|
return;
|
|
}
|
|
|
|
if (WIFEXITED(status) && WEXITSTATUS(status) == TCONF)
|
|
tst_brk(TCONF, "syscall not implemented");
|
|
|
|
tst_brk(TBROK, "Child %s", tst_strstatus(status));
|
|
}
|
|
|
|
static struct tst_test test = {
|
|
.test_all = do_test,
|
|
.forks_child = 1,
|
|
.tags = (const struct tst_tag[]) {
|
|
{"CVE", "2017-12912"},
|
|
{"linux-git", "37863c43b2c6"},
|
|
{}
|
|
}
|
|
};
|