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