1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) 2020 SUSE LLC <mdoucha@suse.cz> 4 */ 5 6/* 7 * CVE-2016-8655 8 * 9 * Check for race condition between packet_set_ring() and tp_version. On some 10 * kernels, this may lead to use-after-free. Kernel crash fixed in: 11 * 12 * commit 84ac7260236a49c79eede91617700174c2c19b0c 13 * Author: Philip Pettersson <philip.pettersson@gmail.com> 14 * Date: Wed Nov 30 14:55:36 2016 -0800 15 * 16 * packet: fix race condition in packet_set_ring 17 */ 18 19#include <unistd.h> 20#include <sys/types.h> 21#include <sys/socket.h> 22 23#include "tst_test.h" 24#include "tst_fuzzy_sync.h" 25#include "lapi/if_packet.h" 26#include "lapi/if_ether.h" 27 28static int sock = -1; 29static unsigned int pagesize; 30static struct tst_fzsync_pair fzsync_pair; 31 32static void setup(void) 33{ 34 pagesize = SAFE_SYSCONF(_SC_PAGESIZE); 35 tst_setup_netns(); 36 37 fzsync_pair.exec_loops = 100000; 38 tst_fzsync_pair_init(&fzsync_pair); 39} 40 41static void *thread_run(void *arg) 42{ 43 int ret; 44 struct tpacket_req3 req = { 45 .tp_block_size = pagesize, 46 .tp_block_nr = 1, 47 .tp_frame_size = pagesize, 48 .tp_frame_nr = 1, 49 .tp_retire_blk_tov = 100 50 }; 51 52 while (tst_fzsync_run_b(&fzsync_pair)) { 53 tst_fzsync_start_race_b(&fzsync_pair); 54 ret = setsockopt(sock, SOL_PACKET, PACKET_RX_RING, &req, 55 sizeof(req)); 56 tst_fzsync_end_race_b(&fzsync_pair); 57 58 if (!ret) 59 tst_fzsync_pair_add_bias(&fzsync_pair, -10); 60 } 61 62 return arg; 63} 64 65static void run(void) 66{ 67 int val1 = TPACKET_V1, val3 = TPACKET_V3; 68 69 tst_fzsync_pair_reset(&fzsync_pair, thread_run); 70 71 while (tst_fzsync_run_a(&fzsync_pair)) { 72 sock = SAFE_SOCKET(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 73 TEST(setsockopt(sock, SOL_PACKET, PACKET_VERSION, &val3, 74 sizeof(val3))); 75 76 if (TST_RET == -1 && TST_ERR == EINVAL) 77 tst_brk(TCONF | TTERRNO, "TPACKET_V3 not supported"); 78 79 if (TST_RET) { 80 tst_brk(TBROK | TTERRNO, 81 "setsockopt(PACKET_VERSION, TPACKET_V3"); 82 } 83 84 tst_fzsync_start_race_a(&fzsync_pair); 85 setsockopt(sock, SOL_PACKET, PACKET_VERSION, &val1, 86 sizeof(val1)); 87 tst_fzsync_end_race_a(&fzsync_pair); 88 SAFE_CLOSE(sock); 89 } 90 91 /* setsockopt(PACKET_RX_RING) created a 100ms timer. Wait for it. */ 92 usleep(300000); 93 94 if (tst_taint_check()) { 95 tst_res(TFAIL, "Kernel is vulnerable"); 96 return; 97 } 98 99 tst_res(TPASS, "Nothing bad happened, probably"); 100} 101 102static void cleanup(void) 103{ 104 tst_fzsync_pair_cleanup(&fzsync_pair); 105 106 if (sock >= 0) 107 SAFE_CLOSE(sock); 108} 109 110static struct tst_test test = { 111 .test_all = run, 112 .setup = setup, 113 .cleanup = cleanup, 114 .max_runtime = 270, 115 .taint_check = TST_TAINT_W | TST_TAINT_D, 116 .needs_kconfigs = (const char *[]) { 117 "CONFIG_USER_NS=y", 118 "CONFIG_NET_NS=y", 119 NULL 120 }, 121 .save_restore = (const struct tst_path_val[]) { 122 {"/proc/sys/user/max_user_namespaces", "1024", TST_SR_SKIP}, 123 {} 124 }, 125 .tags = (const struct tst_tag[]) { 126 {"linux-git", "84ac7260236a"}, 127 {"CVE", "2016-8655"}, 128 {} 129 } 130}; 131