1 /* 2 * Copyright (c) 2017 Richard Palethorpe <rpalethorpe (at) suse.com> 3 * Copyright (c) 2012, Kees Cook <keescook (at) chromium.org> 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 /* 19 * Check that memory after the string terminator in all the utsname fields has 20 * been zeroed. cve-2012-0957 leaked kernel memory through the release field 21 * when the UNAME26 personality was set. 22 * 23 * Thanks to Kees Cook for the original proof of concept: 24 * http://www.securityfocus.com/bid/55855/info 25 */ 26 27 #include <string.h> 28 #include <sys/utsname.h> 29 #include "tst_test.h" 30 #include "lapi/personality.h" 31 32 static struct utsname saved_buf; 33 34 static int check_field(char *bytes, char *saved_bytes, size_t length, 35 char *field) 36 { 37 size_t i = strlen(bytes) + 1; 38 39 for (; i < length; i++) { 40 if (bytes[i] && (bytes[i] != saved_bytes[i])) { 41 tst_res(TFAIL, "Bytes leaked in %s!", field); 42 return 1; 43 } 44 } 45 return 0; 46 } 47 48 49 static void try_leak_bytes(unsigned int test_nr) 50 { 51 struct utsname buf; 52 53 memset(&buf, 0, sizeof(buf)); 54 55 if (uname(&buf)) 56 tst_brk(TBROK | TERRNO, "Call to uname failed"); 57 58 if (!test_nr) 59 memcpy(&saved_buf, &buf, sizeof(saved_buf)); 60 61 #define CHECK_FIELD(field_name) \ 62 (check_field(buf.field_name, saved_buf.field_name, \ 63 ARRAY_SIZE(buf.field_name), #field_name)) 64 65 if (!(CHECK_FIELD(release) | 66 CHECK_FIELD(sysname) | 67 CHECK_FIELD(nodename) | 68 CHECK_FIELD(version) | 69 CHECK_FIELD(machine) | 70 #ifdef HAVE_STRUCT_UTSNAME_DOMAINNAME 71 CHECK_FIELD(domainname) | 72 #endif 73 0)) { 74 tst_res(TPASS, "No bytes leaked"); 75 } 76 #undef CHECK_FIELD 77 } 78 79 static void run(unsigned int test_nr) 80 { 81 if (!test_nr) { 82 tst_res(TINFO, "Calling uname with default personality"); 83 } else { 84 SAFE_PERSONALITY(PER_LINUX | UNAME26); 85 tst_res(TINFO, "Calling uname with UNAME26 personality"); 86 } 87 88 try_leak_bytes(test_nr); 89 } 90 91 static struct tst_test test = { 92 .test = run, 93 .tcnt = 2, 94 }; 95