1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (C) 2017 Christoph Paasch <cpaasch@apple.com> 4f08c3bdfSopenharmony_ci * Copyright (C) 2020 SUSE LLC <mdoucha@suse.cz> 5f08c3bdfSopenharmony_ci * 6f08c3bdfSopenharmony_ci * CVE-2018-9568 7f08c3bdfSopenharmony_ci * 8f08c3bdfSopenharmony_ci * Test that connect() to AF_UNSPEC address correctly converts IPV6 socket 9f08c3bdfSopenharmony_ci * to IPV4 listen socket when IPV6_ADDRFORM is set to AF_INET. 10f08c3bdfSopenharmony_ci * Kernel memory corruption fixed in: 11f08c3bdfSopenharmony_ci * 12f08c3bdfSopenharmony_ci * commit 9d538fa60bad4f7b23193c89e843797a1cf71ef3 13f08c3bdfSopenharmony_ci * Author: Christoph Paasch <cpaasch@apple.com> 14f08c3bdfSopenharmony_ci * Date: Tue Sep 26 17:38:50 2017 -0700 15f08c3bdfSopenharmony_ci * 16f08c3bdfSopenharmony_ci * net: Set sk_prot_creator when cloning sockets to the right proto 17f08c3bdfSopenharmony_ci * 18f08c3bdfSopenharmony_ci * 19f08c3bdfSopenharmony_ci * Note: This test also detects setsockopt(IP_ADDRFORM) breakage caused by 20f08c3bdfSopenharmony_ci * kernel commit b6f6118901d1. This bug is unrelated to CVE-2018-9568. 21f08c3bdfSopenharmony_ci * Fixed in: 22f08c3bdfSopenharmony_ci * 23f08c3bdfSopenharmony_ci * commit 82c9ae440857840c56e05d4fb1427ee032531346 24f08c3bdfSopenharmony_ci * Author: John Haxby <john.haxby@oracle.com> 25f08c3bdfSopenharmony_ci * Date: Sat Apr 18 16:30:49 2020 +0100 26f08c3bdfSopenharmony_ci * 27f08c3bdfSopenharmony_ci * ipv6: fix restrict IPV6_ADDRFORM operation 28f08c3bdfSopenharmony_ci */ 29f08c3bdfSopenharmony_ci 30f08c3bdfSopenharmony_ci#include <sys/types.h> 31f08c3bdfSopenharmony_ci#include <sys/socket.h> 32f08c3bdfSopenharmony_ci#include <netinet/in.h> 33f08c3bdfSopenharmony_ci#include <netinet/tcp.h> 34f08c3bdfSopenharmony_ci#include <arpa/inet.h> 35f08c3bdfSopenharmony_ci 36f08c3bdfSopenharmony_ci#include "tst_test.h" 37f08c3bdfSopenharmony_ci#include "tst_net.h" 38f08c3bdfSopenharmony_ci 39f08c3bdfSopenharmony_cistatic int listenfd = -1, fd = -1, confd1 = -1, confd2 = -1, confd3 = -1; 40f08c3bdfSopenharmony_cistatic struct sockaddr_in6 bind_addr; 41f08c3bdfSopenharmony_cistatic struct sockaddr_in bind_addr4, client_addr; 42f08c3bdfSopenharmony_cistatic struct sockaddr reset_addr; 43f08c3bdfSopenharmony_ci 44f08c3bdfSopenharmony_cistatic void setup(void) 45f08c3bdfSopenharmony_ci{ 46f08c3bdfSopenharmony_ci socklen_t size = sizeof(bind_addr); 47f08c3bdfSopenharmony_ci 48f08c3bdfSopenharmony_ci tst_init_sockaddr_inet6_bin(&bind_addr, &in6addr_any, 0); 49f08c3bdfSopenharmony_ci tst_init_sockaddr_inet_bin(&bind_addr4, INADDR_ANY, 0); 50f08c3bdfSopenharmony_ci memset(&reset_addr, 0, sizeof(reset_addr)); 51f08c3bdfSopenharmony_ci reset_addr.sa_family = AF_UNSPEC; 52f08c3bdfSopenharmony_ci 53f08c3bdfSopenharmony_ci listenfd = SAFE_SOCKET(AF_INET6, SOCK_STREAM, IPPROTO_TCP); 54f08c3bdfSopenharmony_ci SAFE_BIND(listenfd, (struct sockaddr *)&bind_addr, sizeof(bind_addr)); 55f08c3bdfSopenharmony_ci SAFE_LISTEN(listenfd, 5); 56f08c3bdfSopenharmony_ci SAFE_GETSOCKNAME(listenfd, (struct sockaddr *)&bind_addr, &size); 57f08c3bdfSopenharmony_ci tst_init_sockaddr_inet(&client_addr, "127.0.0.1", 58f08c3bdfSopenharmony_ci htons(bind_addr.sin6_port)); 59f08c3bdfSopenharmony_ci} 60f08c3bdfSopenharmony_ci 61f08c3bdfSopenharmony_cistatic void cleanup(void) 62f08c3bdfSopenharmony_ci{ 63f08c3bdfSopenharmony_ci if (confd3 >= 0) 64f08c3bdfSopenharmony_ci SAFE_CLOSE(confd3); 65f08c3bdfSopenharmony_ci 66f08c3bdfSopenharmony_ci if (confd2 >= 0) 67f08c3bdfSopenharmony_ci SAFE_CLOSE(confd2); 68f08c3bdfSopenharmony_ci 69f08c3bdfSopenharmony_ci if (confd1 >= 0) 70f08c3bdfSopenharmony_ci SAFE_CLOSE(confd1); 71f08c3bdfSopenharmony_ci 72f08c3bdfSopenharmony_ci if (fd >= 0) 73f08c3bdfSopenharmony_ci SAFE_CLOSE(fd); 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_ci if (listenfd >= 0) 76f08c3bdfSopenharmony_ci SAFE_CLOSE(listenfd); 77f08c3bdfSopenharmony_ci} 78f08c3bdfSopenharmony_ci 79f08c3bdfSopenharmony_cistatic void run(void) 80f08c3bdfSopenharmony_ci{ 81f08c3bdfSopenharmony_ci int i, addrlen, optval = AF_INET; 82f08c3bdfSopenharmony_ci struct sockaddr_storage client_addr2; 83f08c3bdfSopenharmony_ci 84f08c3bdfSopenharmony_ci for (i = 0; i < 1000; i++) { 85f08c3bdfSopenharmony_ci confd1 = SAFE_SOCKET(AF_INET, SOCK_STREAM, IPPROTO_TCP); 86f08c3bdfSopenharmony_ci SAFE_CONNECT(confd1, (struct sockaddr *)&client_addr, 87f08c3bdfSopenharmony_ci sizeof(client_addr)); 88f08c3bdfSopenharmony_ci 89f08c3bdfSopenharmony_ci fd = SAFE_ACCEPT(listenfd, NULL, NULL); 90f08c3bdfSopenharmony_ci TEST(setsockopt(fd, SOL_IPV6, IPV6_ADDRFORM, &optval, 91f08c3bdfSopenharmony_ci sizeof(optval))); 92f08c3bdfSopenharmony_ci 93f08c3bdfSopenharmony_ci if (TST_RET == -1) { 94f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, 95f08c3bdfSopenharmony_ci "setsockopt(IPV6_ADDRFORM) failed"); 96f08c3bdfSopenharmony_ci return; 97f08c3bdfSopenharmony_ci } 98f08c3bdfSopenharmony_ci 99f08c3bdfSopenharmony_ci if (TST_RET != 0) 100f08c3bdfSopenharmony_ci tst_brk(TBROK | TTERRNO, "setsockopt(IPV6_ADDRFORM) " 101f08c3bdfSopenharmony_ci "returned invalid value"); 102f08c3bdfSopenharmony_ci 103f08c3bdfSopenharmony_ci SAFE_CONNECT(fd, (struct sockaddr *)&reset_addr, 104f08c3bdfSopenharmony_ci sizeof(reset_addr)); 105f08c3bdfSopenharmony_ci SAFE_BIND(fd, (struct sockaddr *)&bind_addr4, 106f08c3bdfSopenharmony_ci sizeof(bind_addr4)); 107f08c3bdfSopenharmony_ci SAFE_LISTEN(fd, 5); 108f08c3bdfSopenharmony_ci 109f08c3bdfSopenharmony_ci addrlen = tst_get_connect_address(fd, &client_addr2); 110f08c3bdfSopenharmony_ci confd2 = SAFE_SOCKET(AF_INET, SOCK_STREAM, IPPROTO_TCP); 111f08c3bdfSopenharmony_ci SAFE_CONNECT(confd2, (struct sockaddr *)&client_addr2, addrlen); 112f08c3bdfSopenharmony_ci confd3 = SAFE_ACCEPT(fd, NULL, NULL); 113f08c3bdfSopenharmony_ci 114f08c3bdfSopenharmony_ci SAFE_CLOSE(confd3); 115f08c3bdfSopenharmony_ci SAFE_CLOSE(confd2); 116f08c3bdfSopenharmony_ci SAFE_CLOSE(confd1); 117f08c3bdfSopenharmony_ci SAFE_CLOSE(fd); 118f08c3bdfSopenharmony_ci 119f08c3bdfSopenharmony_ci if (tst_taint_check()) { 120f08c3bdfSopenharmony_ci tst_res(TFAIL, "Kernel is vulnerable"); 121f08c3bdfSopenharmony_ci return; 122f08c3bdfSopenharmony_ci } 123f08c3bdfSopenharmony_ci } 124f08c3bdfSopenharmony_ci 125f08c3bdfSopenharmony_ci tst_res(TPASS, "Nothing bad happened, probably"); 126f08c3bdfSopenharmony_ci} 127f08c3bdfSopenharmony_ci 128f08c3bdfSopenharmony_cistatic struct tst_test test = { 129f08c3bdfSopenharmony_ci .test_all = run, 130f08c3bdfSopenharmony_ci .setup = setup, 131f08c3bdfSopenharmony_ci .cleanup = cleanup, 132f08c3bdfSopenharmony_ci .taint_check = TST_TAINT_W | TST_TAINT_D, 133f08c3bdfSopenharmony_ci .tags = (const struct tst_tag[]) { 134f08c3bdfSopenharmony_ci {"linux-git", "9d538fa60bad"}, 135f08c3bdfSopenharmony_ci {"linux-git", "82c9ae440857"}, 136f08c3bdfSopenharmony_ci {"CVE", "2018-9568"}, 137f08c3bdfSopenharmony_ci {} 138f08c3bdfSopenharmony_ci } 139f08c3bdfSopenharmony_ci}; 140