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
20static struct utsname saved_buf;
21
22static 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
37static 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
67static 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
79static struct tst_test test = {
80	.test = run,
81	.tcnt = 2,
82	.tags = (const struct tst_tag[]) {
83		{"CVE", "2012-0957"},
84		{}
85	}
86};
87