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