Received: by 2002:a05:6a10:af89:0:0:0:0 with SMTP id iu9csp3366075pxb; Mon, 17 Jan 2022 18:43:44 -0800 (PST) X-Google-Smtp-Source: ABdhPJznn79VvaD/4Ft07pEOBNeJXmVPpDtnBlacpBDZhFaz02a5PZZMoyVwQS7IUIvpyvCSM3ma X-Received: by 2002:a17:90b:4d11:: with SMTP id mw17mr18487390pjb.100.1642473824263; Mon, 17 Jan 2022 18:43:44 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1642473824; cv=none; d=google.com; s=arc-20160816; b=vA05MpskcpjH64ddhCksrBe/iVLBCuN6/TbWB7GHgNc/OlFPqv6p0aktm02fw22U1V syd2pRHJobePEMfOdSmsM8Nhg9yKqGGsoQp8qY6Bb2B+Z9lFeG7qAtUdQrETuV2NDxsB OJ0SOX9NFHQngYVOGkJL34FffeSxlagq+4+5Enj8XLQgTmOerwG2cKYUwAcZsLKK0kXy ID0L2zub/iZMYA7qdAn2rNI//mMr77ojm15Q6rVwozj44+ShIoTc724F63dCB3ywwAOv ipMtwOinIs72sNzjyYeDJ/CZwtMqZffBDk/JyA5QAi44lC3UilvT/VzfxiSE1QwqaBvW 088g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=YbzaPXdC9WkI+9IwCQ76GRCRBNMASzz5nz46qHZO7+E=; b=qIRYwin5tOnja1C7H6Dj/u5A2HaW05FHP8wBRrns7IlrbZ3PVWmv6Ry1cLbEnHwphZ ucZHmyMD1fs33LBw2jBP3sMXsrvVc9mWfPzVAjcrZoMMcR1vlqGQiri68qlv+q/Fg6c1 I2E2twgzLpUXWGijYlyIc1JeFTIpyclGZEAbubJQzxlJrTVX/HVMsV7oxaVifrpm1jbY SBfAoC9ofVp5EV7sfRqJTBqjKiPda8duKmbg/vME3dwTXwhlfviw/eM4d2qGvNa3yxkV W8ayY+3FGh7AKcShYDyZ4ukIs7iQ3siixnfW9qlFeX0I5w7xaeDaEXlNY4aHIR0lCC6P PMFw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=rePMvyqs; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id b21si11092826pfv.107.2022.01.17.18.43.32; Mon, 17 Jan 2022 18:43:44 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=rePMvyqs; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241937AbiAQRBj (ORCPT + 99 others); Mon, 17 Jan 2022 12:01:39 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45020 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241740AbiAQRAl (ORCPT ); Mon, 17 Jan 2022 12:00:41 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BCB0EC061751; Mon, 17 Jan 2022 09:00:40 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 5D129611B9; Mon, 17 Jan 2022 17:00:40 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 01017C36AE7; Mon, 17 Jan 2022 17:00:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1642438839; bh=fgpNcpGwTQOlUCWiGZGZm/cuplCzU4SORglq/H8Knog=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=rePMvyqs67cKnsozoGdD5jCYryZ6KIpvurQzfgm2Sw/20hS6f/+uWWHCs7t6SBAop Lctt6sqmt/m+86WRHsHiVp15SLVw0iFKRy4A7PcNsSVUUn3KcLoGGWcjFeQ1+3zMvu qGqSs+zHYZTCRvJQ9XlEMKyP+ByiKPpf51rVehoKcJLejFh3cQGAp5/5rsZ66aWBb4 QH40PwLGlI1OobO34rTqEnQ4ozCfYEQvg2Hxd/aHSC8eUaN9NVA3mAz9MwgMuuZAa1 FgWCl9DtHdAyfM5CSZN1wyzgYVM+8NV24T84cUHGz+KdT3tyE9SzLnyj1MOTwEERFA xCXL1nT2Y6TXQ== From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Michael Ellerman , Sasha Levin , shuah@kernel.org, linuxppc-dev@lists.ozlabs.org, linux-kselftest@vger.kernel.org Subject: [PATCH AUTOSEL 5.16 39/52] selftests/powerpc: Add a test of sigreturning to the kernel Date: Mon, 17 Jan 2022 11:58:40 -0500 Message-Id: <20220117165853.1470420-39-sashal@kernel.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220117165853.1470420-1-sashal@kernel.org> References: <20220117165853.1470420-1-sashal@kernel.org> MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Michael Ellerman [ Upstream commit a8968521cfdc3e339fe69473d6632e0aa8d7202a ] We have a general signal fuzzer, sigfuz, which can modify the MSR & NIP before sigreturn. But the chance of it hitting a kernel address and also clearing MSR_PR is fairly slim. So add a specific test of sigreturn to a kernel address, both with and without attempting to clear MSR_PR (which the kernel must block). Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20211209115944.4062384-1-mpe@ellerman.id.au Signed-off-by: Sasha Levin --- .../selftests/powerpc/signal/.gitignore | 1 + .../testing/selftests/powerpc/signal/Makefile | 1 + .../powerpc/signal/sigreturn_kernel.c | 132 ++++++++++++++++++ 3 files changed, 134 insertions(+) create mode 100644 tools/testing/selftests/powerpc/signal/sigreturn_kernel.c diff --git a/tools/testing/selftests/powerpc/signal/.gitignore b/tools/testing/selftests/powerpc/signal/.gitignore index ce3375cd8e73e..8f6c816099a48 100644 --- a/tools/testing/selftests/powerpc/signal/.gitignore +++ b/tools/testing/selftests/powerpc/signal/.gitignore @@ -4,3 +4,4 @@ signal_tm sigfuz sigreturn_vdso sig_sc_double_restart +sigreturn_kernel diff --git a/tools/testing/selftests/powerpc/signal/Makefile b/tools/testing/selftests/powerpc/signal/Makefile index d6ae54663aed7..84e201572466d 100644 --- a/tools/testing/selftests/powerpc/signal/Makefile +++ b/tools/testing/selftests/powerpc/signal/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 TEST_GEN_PROGS := signal signal_tm sigfuz sigreturn_vdso sig_sc_double_restart +TEST_GEN_PROGS += sigreturn_kernel CFLAGS += -maltivec $(OUTPUT)/signal_tm: CFLAGS += -mhtm diff --git a/tools/testing/selftests/powerpc/signal/sigreturn_kernel.c b/tools/testing/selftests/powerpc/signal/sigreturn_kernel.c new file mode 100644 index 0000000000000..0a1b6e591eeed --- /dev/null +++ b/tools/testing/selftests/powerpc/signal/sigreturn_kernel.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Test that we can't sigreturn to kernel addresses, or to kernel mode. + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include + +#include "utils.h" + +#define MSR_PR (1ul << 14) + +static volatile unsigned long long sigreturn_addr; +static volatile unsigned long long sigreturn_msr_mask; + +static void sigusr1_handler(int signo, siginfo_t *si, void *uc_ptr) +{ + ucontext_t *uc = (ucontext_t *)uc_ptr; + + if (sigreturn_addr) + UCONTEXT_NIA(uc) = sigreturn_addr; + + if (sigreturn_msr_mask) + UCONTEXT_MSR(uc) &= sigreturn_msr_mask; +} + +static pid_t fork_child(void) +{ + pid_t pid; + + pid = fork(); + if (pid == 0) { + raise(SIGUSR1); + exit(0); + } + + return pid; +} + +static int expect_segv(pid_t pid) +{ + int child_ret; + + waitpid(pid, &child_ret, 0); + FAIL_IF(WIFEXITED(child_ret)); + FAIL_IF(!WIFSIGNALED(child_ret)); + FAIL_IF(WTERMSIG(child_ret) != 11); + + return 0; +} + +int test_sigreturn_kernel(void) +{ + struct sigaction act; + int child_ret, i; + pid_t pid; + + act.sa_sigaction = sigusr1_handler; + act.sa_flags = SA_SIGINFO; + sigemptyset(&act.sa_mask); + + FAIL_IF(sigaction(SIGUSR1, &act, NULL)); + + for (i = 0; i < 2; i++) { + // Return to kernel + sigreturn_addr = 0xcull << 60; + pid = fork_child(); + expect_segv(pid); + + // Return to kernel virtual + sigreturn_addr = 0xc008ull << 48; + pid = fork_child(); + expect_segv(pid); + + // Return out of range + sigreturn_addr = 0xc010ull << 48; + pid = fork_child(); + expect_segv(pid); + + // Return to no-man's land, just below PAGE_OFFSET + sigreturn_addr = (0xcull << 60) - (64 * 1024); + pid = fork_child(); + expect_segv(pid); + + // Return to no-man's land, above TASK_SIZE_4PB + sigreturn_addr = 0x1ull << 52; + pid = fork_child(); + expect_segv(pid); + + // Return to 0xd space + sigreturn_addr = 0xdull << 60; + pid = fork_child(); + expect_segv(pid); + + // Return to 0xe space + sigreturn_addr = 0xeull << 60; + pid = fork_child(); + expect_segv(pid); + + // Return to 0xf space + sigreturn_addr = 0xfull << 60; + pid = fork_child(); + expect_segv(pid); + + // Attempt to set PR=0 for 2nd loop (should be blocked by kernel) + sigreturn_msr_mask = ~MSR_PR; + } + + printf("All children killed as expected\n"); + + // Don't change address, just MSR, should return to user as normal + sigreturn_addr = 0; + sigreturn_msr_mask = ~MSR_PR; + pid = fork_child(); + waitpid(pid, &child_ret, 0); + FAIL_IF(!WIFEXITED(child_ret)); + FAIL_IF(WIFSIGNALED(child_ret)); + FAIL_IF(WEXITSTATUS(child_ret) != 0); + + return 0; +} + +int main(void) +{ + return test_harness(test_sigreturn_kernel, "sigreturn_kernel"); +} -- 2.34.1