Received: by 2002:a05:7412:5112:b0:fa:6e18:a558 with SMTP id fm18csp1576864rdb; Wed, 24 Jan 2024 22:44:29 -0800 (PST) X-Google-Smtp-Source: AGHT+IFtjVByfDD3lyRbUFgVQfTlfP6xxNvYCNT/1DQUsDFu7Jl/Lp/rO7cFNSJHlCRDtlROYzI5 X-Received: by 2002:a17:902:d2c6:b0:1d7:3533:9660 with SMTP id n6-20020a170902d2c600b001d735339660mr811952plc.17.1706165069058; Wed, 24 Jan 2024 22:44:29 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1706165069; cv=pass; d=google.com; s=arc-20160816; b=Jw6MQm7TdhQ/7OR3Sz5xZS8HB2eooyL1xXwxSGcqStAZ9QZ5T8K/0GhLL4DhYi4GXH +vhVjnO+Hh+RIPy8v80m4lYRK+0NqYnxIZnrh6Lkac6LKIAdaIRgpT+mL9HEQwIKL7o1 R8+BL7KO7SXJ5HzCO+UX8+8Xhc2dBu3dS6SCXbGVWmU72bLlTjxWYy9TzgO4Uh+psSlF kvKGuu6qZbnQe/qWX+aKMOfr3dYmGMxh+m9rBzBJUb75OE00nZWmx8Bq9qdubptrJaRc CmfYX8Zn+ORy6tERxvivsPkXIyG9OZ7jSugSiofXwaJPNUtwnZJVsmlqCGQzy6RGOdYs 9Vvg== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=Rd0guRwVXbpygS5QcHTElt8jUaWNDA8n6eGW6ag7sBw=; fh=oy7V1wWqiaug32hsWRXm98kKNp5NFPTWbY7PiGr4deM=; b=Bw2F58II7hMKpWNnLlMGHW9z/5S9woZs0JCNNFeB4KQ1eKtgbtx6S3D5VZ78sCpxzl HeA1+KGzSE9KB3nyn0Mkd/G564OOcmfcQEF9w4nxVqnKOGYUivRY7GD0hBs1BsATx183 Zxu7J/M+g3hvtCZs4pH8OlCEEl2iysAFluw+pTiCe4qn4h99UdJoSe2ljbERSEbE3i+u GhFqxpv1EBxbk33jwFdSxuBedWON3Tk9wJZMYyhFL+4U+Z2l2U7NmEb7C2vQT+vnzWXq o4mUFbXqyzZBBBRaaebuAyKnnIv1LSYSmh8de//Aak8+rP44d1PLdLTKqnr69UgkNOUh Yuqg== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@rivosinc-com.20230601.gappssmtp.com header.s=20230601 header.b=ObS6LeGj; arc=pass (i=1 spf=pass spfdomain=rivosinc.com dkim=pass dkdomain=rivosinc-com.20230601.gappssmtp.com); spf=pass (google.com: domain of linux-kernel+bounces-38031-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-38031-linux.lists.archive=gmail.com@vger.kernel.org" Return-Path: Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org. [2604:1380:40f1:3f00::1]) by mx.google.com with ESMTPS id k10-20020a170902c40a00b001bb8c4279f5si13302414plk.148.2024.01.24.22.44.28 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 24 Jan 2024 22:44:29 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-38031-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) client-ip=2604:1380:40f1:3f00::1; Authentication-Results: mx.google.com; dkim=pass header.i=@rivosinc-com.20230601.gappssmtp.com header.s=20230601 header.b=ObS6LeGj; arc=pass (i=1 spf=pass spfdomain=rivosinc.com dkim=pass dkdomain=rivosinc-com.20230601.gappssmtp.com); spf=pass (google.com: domain of linux-kernel+bounces-38031-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-38031-linux.lists.archive=gmail.com@vger.kernel.org" Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sy.mirrors.kernel.org (Postfix) with ESMTPS id 39DB1B27200 for ; Thu, 25 Jan 2024 06:36:52 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 199B11BF5A; Thu, 25 Jan 2024 06:30:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=rivosinc-com.20230601.gappssmtp.com header.i=@rivosinc-com.20230601.gappssmtp.com header.b="ObS6LeGj" Received: from mail-oi1-f178.google.com (mail-oi1-f178.google.com [209.85.167.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BAFD01BF5B for ; Thu, 25 Jan 2024 06:30:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.178 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706164225; cv=none; b=VNKzylL5pHHQXkdvd7RugEQrUmg0p7nlsn2n6kLwjAhDY61MOhYuqIyEUB7PlV9FoDUDf6wT5mRqNHJS8HhT5n/97WiC+TKCJVo5K+46pJAeasU2jT2YKVfcgJufnX1vuZQXNq5gkOONAS/oG1HQTVn17MyelUI8rI7/eFC63g8= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706164225; c=relaxed/simple; bh=sFvLfcCpHsAUbdq4VBtGoEMVxhVYE7ITkN8XQXWveCI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=oK1a5KkxHW7pJ7Agf0Jo2cda9KZ9tHN9bOJMLSnTGkmNj9qLxRPLcVLLB0oTaVGCSaaxZtvqujlqYmuN9RBfOdJeGc9VvJFLNCWMUcJCIqwxXAFBJGqCs9Wi4tWx8kGEixVoG4Bu524+UluM8HkPasoCEYxUBLjkZNgZgmS2Y2U= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=rivosinc.com; spf=pass smtp.mailfrom=rivosinc.com; dkim=pass (2048-bit key) header.d=rivosinc-com.20230601.gappssmtp.com header.i=@rivosinc-com.20230601.gappssmtp.com header.b=ObS6LeGj; arc=none smtp.client-ip=209.85.167.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=rivosinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rivosinc.com Received: by mail-oi1-f178.google.com with SMTP id 5614622812f47-3bd67e9d6ceso3979979b6e.3 for ; Wed, 24 Jan 2024 22:30:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rivosinc-com.20230601.gappssmtp.com; s=20230601; t=1706164222; x=1706769022; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Rd0guRwVXbpygS5QcHTElt8jUaWNDA8n6eGW6ag7sBw=; b=ObS6LeGj04kh78N7icUMVwuljQJjzK9GGT97Rm21CZsSIYJLSkuadJjdDL/LtxmT8L orzQEEJW9O6/BIzWNcz5ZZoDXZXkkW5eQIimCS4ItduSNrCRUB4V1a4q8h7YYOAtREGB FX864QnX9TKC6S6C5OAErK3cl247P4Q9EOMr1MG6NPrnxmlVXekUN1d2IHYSJsT3QTr9 yGO9kU5eb8lB5eoblOOzoSAGmm66lOHr8ZkhUBPbdrKOLXr4pYLT2KP6AIyoNtxsPq09 TSkCDlSc+kyoI50OlBNllS4GRX7s9BHX8V2GaPspzRaMr9Cw4J1/wRuXQWQnT/t6Eb/t dkKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706164222; x=1706769022; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Rd0guRwVXbpygS5QcHTElt8jUaWNDA8n6eGW6ag7sBw=; b=iqIv62OVnabD4uHaDiPzTWzwiNCbF06qxaZ6h/DnQ226vErXL/B8hm1hSPrrtd1o5x EmtzoYF+Bn7SwjubSzpig1enbnZ0qY15qpNkAWkelQHHg6vHMP9BHFhpeVripKwKEShu yaXOy4zPVS/EyyWPRAArpXs8tntzDqYLTx6kuMV3iiPk5rFNzRBacrOdTcdOlddtLo6I D26BjD9Qzqy8yrvh/XCXSXxTG12aoqLbKu4ezmqNjuzS4F8Zq7yymxuJ8y2RnJIV1adq rV9MUCW80+1hls3HeEVlo3uUQd9fGgp3bnACQsRaLKTEWkfVzk6ZQDXSyLGnlRT8aj86 VlIQ== X-Gm-Message-State: AOJu0Yw3Sjte0DZzqj38OrkwAv96ArGUsfC3nJ9cQqYhvqXvH3IPqTuJ ruWbvADEH570U3CiIipxWZEJ9qEEWh4jSWXq67q9HQ+VHcVtBcIbj4ksQS66Kwc= X-Received: by 2002:a05:6808:319b:b0:3bd:c4e3:455e with SMTP id cd27-20020a056808319b00b003bdc4e3455emr586022oib.61.1706164221729; Wed, 24 Jan 2024 22:30:21 -0800 (PST) Received: from debug.ba.rivosinc.com ([64.71.180.162]) by smtp.gmail.com with ESMTPSA id t19-20020a056a00139300b006dd870b51b8sm3201139pfg.126.2024.01.24.22.30.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 24 Jan 2024 22:30:21 -0800 (PST) From: debug@rivosinc.com To: rick.p.edgecombe@intel.com, broonie@kernel.org, Szabolcs.Nagy@arm.com, kito.cheng@sifive.com, keescook@chromium.org, ajones@ventanamicro.com, paul.walmsley@sifive.com, palmer@dabbelt.com, conor.dooley@microchip.com, cleger@rivosinc.com, atishp@atishpatra.org, alex@ghiti.fr, bjorn@rivosinc.com, alexghiti@rivosinc.com Cc: corbet@lwn.net, aou@eecs.berkeley.edu, oleg@redhat.com, akpm@linux-foundation.org, arnd@arndb.de, ebiederm@xmission.com, shuah@kernel.org, brauner@kernel.org, debug@rivosinc.com, guoren@kernel.org, samitolvanen@google.com, evan@rivosinc.com, xiao.w.wang@intel.com, apatel@ventanamicro.com, mchitale@ventanamicro.com, waylingii@gmail.com, greentime.hu@sifive.com, heiko@sntech.de, jszhang@kernel.org, shikemeng@huaweicloud.com, david@redhat.com, charlie@rivosinc.com, panqinglin2020@iscas.ac.cn, willy@infradead.org, vincent.chen@sifive.com, andy.chiu@sifive.com, gerg@kernel.org, jeeheng.sia@starfivetech.com, mason.huo@starfivetech.com, ancientmodern4@gmail.com, mathis.salmen@matsal.de, cuiyunhui@bytedance.com, bhe@redhat.com, chenjiahao16@huawei.com, ruscur@russell.cc, bgray@linux.ibm.com, alx@kernel.org, baruch@tkos.co.il, zhangqing@loongson.cn, catalin.marinas@arm.com, revest@chromium.org, josh@joshtriplett.org, joey.gouly@arm.com, shr@devkernel.io, omosnace@redhat.com, ojeda@kernel.org, jhubbard@nvidia.com, linux-doc@vger.kernel.org, linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-arch@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [RFC PATCH v1 23/28] riscv signal: Save and restore of shadow stack for signal Date: Wed, 24 Jan 2024 22:21:48 -0800 Message-ID: <20240125062739.1339782-24-debug@rivosinc.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240125062739.1339782-1-debug@rivosinc.com> References: <20240125062739.1339782-1-debug@rivosinc.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Deepak Gupta Save shadow stack pointer in sigcontext structure while delivering signal. Restore shadow stack pointer from sigcontext on sigreturn. Signed-off-by: Deepak Gupta --- arch/riscv/include/asm/usercfi.h | 18 ++++++++++++ arch/riscv/kernel/signal.c | 45 ++++++++++++++++++++++++++++++ arch/riscv/kernel/usercfi.c | 47 ++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+) diff --git a/arch/riscv/include/asm/usercfi.h b/arch/riscv/include/asm/usercfi.h index 4bd10dcd48aa..28c67866ff6f 100644 --- a/arch/riscv/include/asm/usercfi.h +++ b/arch/riscv/include/asm/usercfi.h @@ -33,6 +33,9 @@ bool is_shstk_enabled(struct task_struct *task); bool is_shstk_locked(struct task_struct *task); bool is_indir_lp_enabled(struct task_struct *task); bool is_indir_lp_locked(struct task_struct *task); +unsigned long get_active_shstk(struct task_struct *task); +int restore_user_shstk(struct task_struct *tsk, unsigned long shstk_ptr); +int save_user_shstk(struct task_struct *tsk, unsigned long *saved_shstk_ptr); #define PR_SHADOW_STACK_SUPPORTED_STATUS_MASK (PR_SHADOW_STACK_ENABLE) @@ -70,6 +73,16 @@ static inline bool is_shstk_locked(struct task_struct *task) return false; } +int restore_user_shstk(struct task_struct *tsk, unsigned long shstk_ptr) +{ + return -EINVAL; +} + +int save_user_shstk(struct task_struct *tsk, unsigned long *saved_shstk_ptr) +{ + return -EINVAL; +} + static inline bool is_indir_lp_enabled(struct task_struct *task) { return false; @@ -81,6 +94,11 @@ static inline bool is_indir_lp_locked(struct task_struct *task) return false; } +static inline unsigned long get_active_shstk(struct task_struct *task) +{ + return 0; +} + #endif /* CONFIG_RISCV_USER_CFI */ #endif /* __ASSEMBLY__ */ diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c index 88b6220b2608..d1092f0a6363 100644 --- a/arch/riscv/kernel/signal.c +++ b/arch/riscv/kernel/signal.c @@ -22,6 +22,7 @@ #include #include #include +#include unsigned long signal_minsigstksz __ro_after_init; @@ -229,6 +230,7 @@ SYSCALL_DEFINE0(rt_sigreturn) struct pt_regs *regs = current_pt_regs(); struct rt_sigframe __user *frame; struct task_struct *task; + unsigned long ss_ptr = 0; sigset_t set; size_t frame_size = get_rt_frame_size(false); @@ -251,6 +253,26 @@ SYSCALL_DEFINE0(rt_sigreturn) if (restore_altstack(&frame->uc.uc_stack)) goto badframe; + /* + * Restore shadow stack as a form of token stored on shadow stack itself as a safe + * way to restore. + * A token on shadow gives following properties + * - Safe save and restore for shadow stack switching. Any save of shadow stack + * must have had saved a token on shadow stack. Similarly any restore of shadow + * stack must check the token before restore. Since writing to shadow stack with + * address of shadow stack itself is not easily allowed. A restore without a save + * is quite difficult for an attacker to perform. + * - A natural break. A token in shadow stack provides a natural break in shadow stack + * So a single linear range can be bucketed into different shadow stack segments. + * sspopchk will detect the condition and fault to kernel as sw check exception. + */ + if (__copy_from_user(&ss_ptr, &frame->uc.uc_mcontext.sc_cfi_state.ss_ptr, + sizeof(unsigned long))) + goto badframe; + + if (is_shstk_enabled(current) && restore_user_shstk(current, ss_ptr)) + goto badframe; + regs->cause = -1UL; return regs->a0; @@ -320,6 +342,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct rt_sigframe __user *frame; long err = 0; unsigned long __maybe_unused addr; + unsigned long ss_ptr = 0; size_t frame_size = get_rt_frame_size(false); frame = get_sigframe(ksig, regs, frame_size); @@ -331,6 +354,23 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(NULL, &frame->uc.uc_link); + /* + * Save a pointer to shadow stack itself on shadow stack as a form of token. + * A token on shadow gives following properties + * - Safe save and restore for shadow stack switching. Any save of shadow stack + * must have had saved a token on shadow stack. Similarly any restore of shadow + * stack must check the token before restore. Since writing to shadow stack with + * address of shadow stack itself is not easily allowed. A restore without a save + * is quite difficult for an attacker to perform. + * - A natural break. A token in shadow stack provides a natural break in shadow stack + * So a single linear range can be bucketed into different shadow stack segments. Any + * sspopchk will detect the condition and fault to kernel as sw check exception. + */ + if (is_shstk_enabled(current)) { + err |= save_user_shstk(current, &ss_ptr); + err |= __put_user(ss_ptr, &frame->uc.uc_mcontext.sc_cfi_state.ss_ptr); + } + err |= __save_altstack(&frame->uc.uc_stack, regs->sp); err |= setup_sigcontext(frame, regs); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); @@ -341,6 +381,11 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, #ifdef CONFIG_MMU regs->ra = (unsigned long)VDSO_SYMBOL( current->mm->context.vdso, rt_sigreturn); + + /* if bcfi is enabled x1 (ra) and x5 (t0) must match. not sure if we need this? */ + if (is_shstk_enabled(current)) + regs->t0 = regs->ra; + #else /* * For the nommu case we don't have a VDSO. Instead we push two diff --git a/arch/riscv/kernel/usercfi.c b/arch/riscv/kernel/usercfi.c index af8cc8f4616c..f5eb0124571b 100644 --- a/arch/riscv/kernel/usercfi.c +++ b/arch/riscv/kernel/usercfi.c @@ -52,6 +52,11 @@ void set_active_shstk(struct task_struct *task, unsigned long shstk_addr) task->thread_info.user_cfi_state.user_shdw_stk = shstk_addr; } +unsigned long get_active_shstk(struct task_struct *task) +{ + return task->thread_info.user_cfi_state.user_shdw_stk; +} + void set_shstk_status(struct task_struct *task, bool enable) { task->thread_info.user_cfi_state.ubcfi_en = enable ? 1 : 0; @@ -165,6 +170,48 @@ static int create_rstor_token(unsigned long ssp, unsigned long *token_addr) return 0; } +/* + * Save user shadow stack pointer on shadow stack itself and return pointer to saved location + * returns -EFAULT if operation was unsuccessful + */ +int save_user_shstk(struct task_struct *tsk, unsigned long *saved_shstk_ptr) +{ + unsigned long ss_ptr = 0; + unsigned long token_loc = 0; + int ret = 0; + + if (saved_shstk_ptr == NULL) + return -EINVAL; + + ss_ptr = get_active_shstk(tsk); + ret = create_rstor_token(ss_ptr, &token_loc); + + *saved_shstk_ptr = token_loc; + return ret; +} + +/* + * Restores user shadow stack pointer from token on shadow stack for task `tsk` + * returns -EFAULT if operation was unsuccessful + */ +int restore_user_shstk(struct task_struct *tsk, unsigned long shstk_ptr) +{ + unsigned long token = 0; + + token = amo_user_shstk((unsigned long __user *)shstk_ptr, 0); + + if (token == -1) + return -EFAULT; + + /* invalid token, return EINVAL */ + if ((token - shstk_ptr) != SHSTK_ENTRY_SIZE) + return -EINVAL; + + /* all checks passed, set active shstk and return success */ + set_active_shstk(tsk, token); + return 0; +} + static unsigned long allocate_shadow_stack(unsigned long addr, unsigned long size, unsigned long token_offset, bool set_tok) -- 2.43.0