/* * Copyright (c) 2018 Michael Moese <mmoese@suse.de> * * 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/>. */ /* Regression test for commit: * 1137b5e2529a ipsec: Fix aborted xfrm policy dump crash aka CVE-2017-16939 * * Based on the reproducing code from Mohammed Ghannam, published on * https://blogs.securiteam.com/index.php/archives/3535 * * CAUTION! If your system is vulnerable to this CVE, the kernel * WILL DIE! */ #include <unistd.h> #include <sched.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <sys/wait.h> #include <netinet/in.h> #include <linux/netlink.h> #include "lapi/xfrm.h" #include "tst_test.h" #include "tst_res_flags.h" #include "tst_safe_macros.h" #include "tst_safe_net.h" #include "lapi/namespaces_constants.h" #define BUFSIZE 2048 static int fd; static struct sockaddr_nl addr; struct msg_policy { struct nlmsghdr msg; char buf[BUFSIZE]; }; static struct msg_policy *p; static void setup(void) { if (unshare(CLONE_NEWUSER) != 0) tst_brk(TCONF, "unshare(CLONE_NEWUSER) failed"); if (unshare(CLONE_NEWNET) != 0) tst_brk(TCONF, "unshare(CLONE_NEWNET) failed"); fd = SAFE_SOCKET(PF_NETLINK, SOCK_RAW, NETLINK_XFRM); memset(&addr, 0, sizeof(struct sockaddr_nl)); addr.nl_family = AF_NETLINK; addr.nl_pid = 0; /* packet goes into the kernel */ addr.nl_groups = XFRMNLGRP_NONE; /* no need for multicast group */ p = SAFE_MALLOC(sizeof(struct msg_policy)); memset(p, 0, sizeof(struct msg_policy)); p->msg.nlmsg_len = 0x10; p->msg.nlmsg_type = XFRM_MSG_GETPOLICY; p->msg.nlmsg_flags = NLM_F_MATCH | NLM_F_MULTI | NLM_F_REQUEST; p->msg.nlmsg_seq = 0x1; p->msg.nlmsg_pid = 2; } static void run(void) { int var = 0x100; SAFE_SETSOCKOPT(fd, 1, SO_RCVBUF, &var, sizeof(int)); SAFE_SENDTO(1, fd, (void *) &p->msg, p->msg.nlmsg_len, 0, (struct sockaddr *) &addr, sizeof(struct sockaddr_nl)); tst_res(TPASS, "Kernel seems to have survived"); } static struct tst_test test = { .setup = setup, .test_all = run, };