| /* |
| * 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, |
| }; |