From mboxrd@z Thu Jan 1 00:00:00 1970 From: Richard Palethorpe Date: Fri, 23 Jun 2017 14:22:06 +0200 Subject: [LTP] [PATCH v3 4/9] Test for uname26 exploit CVE-2012-0957 In-Reply-To: <20170623122211.29575-1-rpalethorpe@suse.com> References: <20170623122211.29575-1-rpalethorpe@suse.com> Message-ID: <20170623122211.29575-5-rpalethorpe@suse.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: ltp@lists.linux.it Attempt to exploit the uname kernel memory leak which occurred when the UNAME26 personality was set. Signed-off-by: Richard Palethorpe --- configure.ac | 1 + m4/ltp-uname.m4 | 20 ++++++++++ testcases/cve/cve-2012-0957.c | 89 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 m4/ltp-uname.m4 create mode 100644 testcases/cve/cve-2012-0957.c diff --git a/configure.ac b/configure.ac index 326da8ece..658003972 100644 --- a/configure.ac +++ b/configure.ac @@ -193,5 +193,6 @@ LTP_CHECK_KEYUTILS_SUPPORT LTP_CHECK_SYNC_ADD_AND_FETCH LTP_CHECK_BUILTIN_CLEAR_CACHE LTP_CHECK_MMSGHDR +LTP_CHECK_UNAME_DOMAINNAME AC_OUTPUT diff --git a/m4/ltp-uname.m4 b/m4/ltp-uname.m4 new file mode 100644 index 000000000..5a3002200 --- /dev/null +++ b/m4/ltp-uname.m4 @@ -0,0 +1,20 @@ +dnl Copyright (c) 2017 Richard Palethorpe +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See +dnl the GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program. If not, see . + +AC_DEFUN([LTP_CHECK_UNAME_DOMAINNAME],[ +AC_CHECK_MEMBERS([struct utsname.domainname],,,[ +#define _GNU_SOURCE +#include +])]) diff --git a/testcases/cve/cve-2012-0957.c b/testcases/cve/cve-2012-0957.c new file mode 100644 index 000000000..f065735a1 --- /dev/null +++ b/testcases/cve/cve-2012-0957.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2017 Richard Palethorpe + * Copyright (c) 2012, Kees Cook + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/* + * Check that memory after the string terminator in all the utsname fields has + * been zeroed. cve-2012-0957 leaked kernel memory through the release field + * when the UNAME26 personality was set. + * + * Thanks to Kees Cook for the original proof of concept: + * http://www.securityfocus.com/bid/55855/info + */ + +#include +#include +#include +#include "tst_test.h" + +#define UNAME26 0x0020000 + +static int check_field(char *bytes, size_t length, char *field) +{ + size_t i = strlen(bytes) + 1; + + for (; i < length; i++) { + if (bytes[i]) { + tst_res(TFAIL, "Bytes leaked in %s!", field); + return 1; + } + } + return 0; +} + + +static void try_leak_bytes(void) +{ + struct utsname buf; + + if (uname(&buf)) + tst_brk(TBROK | TERRNO, "Call to uname failed"); + +#define CHECK_FIELD(field_name) \ + (check_field(buf.field_name, ARRAY_SIZE(buf.field_name), #field_name)) + + if (!(CHECK_FIELD(release) | + CHECK_FIELD(sysname) | + CHECK_FIELD(nodename) | + CHECK_FIELD(version) | + CHECK_FIELD(machine) | +#ifdef HAVE_STRUCT_UTSNAME_DOMAINNAME + CHECK_FIELD(domainname) | +#endif + 0)) { + tst_res(TPASS, "All fields zeroed after string terminator"); + } +#undef CHECK_FIELD +} + +static void run(unsigned int test_nr) +{ + if (!test_nr) { + tst_res(TINFO, "Calling uname with default personality"); + try_leak_bytes(); + } else { + if (personality(PER_LINUX | UNAME26) < 0) + tst_brk(TCONF | TERRNO, + "Could not change personality to UNAME26"); + tst_res(TINFO, "Calling uname with UNAME26 personality"); + try_leak_bytes(); + } +} + +static struct tst_test test = { + .test = run, + .tcnt = 2, +}; -- 2.12.2