From patchwork Mon Jun 3 06:27:01 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Amann X-Patchwork-Id: 1109074 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=lists.linux.it (client-ip=213.254.12.146; helo=picard.linux.it; envelope-from=ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=suse.com Received: from picard.linux.it (picard.linux.it [213.254.12.146]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45HQ8306FFz9s7h for ; Mon, 3 Jun 2019 16:27:14 +1000 (AEST) Received: from picard.linux.it (localhost [IPv6:::1]) by picard.linux.it (Postfix) with ESMTP id 603002D014A for ; Mon, 3 Jun 2019 08:27:10 +0200 (CEST) X-Original-To: ltp@lists.linux.it Delivered-To: ltp@picard.linux.it Received: from in-2.smtp.seeweb.it (in-2.smtp.seeweb.it [217.194.8.2]) by picard.linux.it (Postfix) with ESMTP id 119382B02EF for ; Mon, 3 Jun 2019 08:27:08 +0200 (CEST) Received: from mx1.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by in-2.smtp.seeweb.it (Postfix) with ESMTPS id 6898460067A for ; Mon, 3 Jun 2019 08:27:06 +0200 (CEST) Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 6B3C8AEF3 for ; Mon, 3 Jun 2019 06:27:06 +0000 (UTC) From: Christian Amann To: ltp@lists.linux.it Date: Mon, 3 Jun 2019 08:27:01 +0200 Message-Id: <20190603062701.9728-1-camann@suse.com> X-Mailer: git-send-email 2.16.4 X-Virus-Scanned: clamav-milter 0.99.2 at in-2.smtp.seeweb.it X-Virus-Status: Clean X-Spam-Status: No, score=0.0 required=7.0 tests=SPF_HELO_NONE,SPF_PASS autolearn=disabled version=3.4.0 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on in-2.smtp.seeweb.it Subject: [LTP] [PATCH v1] syscalls/accept02: add CVE-2017-8890 test case X-BeenThere: ltp@lists.linux.it X-Mailman-Version: 2.1.18 Precedence: list List-Id: Linux Test Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it Sender: "ltp" In Kernels prior to 4.10.15 missing commit 657831ff the multicast group of a socket was copied over to a new socket created using the accept() syscall. This leads to a double free when closing both those sockets. This can only be checked once a new socket was created which has to be closed eventually. That means that this test case can cause an unstable system if it does not succeed. Signed-off-by: Christian Amann --- runtest/syscalls | 2 + testcases/kernel/syscalls/accept/.gitignore | 1 + testcases/kernel/syscalls/accept/Makefile | 2 + testcases/kernel/syscalls/accept/accept02.c | 143 ++++++++++++++++++++++++++++ 4 files changed, 148 insertions(+) create mode 100644 testcases/kernel/syscalls/accept/accept02.c diff --git a/runtest/syscalls b/runtest/syscalls index 762b15b1f..79ef294fe 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -2,6 +2,8 @@ abort01 abort01 accept01 accept01 +accept02 accept02 + accept4_01 accept4_01 access01 access01 diff --git a/testcases/kernel/syscalls/accept/.gitignore b/testcases/kernel/syscalls/accept/.gitignore index 1f6f8ada0..5b1462699 100644 --- a/testcases/kernel/syscalls/accept/.gitignore +++ b/testcases/kernel/syscalls/accept/.gitignore @@ -1 +1,2 @@ /accept01 +/accept02 diff --git a/testcases/kernel/syscalls/accept/Makefile b/testcases/kernel/syscalls/accept/Makefile index bd617d806..0910871c7 100644 --- a/testcases/kernel/syscalls/accept/Makefile +++ b/testcases/kernel/syscalls/accept/Makefile @@ -21,3 +21,5 @@ top_srcdir ?= ../../../.. include $(top_srcdir)/include/mk/testcases.mk include $(top_srcdir)/include/mk/generic_leaf_target.mk + +accept02: CFLAGS += -pthread diff --git a/testcases/kernel/syscalls/accept/accept02.c b/testcases/kernel/syscalls/accept/accept02.c new file mode 100644 index 000000000..662ae4346 --- /dev/null +++ b/testcases/kernel/syscalls/accept/accept02.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2019 SUSE LLC + * Author: Christian Amann + */ +/* Test for CVE-2017-8890 + * + * In Kernels up to 4.10.15 missing commit 657831ff the multicast + * group information of a socket gets copied over to a newly created + * socket when using the accept() syscall. This will cause a double free + * when closing the original and the cloned socket. + * + * WARNING: + * There is a high chance that this test will cause an unstable system + * if it does not succeed! + * + * For more information about this CVE see: + * https://www.suse.com/security/cve/CVE-2017-8890/ + */ + +#include +#include +#include "tst_test.h" +#include "tst_safe_net.h" +#include "tst_safe_pthread.h" + +#define MULTICASTIP "224.0.0.0" +#define LOCALHOSTIP "127.0.0.1" + +static int server_sockfd; +static int clone_server_sockfd; +static int client_sockfd; +static int server_port; +static socklen_t addr_len; + +static struct sockaddr_in server_addr; +static struct sockaddr_in client_addr; +static struct group_req mc_group; + + +static void *server_thread(void *arg) +{ + int op, op_len, mc_group_len; + + op = 1; + op_len = sizeof(op); + mc_group_len = sizeof(mc_group); + + server_sockfd = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0); + + SAFE_SETSOCKOPT(server_sockfd, SOL_SOCKET, SO_REUSEADDR, &op, op_len); + SAFE_SETSOCKOPT(server_sockfd, SOL_IP, MCAST_JOIN_GROUP, + &mc_group, mc_group_len); + + SAFE_BIND(server_sockfd, (struct sockaddr *)&server_addr, addr_len); + SAFE_LISTEN(server_sockfd, 1); + + TST_CHECKPOINT_WAKE(0); + + TEST(accept(server_sockfd, (struct sockaddr *)&client_addr, &addr_len)); + if (TST_RET == -1) + tst_brk(TBROK | TTERRNO, "Could not accept connection"); + + clone_server_sockfd = TST_RET; + + TEST(setsockopt(clone_server_sockfd, SOL_IP, MCAST_LEAVE_GROUP, + &mc_group, mc_group_len)); + + if (TST_RET != -1) + tst_res(TFAIL, "Multicast group was copied!"); + else if (TST_ERR == EADDRNOTAVAIL) + tst_res(TPASS | TTERRNO, "Multicast group was not copied"); + else + tst_brk(TBROK | TTERRNO, "setsockopt() failed unexpectedly"); + + SAFE_CLOSE(server_sockfd); + return arg; +} + +static void *client_thread(void *arg) +{ + client_sockfd = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0); + SAFE_BIND(client_sockfd, (struct sockaddr *)&client_addr, addr_len); + + SAFE_CONNECT(client_sockfd, (struct sockaddr *)&server_addr, addr_len); + + SAFE_CLOSE(client_sockfd); + return arg; +} + +static void run(void) +{ + pthread_t server_thr, client_thr; + + server_addr.sin_port = htons(server_port); + client_addr.sin_port = htons(0); + + SAFE_PTHREAD_CREATE(&server_thr, NULL, server_thread, NULL); + TST_CHECKPOINT_WAIT(0); + SAFE_PTHREAD_CREATE(&client_thr, NULL, client_thread, NULL); + + SAFE_PTHREAD_JOIN(server_thr, NULL); + SAFE_PTHREAD_JOIN(client_thr, NULL); +} + +static void setup(void) +{ + struct sockaddr_in *mc_group_addr; + + mc_group.gr_interface = 0; + mc_group_addr = (struct sockaddr_in *) &mc_group.gr_group; + mc_group_addr->sin_family = AF_INET; + inet_aton(MULTICASTIP, &mc_group_addr->sin_addr); + + server_addr.sin_family = AF_INET; + inet_aton(LOCALHOSTIP, &server_addr.sin_addr); + + client_addr.sin_family = AF_INET; + client_addr.sin_addr.s_addr = htons(INADDR_ANY); + + addr_len = sizeof(struct sockaddr_in); + + server_port = TST_GET_UNUSED_PORT(AF_INET, SOCK_STREAM); + tst_res(TINFO, "Starting listener on port: %d", server_port); +} + +static void cleanup(void) +{ + if (clone_server_sockfd > 0) + SAFE_CLOSE(clone_server_sockfd); + if (client_sockfd > 0) + SAFE_CLOSE(client_sockfd); + if (server_sockfd > 0) + SAFE_CLOSE(server_sockfd); +} + +static struct tst_test test = { + .test_all = run, + .setup = setup, + .cleanup = cleanup, + .needs_checkpoints = 1, + .needs_root = 1, +};