From patchwork Thu Feb 22 13:12:26 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Petr Tesarik X-Patchwork-Id: 13567317 Received: from frasgout12.his.huawei.com (frasgout12.his.huawei.com [14.137.139.154]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6935E3C480; Thu, 22 Feb 2024 13:13:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=14.137.139.154 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708607632; cv=none; b=sthz6P0oPMb3Ox8TxSCGVwknBC9dvwAgDqwD8X2BPLH0mnx03DOm3aa/WPyRVxcQ57Obx7yCKQHPGM5mJHa/DQhD/4qmwCWUVupms29e3I/u/Z2NcBubCz3bual6EGiToFZoy1yzUaA51UPhw94NBlDyGkW2h3h73yx62FQhoC0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708607632; c=relaxed/simple; bh=Uy376ED34WIMkkv3zbgADLtj7CtDO3E0JZj2bvWXW3w=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=isPsE3PZ2w97Ar1NegwL5khFBLFj0jgvE2M02ALhvGDa0qKvy4Al5qjHQtHVjjYPZ0z1Afwm3MyLqoUBLhwCbBGhe2WDmIVbhed2nGVX3Bcj9E2QrWPB44TSwaAxz3n9p8+och7uWP/kAaMYbOIDTcj0fugGXdIqzEmL4ZAN1R0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=14.137.139.154 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.18.186.29]) by frasgout12.his.huawei.com (SkyGuard) with ESMTP id 4TgY4Y3wljz9xww9; Thu, 22 Feb 2024 20:54:21 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.47]) by mail.maildlp.com (Postfix) with ESMTP id 95B41140ED3; Thu, 22 Feb 2024 21:13:32 +0800 (CST) Received: from huaweicloud.com (unknown [10.45.157.235]) by APP1 (Coremail) with SMTP id LxC2BwDXzhdSSNdlhi4AAw--.34998S3; Thu, 22 Feb 2024 14:13:31 +0100 (CET) From: Petr Tesarik To: Dave Hansen Cc: =?utf-8?b?UGV0ciBUZXNhxZnDrWs=?= , Petr Tesarik , Jonathan Corbet , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT)" , "H. Peter Anvin" , Andy Lutomirski , Oleg Nesterov , Peter Zijlstra , Xin Li , Arnd Bergmann , Andrew Morton , Rick Edgecombe , Kees Cook , "Masami Hiramatsu (Google)" , Pengfei Xu , Josh Poimboeuf , Ze Gao , "Kirill A. Shutemov" , Kai Huang , David Woodhouse , Brian Gerst , Jason Gunthorpe , Joerg Roedel , "Mike Rapoport (IBM)" , Tina Zhang , Jacob Pan , "open list:DOCUMENTATION" , open list , Roberto Sassu , John Johansen , Paul Moore , James Morris , "Serge E. Hallyn" , apparmor@lists.ubuntu.com, linux-security-module@vger.kernel.org, Petr Tesarik Subject: [RFC 1/5] sbm: x86: fix SBM error entry path Date: Thu, 22 Feb 2024 14:12:26 +0100 Message-Id: <20240222131230.635-2-petrtesarik@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240222131230.635-1-petrtesarik@huaweicloud.com> References: <20240222131230.635-1-petrtesarik@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: LxC2BwDXzhdSSNdlhi4AAw--.34998S3 X-Coremail-Antispam: 1UD129KBjvJXoW7Kw1DWF1rJw4kJFW3Kr45ZFb_yoW8Gry5pF nrC3Z7JF40vrySyw1fG3W8ZFZ8ua90gF45CFn7Kw1ft3W5t34UGr10k397W34furykGa4r XF1YvF1jy3WUAaDanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPF14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_Jr4l82xGYIkIc2 x26xkF7I0E14v26ryj6s0DM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48ve4kI8wA2z4x0 Y4vE2Ix0cI8IcVAFwI0_Jr0_JF4l84ACjcxK6xIIjxv20xvEc7CjxVAFwI0_Cr0_Gr1UM2 8EF7xvwVC2z280aVAFwI0_Gr0_Cr1l84ACjcxK6I8E87Iv6xkF7I0E14v26r4UJVWxJr1l e2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2WlYx0E2Ix0cI 8IcVAFwI0_Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE7xkEbVWUJVW8JwAC jcxG0xvY0x0EwIxGrwACjI8F5VA0II8E6IAqYI8I648v4I1lFIxGxcIEc7CjxVA2Y2ka0x kIwI1l42xK82IYc2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AK xVWUJVWUGwC20s026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26rWY6r4UJwCIc4 0Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcVCY1x0267AK xVWxJVW8Jr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r1j6r 4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr1j6F4UJbIYCTnIWIevJa73UjIFyTuYvjfUOR6z UUUUU X-CM-SenderInfo: hshw23xhvd2x3n6k3tpzhluzxrxghudrp/ From: Petr Tesarik Normal interrupt entry from SBM should be generally treated as entry from kernel mode (no swapgs, no speculation mitigations), but since there is a CPL change, the interrupt handler runs on the trampoline stack, which may get reused if the current task is re-scheduled. Make sure to switch to the SBM exception stack. Signed-off-by: Petr Tesarik --- arch/x86/entry/entry_64.S | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index 4ba3eea38102..96830591302d 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -1062,14 +1062,20 @@ SYM_CODE_START(error_entry) /* * If sandbox mode was active, adjust the saved CS, * unconditionally switch to kernel CR3 and continue - * as if the interrupt was from kernel space. + * as if the interrupt was from kernel space, but + * switch away from the trampoline stack. */ movq x86_sbm_state + SBM_kernel_cr3, %rcx jrcxz .Lerror_swapgs andb $~3, CS+8(%rsp) movq %rcx, %cr3 - jmp .Lerror_entry_done_lfence + + FENCE_SWAPGS_KERNEL_ENTRY + CALL_DEPTH_ACCOUNT + leaq 8(%rsp), %rdi + /* Put us onto the SBM exception stack. */ + jmp sync_regs #endif .Lerror_swapgs: From patchwork Thu Feb 22 13:12:27 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Petr Tesarik X-Patchwork-Id: 13567318 Received: from frasgout11.his.huawei.com (frasgout11.his.huawei.com [14.137.139.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 20E553C480; Thu, 22 Feb 2024 13:13:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=14.137.139.23 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708607641; cv=none; b=lh55VVvwUb3+9peZRVmcVHWSf87yPpLZDk7Q8c8SiStUfzFRyMEedY9+QTDTsfVSWmA8LXT2s6PmBg0hfcbS6l5ZeuSD+g6p6ZhlJ1LH0zMW/G1RV1jo/zHG2Guii4MM7VTClJlmzPmhvfitUHhMER6oJIoqHWmz0dk3NxwNMW0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708607641; c=relaxed/simple; bh=F3iXk0RojxwMAJ5ReWNZ/Q0B9a6KDQu7r5NS89bSCQE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=cSDsRgobtEi4jj/IGVXVZTeRC+5JX+t51UEGKrZMeDAgIxcWQ+mt2cv4DIULAkqrKTD1y/v4205PwAI1WZyUdiKMnYxctzINk0e012qpM3E8tTqyvkJy72550wCk5omI6TFKgSl2s516wpWB9Pzscle+P4ndMJNqsJA5WtQKdSY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=14.137.139.23 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.18.186.29]) by frasgout11.his.huawei.com (SkyGuard) with ESMTP id 4TgY9L11pGz9xyNm; Thu, 22 Feb 2024 20:58:30 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.47]) by mail.maildlp.com (Postfix) with ESMTP id 17122140EF1; Thu, 22 Feb 2024 21:13:51 +0800 (CST) Received: from huaweicloud.com (unknown [10.45.157.235]) by APP1 (Coremail) with SMTP id LxC2BwDXzhdSSNdlhi4AAw--.34998S4; Thu, 22 Feb 2024 14:13:50 +0100 (CET) From: Petr Tesarik To: Dave Hansen Cc: =?utf-8?b?UGV0ciBUZXNhxZnDrWs=?= , Petr Tesarik , Jonathan Corbet , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT)" , "H. Peter Anvin" , Andy Lutomirski , Oleg Nesterov , Peter Zijlstra , Xin Li , Arnd Bergmann , Andrew Morton , Rick Edgecombe , Kees Cook , "Masami Hiramatsu (Google)" , Pengfei Xu , Josh Poimboeuf , Ze Gao , "Kirill A. Shutemov" , Kai Huang , David Woodhouse , Brian Gerst , Jason Gunthorpe , Joerg Roedel , "Mike Rapoport (IBM)" , Tina Zhang , Jacob Pan , "open list:DOCUMENTATION" , open list , Roberto Sassu , John Johansen , Paul Moore , James Morris , "Serge E. Hallyn" , apparmor@lists.ubuntu.com, linux-security-module@vger.kernel.org, Petr Tesarik Subject: [RFC 2/5] sbm: enhance buffer mapping API Date: Thu, 22 Feb 2024 14:12:27 +0100 Message-Id: <20240222131230.635-3-petrtesarik@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240222131230.635-1-petrtesarik@huaweicloud.com> References: <20240222131230.635-1-petrtesarik@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: LxC2BwDXzhdSSNdlhi4AAw--.34998S4 X-Coremail-Antispam: 1UD129KBjvJXoWxWFWfAFW5GrW5AFW3AFy7ZFb_yoWrCw4fpF n8JFs8GF45AF17Jr43Gw10vw1rJan7XF1UK39xC3s0y3Z8try7urn5GFy3JFsxAr9rGFWF yrs5KFZ5Cw4xJ3DanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPI14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_Jryl82xGYIkIc2 x26xkF7I0E14v26ryj6s0DM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48ve4kI8wA2z4x0 Y4vE2Ix0cI8IcVAFwI0_Jr0_JF4l84ACjcxK6xIIjxv20xvEc7CjxVAFwI0_Gr1j6F4UJw A2z4x0Y4vEx4A2jsIE14v26r4j6F4UM28EF7xvwVC2z280aVCY1x0267AKxVW8Jr0_Cr1U M2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjx v20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_Jr0_Gr1l F7xvr2IYc2Ij64vIr41lF7I21c0EjII2zVCS5cI20VAGYxC7M4IIrI8v6xkF7I0E8cxan2 IY04v7MxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E5I8CrVAF wI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWrXVW8Jr1lIx kGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUJVWUCwCI42IY6xIIjxv20xvEc7CjxVAF wI0_Gr1j6F4UJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Jr 0_Gr1lIxAIcVC2z280aVCY1x0267AKxVW8Jr0_Cr1UYxBIdaVFxhVjvjDU0xZFpf9x0JUH byAUUUUU= X-CM-SenderInfo: hshw23xhvd2x3n6k3tpzhluzxrxghudrp/ From: Petr Tesarik Add SBM_MAP_READONLY() and SBM_MAP_WRITABLE() to the public API to allow mapping kernel buffers directly into the sandbox with no copying. Signed-off-by: Petr Tesarik --- include/linux/sbm.h | 71 +++++++++++++++++++++++++++++++++++++++++++++ kernel/sbm.c | 34 ++++++++++++++++++++++ 2 files changed, 105 insertions(+) diff --git a/include/linux/sbm.h b/include/linux/sbm.h index 98fd27cd58d0..dbdc0781349f 100644 --- a/include/linux/sbm.h +++ b/include/linux/sbm.h @@ -181,6 +181,31 @@ static inline void *sbm_add_buf(struct sbm *sbm, struct sbm_buf **list, #define SBM_COPY_INOUT(sbm, buf, size) \ ((typeof(({buf; })))sbm_add_buf((sbm), &(sbm)->io, (buf), (size))) +/** + * sbm_map_readonly() - Map memory for reading. + * @sbm: SBM instance. + * @ptr: Starting virtual address. + * @size: Size in bytes. + * + * Make the specified virtual address range readable in sandbox code. + * + * Return: Address of the buffer, or %NULL on error. + */ +void *sbm_map_readonly(struct sbm *sbm, const void *ptr, size_t size); + +/** + * sbm_map_writable() - Map memory for reading and writing. + * @sbm: SBM instance. + * @ptr: Starting virtual address. + * @size: Size in bytes. + * + * Make the specified virtual address range readable and writable in sandbox + * code. + * + * Return: Address of the buffer, or %NULL on error. + */ +void *sbm_map_writable(struct sbm *sbm, const void *ptr, size_t size); + #ifdef CONFIG_HAVE_ARCH_SBM /** @@ -303,8 +328,54 @@ static inline int sbm_exec(struct sbm *sbm, sbm_func func, void *data) #define SBM_COPY_OUT(sbm, buf, size) __SBM_EVAL(buf) #define SBM_COPY_INOUT(sbm, buf, size) __SBM_EVAL(buf) +static inline void *sbm_map_readonly(struct sbm *sbm, const void *ptr, + size_t size) +{ + return (void *)ptr; +} + +static inline void *sbm_map_writable(struct sbm *sbm, const void *ptr, + size_t size) +{ + return (void *)ptr; +} + #endif /* CONFIG_SANDBOX_MODE */ +/** + * SBM_MAP_READONLY() - Map an input buffer into SBM. + * @sbm: SBM instance. + * @buf: Buffer virtual address. + * @size: Size of the buffer. + * + * Make a read-only mapping of buffer in sandbox mode. + * + * This works with page granularity. If the buffer is not page-aligned, + * some data before and/or after the page is also mappeed into the sandbox. + * The mapping does not ensure guard pages either. + * + * Return: Buffer address in sandbox mode (same as kernel mode). + */ +#define SBM_MAP_READONLY(sbm, buf, size) \ + ((typeof(({buf; })))sbm_map_readonly((sbm), (buf), (size))) + +/** + * SBM_MAP_WRITABLE() - Map an input/output buffer into SBM. + * @sbm: SBM instance. + * @buf: Buffer virtual address. + * @size: Size of the buffer. + * + * Make a writable mapping of buffer in sandbox mode. + * + * This works with page granularity. If the buffer is not page-aligned, + * some data before and/or after the page is also mappeed into the sandbox. + * The mapping does not ensure guard pages either. + * + * Return: Buffer address in sandbox mode (same as kernel mode). + */ +#define SBM_MAP_WRITABLE(sbm, buf, size) \ + ((typeof(({buf; })))sbm_map_writable((sbm), (buf), (size))) + /** * __SBM_MAP() - Convert parameters to comma-separated expressions. * @m: Macro used to convert each pair. diff --git a/kernel/sbm.c b/kernel/sbm.c index df57184f5d87..c832808b538e 100644 --- a/kernel/sbm.c +++ b/kernel/sbm.c @@ -71,6 +71,40 @@ void sbm_destroy(struct sbm *sbm) } EXPORT_SYMBOL(sbm_destroy); +void *sbm_map_readonly(struct sbm *sbm, const void *ptr, size_t size) +{ + struct sbm_buf buf; + + if (sbm->error) + return NULL; + + buf.sbm_ptr = (void *)ptr; + buf.size = size; + sbm->error = arch_sbm_map_readonly(sbm, &buf); + if (sbm->error) + return NULL; + + return buf.sbm_ptr; +} +EXPORT_SYMBOL(sbm_map_readonly); + +void *sbm_map_writable(struct sbm *sbm, const void *ptr, size_t size) +{ + struct sbm_buf buf; + + if (sbm->error) + return NULL; + + buf.sbm_ptr = (void *)ptr; + buf.size = size; + sbm->error = arch_sbm_map_writable(sbm, &buf); + if (sbm->error) + return NULL; + + return buf.sbm_ptr; +} +EXPORT_SYMBOL(sbm_map_writable); + /* Copy input buffers into a sandbox. */ static int sbm_copy_in(struct sbm *sbm) { From patchwork Thu Feb 22 13:12:28 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Petr Tesarik X-Patchwork-Id: 13567319 Received: from frasgout11.his.huawei.com (frasgout11.his.huawei.com [14.137.139.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9A51012EBC0; Thu, 22 Feb 2024 13:14:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=14.137.139.23 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708607661; cv=none; b=Gb4eCSXNTpuiHadIbzBNftclSRgMCn5i2Y9B/DD9K5ihldMYY+y8e3EkEXkmVGqUGHsHX4pQtaIhyaqgNuWP+vHN8n8pYx+q/Pxf7GhVymhwnzp6bMYhlNRwzCsZPwe3u1hEHvXTC5+z/EK4GBcm5D+lCylUUO35rbSRQrH04WY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708607661; c=relaxed/simple; bh=l1LXd2PtDa/poAjn4NuvIvrOvIKcsTgZXd2qiIvDP6E=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=HKvw7lB1mPOSQOVDqQ/KkiZ8LFpUifqEeFWXJZKifdMCwE4yQpIJj8ELZ2+nEpinFmLzAhYQa2ndSzL8u6q7bQl/T7Ee/odaFjYJQH4pjv0ocpqqILbI6M8ti811dnIuh2AFgi9NpkBI9O+Ffd5GO4BYXsg55UAVTPKu+3Gax2E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=14.137.139.23 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.18.186.29]) by frasgout11.his.huawei.com (SkyGuard) with ESMTP id 4TgY9k4qxhz9xyNZ; Thu, 22 Feb 2024 20:58:50 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.47]) by mail.maildlp.com (Postfix) with ESMTP id 8C031140EF1; Thu, 22 Feb 2024 21:14:09 +0800 (CST) Received: from huaweicloud.com (unknown [10.45.157.235]) by APP1 (Coremail) with SMTP id LxC2BwDXzhdSSNdlhi4AAw--.34998S5; Thu, 22 Feb 2024 14:14:08 +0100 (CET) From: Petr Tesarik To: Dave Hansen Cc: =?utf-8?b?UGV0ciBUZXNhxZnDrWs=?= , Petr Tesarik , Jonathan Corbet , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT)" , "H. Peter Anvin" , Andy Lutomirski , Oleg Nesterov , Peter Zijlstra , Xin Li , Arnd Bergmann , Andrew Morton , Rick Edgecombe , Kees Cook , "Masami Hiramatsu (Google)" , Pengfei Xu , Josh Poimboeuf , Ze Gao , "Kirill A. Shutemov" , Kai Huang , David Woodhouse , Brian Gerst , Jason Gunthorpe , Joerg Roedel , "Mike Rapoport (IBM)" , Tina Zhang , Jacob Pan , "open list:DOCUMENTATION" , open list , Roberto Sassu , John Johansen , Paul Moore , James Morris , "Serge E. Hallyn" , apparmor@lists.ubuntu.com, linux-security-module@vger.kernel.org, Petr Tesarik Subject: [RFC 3/5] sbm: x86: infrastructure to fix up sandbox faults Date: Thu, 22 Feb 2024 14:12:28 +0100 Message-Id: <20240222131230.635-4-petrtesarik@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240222131230.635-1-petrtesarik@huaweicloud.com> References: <20240222131230.635-1-petrtesarik@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: LxC2BwDXzhdSSNdlhi4AAw--.34998S5 X-Coremail-Antispam: 1UD129KBjvJXoW3Xw45Cr15Gry8Xr43Kr18Grg_yoW7uw4DpF srA3WDGF4jyFy7Ar9xJrs5Zr90yw18Kw1Fkr9rG34fZ3WUtw1fXr1vv3Zrtr1rA348KF4a yF4fZFy5uw15J37anT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPI14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_JrWl82xGYIkIc2 x26xkF7I0E14v26ryj6s0DM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48ve4kI8wA2z4x0 Y4vE2Ix0cI8IcVAFwI0_Jr0_JF4l84ACjcxK6xIIjxv20xvEc7CjxVAFwI0_Gr1j6F4UJw A2z4x0Y4vEx4A2jsIE14v26r4j6F4UM28EF7xvwVC2z280aVCY1x0267AKxVW8Jr0_Cr1U M2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjx v20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_Jr0_Gr1l F7xvr2IYc2Ij64vIr41lF7I21c0EjII2zVCS5cI20VAGYxC7M4IIrI8v6xkF7I0E8cxan2 IY04v7MxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E5I8CrVAF wI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWrXVW8Jr1lIx kGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUJVWUCwCI42IY6xIIjxv20xvEc7CjxVAF wI0_Gr1j6F4UJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Jr 0_Gr1lIxAIcVC2z280aVCY1x0267AKxVW8Jr0_Cr1UYxBIdaVFxhVjvjDU0xZFpf9x0JUd 8n5UUUUU= X-CM-SenderInfo: hshw23xhvd2x3n6k3tpzhluzxrxghudrp/ From: Petr Tesarik Since sandbox mode cannot modify kernel data, much of the core API cannot be used directly. Provide a method to call a known subset of kernel functions from the sandbox fault handler on behalf of the sandbox code. Since SBM permissions have page granularity, the code of an intercepted function must not be in the same page as another function running in sandbox mode. Provide a __nosbm marker to move the intercepted functions into a special ELF section, align it to page boundaries and map it so that it is not executable in sandbox mode. To minimize alignment padding, merge the __nosbm section with the kernel entry code. Signed-off-by: Petr Tesarik --- arch/x86/kernel/sbm/call_64.S | 20 +++++++++++ arch/x86/kernel/sbm/core.c | 65 +++++++++++++++++++++++++++++++++-- arch/x86/kernel/vmlinux.lds.S | 9 +++++ include/linux/sbm.h | 6 ++++ 4 files changed, 98 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/sbm/call_64.S b/arch/x86/kernel/sbm/call_64.S index 21edce5666bc..6d8ae30a0984 100644 --- a/arch/x86/kernel/sbm/call_64.S +++ b/arch/x86/kernel/sbm/call_64.S @@ -93,3 +93,23 @@ SYM_INNER_LABEL(x86_sbm_return, SYM_L_GLOBAL) pop %rbp RET SYM_FUNC_END(x86_sbm_exec) + +.text + +/* + * arguments: + * rdi .. state (ignored) + * rsi .. target function + * rdx .. struct pt_regs +*/ +SYM_FUNC_START(x86_sbm_proxy_call) + mov %rdx, %r10 + mov %rsi, %r11 + mov pt_regs_di(%r10), %rdi + mov pt_regs_si(%r10), %rsi + mov pt_regs_dx(%r10), %rdx + mov pt_regs_cx(%r10), %rcx + mov pt_regs_r8(%r10), %r8 + mov pt_regs_r9(%r10), %r9 + JMP_NOSPEC r11 +SYM_FUNC_END(x86_sbm_proxy_call) diff --git a/arch/x86/kernel/sbm/core.c b/arch/x86/kernel/sbm/core.c index 296f1fde3c22..c8ac7ecb08cc 100644 --- a/arch/x86/kernel/sbm/core.c +++ b/arch/x86/kernel/sbm/core.c @@ -28,6 +28,60 @@ asmlinkage int x86_sbm_exec(struct x86_sbm_state *state, sbm_func func, unsigned long exc_tos); extern char x86_sbm_return[]; +extern char __nosbm_text_start[], __nosbm_text_end[]; + +/************************************************************* + * HACK: PROOF-OF-CONCEPT FIXUP CODE STARTS HERE + */ + +typedef unsigned long (*sbm_proxy_call_fn)(struct x86_sbm_state *, + unsigned long func, + struct pt_regs *); + +asmlinkage unsigned long x86_sbm_proxy_call(struct x86_sbm_state *state, + unsigned long func, + struct pt_regs *regs); + +/** + * struct sbm_fixup - Describe a sandbox fault fixup. + * @target: Target function to be called. + * @proxy: Proxy call function. + */ +struct sbm_fixup { + void *target; + sbm_proxy_call_fn proxy; +}; + +static const struct sbm_fixup fixups[] = +{ + { } +}; + +/* Fix up a page fault if it is one of the known exceptions. */ +static bool fixup_sbm_call(struct x86_sbm_state *state, + struct pt_regs *regs, unsigned long address) +{ + const struct sbm_fixup *fixup; + + for (fixup = fixups; fixup->target; ++fixup) { + if (address == (unsigned long)fixup->target) { + regs->ax = fixup->proxy(state, address, regs); + return true; + } + } + + return false; +} + +/* Execution in sandbox mode continues here after fixup. */ +static void x86_sbm_continue(void) +{ +} + +/* + * HACK: PROOF-OF-CONCEPT FIXUP CODE ENDS HERE + *************************************************************/ + union { struct x86_sbm_state state; char page[PAGE_SIZE]; @@ -140,8 +194,8 @@ static int map_kernel(struct x86_sbm_state *state) if (err) return err; - err = map_range(state, (unsigned long)__entry_text_start, - (unsigned long)__entry_text_end, PAGE_KERNEL_ROX); + err = map_range(state, (unsigned long)__nosbm_text_start, + (unsigned long)__nosbm_text_end, PAGE_KERNEL_ROX); if (err) return err; @@ -482,6 +536,13 @@ void handle_sbm_fault(struct pt_regs *regs, unsigned long error_code, if (spurious_sbm_fault(state, error_code, address)) return; + if ((error_code & ~X86_PF_PROT) == (X86_PF_USER | X86_PF_INSTR) && + fixup_sbm_call(state, regs, address)) { + /* Return back to sandbox... */ + regs->ip = (unsigned long)x86_sbm_continue; + return; + } + /* * Force -EFAULT unless the fault was due to a user-mode instruction * fetch from the designated return address. diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index a349dbfc6d5a..c530a7faaa9a 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -139,8 +139,17 @@ SECTIONS STATIC_CALL_TEXT ALIGN_ENTRY_TEXT_BEGIN +#ifdef CONFIG_SANDBOX_MODE + . = ALIGN(PAGE_SIZE); + __nosbm_text_start = .; +#endif *(.text..__x86.rethunk_untrain) ENTRY_TEXT +#ifdef CONFIG_SANDBOX_MODE + *(.text.nosbm) + . = ALIGN(PAGE_SIZE); + __nosbm_text_end = .; +#endif #ifdef CONFIG_CPU_SRSO /* diff --git a/include/linux/sbm.h b/include/linux/sbm.h index dbdc0781349f..9d7eb525e489 100644 --- a/include/linux/sbm.h +++ b/include/linux/sbm.h @@ -267,6 +267,8 @@ int arch_sbm_map_writable(struct sbm *sbm, const struct sbm_buf *buf); */ int arch_sbm_exec(struct sbm *sbm, sbm_func func, void *data); +#define __nosbm __section(".text.nosbm") + #else /* !CONFIG_HAVE_ARCH_SBM */ static inline int arch_sbm_init(struct sbm *sbm) @@ -295,6 +297,8 @@ static inline int arch_sbm_exec(struct sbm *sbm, sbm_func func, void *data) return func(data); } +#define __nosbm + #endif /* CONFIG_HAVE_ARCH_SBM */ #else /* !CONFIG_SANDBOX_MODE */ @@ -340,6 +344,8 @@ static inline void *sbm_map_writable(struct sbm *sbm, const void *ptr, return (void *)ptr; } +#define __nosbm + #endif /* CONFIG_SANDBOX_MODE */ /** From patchwork Thu Feb 22 13:12:29 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Petr Tesarik X-Patchwork-Id: 13567320 Received: from frasgout11.his.huawei.com (frasgout11.his.huawei.com [14.137.139.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BE1BE3F9ED; Thu, 22 Feb 2024 13:14:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=14.137.139.23 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708607682; cv=none; b=Jf3AeDeg7KgzYGlxq6/hBbwirUeUblucKS8jAk0LS1e3LRtUx+IWk9VZrBqa37P+1Yh1U/Y21Y6q4eNLkWyshQ0Errv/3Gl5DB09HKo/BdtVMdYKjGy8GGDiVCn9fLNbQxG4vUbeBosEQe0NFfQiM8Aitgd1UM5jhKtH5cs2Yjs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708607682; c=relaxed/simple; bh=Q/+WYKnLN3DR/LqtTKMcu0loAE6e1ujPVVq8kRwUNEc=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Y9mgG25zzOvvrKoqPxwnU9yKGbOqsOsDR3l7BCKXZvWYHxtW/C+NZvd+z2ZsxRpOzXtkyLUyc3t440wUAMN3lCU3AMNOUgAy5GD5ePsl9hKwlHkySdgN5nVh/EfeWeKGCgmj/P4F+TXy5S72y99VyfWwaRDJG7pnS89dNt1P5SQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=14.137.139.23 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.18.186.51]) by frasgout11.his.huawei.com (SkyGuard) with ESMTP id 4TgYB76pHpz9xyNs; Thu, 22 Feb 2024 20:59:11 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.47]) by mail.maildlp.com (Postfix) with ESMTP id 0B667140684; Thu, 22 Feb 2024 21:14:28 +0800 (CST) Received: from huaweicloud.com (unknown [10.45.157.235]) by APP1 (Coremail) with SMTP id LxC2BwDXzhdSSNdlhi4AAw--.34998S6; Thu, 22 Feb 2024 14:14:27 +0100 (CET) From: Petr Tesarik To: Dave Hansen Cc: =?utf-8?b?UGV0ciBUZXNhxZnDrWs=?= , Petr Tesarik , Jonathan Corbet , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT)" , "H. Peter Anvin" , Andy Lutomirski , Oleg Nesterov , Peter Zijlstra , Xin Li , Arnd Bergmann , Andrew Morton , Rick Edgecombe , Kees Cook , "Masami Hiramatsu (Google)" , Pengfei Xu , Josh Poimboeuf , Ze Gao , "Kirill A. Shutemov" , Kai Huang , David Woodhouse , Brian Gerst , Jason Gunthorpe , Joerg Roedel , "Mike Rapoport (IBM)" , Tina Zhang , Jacob Pan , "open list:DOCUMENTATION" , open list , Roberto Sassu , John Johansen , Paul Moore , James Morris , "Serge E. Hallyn" , apparmor@lists.ubuntu.com, linux-security-module@vger.kernel.org, Petr Tesarik Subject: [RFC 4/5] sbm: fix up calls to dynamic memory allocators Date: Thu, 22 Feb 2024 14:12:29 +0100 Message-Id: <20240222131230.635-5-petrtesarik@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240222131230.635-1-petrtesarik@huaweicloud.com> References: <20240222131230.635-1-petrtesarik@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: LxC2BwDXzhdSSNdlhi4AAw--.34998S6 X-Coremail-Antispam: 1UD129KBjvJXoW3Xw4rWrWfury8KFy8Gry8Xwb_yoW3tFW3pF 4xuFn8GFWrtryUCry7ArWjqryDW3WDJF40kaya9a4fZasxtF1xGr1qv34qqr48ArWkuF1Y kF9YqrZ8Aw48Aw7anT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPq14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_JF0E3s1l82xGYI kIc2x26xkF7I0E14v26ryj6s0DM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48ve4kI8wA2 z4x0Y4vE2Ix0cI8IcVAFwI0_Jr0_JF4l84ACjcxK6xIIjxv20xvEc7CjxVAFwI0_Gr1j6F 4UJwA2z4x0Y4vEx4A2jsIE14v26r4j6F4UM28EF7xvwVC2z280aVCY1x0267AKxVW8Jr0_ Cr1UM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6x IIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_Jr0_ Gr1lF7xvr2IYc2Ij64vIr41lF7I21c0EjII2zVCS5cI20VAGYxC7M4IIrI8v6xkF7I0E8c xan2IY04v7MxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E5I8C rVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWrXVW8Jr 1lIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUJVWUCwCI42IY6xIIjxv20xvEc7Cj xVAFwI0_Gr1j6F4UJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI 0_Gr0_Cr1lIxAIcVC2z280aVCY1x0267AKxVW8Jr0_Cr1UYxBIdaVFxhVjvjDU0xZFpf9x 0JUQSdkUUUUU= X-CM-SenderInfo: hshw23xhvd2x3n6k3tpzhluzxrxghudrp/ From: Petr Tesarik Add fixup functions to call kmalloc(), vmalloc() and friends on behalf of the sandbox code. Signed-off-by: Petr Tesarik --- arch/x86/kernel/sbm/core.c | 81 ++++++++++++++++++++++++++++++++++++++ mm/slab_common.c | 3 +- mm/slub.c | 17 ++++---- mm/vmalloc.c | 11 +++--- 4 files changed, 98 insertions(+), 14 deletions(-) diff --git a/arch/x86/kernel/sbm/core.c b/arch/x86/kernel/sbm/core.c index c8ac7ecb08cc..3cf3842292b9 100644 --- a/arch/x86/kernel/sbm/core.c +++ b/arch/x86/kernel/sbm/core.c @@ -20,6 +20,12 @@ #include #include +/* + * FIXME: Remove these includes when there is proper API for defining + * which functions can be called from sandbox mode. + */ +#include + #define GFP_SBM_PGTABLE (GFP_KERNEL | __GFP_ZERO) #define PGD_ORDER get_order(sizeof(pgd_t) * PTRS_PER_PGD) @@ -52,8 +58,83 @@ struct sbm_fixup { sbm_proxy_call_fn proxy; }; +static int map_range(struct x86_sbm_state *state, unsigned long start, + unsigned long end, pgprot_t prot); + +/* Map the newly allocated dynamic memory region. */ +static unsigned long post_alloc(struct x86_sbm_state *state, + unsigned long objp, size_t size) +{ + int err; + + if (!objp) + return objp; + + err = map_range(state, objp, objp + size, PAGE_SHARED); + if (err) { + kfree((void*)objp); + return 0UL; + } + return objp; +} + +/* Allocation proxy handler if size is the 1st parameter. */ +static unsigned long proxy_alloc1(struct x86_sbm_state *state, + unsigned long func, struct pt_regs *regs) +{ + unsigned long objp; + + objp = x86_sbm_proxy_call(state, func, regs); + return post_alloc(state, objp, regs->di); +} + +/* Allocation proxy handler if size is the 2nd parameter. */ +static unsigned long proxy_alloc2(struct x86_sbm_state *state, + unsigned long func, struct pt_regs *regs) +{ + unsigned long objp; + + objp = x86_sbm_proxy_call(state, func, regs); + return post_alloc(state, objp, regs->si); +} + +/* Allocation proxy handler if size is the 3rd parameter. */ +static unsigned long proxy_alloc3(struct x86_sbm_state *state, + unsigned long func, struct pt_regs *regs) +{ + unsigned long objp; + + objp = x86_sbm_proxy_call(state, func, regs); + return post_alloc(state, objp, regs->dx); +} + +/* Proxy handler to free previously allocated memory. */ +static unsigned long proxy_free(struct x86_sbm_state *state, + unsigned long func, struct pt_regs *regs) +{ + /* TODO: unmap allocated addresses from sandbox! */ + return x86_sbm_proxy_call(state, func, regs); +} + static const struct sbm_fixup fixups[] = { + /* kmalloc() and friends */ + { kmalloc_trace, proxy_alloc3 }, + { __kmalloc, proxy_alloc1 }, + { __kmalloc_node, proxy_alloc1 }, + { __kmalloc_node_track_caller, proxy_alloc1 }, + { kmalloc_large, proxy_alloc1 }, + { kmalloc_large_node, proxy_alloc1 }, + { krealloc, proxy_alloc2 }, + { kfree, proxy_free }, + + /* vmalloc() and friends */ + { vmalloc, proxy_alloc1 }, + { __vmalloc, proxy_alloc1 }, + { __vmalloc_node, proxy_alloc1 }, + { vzalloc, proxy_alloc1 }, + { vfree, proxy_free }, + { } }; diff --git a/mm/slab_common.c b/mm/slab_common.c index 238293b1dbe1..2b72118d9bfa 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "internal.h" #include "slab.h" @@ -1208,7 +1209,7 @@ __do_krealloc(const void *p, size_t new_size, gfp_t flags) * * Return: pointer to the allocated memory or %NULL in case of error */ -void *krealloc(const void *p, size_t new_size, gfp_t flags) +void * __nosbm krealloc(const void *p, size_t new_size, gfp_t flags) { void *ret; diff --git a/mm/slub.c b/mm/slub.c index 2ef88bbf56a3..5f2290fe4df0 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -3913,7 +3914,7 @@ EXPORT_SYMBOL(kmem_cache_alloc_node); * directly to the page allocator. We use __GFP_COMP, because we will need to * know the allocation order to free the pages properly in kfree. */ -static void *__kmalloc_large_node(size_t size, gfp_t flags, int node) +static void * __nosbm __kmalloc_large_node(size_t size, gfp_t flags, int node) { struct folio *folio; void *ptr = NULL; @@ -3938,7 +3939,7 @@ static void *__kmalloc_large_node(size_t size, gfp_t flags, int node) return ptr; } -void *kmalloc_large(size_t size, gfp_t flags) +void * __nosbm kmalloc_large(size_t size, gfp_t flags) { void *ret = __kmalloc_large_node(size, flags, NUMA_NO_NODE); @@ -3983,26 +3984,26 @@ void *__do_kmalloc_node(size_t size, gfp_t flags, int node, return ret; } -void *__kmalloc_node(size_t size, gfp_t flags, int node) +void * __nosbm __kmalloc_node(size_t size, gfp_t flags, int node) { return __do_kmalloc_node(size, flags, node, _RET_IP_); } EXPORT_SYMBOL(__kmalloc_node); -void *__kmalloc(size_t size, gfp_t flags) +void * __nosbm __kmalloc(size_t size, gfp_t flags) { return __do_kmalloc_node(size, flags, NUMA_NO_NODE, _RET_IP_); } EXPORT_SYMBOL(__kmalloc); -void *__kmalloc_node_track_caller(size_t size, gfp_t flags, - int node, unsigned long caller) +void * __nosbm __kmalloc_node_track_caller(size_t size, gfp_t flags, + int node, unsigned long caller) { return __do_kmalloc_node(size, flags, node, caller); } EXPORT_SYMBOL(__kmalloc_node_track_caller); -void *kmalloc_trace(struct kmem_cache *s, gfp_t gfpflags, size_t size) +void * __nosbm kmalloc_trace(struct kmem_cache *s, gfp_t gfpflags, size_t size) { void *ret = slab_alloc_node(s, NULL, gfpflags, NUMA_NO_NODE, _RET_IP_, size); @@ -4386,7 +4387,7 @@ static void free_large_kmalloc(struct folio *folio, void *object) * * If @object is NULL, no operation is performed. */ -void kfree(const void *object) +void __nosbm kfree(const void *object) { struct folio *folio; struct slab *slab; diff --git a/mm/vmalloc.c b/mm/vmalloc.c index d12a17fc0c17..d7a5b715ac03 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -2804,7 +2805,7 @@ void vfree_atomic(const void *addr) * if we have CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG, but making the calling * conventions for vfree() arch-dependent would be a really bad idea). */ -void vfree(const void *addr) +void __nosbm vfree(const void *addr) { struct vm_struct *vm; int i; @@ -3379,7 +3380,7 @@ void *__vmalloc_node_range(unsigned long size, unsigned long align, * * Return: pointer to the allocated memory or %NULL on error */ -void *__vmalloc_node(unsigned long size, unsigned long align, +void * __nosbm __vmalloc_node(unsigned long size, unsigned long align, gfp_t gfp_mask, int node, const void *caller) { return __vmalloc_node_range(size, align, VMALLOC_START, VMALLOC_END, @@ -3394,7 +3395,7 @@ void *__vmalloc_node(unsigned long size, unsigned long align, EXPORT_SYMBOL_GPL(__vmalloc_node); #endif -void *__vmalloc(unsigned long size, gfp_t gfp_mask) +void * __nosbm __vmalloc(unsigned long size, gfp_t gfp_mask) { return __vmalloc_node(size, 1, gfp_mask, NUMA_NO_NODE, __builtin_return_address(0)); @@ -3413,7 +3414,7 @@ EXPORT_SYMBOL(__vmalloc); * * Return: pointer to the allocated memory or %NULL on error */ -void *vmalloc(unsigned long size) +void * __nosbm vmalloc(unsigned long size) { return __vmalloc_node(size, 1, GFP_KERNEL, NUMA_NO_NODE, __builtin_return_address(0)); @@ -3453,7 +3454,7 @@ EXPORT_SYMBOL_GPL(vmalloc_huge); * * Return: pointer to the allocated memory or %NULL on error */ -void *vzalloc(unsigned long size) +void * __nosbm vzalloc(unsigned long size) { return __vmalloc_node(size, 1, GFP_KERNEL | __GFP_ZERO, NUMA_NO_NODE, __builtin_return_address(0)); From patchwork Thu Feb 22 13:12:30 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Petr Tesarik X-Patchwork-Id: 13567321 Received: from frasgout13.his.huawei.com (frasgout13.his.huawei.com [14.137.139.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7DDB36214C; Thu, 22 Feb 2024 13:15:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=14.137.139.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708607706; cv=none; b=VzFXm8JNrHvk7YOAs3lpry+2AUXaguqEdb5JfcjhXbgB+IC/3tq5+X+4h7c8TFgmsiGcNTw7wRTanxkVCyerwapGUWubRP/VDDupA+La6k6PFTpv5+BBSEJLcMtvkGvGm6aWaYrtNsQfLrcvC/QTMuNnEu/AjqAJHFW+uuFjLx8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708607706; c=relaxed/simple; bh=0R4jerlglq3bNBg/x4s4XMHJOfkR8wKF4csLY3Q1E2E=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=aUfMx87ctyQaCrehOy2jmtYOqm4iCR3sqOAAh7eTpioCvy52iHJzcIuN0x+Em1qaNiFGwr769vBnfuMRhNRyvnHsDbr2/UlFHRJSlEKmlF3yGW53y+aQqicl+sCQFQexUC2ZwP7rWUPXuWjT49Xm5urP0SI+p283/Cw5Z5dMuNY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=14.137.139.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.18.186.29]) by frasgout13.his.huawei.com (SkyGuard) with ESMTP id 4TgYBX5DTcz9y3DR; Thu, 22 Feb 2024 20:59:32 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.47]) by mail.maildlp.com (Postfix) with ESMTP id 8615D140DEC; Thu, 22 Feb 2024 21:14:46 +0800 (CST) Received: from huaweicloud.com (unknown [10.45.157.235]) by APP1 (Coremail) with SMTP id LxC2BwDXzhdSSNdlhi4AAw--.34998S7; Thu, 22 Feb 2024 14:14:45 +0100 (CET) From: Petr Tesarik To: Dave Hansen Cc: =?utf-8?b?UGV0ciBUZXNhxZnDrWs=?= , Petr Tesarik , Jonathan Corbet , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT)" , "H. Peter Anvin" , Andy Lutomirski , Oleg Nesterov , Peter Zijlstra , Xin Li , Arnd Bergmann , Andrew Morton , Rick Edgecombe , Kees Cook , "Masami Hiramatsu (Google)" , Pengfei Xu , Josh Poimboeuf , Ze Gao , "Kirill A. Shutemov" , Kai Huang , David Woodhouse , Brian Gerst , Jason Gunthorpe , Joerg Roedel , "Mike Rapoport (IBM)" , Tina Zhang , Jacob Pan , "open list:DOCUMENTATION" , open list , Roberto Sassu , John Johansen , Paul Moore , James Morris , "Serge E. Hallyn" , apparmor@lists.ubuntu.com, linux-security-module@vger.kernel.org, Petr Tesarik Subject: [RFC 5/5] apparmor: parse profiles in sandbox mode Date: Thu, 22 Feb 2024 14:12:30 +0100 Message-Id: <20240222131230.635-6-petrtesarik@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240222131230.635-1-petrtesarik@huaweicloud.com> References: <20240222131230.635-1-petrtesarik@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: LxC2BwDXzhdSSNdlhi4AAw--.34998S7 X-Coremail-Antispam: 1UD129KBjvJXoW3Xw48Cryrtw48tFWxGw17ZFb_yoW3JF4UpF srCFWDGF4kCF9FvrsxJa1akrWSv3yrXw1av39xGa4Yy3Zxtr4kGr47AFyjkFyrZ3ykC3WF gFW7Kr95ur1DArJanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPq14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_JF0E3s1l82xGYI kIc2x26xkF7I0E14v26ryj6s0DM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48ve4kI8wA2 z4x0Y4vE2Ix0cI8IcVAFwI0_JFI_Gr1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI0_Gr1j6F 4UJwA2z4x0Y4vEx4A2jsIE14v26r4j6F4UM28EF7xvwVC2z280aVCY1x0267AKxVW8Jr0_ Cr1UM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6x IIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_Jr0_ Gr1lF7xvr2IYc2Ij64vIr41lF7I21c0EjII2zVCS5cI20VAGYxC7M4IIrI8v6xkF7I0E8c xan2IY04v7MxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E5I8C rVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWrXVW8Jr 1lIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUCVW8JwCI42IY6xIIjxv20xvEc7Cj xVAFwI0_Gr1j6F4UJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI 0_Gr0_Cr1lIxAIcVC2z280aVCY1x0267AKxVW8Jr0_Cr1UYxBIdaVFxhVjvjDU0xZFpf9x 0JUQSdkUUUUU= X-CM-SenderInfo: hshw23xhvd2x3n6k3tpzhluzxrxghudrp/ From: Petr Tesarik Run aa_unpack() in sandbox mode. Map the input data read-only and then walk the resulting list created in sandbox mode. Hashes are calculated in kernel mode, because crypto routines are not sandboxed. The fixups should sanitize the parameters of AppArmor functions and they should be defined close to the target functions. Both requires extending the generic API and adding some more arch hooks, which would grow this patch series too much. For demonstration purposes, the fixups blindly trust the input from sandbox mode and are hard-wired in the arch code. Signed-off-by: Petr Tesarik --- arch/x86/kernel/sbm/core.c | 15 +++++++++++++++ security/apparmor/crypto.c | 7 ++++--- security/apparmor/policy.c | 29 ++++++++++++++++++++++------- security/apparmor/secid.c | 3 ++- 4 files changed, 43 insertions(+), 11 deletions(-) diff --git a/arch/x86/kernel/sbm/core.c b/arch/x86/kernel/sbm/core.c index 3cf3842292b9..3268c00da873 100644 --- a/arch/x86/kernel/sbm/core.c +++ b/arch/x86/kernel/sbm/core.c @@ -40,6 +40,16 @@ extern char __nosbm_text_start[], __nosbm_text_end[]; * HACK: PROOF-OF-CONCEPT FIXUP CODE STARTS HERE */ +/* + * HACK: These declarations are needed to make a proxy call, but in the + * final version, AppArmor itself will define the proxies. At least, do + * not make the functions callable from here. All we need are their + * entry point addresses. + */ +extern char aa_alloc_secid[]; +extern char aa_calc_hash[]; +extern char aa_calc_profile_hash[]; + typedef unsigned long (*sbm_proxy_call_fn)(struct x86_sbm_state *, unsigned long func, struct pt_regs *); @@ -135,6 +145,11 @@ static const struct sbm_fixup fixups[] = { vzalloc, proxy_alloc1 }, { vfree, proxy_free }, + /* AppArmor */ + { aa_alloc_secid, x86_sbm_proxy_call }, + { aa_calc_hash, x86_sbm_proxy_call }, + { aa_calc_profile_hash, x86_sbm_proxy_call }, + { } }; diff --git a/security/apparmor/crypto.c b/security/apparmor/crypto.c index aad486b2fca6..db349cd4e467 100644 --- a/security/apparmor/crypto.c +++ b/security/apparmor/crypto.c @@ -12,6 +12,7 @@ */ #include +#include #include "include/apparmor.h" #include "include/crypto.h" @@ -25,7 +26,7 @@ unsigned int aa_hash_size(void) return apparmor_hash_size; } -char *aa_calc_hash(void *data, size_t len) +char * __nosbm aa_calc_hash(void *data, size_t len) { SHASH_DESC_ON_STACK(desc, apparmor_tfm); char *hash; @@ -58,8 +59,8 @@ char *aa_calc_hash(void *data, size_t len) return ERR_PTR(error); } -int aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start, - size_t len) +int __nosbm aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start, + size_t len) { SHASH_DESC_ON_STACK(desc, apparmor_tfm); int error; diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index 957654d253dd..f2b9bf851be0 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c @@ -74,6 +74,7 @@ #include #include #include +#include #include "include/apparmor.h" #include "include/capability.h" @@ -1040,6 +1041,11 @@ static struct aa_profile *update_to_newest_parent(struct aa_profile *new) return newest; } +static SBM_DEFINE_CALL(aa_unpack, struct aa_loaddata *, udata, + struct list_head *, lh, const char **, ns); +static SBM_DEFINE_THUNK(aa_unpack, struct aa_loaddata *, udata, + struct list_head *, lh, const char **, ns); + /** * aa_replace_profiles - replace profile(s) on the profile list * @policy_ns: namespace load is occurring on @@ -1063,12 +1069,20 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_label *label, struct aa_loaddata *rawdata_ent; const char *op; ssize_t count, error; - LIST_HEAD(lh); + struct list_head lh, *sbm_lh; + struct sbm sbm; op = mask & AA_MAY_REPLACE_POLICY ? OP_PROF_REPL : OP_PROF_LOAD; aa_get_loaddata(udata); /* released below */ - error = aa_unpack(udata, &lh, &ns_name); + sbm_init(&sbm); + SBM_MAP_READONLY(&sbm, udata->data, udata->size); + /* TODO: Handling of list heads could be improved */ + sbm_lh = SBM_COPY_OUT(&sbm, &lh, sizeof(lh)); + INIT_LIST_HEAD(sbm_lh); + error = sbm_call(&sbm, aa_unpack, + SBM_COPY_INOUT(&sbm, udata, sizeof(*udata)), sbm_lh, + SBM_COPY_OUT(&sbm, &ns_name, sizeof(ns_name))); if (error) goto out; @@ -1078,7 +1092,7 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_label *label, * fail. Sort ent list and take ns locks in hierarchy order */ count = 0; - list_for_each_entry(ent, &lh, list) { + list_for_each_entry(ent, sbm_lh, list) { if (ns_name) { if (ent->ns_name && strcmp(ent->ns_name, ns_name) != 0) { @@ -1128,7 +1142,7 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_label *label, } } /* setup parent and ns info */ - list_for_each_entry(ent, &lh, list) { + list_for_each_entry(ent, sbm_lh, list) { struct aa_policy *policy; struct aa_profile *p; @@ -1159,7 +1173,7 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_label *label, policy = __lookup_parent(ns, ent->new->base.hname); if (!policy) { /* first check for parent in the load set */ - p = __list_lookup_parent(&lh, ent->new); + p = __list_lookup_parent(sbm_lh, ent->new); if (!p) { /* * fill in missing parent with null @@ -1198,7 +1212,7 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_label *label, goto fail_lock; } } - list_for_each_entry(ent, &lh, list) { + list_for_each_entry(ent, sbm_lh, list) { if (!ent->old) { struct dentry *parent; if (rcu_access_pointer(ent->new->parent)) { @@ -1220,7 +1234,7 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_label *label, __aa_bump_ns_revision(ns); if (aa_g_export_binary) __aa_loaddata_update(udata, ns->revision); - list_for_each_entry_safe(ent, tmp, &lh, list) { + list_for_each_entry_safe(ent, tmp, sbm_lh, list) { list_del_init(&ent->list); op = (!ent->old && !ent->rename) ? OP_PROF_LOAD : OP_PROF_REPL; @@ -1265,6 +1279,7 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_label *label, mutex_unlock(&ns->lock); out: + sbm_destroy(&sbm); aa_put_ns(ns); aa_put_loaddata(udata); kfree(ns_name); diff --git a/security/apparmor/secid.c b/security/apparmor/secid.c index 83d3d1e6d9dc..4190666d2dee 100644 --- a/security/apparmor/secid.c +++ b/security/apparmor/secid.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "include/cred.h" #include "include/lib.h" @@ -116,7 +117,7 @@ void apparmor_release_secctx(char *secdata, u32 seclen) * Returns: 0 with @label->secid initialized * <0 returns error with @label->secid set to AA_SECID_INVALID */ -int aa_alloc_secid(struct aa_label *label, gfp_t gfp) +int __nosbm aa_alloc_secid(struct aa_label *label, gfp_t gfp) { unsigned long flags; int ret;