1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) 2017 Richard Palethorpe <rpalethorpe@suse.com> 4f08c3bdfSopenharmony_ci */ 5f08c3bdfSopenharmony_ci/* Test for CVE-2017-7308 on a raw socket's ring buffer 6f08c3bdfSopenharmony_ci * 7f08c3bdfSopenharmony_ci * Try to set tpacket_req3.tp_sizeof_priv to a value with the high bit set. So 8f08c3bdfSopenharmony_ci * that tp_block_size < tp_sizeof_priv. If the vulnerability is present then 9f08c3bdfSopenharmony_ci * this will cause an integer arithmetic overflow and the absurd 10f08c3bdfSopenharmony_ci * tp_sizeof_priv value will be allowed. If it has been fixed then setsockopt 11f08c3bdfSopenharmony_ci * will fail with EINVAL. 12f08c3bdfSopenharmony_ci * 13f08c3bdfSopenharmony_ci * We also try a good configuration to make sure it is not failing with EINVAL 14f08c3bdfSopenharmony_ci * for some other reason. 15f08c3bdfSopenharmony_ci * 16f08c3bdfSopenharmony_ci * For a better and more interesting discussion of this CVE see: 17f08c3bdfSopenharmony_ci * https://googleprojectzero.blogspot.com/2017/05/exploiting-linux-kernel-via-packet.html 18f08c3bdfSopenharmony_ci */ 19f08c3bdfSopenharmony_ci 20f08c3bdfSopenharmony_ci#include <errno.h> 21f08c3bdfSopenharmony_ci#include "tst_test.h" 22f08c3bdfSopenharmony_ci#include "tst_safe_net.h" 23f08c3bdfSopenharmony_ci#include "lapi/if_packet.h" 24f08c3bdfSopenharmony_ci#include "lapi/if_ether.h" 25f08c3bdfSopenharmony_ci 26f08c3bdfSopenharmony_cistatic int sk; 27f08c3bdfSopenharmony_cistatic long pgsz; 28f08c3bdfSopenharmony_ci 29f08c3bdfSopenharmony_cistatic void setup(void) 30f08c3bdfSopenharmony_ci{ 31f08c3bdfSopenharmony_ci pgsz = SAFE_SYSCONF(_SC_PAGESIZE); 32f08c3bdfSopenharmony_ci} 33f08c3bdfSopenharmony_ci 34f08c3bdfSopenharmony_cistatic void cleanup(void) 35f08c3bdfSopenharmony_ci{ 36f08c3bdfSopenharmony_ci if (sk > 0) 37f08c3bdfSopenharmony_ci SAFE_CLOSE(sk); 38f08c3bdfSopenharmony_ci} 39f08c3bdfSopenharmony_ci 40f08c3bdfSopenharmony_cistatic int create_skbuf(unsigned int sizeof_priv) 41f08c3bdfSopenharmony_ci{ 42f08c3bdfSopenharmony_ci int ver = TPACKET_V3; 43f08c3bdfSopenharmony_ci struct tpacket_req3 req = {}; 44f08c3bdfSopenharmony_ci 45f08c3bdfSopenharmony_ci req.tp_block_size = pgsz; 46f08c3bdfSopenharmony_ci req.tp_block_nr = 2; 47f08c3bdfSopenharmony_ci req.tp_frame_size = req.tp_block_size; 48f08c3bdfSopenharmony_ci req.tp_frame_nr = req.tp_block_nr; 49f08c3bdfSopenharmony_ci req.tp_retire_blk_tov = 100; 50f08c3bdfSopenharmony_ci 51f08c3bdfSopenharmony_ci req.tp_sizeof_priv = sizeof_priv; 52f08c3bdfSopenharmony_ci 53f08c3bdfSopenharmony_ci sk = SAFE_SOCKET(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 54f08c3bdfSopenharmony_ci TEST(setsockopt(sk, SOL_PACKET, PACKET_VERSION, &ver, sizeof(ver))); 55f08c3bdfSopenharmony_ci if (TST_RET && TST_ERR == EINVAL) 56f08c3bdfSopenharmony_ci tst_brk(TCONF | TTERRNO, "TPACKET_V3 not supported"); 57f08c3bdfSopenharmony_ci if (TST_RET) 58f08c3bdfSopenharmony_ci tst_brk(TBROK | TTERRNO, "setsockopt(sk, SOL_PACKET, PACKET_VERSION, TPACKET_V3)"); 59f08c3bdfSopenharmony_ci 60f08c3bdfSopenharmony_ci return setsockopt(sk, SOL_PACKET, PACKET_RX_RING, &req, sizeof(req)); 61f08c3bdfSopenharmony_ci} 62f08c3bdfSopenharmony_ci 63f08c3bdfSopenharmony_cistatic void good_size(void) 64f08c3bdfSopenharmony_ci{ 65f08c3bdfSopenharmony_ci TEST(create_skbuf(512)); 66f08c3bdfSopenharmony_ci if (TST_RET) 67f08c3bdfSopenharmony_ci tst_brk(TBROK | TTERRNO, "Can't create ring buffer with good settings"); 68f08c3bdfSopenharmony_ci 69f08c3bdfSopenharmony_ci tst_res(TPASS, "Can create ring buffer with good settinegs"); 70f08c3bdfSopenharmony_ci} 71f08c3bdfSopenharmony_ci 72f08c3bdfSopenharmony_cistatic void bad_size(void) 73f08c3bdfSopenharmony_ci{ 74f08c3bdfSopenharmony_ci TEST(create_skbuf(3U << 30)); 75f08c3bdfSopenharmony_ci if (TST_RET && TST_ERR != EINVAL) 76f08c3bdfSopenharmony_ci tst_brk(TBROK | TTERRNO, "Unexpected setsockopt() error"); 77f08c3bdfSopenharmony_ci if (TST_RET) 78f08c3bdfSopenharmony_ci tst_res(TPASS | TTERRNO, "Refused bad tp_sizeof_priv value"); 79f08c3bdfSopenharmony_ci else 80f08c3bdfSopenharmony_ci tst_res(TFAIL, "Allowed bad tp_sizeof_priv value"); 81f08c3bdfSopenharmony_ci} 82f08c3bdfSopenharmony_ci 83f08c3bdfSopenharmony_cistatic void run(unsigned int i) 84f08c3bdfSopenharmony_ci{ 85f08c3bdfSopenharmony_ci if (i == 0) 86f08c3bdfSopenharmony_ci good_size(); 87f08c3bdfSopenharmony_ci else 88f08c3bdfSopenharmony_ci bad_size(); 89f08c3bdfSopenharmony_ci 90f08c3bdfSopenharmony_ci SAFE_CLOSE(sk); 91f08c3bdfSopenharmony_ci} 92f08c3bdfSopenharmony_ci 93f08c3bdfSopenharmony_cistatic struct tst_test test = { 94f08c3bdfSopenharmony_ci .test = run, 95f08c3bdfSopenharmony_ci .tcnt = 2, 96f08c3bdfSopenharmony_ci .needs_root = 1, 97f08c3bdfSopenharmony_ci .setup = setup, 98f08c3bdfSopenharmony_ci .cleanup = cleanup, 99f08c3bdfSopenharmony_ci .tags = (const struct tst_tag[]) { 100f08c3bdfSopenharmony_ci {"CVE", "2017-7308"}, 101f08c3bdfSopenharmony_ci {} 102f08c3bdfSopenharmony_ci } 103f08c3bdfSopenharmony_ci}; 104