xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/uname/uname04.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 Richard Palethorpe <[email protected]>
4*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (c) 2012, Kees Cook <[email protected]>
5*49cdfc7eSAndroid Build Coastguard Worker  */
6*49cdfc7eSAndroid Build Coastguard Worker /*
7*49cdfc7eSAndroid Build Coastguard Worker  * Check that memory after the string terminator in all the utsname fields has
8*49cdfc7eSAndroid Build Coastguard Worker  * been zeroed. cve-2012-0957 leaked kernel memory through the release field
9*49cdfc7eSAndroid Build Coastguard Worker  * when the UNAME26 personality was set.
10*49cdfc7eSAndroid Build Coastguard Worker  *
11*49cdfc7eSAndroid Build Coastguard Worker  * Thanks to Kees Cook for the original proof of concept:
12*49cdfc7eSAndroid Build Coastguard Worker  * http://www.securityfocus.com/bid/55855/info
13*49cdfc7eSAndroid Build Coastguard Worker  */
14*49cdfc7eSAndroid Build Coastguard Worker 
15*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
16*49cdfc7eSAndroid Build Coastguard Worker #include <sys/utsname.h>
17*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
18*49cdfc7eSAndroid Build Coastguard Worker #include "lapi/personality.h"
19*49cdfc7eSAndroid Build Coastguard Worker 
20*49cdfc7eSAndroid Build Coastguard Worker static struct utsname saved_buf;
21*49cdfc7eSAndroid Build Coastguard Worker 
check_field(char * bytes,char * saved_bytes,size_t length,char * field)22*49cdfc7eSAndroid Build Coastguard Worker static int check_field(char *bytes, char *saved_bytes, size_t length,
23*49cdfc7eSAndroid Build Coastguard Worker 		       char *field)
24*49cdfc7eSAndroid Build Coastguard Worker {
25*49cdfc7eSAndroid Build Coastguard Worker 	size_t i = strlen(bytes) + 1;
26*49cdfc7eSAndroid Build Coastguard Worker 
27*49cdfc7eSAndroid Build Coastguard Worker 	for (; i < length; i++) {
28*49cdfc7eSAndroid Build Coastguard Worker 		if (bytes[i] && (bytes[i] != saved_bytes[i])) {
29*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TFAIL, "Bytes leaked in %s!", field);
30*49cdfc7eSAndroid Build Coastguard Worker 			return 1;
31*49cdfc7eSAndroid Build Coastguard Worker 		}
32*49cdfc7eSAndroid Build Coastguard Worker 	}
33*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
34*49cdfc7eSAndroid Build Coastguard Worker }
35*49cdfc7eSAndroid Build Coastguard Worker 
36*49cdfc7eSAndroid Build Coastguard Worker 
try_leak_bytes(unsigned int test_nr)37*49cdfc7eSAndroid Build Coastguard Worker static void try_leak_bytes(unsigned int test_nr)
38*49cdfc7eSAndroid Build Coastguard Worker {
39*49cdfc7eSAndroid Build Coastguard Worker 	struct utsname buf;
40*49cdfc7eSAndroid Build Coastguard Worker 
41*49cdfc7eSAndroid Build Coastguard Worker 	memset(&buf, 0, sizeof(buf));
42*49cdfc7eSAndroid Build Coastguard Worker 
43*49cdfc7eSAndroid Build Coastguard Worker 	if (uname(&buf))
44*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK | TERRNO, "Call to uname failed");
45*49cdfc7eSAndroid Build Coastguard Worker 
46*49cdfc7eSAndroid Build Coastguard Worker 	if (!test_nr)
47*49cdfc7eSAndroid Build Coastguard Worker 		memcpy(&saved_buf, &buf, sizeof(saved_buf));
48*49cdfc7eSAndroid Build Coastguard Worker 
49*49cdfc7eSAndroid Build Coastguard Worker #define CHECK_FIELD(field_name) \
50*49cdfc7eSAndroid Build Coastguard Worker 	(check_field(buf.field_name, saved_buf.field_name, \
51*49cdfc7eSAndroid Build Coastguard Worker 		     ARRAY_SIZE(buf.field_name), #field_name))
52*49cdfc7eSAndroid Build Coastguard Worker 
53*49cdfc7eSAndroid Build Coastguard Worker 	if (!(CHECK_FIELD(release) |
54*49cdfc7eSAndroid Build Coastguard Worker 	    CHECK_FIELD(sysname) |
55*49cdfc7eSAndroid Build Coastguard Worker 	    CHECK_FIELD(nodename) |
56*49cdfc7eSAndroid Build Coastguard Worker 	    CHECK_FIELD(version) |
57*49cdfc7eSAndroid Build Coastguard Worker 	    CHECK_FIELD(machine) |
58*49cdfc7eSAndroid Build Coastguard Worker #ifdef HAVE_STRUCT_UTSNAME_DOMAINNAME
59*49cdfc7eSAndroid Build Coastguard Worker 	    CHECK_FIELD(domainname) |
60*49cdfc7eSAndroid Build Coastguard Worker #endif
61*49cdfc7eSAndroid Build Coastguard Worker 		    0)) {
62*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TPASS, "No bytes leaked");
63*49cdfc7eSAndroid Build Coastguard Worker 	}
64*49cdfc7eSAndroid Build Coastguard Worker #undef CHECK_FIELD
65*49cdfc7eSAndroid Build Coastguard Worker }
66*49cdfc7eSAndroid Build Coastguard Worker 
run(unsigned int test_nr)67*49cdfc7eSAndroid Build Coastguard Worker static void run(unsigned int test_nr)
68*49cdfc7eSAndroid Build Coastguard Worker {
69*49cdfc7eSAndroid Build Coastguard Worker 	if (!test_nr) {
70*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "Calling uname with default personality");
71*49cdfc7eSAndroid Build Coastguard Worker 	} else {
72*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_PERSONALITY(PER_LINUX | UNAME26);
73*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "Calling uname with UNAME26 personality");
74*49cdfc7eSAndroid Build Coastguard Worker 	}
75*49cdfc7eSAndroid Build Coastguard Worker 
76*49cdfc7eSAndroid Build Coastguard Worker 	try_leak_bytes(test_nr);
77*49cdfc7eSAndroid Build Coastguard Worker }
78*49cdfc7eSAndroid Build Coastguard Worker 
79*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
80*49cdfc7eSAndroid Build Coastguard Worker 	.test = run,
81*49cdfc7eSAndroid Build Coastguard Worker 	.tcnt = 2,
82*49cdfc7eSAndroid Build Coastguard Worker 	.tags = (const struct tst_tag[]) {
83*49cdfc7eSAndroid Build Coastguard Worker 		{"CVE", "2012-0957"},
84*49cdfc7eSAndroid Build Coastguard Worker 		{}
85*49cdfc7eSAndroid Build Coastguard Worker 	}
86*49cdfc7eSAndroid Build Coastguard Worker };
87