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