xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/keyctl/keyctl07.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (c) 2017 Google, Inc.
4*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (c) Linux Test Project, 2018-2024
5*49cdfc7eSAndroid Build Coastguard Worker  */
6*49cdfc7eSAndroid Build Coastguard Worker 
7*49cdfc7eSAndroid Build Coastguard Worker /*\
8*49cdfc7eSAndroid Build Coastguard Worker  * [Description]
9*49cdfc7eSAndroid Build Coastguard Worker  *
10*49cdfc7eSAndroid Build Coastguard Worker  * Regression test for commit 37863c43b2c6 ("KEYS: prevent KEYCTL_READ on
11*49cdfc7eSAndroid Build Coastguard Worker  * negative key").  This is CVE-2017-12192.
12*49cdfc7eSAndroid Build Coastguard Worker  */
13*49cdfc7eSAndroid Build Coastguard Worker 
14*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
15*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
16*49cdfc7eSAndroid Build Coastguard Worker #include <sys/wait.h>
17*49cdfc7eSAndroid Build Coastguard Worker 
18*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
19*49cdfc7eSAndroid Build Coastguard Worker #include "lapi/keyctl.h"
20*49cdfc7eSAndroid Build Coastguard Worker 
try_to_read_negative_key(void)21*49cdfc7eSAndroid Build Coastguard Worker static void try_to_read_negative_key(void)
22*49cdfc7eSAndroid Build Coastguard Worker {
23*49cdfc7eSAndroid Build Coastguard Worker 	key_serial_t key_id;
24*49cdfc7eSAndroid Build Coastguard Worker 	char buffer[128];
25*49cdfc7eSAndroid Build Coastguard Worker 
26*49cdfc7eSAndroid Build Coastguard Worker 	/*
27*49cdfc7eSAndroid Build Coastguard Worker 	 * Create a negatively instantiated key of the "user" key type.  This
28*49cdfc7eSAndroid Build Coastguard Worker 	 * key type is chosen because it has a ->read() method (which makes the
29*49cdfc7eSAndroid Build Coastguard Worker 	 * bug reachable) and is available whenever CONFIG_KEYS is enabled.
30*49cdfc7eSAndroid Build Coastguard Worker 	 *
31*49cdfc7eSAndroid Build Coastguard Worker 	 * request_key() will result in the creation of a negative key provided
32*49cdfc7eSAndroid Build Coastguard Worker 	 * that /sbin/request-key isn't configured to positively instantiate the
33*49cdfc7eSAndroid Build Coastguard Worker 	 * key, based on the provided type, description, and callout_info.  If
34*49cdfc7eSAndroid Build Coastguard Worker 	 * /sbin/request-key doesn't exist, errno will be ENOENT; while if it
35*49cdfc7eSAndroid Build Coastguard Worker 	 * does exist and we specify some random unprefixed description, errno
36*49cdfc7eSAndroid Build Coastguard Worker 	 * should be ENOKEY (since /sbin/request-key should not be configured to
37*49cdfc7eSAndroid Build Coastguard Worker 	 * instantiate random user keys).  In either case a negative key should
38*49cdfc7eSAndroid Build Coastguard Worker 	 * be created and we can continue on with the test.  Negative keys last
39*49cdfc7eSAndroid Build Coastguard Worker 	 * for 60 seconds so there should be plenty of time for the test.
40*49cdfc7eSAndroid Build Coastguard Worker 	 */
41*49cdfc7eSAndroid Build Coastguard Worker 	TEST(request_key("user", "description", "callout_info",
42*49cdfc7eSAndroid Build Coastguard Worker 			 KEY_SPEC_PROCESS_KEYRING));
43*49cdfc7eSAndroid Build Coastguard Worker 	if (TST_RET != -1)
44*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "request_key() unexpectedly succeeded");
45*49cdfc7eSAndroid Build Coastguard Worker 
46*49cdfc7eSAndroid Build Coastguard Worker 	if (TST_ERR != ENOKEY && TST_ERR != ENOENT) {
47*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK | TTERRNO,
48*49cdfc7eSAndroid Build Coastguard Worker 			"request_key() failed with unexpected error");
49*49cdfc7eSAndroid Build Coastguard Worker 	}
50*49cdfc7eSAndroid Build Coastguard Worker 
51*49cdfc7eSAndroid Build Coastguard Worker 	/* Get the ID of the negative key by reading the keyring */
52*49cdfc7eSAndroid Build Coastguard Worker 	TEST(keyctl(KEYCTL_READ, KEY_SPEC_PROCESS_KEYRING,
53*49cdfc7eSAndroid Build Coastguard Worker 		    &key_id, sizeof(key_id)));
54*49cdfc7eSAndroid Build Coastguard Worker 	if (TST_RET < 0)
55*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK | TTERRNO, "KEYCTL_READ unexpectedly failed");
56*49cdfc7eSAndroid Build Coastguard Worker 	if (TST_RET != sizeof(key_id)) {
57*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK, "KEYCTL_READ returned %ld but expected %zu",
58*49cdfc7eSAndroid Build Coastguard Worker 			TST_RET, sizeof(key_id));
59*49cdfc7eSAndroid Build Coastguard Worker 	}
60*49cdfc7eSAndroid Build Coastguard Worker 
61*49cdfc7eSAndroid Build Coastguard Worker 	/*
62*49cdfc7eSAndroid Build Coastguard Worker 	 * Now try to read the negative key.  Unpatched kernels will oops trying
63*49cdfc7eSAndroid Build Coastguard Worker 	 * to read from memory address 0x00000000ffffff92.
64*49cdfc7eSAndroid Build Coastguard Worker 	 */
65*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO, "trying to read from the negative key...");
66*49cdfc7eSAndroid Build Coastguard Worker 	TEST(keyctl(KEYCTL_READ, key_id, buffer, sizeof(buffer)));
67*49cdfc7eSAndroid Build Coastguard Worker 	if (TST_RET != -1) {
68*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TFAIL,
69*49cdfc7eSAndroid Build Coastguard Worker 			"KEYCTL_READ on negative key unexpectedly succeeded");
70*49cdfc7eSAndroid Build Coastguard Worker 	}
71*49cdfc7eSAndroid Build Coastguard Worker 	if (TST_ERR != ENOKEY) {
72*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TFAIL | TTERRNO,
73*49cdfc7eSAndroid Build Coastguard Worker 			"KEYCTL_READ on negative key failed with unexpected error");
74*49cdfc7eSAndroid Build Coastguard Worker 	}
75*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TPASS,
76*49cdfc7eSAndroid Build Coastguard Worker 		"KEYCTL_READ on negative key expectedly failed with ENOKEY");
77*49cdfc7eSAndroid Build Coastguard Worker }
78*49cdfc7eSAndroid Build Coastguard Worker 
do_test(void)79*49cdfc7eSAndroid Build Coastguard Worker static void do_test(void)
80*49cdfc7eSAndroid Build Coastguard Worker {
81*49cdfc7eSAndroid Build Coastguard Worker 	int status;
82*49cdfc7eSAndroid Build Coastguard Worker 
83*49cdfc7eSAndroid Build Coastguard Worker 	if (SAFE_FORK() == 0) {
84*49cdfc7eSAndroid Build Coastguard Worker 		try_to_read_negative_key();
85*49cdfc7eSAndroid Build Coastguard Worker 		return;
86*49cdfc7eSAndroid Build Coastguard Worker 	}
87*49cdfc7eSAndroid Build Coastguard Worker 
88*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_WAIT(&status);
89*49cdfc7eSAndroid Build Coastguard Worker 
90*49cdfc7eSAndroid Build Coastguard Worker 	if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
91*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TPASS, "didn't crash while reading from negative key");
92*49cdfc7eSAndroid Build Coastguard Worker 		return;
93*49cdfc7eSAndroid Build Coastguard Worker 	}
94*49cdfc7eSAndroid Build Coastguard Worker 
95*49cdfc7eSAndroid Build Coastguard Worker 	if (WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL) {
96*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TFAIL, "reading from negative key caused kernel oops");
97*49cdfc7eSAndroid Build Coastguard Worker 		return;
98*49cdfc7eSAndroid Build Coastguard Worker 	}
99*49cdfc7eSAndroid Build Coastguard Worker 
100*49cdfc7eSAndroid Build Coastguard Worker 	if (WIFEXITED(status) && WEXITSTATUS(status) == TCONF)
101*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TCONF, "syscall not implemented");
102*49cdfc7eSAndroid Build Coastguard Worker 
103*49cdfc7eSAndroid Build Coastguard Worker 	tst_brk(TBROK, "Child %s", tst_strstatus(status));
104*49cdfc7eSAndroid Build Coastguard Worker }
105*49cdfc7eSAndroid Build Coastguard Worker 
106*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
107*49cdfc7eSAndroid Build Coastguard Worker 	.test_all = do_test,
108*49cdfc7eSAndroid Build Coastguard Worker 	.forks_child = 1,
109*49cdfc7eSAndroid Build Coastguard Worker 	.tags = (const struct tst_tag[]) {
110*49cdfc7eSAndroid Build Coastguard Worker 		{"CVE", "2017-12192"},
111*49cdfc7eSAndroid Build Coastguard Worker 		{"linux-git", "37863c43b2c6"},
112*49cdfc7eSAndroid Build Coastguard Worker 		{}
113*49cdfc7eSAndroid Build Coastguard Worker 	}
114*49cdfc7eSAndroid Build Coastguard Worker };
115