Test for CVE-2016-4997 on setsockopt
PATCH 2/4 Test for CVE-2016-4997 on setsockopt
--- testcases/cve/cve-2016-4997.c | 87 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 testcases/cve/cve-2016-4997.c
testcases/cve/cve-2016-4997.c new file +87 -0
@@ -0,0 +1,87 @@ +/* +* Copyright (c) 2017 Richard Palethorpe <[email protected]> +* Based on repro-compatReleaseEntry.c by NCC group +* +* 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 <http://www.gnu.org/licenses/>. +*/ +/* +* Test for CVE-2016-4997 +* +* For a full explanation of how the vulnerability works see: +* https://github.com/nccgroup/TriforceLinuxSyscallFuzzer/tree/master/crash_reports/report_compatIpt +* +* The original vulnerability was present in the 32-bit compatibility system +* call, so the test should be compiled with -m32 and run on a 64-bit kernel. +* For simplicities sake the test requests root privliges instead of creating +* a user namespace. +*/ + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <net/if.h> +#include <linux/netfilter_ipv4/ip_tables.h> + +#include "tst_test.h" +#include "tst_safe_net.h" + + +#define TOO_SMALL_OFFSET 74 +#define OFFSET_OVERWRITE 0xFFFF +#define NEXT_OFFSET (sizeof(struct ipt_entry) \ + + sizeof(struct xt_entry_match) \ + + sizeof(struct xt_entry_target)) +#define PADDING (OFFSET_OVERWRITE - NEXT_OFFSET) + +struct payload { +struct ipt_replace repl; +struct ipt_entry ent; +struct xt_entry_match match; +struct xt_entry_target targ; +char padding[PADDING ]; +struct xt_entry_target targ2; +}; + +static void run (void ) +{ +int ret, sock_fd; +struct payload p = {0 }; + + sock_fd =SAFE_SOCKET (AF_INET ,SOCK_DGRAM ,0 ); + +strncpy (p.match.u.user.name,"icmp" ,sizeof (p.match.u.user.name)); + p.match.u.match_size =OFFSET_OVERWRITE ; + + p.ent.next_offset =NEXT_OFFSET ; + p.ent.target_offset =TOO_SMALL_OFFSET ; + + p.repl.num_entries =2 ; + p.repl.num_counters =1 ; + p.repl.size =sizeof (struct payload ); + p.repl.valid_hooks =0 ; + + ret =setsockopt (sock_fd,SOL_IP ,IPT_SO_SET_REPLACE , + &p,sizeof (struct payload )); +tst_res (TPASS |TERRNO ,"We didn't cause a crash, setsockopt returned %d" , ret); +if (sizeof (long ) >4 ) +tst_res (TCONF , +"The original vulnerability was only present in 32-bit compat mode" ); +} + +static struct tst_test test = { + .tid ="cve-2016-4997" , + .min_kver ="2.6.32" , + .test_all = run, + .needs_root =1 , +};
Signature · 1 line
2.12.0
PATCH 2/4 Test for CVE-2016-4997 on setsockopt
Hi!
Quoted 14 lines
testcases/cve/cve-2016-4997.c new file +14
-0+static void run (void ) +{ +int ret, sock_fd; +struct payload p = {0 }; + + sock_fd =SAFE_SOCKET (AF_INET ,SOCK_DGRAM ,0 ); + +strncpy (p.match.u.user.name,"icmp" ,sizeof (p.match.u.user.name)); + p.match.u.match_size =OFFSET_OVERWRITE ; + + p.ent.next_offset =NEXT_OFFSET ; + p.ent.target_offset =TOO_SMALL_OFFSET ; + + p.repl.num_entries =2 ;
testcases/cve/cve-2016-4997.c line 79
Quoted 10 lines
testcases/cve/cve-2016-4997.c new file +10
-0+ p.repl.num_counters =1 ; + p.repl.size =sizeof (struct payload ); + p.repl.valid_hooks =0 ; + + ret =setsockopt (sock_fd,SOL_IP ,IPT_SO_SET_REPLACE , + &p,sizeof (struct payload )); +tst_res (TPASS |TERRNO ,"We didn't cause a crash, setsockopt returned %d" , ret); +if (sizeof (long ) >4 ) +tst_res (TCONF , +"The original vulnerability was only present in 32-bit compat mode" );
Why do we issue the TCONF at the end of the test? Shouldn't this be something do in the test setup?
Also we have tst_kernel_bits() in the test library, so we can do something as:
if (tst_kernel_bits() == 32 || sizeof(long) > 4)
tst_res(TCONF, "...");
testcases/cve/cve-2016-4997.c line 87
Quoted 8 lines
testcases/cve/cve-2016-4997.c new file +8
-0+} + +static struct tst_test test = { + .tid ="cve-2016-4997" , + .min_kver ="2.6.32" , + .test_all = run, + .needs_root =1 , +};
I also wonder if we should compile the test with -m32 by default, we whould have to add a configure test if compilation with -m32 works though.
Signature · 2 lines
Cyril Hrubis [email protected]
PATCH 2/4 Test for CVE-2016-4997 on setsockopt
Hello Metan,
On Mon, 27 Mar 2017 17:34:40 +0200
"Cyril Hrubis" <[email protected]> wrote:
", ret);
Quoted 6 lines
testcases/cve/cve-2016-4997.c line 79
Quoted 3 lines
testcases/cve/cve-2016-4997.c new file +3
-0+if (sizeof (long ) >4 ) +tst_res (TCONF , +"The original vulnerability was only present in 32-bit compat mode" );Why do we issue the TCONF at the end of the test? Shouldn't this be something do in the test setup?
Setup makes more sense.
Quoted 6 lines
Also we have
tst_kernel_bits()in the test library, so we can do something as:if (
tst_kernel_bits()== 32 || sizeof(long) > 4)tst_res(TCONF, "...");
OK, great.
Quoted 14 lines
testcases/cve/cve-2016-4997.c line 87
Quoted 9 lines
testcases/cve/cve-2016-4997.c new file +8
-0+} + +static struct tst_test test = { + .tid ="cve-2016-4997" , + .min_kver ="2.6.32" , + .test_all = run, + .needs_root =1 , +};I also wonder if we should compile the test with -m32 by default, we whould have to add a configure test if compilation with -m32 works though.
Yes, I think that is best, but passing -m32 to the test's make target does not cause the LTP library to be compiled with -m32 so linking fails. I'm not sure how to get it to build both binaries.
Thank you,
Richard.
PATCH 2/4 Test for CVE-2016-4997 on setsockopt
Hi!
Quoted 12 lines
Quoted 11 lines
testcases/cve/cve-2016-4997.c line 87
Quoted 6 lines
testcases/cve/cve-2016-4997.c new file +6
-0+static struct tst_test test = { + .tid ="cve-2016-4997" , + .min_kver ="2.6.32" , + .test_all = run, + .needs_root =1 , +};I also wonder if we should compile the test with -m32 by default, we whould have to add a configure test if compilation with -m32 works though.
Quoted 3 lines
Yes, I think that is best, but passing -m32 to the test's make target does not cause the LTP library to be compiled with -m32 so linking fails. I'm not sure how to get it to build both binaries.
Hmm, right, we would have to compile the test library for 32bit as well, that may be tricky bussines. On the other hand there are at least two other testcases that does not work when compiled for 64bits which would make use of this as well.
Signature · 2 lines
Cyril Hrubis [email protected]
PATCH 2/4 Test for CVE-2016-4997 on setsockopt
In reply to Richard PalethorpeHi!
Quoted 3 lines
Yes, I think that is best, but passing -m32 to the test's make target does not cause the LTP library to be compiled with -m32 so linking fails. I'm not sure how to get it to build both binaries.
I've hacked around a bit and managed to write a code that builds 32bit library if compiler supports -m32 and also switches between 64bit or 32bit library depending on CFLAGS used to build the test. I will send it as RFC to the LTP ML.
Signature · 2 lines
Cyril Hrubis [email protected]