1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (C) 2020 SUSE LLC <mdoucha@suse.cz> 4 * 5 * CVE-2017-17712 6 * 7 * Test for race condition vulnerability in sendmsg() on SOCK_RAW sockets. 8 * Changing the value of IP_HDRINCL socket option in parallel with sendmsg() 9 * call may lead to uninitialized stack pointer usage, allowing arbitrary code 10 * execution or privilege escalation. Fixed in: 11 * 12 * commit 8f659a03a0ba9289b9aeb9b4470e6fb263d6f483 13 * Author: Mohamed Ghannam <simo.ghannam@gmail.com> 14 * Date: Sun Dec 10 03:50:58 2017 +0000 15 * 16 * net: ipv4: fix for a race condition in raw_sendmsg 17 */ 18#include <sys/types.h> 19#include <sys/socket.h> 20#include <netinet/in.h> 21#include "tst_test.h" 22#include "tst_fuzzy_sync.h" 23 24#define IOVEC_COUNT 4 25#define PACKET_SIZE 100 26 27static int sockfd = -1; 28static struct msghdr msg; 29/* addr must be full of zeroes to trigger the kernel bug */ 30static struct sockaddr_in addr; 31static struct iovec iov[IOVEC_COUNT]; 32static unsigned char buf[PACKET_SIZE]; 33static struct tst_fzsync_pair fzsync_pair; 34 35static void setup(void) 36{ 37 int i; 38 39 tst_setup_netns(); 40 41 sockfd = SAFE_SOCKET(AF_INET, SOCK_RAW, IPPROTO_ICMP); 42 43 memset(buf, 0xcc, PACKET_SIZE); 44 45 for (i = 0; i < IOVEC_COUNT; i++) { 46 iov[i].iov_base = buf; 47 iov[i].iov_len = PACKET_SIZE; 48 } 49 50 msg.msg_name = &addr; 51 msg.msg_namelen = sizeof(addr); 52 msg.msg_iov = iov; 53 msg.msg_iovlen = IOVEC_COUNT; 54 55 fzsync_pair.exec_loops = 100000; 56 tst_fzsync_pair_init(&fzsync_pair); 57} 58 59static void cleanup(void) 60{ 61 if (sockfd > 0) 62 SAFE_CLOSE(sockfd); 63 tst_fzsync_pair_cleanup(&fzsync_pair); 64} 65 66static void *thread_run(void *arg) 67{ 68 int val = 0; 69 70 while (tst_fzsync_run_b(&fzsync_pair)) { 71 tst_fzsync_start_race_b(&fzsync_pair); 72 setsockopt(sockfd, SOL_IP, IP_HDRINCL, &val, sizeof(val)); 73 tst_fzsync_end_race_b(&fzsync_pair); 74 } 75 76 return arg; 77} 78 79static void run(void) 80{ 81 int hdrincl = 1; 82 83 tst_fzsync_pair_reset(&fzsync_pair, thread_run); 84 85 while (tst_fzsync_run_a(&fzsync_pair)) { 86 SAFE_SETSOCKOPT_INT(sockfd, SOL_IP, IP_HDRINCL, hdrincl); 87 88 tst_fzsync_start_race_a(&fzsync_pair); 89 sendmsg(sockfd, &msg, 0); 90 tst_fzsync_end_race_a(&fzsync_pair); 91 92 if (tst_taint_check()) { 93 tst_res(TFAIL, "Kernel is vulnerable"); 94 return; 95 } 96 } 97 98 tst_res(TPASS, "Nothing bad happened, probably"); 99} 100 101static struct tst_test test = { 102 .test_all = run, 103 .setup = setup, 104 .cleanup = cleanup, 105 .taint_check = TST_TAINT_W | TST_TAINT_D, 106 .max_runtime = 150, 107 .needs_kconfigs = (const char *[]) { 108 "CONFIG_USER_NS=y", 109 "CONFIG_NET_NS=y", 110 NULL 111 }, 112 .save_restore = (const struct tst_path_val[]) { 113 {"/proc/sys/user/max_user_namespaces", "1024", TST_SR_SKIP}, 114 {} 115 }, 116 .tags = (const struct tst_tag[]) { 117 {"linux-git", "8f659a03a0ba"}, 118 {"CVE", "2017-17712"}, 119 {} 120 } 121}; 122