1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) 2022 SUSE LLC 4f08c3bdfSopenharmony_ci * Author: Marcos Paulo de Souza <mpdesouza@suse.com> 5f08c3bdfSopenharmony_ci * LTP port: Martin Doucha <mdoucha@suse.cz> 6f08c3bdfSopenharmony_ci */ 7f08c3bdfSopenharmony_ci 8f08c3bdfSopenharmony_ci/*\ 9f08c3bdfSopenharmony_ci * [Description] 10f08c3bdfSopenharmony_ci * 11f08c3bdfSopenharmony_ci * Check for possible double free of rx_owner_map after switching packet 12f08c3bdfSopenharmony_ci * interface versions aka CVE-2021-22600. 13f08c3bdfSopenharmony_ci * 14f08c3bdfSopenharmony_ci * Kernel crash fixed in: 15f08c3bdfSopenharmony_ci * 16f08c3bdfSopenharmony_ci * commit ec6af094ea28f0f2dda1a6a33b14cd57e36a9755 17f08c3bdfSopenharmony_ci * Author: Willem de Bruijn <willemb@google.com> 18f08c3bdfSopenharmony_ci * Date: Wed Dec 15 09:39:37 2021 -0500 19f08c3bdfSopenharmony_ci * 20f08c3bdfSopenharmony_ci * net/packet: rx_owner_map depends on pg_vec 21f08c3bdfSopenharmony_ci * 22f08c3bdfSopenharmony_ci * commit c800aaf8d869f2b9b47b10c5c312fe19f0a94042 23f08c3bdfSopenharmony_ci * Author: WANG Cong <xiyou.wangcong@gmail.com> 24f08c3bdfSopenharmony_ci * Date: Mon Jul 24 10:07:32 2017 -0700 25f08c3bdfSopenharmony_ci * 26f08c3bdfSopenharmony_ci * packet: fix use-after-free in prb_retire_rx_blk_timer_expired() 27f08c3bdfSopenharmony_ci */ 28f08c3bdfSopenharmony_ci 29f08c3bdfSopenharmony_ci#include <unistd.h> 30f08c3bdfSopenharmony_ci#include <sys/types.h> 31f08c3bdfSopenharmony_ci#include <sys/socket.h> 32f08c3bdfSopenharmony_ci 33f08c3bdfSopenharmony_ci#include "tst_test.h" 34f08c3bdfSopenharmony_ci#include "lapi/if_packet.h" 35f08c3bdfSopenharmony_ci 36f08c3bdfSopenharmony_cistatic int sock = -1; 37f08c3bdfSopenharmony_cistatic unsigned int pagesize; 38f08c3bdfSopenharmony_ci 39f08c3bdfSopenharmony_cistatic void setup(void) 40f08c3bdfSopenharmony_ci{ 41f08c3bdfSopenharmony_ci pagesize = SAFE_SYSCONF(_SC_PAGESIZE); 42f08c3bdfSopenharmony_ci tst_setup_netns(); 43f08c3bdfSopenharmony_ci} 44f08c3bdfSopenharmony_ci 45f08c3bdfSopenharmony_cistatic void run(void) 46f08c3bdfSopenharmony_ci{ 47f08c3bdfSopenharmony_ci unsigned int i, version = TPACKET_V3; 48f08c3bdfSopenharmony_ci struct tpacket_req3 req = { 49f08c3bdfSopenharmony_ci .tp_block_size = 4 * pagesize, 50f08c3bdfSopenharmony_ci .tp_frame_size = TPACKET_ALIGNMENT << 7, 51f08c3bdfSopenharmony_ci .tp_retire_blk_tov = 64, 52f08c3bdfSopenharmony_ci .tp_feature_req_word = TP_FT_REQ_FILL_RXHASH 53f08c3bdfSopenharmony_ci }; 54f08c3bdfSopenharmony_ci 55f08c3bdfSopenharmony_ci for (i = 0; i < 5; i++) { 56f08c3bdfSopenharmony_ci req.tp_block_nr = 256; 57f08c3bdfSopenharmony_ci req.tp_frame_nr = req.tp_block_size * req.tp_block_nr; 58f08c3bdfSopenharmony_ci req.tp_frame_nr /= req.tp_frame_size; 59f08c3bdfSopenharmony_ci 60f08c3bdfSopenharmony_ci sock = SAFE_SOCKET(AF_PACKET, SOCK_RAW, 0); 61f08c3bdfSopenharmony_ci TEST(setsockopt(sock, SOL_PACKET, PACKET_VERSION, &version, 62f08c3bdfSopenharmony_ci sizeof(version))); 63f08c3bdfSopenharmony_ci 64f08c3bdfSopenharmony_ci if (TST_RET == -1 && TST_ERR == EINVAL) 65f08c3bdfSopenharmony_ci tst_brk(TCONF | TTERRNO, "TPACKET_V3 not supported"); 66f08c3bdfSopenharmony_ci 67f08c3bdfSopenharmony_ci if (TST_RET) { 68f08c3bdfSopenharmony_ci tst_brk(TBROK | TTERRNO, 69f08c3bdfSopenharmony_ci "setsockopt(PACKET_VERSION, TPACKET_V3)"); 70f08c3bdfSopenharmony_ci } 71f08c3bdfSopenharmony_ci 72f08c3bdfSopenharmony_ci /* Allocate owner map and then free it again */ 73f08c3bdfSopenharmony_ci SAFE_SETSOCKOPT(sock, SOL_PACKET, PACKET_RX_RING, &req, 74f08c3bdfSopenharmony_ci sizeof(req)); 75f08c3bdfSopenharmony_ci req.tp_block_nr = 0; 76f08c3bdfSopenharmony_ci req.tp_frame_nr = 0; 77f08c3bdfSopenharmony_ci SAFE_SETSOCKOPT(sock, SOL_PACKET, PACKET_RX_RING, &req, 78f08c3bdfSopenharmony_ci sizeof(req)); 79f08c3bdfSopenharmony_ci 80f08c3bdfSopenharmony_ci /* Switch packet version and trigger double free of owner map */ 81f08c3bdfSopenharmony_ci SAFE_SETSOCKOPT_INT(sock, SOL_PACKET, PACKET_VERSION, 82f08c3bdfSopenharmony_ci TPACKET_V2); 83f08c3bdfSopenharmony_ci SAFE_SETSOCKOPT(sock, SOL_PACKET, PACKET_RX_RING, &req, 84f08c3bdfSopenharmony_ci sizeof(req)); 85f08c3bdfSopenharmony_ci SAFE_CLOSE(sock); 86f08c3bdfSopenharmony_ci 87f08c3bdfSopenharmony_ci /* Wait for socket timer to expire just in case */ 88f08c3bdfSopenharmony_ci usleep(req.tp_retire_blk_tov * 3000); 89f08c3bdfSopenharmony_ci 90f08c3bdfSopenharmony_ci if (tst_taint_check()) { 91f08c3bdfSopenharmony_ci tst_res(TFAIL, "Kernel is vulnerable"); 92f08c3bdfSopenharmony_ci return; 93f08c3bdfSopenharmony_ci } 94f08c3bdfSopenharmony_ci } 95f08c3bdfSopenharmony_ci 96f08c3bdfSopenharmony_ci tst_res(TPASS, "Nothing bad happened, probably"); 97f08c3bdfSopenharmony_ci} 98f08c3bdfSopenharmony_ci 99f08c3bdfSopenharmony_cistatic void cleanup(void) 100f08c3bdfSopenharmony_ci{ 101f08c3bdfSopenharmony_ci if (sock >= 0) 102f08c3bdfSopenharmony_ci SAFE_CLOSE(sock); 103f08c3bdfSopenharmony_ci} 104f08c3bdfSopenharmony_ci 105f08c3bdfSopenharmony_cistatic struct tst_test test = { 106f08c3bdfSopenharmony_ci .test_all = run, 107f08c3bdfSopenharmony_ci .setup = setup, 108f08c3bdfSopenharmony_ci .cleanup = cleanup, 109f08c3bdfSopenharmony_ci .taint_check = TST_TAINT_W | TST_TAINT_D, 110f08c3bdfSopenharmony_ci .needs_kconfigs = (const char *[]) { 111f08c3bdfSopenharmony_ci "CONFIG_USER_NS=y", 112f08c3bdfSopenharmony_ci "CONFIG_NET_NS=y", 113f08c3bdfSopenharmony_ci NULL 114f08c3bdfSopenharmony_ci }, 115f08c3bdfSopenharmony_ci .save_restore = (const struct tst_path_val[]) { 116f08c3bdfSopenharmony_ci {"/proc/sys/user/max_user_namespaces", "1024", TST_SR_SKIP}, 117f08c3bdfSopenharmony_ci {} 118f08c3bdfSopenharmony_ci }, 119f08c3bdfSopenharmony_ci .tags = (const struct tst_tag[]) { 120f08c3bdfSopenharmony_ci {"linux-git", "ec6af094ea28"}, 121f08c3bdfSopenharmony_ci {"linux-git", "c800aaf8d869"}, 122f08c3bdfSopenharmony_ci {"CVE", "2021-22600"}, 123f08c3bdfSopenharmony_ci {} 124f08c3bdfSopenharmony_ci } 125f08c3bdfSopenharmony_ci}; 126