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