From patchwork Tue Dec 6 15:02:28 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Xu X-Patchwork-Id: 30365 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp2876436wrr; Tue, 6 Dec 2022 07:10:18 -0800 (PST) X-Google-Smtp-Source: AA0mqf5WyinI4D+FetLUFZ+TkARbTmb0f+Si9ePPX1bTtlGuIN6KZho7Pn4vKVHxTfM+VdtT2o3R X-Received: by 2002:a05:6402:3c9:b0:46a:b56d:92d with SMTP id t9-20020a05640203c900b0046ab56d092dmr940492edw.336.1670339417963; Tue, 06 Dec 2022 07:10:17 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1670339417; cv=none; d=google.com; s=arc-20160816; b=EF7QkfTaJLZOqhjfyZk4DpKQT6aO3hLKE2e2eqpEzJIG6NALerqfOxYuWQGw1DVwO5 zgqs6osQrkJ7+6A5HAEbK1MACx7NyCO77lUBmfFXzQWNWrVu0927bzyjyr+JZvZzkXHw yF3yHUMk0kov40xhRNUl/pfUPP6TJe58YQx5c+vEEG7rc6GhktMU1nOR8Z/CQubb0Zv7 +pyuQBBvt0DbmUpxXkZsMNTNIi2HS+S8m1X3WaTEKb8pgpKhWee6b10AsDqYLitVIk1d NgSEp/nDBAOn7+pbPTt+7wnI0Tu73SttHYewuC1L6ujAZET8oZ/APla+PaD8CeSkaMgD frfw== 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=FWkrRAknVBR+DtqNNWTgcHsNLwaDUPfHC+NIWe1Ak98=; b=r1/YueUWniEbNhiilQcjZ9tHfGA+BCHk6amx1b05dr3WKNdhKKYLGcxLuDKV/Hj2Qs cdWexGUApyls8HAFtTyuODqvO1nGv9tDdeH3/nqN6DO2od9xtLHKyTK/N7PH5nP+gWY+ guGaBrvf6ZvSJQ+XKq1q5/s1COkYvgbkuhQbBo+4ThKyjQ1ObWzmsKB359ah99fqxpFO VRsAUIDM7PZBvP5ZwvyJclIPXg/dceQgaaY97rLTkQOXvUI5mTbO/yH2gBCrp1N4iOwp WTp3ylQsQU8XOfr6R9aqBZbPtcdIIXgQ40PpGHFzecMeS70BSbnocnNv0c54VacRGtKg ZPTw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=QV0CaNM9; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id y15-20020a056402358f00b0046d2975b08fsi1088651edc.555.2022.12.06.07.09.37; Tue, 06 Dec 2022 07:10:17 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=QV0CaNM9; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235193AbiLFPHa (ORCPT + 99 others); Tue, 6 Dec 2022 10:07:30 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60700 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234957AbiLFPGb (ORCPT ); Tue, 6 Dec 2022 10:06:31 -0500 Received: from mail-pj1-x1031.google.com (mail-pj1-x1031.google.com [IPv6:2607:f8b0:4864:20::1031]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D096F29822 for ; Tue, 6 Dec 2022 07:02:48 -0800 (PST) Received: by mail-pj1-x1031.google.com with SMTP id o1-20020a17090a678100b00219cf69e5f0so6322749pjj.2 for ; Tue, 06 Dec 2022 07:02:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; 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=FWkrRAknVBR+DtqNNWTgcHsNLwaDUPfHC+NIWe1Ak98=; b=QV0CaNM9WiSGeS6ovz8FZ+s36DTHQgyDc2qJhuQZWS+8Cc0b75tuIxwziO9cqnBDrS d62yHSr7sI+gLZtQ0eFneYw5KkhAi9V7PEQ+/5diopD1jIjEnjX1PYq6f74fwGV39y2J UaiWrQA9IDEXUuIndZ63KqFP17HO9XEhXj9/w= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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=FWkrRAknVBR+DtqNNWTgcHsNLwaDUPfHC+NIWe1Ak98=; b=7GAJJpuG3G2JCf5p/41vqsuUu63eDXYhpdLhaJV0JE+47cWyIx3xBdQ2aECkjmB4Um FVK8dgUABmYAMcVeWMYrWFi//ohHSBIWYI6wei607TtKLeFrxqtkX3CHLAg4m7y42JZA wjL2cFO7mAEXKVTdssvspbF02n9AVTiq2BLPHliUaVFdSW1iLQbaYbFoTs1Pix8L6j9b F6PltY4NJnWuG2KdeUo0QPw7akA7rU/SezrmrO8i9aBENXanUVgnek1zOHwdPBxdFzAI n6IN/NGZrPFyHaXJRB9FYd6e03SnV2iiUAYFdkjlBFYf2vrb7pYFXrAsbkXNeqVk/rhC LqAQ== X-Gm-Message-State: ANoB5pnJzBrHTH22kUs82TkYRSO6bWz2hprhjor7YUY/UvtafqMZ9zPp vOcxwg7yEf+p7so6S7Pus3+DOA== X-Received: by 2002:a17:90a:8c96:b0:218:7e9d:8d0a with SMTP id b22-20020a17090a8c9600b002187e9d8d0amr88986847pjo.41.1670338968356; Tue, 06 Dec 2022 07:02:48 -0800 (PST) Received: from jeffxud.c.googlers.com.com (30.202.168.34.bc.googleusercontent.com. [34.168.202.30]) by smtp.gmail.com with ESMTPSA id 62-20020a621441000000b00575bab45644sm3343019pfu.61.2022.12.06.07.02.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Dec 2022 07:02:47 -0800 (PST) From: jeffxu@chromium.org To: skhan@linuxfoundation.org, keescook@chromium.org Cc: akpm@linux-foundation.org, dmitry.torokhov@gmail.com, dverkamp@chromium.org, hughd@google.com, jeffxu@google.com, jorgelo@chromium.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-mm@kvack.org, jannh@google.com, linux-hardening@vger.kernel.org, Jeff Xu Subject: [PATCH v4 1/6] mm/memfd: add F_SEAL_EXEC Date: Tue, 6 Dec 2022 15:02:28 +0000 Message-Id: <20221206150233.1963717-2-jeffxu@google.com> X-Mailer: git-send-email 2.39.0.rc0.267.gcb52ba06e7-goog In-Reply-To: <20221206150233.1963717-1-jeffxu@google.com> References: <20221206150233.1963717-1-jeffxu@google.com> MIME-Version: 1.0 X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1751477825634601590?= X-GMAIL-MSGID: =?utf-8?q?1751477825634601590?= From: Daniel Verkamp The new F_SEAL_EXEC flag will prevent modification of the exec bits: written as traditional octal mask, 0111, or as named flags, S_IXUSR | S_IXGRP | S_IXOTH. Any chmod(2) or similar call that attempts to modify any of these bits after the seal is applied will fail with errno EPERM. This will preserve the execute bits as they are at the time of sealing, so the memfd will become either permanently executable or permanently un-executable. Signed-off-by: Daniel Verkamp Co-developed-by: Jeff Xu Signed-off-by: Jeff Xu --- include/uapi/linux/fcntl.h | 1 + mm/memfd.c | 2 ++ mm/shmem.c | 6 ++++++ 3 files changed, 9 insertions(+) diff --git a/include/uapi/linux/fcntl.h b/include/uapi/linux/fcntl.h index 2f86b2ad6d7e..e8c07da58c9f 100644 --- a/include/uapi/linux/fcntl.h +++ b/include/uapi/linux/fcntl.h @@ -43,6 +43,7 @@ #define F_SEAL_GROW 0x0004 /* prevent file from growing */ #define F_SEAL_WRITE 0x0008 /* prevent writes */ #define F_SEAL_FUTURE_WRITE 0x0010 /* prevent future writes while mapped */ +#define F_SEAL_EXEC 0x0020 /* prevent chmod modifying exec bits */ /* (1U << 31) is reserved for signed error codes */ /* diff --git a/mm/memfd.c b/mm/memfd.c index 08f5f8304746..4ebeab94aa74 100644 --- a/mm/memfd.c +++ b/mm/memfd.c @@ -147,6 +147,7 @@ static unsigned int *memfd_file_seals_ptr(struct file *file) } #define F_ALL_SEALS (F_SEAL_SEAL | \ + F_SEAL_EXEC | \ F_SEAL_SHRINK | \ F_SEAL_GROW | \ F_SEAL_WRITE | \ @@ -175,6 +176,7 @@ static int memfd_add_seals(struct file *file, unsigned int seals) * SEAL_SHRINK: Prevent the file from shrinking * SEAL_GROW: Prevent the file from growing * SEAL_WRITE: Prevent write access to the file + * SEAL_EXEC: Prevent modification of the exec bits in the file mode * * As we don't require any trust relationship between two parties, we * must prevent seals from being removed. Therefore, sealing a file diff --git a/mm/shmem.c b/mm/shmem.c index c1d8b8a1aa3b..e18a9cf9d937 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1085,6 +1085,12 @@ static int shmem_setattr(struct user_namespace *mnt_userns, if (error) return error; + if ((info->seals & F_SEAL_EXEC) && (attr->ia_valid & ATTR_MODE)) { + if ((inode->i_mode ^ attr->ia_mode) & 0111) { + return -EPERM; + } + } + if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) { loff_t oldsize = inode->i_size; loff_t newsize = attr->ia_size; From patchwork Tue Dec 6 15:02:29 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Xu X-Patchwork-Id: 30373 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp2877404wrr; Tue, 6 Dec 2022 07:11:47 -0800 (PST) X-Google-Smtp-Source: AA0mqf5BX3pOdhQiKv4Qe6rKt9vWDc+ycDDSkQXte6cJe3+fq4/Cxu6iUYLvjB8VSzj3g+Zed2zz X-Received: by 2002:a17:90a:4889:b0:20d:d531:97cc with SMTP id b9-20020a17090a488900b0020dd53197ccmr96491708pjh.164.1670339506981; Tue, 06 Dec 2022 07:11:46 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1670339506; cv=none; d=google.com; s=arc-20160816; b=ilFX/n1GlTof86PEM1y2jEzBa43tayr6p/GW+yZb4QSFhshiM9D3zbWpfEC2Y2uEqC tOgSrVSMLrlB594kGE+AdTZ0EACtTQEeY6rawQnqFqk9t4a6hPXy5k6zgbRwge3+TOX8 tAsNfWY+/9XZXGSN0gJ/3xq4l7hN6UBVd1HrJ5XBGOEZKSTO4mChUCu2dB72576iA27J 5nE3M0KKPt9gK5hfPimb6/ehQbJJPkZahby7MziH0vxymAgaC/Pq/Hg5sT4O511K4g8R sYORbAKrjqmSR+f3KFGs/9DuTy3KKZFR7S/Qphg+9bMz8iyg7EmBaSasB18VWBLGS7QA 83KQ== 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=kmJ6vAUUVWR2mQbJ18nVP5DOm/6S97wQS9z+LXJq08M=; b=cIIvYORb1+d+RXEVOYkDaYEjf/fC6YGTnhwvfATumTEzTfJYXJVMYKKP64e+cQwHL4 Xawn+T3E9K8fyqmRukmz/IsK5bVu6RC/P8YbXSzIwI7U0lkpkvu9Tnpbc7wRHfyzyy58 Gn2TiACB/bG1wPATGZKZmiYaE+AtZjPA+/EFi729rRoiSQY+KHfHUkGeNQLWl1WXIXHd CD8QNCoafeRJycjeg3FnEAHXIb6AgKhHFWMA1nV2pjY/U4+MURQ9ijUJ5P5d2JBOlByY DS/3P3nB9MZzrugO245fK9PWfL2HuP6apOEisS2sPhm8H8dkIyuNWMX0j+hF5WaulsFv +HRQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=mBzEgGgh; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id j18-20020a17090ae61200b0021812e71e68si17244525pjy.84.2022.12.06.07.11.32; Tue, 06 Dec 2022 07:11:46 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=mBzEgGgh; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234637AbiLFPHj (ORCPT + 99 others); Tue, 6 Dec 2022 10:07:39 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59794 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234648AbiLFPGd (ORCPT ); Tue, 6 Dec 2022 10:06:33 -0500 Received: from mail-pj1-x1036.google.com (mail-pj1-x1036.google.com [IPv6:2607:f8b0:4864:20::1036]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7E1EE29CA0 for ; Tue, 6 Dec 2022 07:02:52 -0800 (PST) Received: by mail-pj1-x1036.google.com with SMTP id w15-20020a17090a380f00b0021873113cb4so15074242pjb.0 for ; Tue, 06 Dec 2022 07:02:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; 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=kmJ6vAUUVWR2mQbJ18nVP5DOm/6S97wQS9z+LXJq08M=; b=mBzEgGghhFXhuTglJ/L1+wl3Zqb+kJf1g0t7Wmcd1QW9nQokkOZUett2xiWp7tYEs4 f6/NFng9UDtQ/SBc64ze+Rxg4tcA0Sk3S/ZX10DCX9Rocpit2YogmnVRjhBESgNO3DPf 3dzmfanK2mMJpatcmm58Ov+Cy7pN5VT3QY5Cs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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=kmJ6vAUUVWR2mQbJ18nVP5DOm/6S97wQS9z+LXJq08M=; b=LSIplb+itkMlf4cZ4b+84KEwQBklw5TgMrto/+dpPJds/3SM2Bc/YabkpF0vVnh/Ft D2D9uYKY6qNngWYW0TBIqBkAXHSyg89Oiw2lGUeKrMdOqzvV0g2e6MdPlCG2UVfByBkv TllFHvJN5dHIVtWo9sTQfYaZw/O8JHV67WydvVNzaJnatiui/VvARln4BXAeBxZ9+gEa P519j6WgiqFjvutHDo7MBgicLF7yO5pgucYU1yD4DezdXN99xfdq9b1meMKYOt6SUNz+ TrZtN5aoZi/Z1j947+qfoNnmcC3N+FWFnQ8ufChe7i4jEdchjeZqzDfEwPMpznjAXg2l 5A8g== X-Gm-Message-State: ANoB5plC3yHYC9KMPoX7oWnJkljcJDGbIkZUneQjKS9W11T24gVKXd+7 snsNlqCozxmU4hLK0ZlaYWH/X/yim5LugnUP X-Received: by 2002:a17:903:28d:b0:189:b74e:cd07 with SMTP id j13-20020a170903028d00b00189b74ecd07mr23520438plr.169.1670338972076; Tue, 06 Dec 2022 07:02:52 -0800 (PST) Received: from jeffxud.c.googlers.com.com (30.202.168.34.bc.googleusercontent.com. [34.168.202.30]) by smtp.gmail.com with ESMTPSA id 62-20020a621441000000b00575bab45644sm3343019pfu.61.2022.12.06.07.02.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Dec 2022 07:02:51 -0800 (PST) From: jeffxu@chromium.org To: skhan@linuxfoundation.org, keescook@chromium.org Cc: akpm@linux-foundation.org, dmitry.torokhov@gmail.com, dverkamp@chromium.org, hughd@google.com, jeffxu@google.com, jorgelo@chromium.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-mm@kvack.org, jannh@google.com, linux-hardening@vger.kernel.org, Jeff Xu Subject: [PATCH v4 2/6] selftests/memfd: add tests for F_SEAL_EXEC Date: Tue, 6 Dec 2022 15:02:29 +0000 Message-Id: <20221206150233.1963717-3-jeffxu@google.com> X-Mailer: git-send-email 2.39.0.rc0.267.gcb52ba06e7-goog In-Reply-To: <20221206150233.1963717-1-jeffxu@google.com> References: <20221206150233.1963717-1-jeffxu@google.com> MIME-Version: 1.0 X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1751477918665854925?= X-GMAIL-MSGID: =?utf-8?q?1751477918665854925?= From: Daniel Verkamp Basic tests to ensure that user/group/other execute bits cannot be changed after applying F_SEAL_EXEC to a memfd. Signed-off-by: Daniel Verkamp Co-developed-by: Jeff Xu Signed-off-by: Jeff Xu --- tools/testing/selftests/memfd/memfd_test.c | 129 ++++++++++++++++++++- 1 file changed, 128 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/memfd/memfd_test.c b/tools/testing/selftests/memfd/memfd_test.c index 94df2692e6e4..1d7e7b36bbdd 100644 --- a/tools/testing/selftests/memfd/memfd_test.c +++ b/tools/testing/selftests/memfd/memfd_test.c @@ -28,12 +28,44 @@ #define MFD_DEF_SIZE 8192 #define STACK_SIZE 65536 +#ifndef F_SEAL_EXEC +#define F_SEAL_EXEC 0x0020 +#endif + +#ifndef MAX_PATH +#define MAX_PATH 256 +#endif + /* * Default is not to test hugetlbfs */ static size_t mfd_def_size = MFD_DEF_SIZE; static const char *memfd_str = MEMFD_STR; +static ssize_t fd2name(int fd, char *buf, size_t bufsize) +{ + char buf1[MAX_PATH]; + int size; + ssize_t nbytes; + + size = snprintf(buf1, MAX_PATH, "/proc/self/fd/%d", fd); + if (size < 0) { + printf("snprintf(%d) failed on %m\n", fd); + abort(); + } + + /* + * reserver one byte for string termination. + */ + nbytes = readlink(buf1, buf, bufsize-1); + if (nbytes == -1) { + printf("readlink(%s) failed %m\n", buf1); + abort(); + } + buf[nbytes] = '\0'; + return nbytes; +} + static int mfd_assert_new(const char *name, loff_t sz, unsigned int flags) { int r, fd; @@ -98,11 +130,14 @@ static unsigned int mfd_assert_get_seals(int fd) static void mfd_assert_has_seals(int fd, unsigned int seals) { + char buf[MAX_PATH]; + int nbytes; unsigned int s; + fd2name(fd, buf, MAX_PATH); s = mfd_assert_get_seals(fd); if (s != seals) { - printf("%u != %u = GET_SEALS(%d)\n", seals, s, fd); + printf("%u != %u = GET_SEALS(%s)\n", seals, s, buf); abort(); } } @@ -594,6 +629,64 @@ static void mfd_fail_grow_write(int fd) } } +static void mfd_assert_mode(int fd, int mode) +{ + struct stat st; + char buf[MAX_PATH]; + int nbytes; + + fd2name(fd, buf, MAX_PATH); + + if (fstat(fd, &st) < 0) { + printf("fstat(%s) failed: %m\n", buf); + abort(); + } + + if ((st.st_mode & 07777) != mode) { + printf("fstat(%s) wrong file mode 0%04o, but expected 0%04o\n", + buf, (int)st.st_mode & 07777, mode); + abort(); + } +} + +static void mfd_assert_chmod(int fd, int mode) +{ + char buf[MAX_PATH]; + int nbytes; + + fd2name(fd, buf, MAX_PATH); + + if (fchmod(fd, mode) < 0) { + printf("fchmod(%s, 0%04o) failed: %m\n", buf, mode); + abort(); + } + + mfd_assert_mode(fd, mode); +} + +static void mfd_fail_chmod(int fd, int mode) +{ + struct stat st; + char buf[MAX_PATH]; + int nbytes; + + fd2name(fd, buf, MAX_PATH); + + if (fstat(fd, &st) < 0) { + printf("fstat(%s) failed: %m\n", buf); + abort(); + } + + if (fchmod(fd, mode) == 0) { + printf("fchmod(%s, 0%04o) didn't fail as expected\n", + buf, mode); + abort(); + } + + /* verify that file mode bits did not change */ + mfd_assert_mode(fd, st.st_mode & 07777); +} + static int idle_thread_fn(void *arg) { sigset_t set; @@ -880,6 +973,39 @@ static void test_seal_resize(void) close(fd); } +/* + * Test SEAL_EXEC + * Test that chmod() cannot change x bits after sealing + */ +static void test_seal_exec(void) +{ + int fd; + + printf("%s SEAL-EXEC\n", memfd_str); + + fd = mfd_assert_new("kern_memfd_seal_exec", + mfd_def_size, + MFD_CLOEXEC | MFD_ALLOW_SEALING); + + mfd_assert_mode(fd, 0777); + + mfd_assert_chmod(fd, 0644); + + mfd_assert_has_seals(fd, 0); + mfd_assert_add_seals(fd, F_SEAL_EXEC); + mfd_assert_has_seals(fd, F_SEAL_EXEC); + + mfd_assert_chmod(fd, 0600); + mfd_fail_chmod(fd, 0777); + mfd_fail_chmod(fd, 0670); + mfd_fail_chmod(fd, 0605); + mfd_fail_chmod(fd, 0700); + mfd_fail_chmod(fd, 0100); + mfd_assert_chmod(fd, 0666); + + close(fd); +} + /* * Test sharing via dup() * Test that seals are shared between dupped FDs and they're all equal. @@ -1059,6 +1185,7 @@ int main(int argc, char **argv) test_seal_shrink(); test_seal_grow(); test_seal_resize(); + test_seal_exec(); test_share_dup("SHARE-DUP", ""); test_share_mmap("SHARE-MMAP", ""); From patchwork Tue Dec 6 15:02:30 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Xu X-Patchwork-Id: 30368 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp2876558wrr; Tue, 6 Dec 2022 07:10:28 -0800 (PST) X-Google-Smtp-Source: AA0mqf7Yyuidk91QpcFtCpyQFte3qqFihxw4P/XwIBWwI1hP6ddpEBfrxgBVerbsQWhc0AAaAjV5 X-Received: by 2002:a17:906:8d2:b0:7c0:deb1:1336 with SMTP id o18-20020a17090608d200b007c0deb11336mr10604600eje.192.1670339428193; Tue, 06 Dec 2022 07:10:28 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1670339428; cv=none; d=google.com; s=arc-20160816; b=1CZAowDYSISlo95NDHKAAyKlIgbVZPfhAbYpmJrfuBVCTDXU4ZWNuM6ecR6DCIgjp6 NJrTbJU9LQf9/aXY5nsR2nO3rznskVXNuS11dl1m/un+Hj7U+7SJtqLI4sTuq2BMU5jo QAe4adTHmGVw4vqgJJ0Cs2uS7l7bwJAH/BDipBuoamVDSQNOfVM4Snc37ExHwEvlUyFx VPp/6C6To3AGUkCHJ4fW4v2OpBq+IKCW7K76xewlFg0G2h1KtMJ7T2eQWzJjUtElBlyg 3UtqB+V0BoXe/9lv7/TycGRyU1MTWVsqI+KTqY3BpOLPHcZSAa+MeiYEw+5teFYMfHB9 Ilwg== 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=SdDrnGbeR2v4+0YeS8iLZurDBTuoZ6giO5nJB6MXDpc=; b=L4ZXj3C6DIU9Dp2BCBtLKu9+LCXUFxbaomN7gKLcBXqO2DwuOOqllJj1fx6OKVO3KI aSQ0IHBLSUVzQ3RoUtbi7ipl8sMdaXFSBM9Rc3BZdwoJKw8R1i1NB7HYPtbnBYGYhDz9 D6RqyPqq205unIANnNDVTAPH6YWKPSnWmeD/32DZwvmCACJ0DuRdGbiB6ZugEicN6z0d VoqurG7TkU8yzNHlJRPgLpM/e3aQxfY08SFySrVFbw+48UIhAyvOfstxZMZ8YnTOUIN5 9enCiGLOHLhYKXM5FtTp/7+jSIfCshF8S5+6bfcKW99b2vUkYoUuopuTCsCFI/7da4x0 0Vcw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=Lp5y3v1T; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id bd9-20020a056402206900b0045cf3759408si1833205edb.49.2022.12.06.07.09.57; Tue, 06 Dec 2022 07:10:28 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=Lp5y3v1T; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231255AbiLFPIC (ORCPT + 99 others); Tue, 6 Dec 2022 10:08:02 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60926 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234207AbiLFPGs (ORCPT ); Tue, 6 Dec 2022 10:06:48 -0500 Received: from mail-pl1-x62f.google.com (mail-pl1-x62f.google.com [IPv6:2607:f8b0:4864:20::62f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4CB4529CA5 for ; Tue, 6 Dec 2022 07:02:54 -0800 (PST) Received: by mail-pl1-x62f.google.com with SMTP id jl24so14165936plb.8 for ; Tue, 06 Dec 2022 07:02:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; 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=SdDrnGbeR2v4+0YeS8iLZurDBTuoZ6giO5nJB6MXDpc=; b=Lp5y3v1TLQ8h+k75OGhKm0tXHLrZxfohFufb3neNr2IkBDTBkoAY93AOiyuZw5b51e 7IxFE7/84U0Z5nyotFdZJ66hbYNqRM2yT/bMCJpQ/cpYcxNvs4VF4dxJP7c7EnaEP46z wQF9YuS6q++mKUojM4AMnHL7/vOCIdT6lTV/I= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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=SdDrnGbeR2v4+0YeS8iLZurDBTuoZ6giO5nJB6MXDpc=; b=qQlzf+sMDMBpvkiyAAUKmv53RpOHDLvX0PkVvqBinXo8TRW0g0LHUL6nD6spm0JdYa RTmS1QFykT/eGN20JSvd9C3D7orEyV5fb6ZF2g8bpnNDDJqBsO2GEbAHX2zgkKML5SGx CQ0OzpkStTEUs50stgaZD2z62RYH1UTPEF2DBZQDKmLbCo5B6fYyfJvUkpffXEuybRVI XtYqIEgu2sADmJZtH9UYohKSDImdAZXDBx5RJY7CibQWLFk8hB6it0GrQFoAVA5+Xz0c AVM4T0VFBBxfALt/Ipoegow88xer02RgZyJs7XjzUGKrp/9UFBA4FQyGaFRw0fzZ6Afg smBQ== X-Gm-Message-State: ANoB5pmJrtIt8WlqTqSe/jw9fUsJhcTxe0UhUrAoHbzOe5FMnUPsXlC1 CaAtoZfbOkDF7R+jq0gQv2Fi5w== X-Received: by 2002:a17:90b:238b:b0:219:7904:6de with SMTP id mr11-20020a17090b238b00b00219790406demr27005323pjb.136.1670338973626; Tue, 06 Dec 2022 07:02:53 -0800 (PST) Received: from jeffxud.c.googlers.com.com (30.202.168.34.bc.googleusercontent.com. [34.168.202.30]) by smtp.gmail.com with ESMTPSA id 62-20020a621441000000b00575bab45644sm3343019pfu.61.2022.12.06.07.02.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Dec 2022 07:02:53 -0800 (PST) From: jeffxu@chromium.org To: skhan@linuxfoundation.org, keescook@chromium.org Cc: akpm@linux-foundation.org, dmitry.torokhov@gmail.com, dverkamp@chromium.org, hughd@google.com, jeffxu@google.com, jorgelo@chromium.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-mm@kvack.org, jannh@google.com, linux-hardening@vger.kernel.org, Jeff Xu , kernel test robot Subject: [PATCH v4 3/6] mm/memfd: add MFD_NOEXEC_SEAL and MFD_EXEC Date: Tue, 6 Dec 2022 15:02:30 +0000 Message-Id: <20221206150233.1963717-4-jeffxu@google.com> X-Mailer: git-send-email 2.39.0.rc0.267.gcb52ba06e7-goog In-Reply-To: <20221206150233.1963717-1-jeffxu@google.com> References: <20221206150233.1963717-1-jeffxu@google.com> MIME-Version: 1.0 X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1751477777920099182?= X-GMAIL-MSGID: =?utf-8?q?1751477836208032815?= From: Jeff Xu The new MFD_NOEXEC_SEAL and MFD_EXEC flags allows application to set executable bit at creation time (memfd_create). When MFD_NOEXEC_SEAL is set, memfd is created without executable bit (mode:0666), and sealed with F_SEAL_EXEC, so it can't be chmod to be executable (mode: 0777) after creation. when MFD_EXEC flag is set, memfd is created with executable bit (mode:0777), this is the same as the old behavior of memfd_create. The new pid namespaced sysctl vm.memfd_noexec has 3 values: 0: memfd_create() without MFD_EXEC nor MFD_NOEXEC_SEAL acts like MFD_EXEC was set. 1: memfd_create() without MFD_EXEC nor MFD_NOEXEC_SEAL acts like MFD_NOEXEC_SEAL was set. 2: memfd_create() without MFD_NOEXEC_SEAL will be rejected. The sysctl allows finer control of memfd_create for old-software that doesn't set the executable bit, for example, a container with vm.memfd_noexec=1 means the old-software will create non-executable memfd by default. Signed-off-by: Jeff Xu Co-developed-by: Daniel Verkamp Signed-off-by: Daniel Verkamp Reported-by: kernel test robot --- include/linux/pid_namespace.h | 19 ++++++++++++++ include/uapi/linux/memfd.h | 4 +++ kernel/pid_namespace.c | 48 +++++++++++++++++++++++++++++++++++ mm/memfd.c | 48 +++++++++++++++++++++++++++++++++-- 4 files changed, 117 insertions(+), 2 deletions(-) diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h index 07481bb87d4e..a4789a7b34a9 100644 --- a/include/linux/pid_namespace.h +++ b/include/linux/pid_namespace.h @@ -16,6 +16,21 @@ struct fs_pin; +#if defined(CONFIG_SYSCTL) && defined(CONFIG_MEMFD_CREATE) +/* + * sysctl for vm.memfd_noexec + * 0: memfd_create() without MFD_EXEC nor MFD_NOEXEC_SEAL + * acts like MFD_EXEC was set. + * 1: memfd_create() without MFD_EXEC nor MFD_NOEXEC_SEAL + * acts like MFD_NOEXEC_SEAL was set. + * 2: memfd_create() without MFD_NOEXEC_SEAL will be + * rejected. + */ +#define MEMFD_NOEXEC_SCOPE_EXEC 0 +#define MEMFD_NOEXEC_SCOPE_NOEXEC_SEAL 1 +#define MEMFD_NOEXEC_SCOPE_NOEXEC_ENFORCED 2 +#endif + struct pid_namespace { struct idr idr; struct rcu_head rcu; @@ -31,6 +46,10 @@ struct pid_namespace { struct ucounts *ucounts; int reboot; /* group exit code if this pidns was rebooted */ struct ns_common ns; +#if defined(CONFIG_SYSCTL) && defined(CONFIG_MEMFD_CREATE) + /* sysctl for vm.memfd_noexec */ + int memfd_noexec_scope; +#endif } __randomize_layout; extern struct pid_namespace init_pid_ns; diff --git a/include/uapi/linux/memfd.h b/include/uapi/linux/memfd.h index 7a8a26751c23..273a4e15dfcf 100644 --- a/include/uapi/linux/memfd.h +++ b/include/uapi/linux/memfd.h @@ -8,6 +8,10 @@ #define MFD_CLOEXEC 0x0001U #define MFD_ALLOW_SEALING 0x0002U #define MFD_HUGETLB 0x0004U +/* not executable and sealed to prevent changing to executable. */ +#define MFD_NOEXEC_SEAL 0x0008U +/* executable */ +#define MFD_EXEC 0x0010U /* * Huge page size encoding when MFD_HUGETLB is specified, and a huge page diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c index f4f8cb0435b4..2b7563ddd22c 100644 --- a/kernel/pid_namespace.c +++ b/kernel/pid_namespace.c @@ -110,6 +110,11 @@ static struct pid_namespace *create_pid_namespace(struct user_namespace *user_ns ns->ucounts = ucounts; ns->pid_allocated = PIDNS_ADDING; +#if defined(CONFIG_SYSCTL) && defined(CONFIG_MEMFD_CREATE) + ns->memfd_noexec_scope = + task_active_pid_ns(current)->memfd_noexec_scope; +#endif + return ns; out_free_idr: @@ -255,6 +260,45 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns) return; } +#if defined(CONFIG_SYSCTL) && defined(CONFIG_MEMFD_CREATE) +static int pid_mfd_noexec_dointvec_minmax(struct ctl_table *table, int write, + void *buffer, size_t *lenp, loff_t *ppos) +{ + struct pid_namespace *ns = task_active_pid_ns(current); + struct ctl_table table_copy; + + if (write && !capable(CAP_SYS_ADMIN)) + return -EPERM; + + table_copy = *table; + if (ns != &init_pid_ns) + table_copy.data = &ns->memfd_noexec_scope; + + /* + * set minimum to current value, the effect is only bigger + * value is accepted. + */ + if (*(int *)table_copy.data > *(int *)table_copy.extra1) + table_copy.extra1 = table_copy.data; + + return proc_dointvec_minmax(&table_copy, write, buffer, lenp, ppos); +} + +static struct ctl_table pid_ns_ctl_table_vm[] = { + { + .procname = "memfd_noexec", + .data = &init_pid_ns.memfd_noexec_scope, + .maxlen = sizeof(init_pid_ns.memfd_noexec_scope), + .mode = 0644, + .proc_handler = pid_mfd_noexec_dointvec_minmax, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_TWO, + }, + { } +}; +static struct ctl_path vm_path[] = { { .procname = "vm", }, { } }; +#endif + #ifdef CONFIG_CHECKPOINT_RESTORE static int pid_ns_ctl_handler(struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos) @@ -455,6 +499,10 @@ static __init int pid_namespaces_init(void) #ifdef CONFIG_CHECKPOINT_RESTORE register_sysctl_paths(kern_path, pid_ns_ctl_table); #endif + +#if defined(CONFIG_SYSCTL) && defined(CONFIG_MEMFD_CREATE) + register_sysctl_paths(vm_path, pid_ns_ctl_table_vm); +#endif return 0; } diff --git a/mm/memfd.c b/mm/memfd.c index 4ebeab94aa74..ec70675a7069 100644 --- a/mm/memfd.c +++ b/mm/memfd.c @@ -18,6 +18,7 @@ #include #include #include +#include #include /* @@ -263,12 +264,14 @@ long memfd_fcntl(struct file *file, unsigned int cmd, unsigned long arg) #define MFD_NAME_PREFIX_LEN (sizeof(MFD_NAME_PREFIX) - 1) #define MFD_NAME_MAX_LEN (NAME_MAX - MFD_NAME_PREFIX_LEN) -#define MFD_ALL_FLAGS (MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_HUGETLB) +#define MFD_ALL_FLAGS (MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_HUGETLB | MFD_NOEXEC_SEAL | MFD_EXEC) SYSCALL_DEFINE2(memfd_create, const char __user *, uname, unsigned int, flags) { + char comm[TASK_COMM_LEN]; + struct pid_namespace *ns; unsigned int *file_seals; struct file *file; int fd, error; @@ -285,6 +288,39 @@ SYSCALL_DEFINE2(memfd_create, return -EINVAL; } + /* Invalid if both EXEC and NOEXEC_SEAL are set.*/ + if ((flags & MFD_EXEC) && (flags & MFD_NOEXEC_SEAL)) + return -EINVAL; + + if (!(flags & (MFD_EXEC | MFD_NOEXEC_SEAL))) { +#ifdef CONFIG_SYSCTL + int sysctl = MEMFD_NOEXEC_SCOPE_EXEC; + + ns = task_active_pid_ns(current); + if (ns) + sysctl = ns->memfd_noexec_scope; + + switch (sysctl) { + case MEMFD_NOEXEC_SCOPE_EXEC: + flags |= MFD_EXEC; + break; + case MEMFD_NOEXEC_SCOPE_NOEXEC_SEAL: + flags |= MFD_NOEXEC_SEAL; + break; + default: + pr_warn_ratelimited( + "memfd_create(): MFD_NOEXEC_SEAL is enforced, pid=%d '%s'\n", + task_pid_nr(current), get_task_comm(comm, current)); + return -EINVAL; + } +#else + flags |= MFD_EXEC; +#endif + pr_warn_ratelimited( + "memfd_create() without MFD_EXEC nor MFD_NOEXEC_SEAL, pid=%d '%s'\n", + task_pid_nr(current), get_task_comm(comm, current)); + } + /* length includes terminating zero */ len = strnlen_user(uname, MFD_NAME_MAX_LEN + 1); if (len <= 0) @@ -328,7 +364,15 @@ SYSCALL_DEFINE2(memfd_create, file->f_mode |= FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE; file->f_flags |= O_LARGEFILE; - if (flags & MFD_ALLOW_SEALING) { + if (flags & MFD_NOEXEC_SEAL) { + struct inode *inode = file_inode(file); + + inode->i_mode &= ~0111; + file_seals = memfd_file_seals_ptr(file); + *file_seals &= ~F_SEAL_SEAL; + *file_seals |= F_SEAL_EXEC; + } else if (flags & MFD_ALLOW_SEALING) { + /* MFD_EXEC and MFD_ALLOW_SEALING are set */ file_seals = memfd_file_seals_ptr(file); *file_seals &= ~F_SEAL_SEAL; } From patchwork Tue Dec 6 15:02:31 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Xu X-Patchwork-Id: 30371 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp2876645wrr; Tue, 6 Dec 2022 07:10:37 -0800 (PST) X-Google-Smtp-Source: AA0mqf6sBnjgLkQOksI7gb7GvnXKwCMUSN96bh0QDrDhDfFWHzRWjiTDmseRf3kWnqqM66qGgR+H X-Received: by 2002:aa7:c509:0:b0:46c:42b8:b3b8 with SMTP id o9-20020aa7c509000000b0046c42b8b3b8mr15689359edq.37.1670339436943; Tue, 06 Dec 2022 07:10:36 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1670339436; cv=none; d=google.com; s=arc-20160816; b=S6sdlctJRIqm+N5r6DrRnEknHEc4FaW0YFrgNylXvmvn4lRBDoOK96Hi42m1r8im2n mKP5K+SuWWOnfa/A5eTWgdJAnYH4a3LiPu6TCwtvEVoDlOU0BqHGWF23I9VKkZ+yNqUn fcsYqHeU3ZW8pvwOIzHzUGk5jC9UDEDrtmvFv3rf9e2jeMHgLMvHf6zux3wS71daQvzT YacWkQ4KO725zdEtrA2hCxCALAmyzOzdPPSNUTZ3HxfVQufNvj7edRsz48cy9f5GjHDz uTNSLzu5n6Xflll8UTWEoYKiW5O/2qsBw/VjZRnIk9Thxsi2eqWsn46I9AsSsPC8bUlH 4lrg== 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=6szhuV271WBRooPiUYxdjBS9FRctTnZzx3+BuNL+4Q4=; b=R8lvhvZjy89oZennpNyE+AwvOzYTI57ZUXteTL9sSBzPLG+qzjhGcIIHGEj9UAtEgg 80wp9RFGj6ujfemGe4b6xM8C7xtjvTlIg6EBQvRbiiZaPP2o9m8rk9NaoUsmNPfJu0zo 289gfz2CFHWpbckwz/XAr7FW0uNph4tgAZtuKRihYGeyjKw3ib/V5ccwT9kHBxwWmOPV LQ+ctFnvbSJN37pQSsDnoXt5TYabD3in/wnTlROGnsjWzxcEC6juyzCDYxqj1pR9RMMt 9yCBEM3GK/R8zRHjHSMvsy4LhNxz+OKzqfa7KJS60Brhh7XJ14mxZTtu5AnjjUH8C94B vnTg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=Z8e7g8VS; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id g20-20020a056402321400b0046cc4440fbasi2232619eda.434.2022.12.06.07.10.08; Tue, 06 Dec 2022 07:10:36 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=Z8e7g8VS; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235279AbiLFPIL (ORCPT + 99 others); Tue, 6 Dec 2022 10:08:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60222 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233977AbiLFPGr (ORCPT ); Tue, 6 Dec 2022 10:06:47 -0500 Received: from mail-pj1-x1029.google.com (mail-pj1-x1029.google.com [IPv6:2607:f8b0:4864:20::1029]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CF1782AC6C for ; Tue, 6 Dec 2022 07:02:55 -0800 (PST) Received: by mail-pj1-x1029.google.com with SMTP id 3-20020a17090a098300b00219041dcbe9so15027735pjo.3 for ; Tue, 06 Dec 2022 07:02:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; 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=6szhuV271WBRooPiUYxdjBS9FRctTnZzx3+BuNL+4Q4=; b=Z8e7g8VSkg7JqHkBqAjKdN+QFOCeoevDFoGXwOSAd/ee3qA5UWiZXi7Xby+6W+6LXD 4TIjYL9Ufdb4C2aZ3GsGXLaCICrkTQOgEsQ2gEIiM1EBmjFWB5wpWVyVQ/1/7i661MBg rsyxjrSh1hIQJGUbYpSgIhT2a55Msluvqmhps= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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=6szhuV271WBRooPiUYxdjBS9FRctTnZzx3+BuNL+4Q4=; b=atMc0olNMvQ/wcrYfs5s8b2Vvxk9Fea5aT8THF4Yrz1EVx3fUlchSexE7HdjbUPeSo YzxJQwWpR33bPvHZ27t5gKCiIKMjGJBW2pBM2Guj2bbMgElzA9hSQ7qVvskj6h38eyCe pkXu8iwly5oMbCTZ+6vTJpHTs4JVUNLyo5GZkrhEKHTfRdATjaeOkw05qe7VG028zVqN OZT8YO5bjo+36WS6dz3PXAaCp9cSqhzKzyOsg7fa2M5oghnH3l2iPXv5P4UXxbQrE0Xx tu4qQ1aZfBSKNtluoRThKC2DfdRcmzPQS5fdlGzTxAOwCF8R+K3Aw3uJNi3hKDvLIVic xJTw== X-Gm-Message-State: ANoB5plgYcRtZIy3xc/PfLq5tdMMIrpDZ86mxx5zQRZm+EGjx04xG9xL G/MyQfGVEQaHvBy6StzaGYhhZQ== X-Received: by 2002:a17:90a:1bc2:b0:218:8bdb:de3f with SMTP id r2-20020a17090a1bc200b002188bdbde3fmr85820069pjr.225.1670338975208; Tue, 06 Dec 2022 07:02:55 -0800 (PST) Received: from jeffxud.c.googlers.com.com (30.202.168.34.bc.googleusercontent.com. [34.168.202.30]) by smtp.gmail.com with ESMTPSA id 62-20020a621441000000b00575bab45644sm3343019pfu.61.2022.12.06.07.02.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Dec 2022 07:02:54 -0800 (PST) From: jeffxu@chromium.org To: skhan@linuxfoundation.org, keescook@chromium.org Cc: akpm@linux-foundation.org, dmitry.torokhov@gmail.com, dverkamp@chromium.org, hughd@google.com, jeffxu@google.com, jorgelo@chromium.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-mm@kvack.org, jannh@google.com, linux-hardening@vger.kernel.org, Jeff Xu Subject: [PATCH v4 4/6] mm/memfd: Add write seals when apply SEAL_EXEC to executable memfd Date: Tue, 6 Dec 2022 15:02:31 +0000 Message-Id: <20221206150233.1963717-5-jeffxu@google.com> X-Mailer: git-send-email 2.39.0.rc0.267.gcb52ba06e7-goog In-Reply-To: <20221206150233.1963717-1-jeffxu@google.com> References: <20221206150233.1963717-1-jeffxu@google.com> MIME-Version: 1.0 X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1751477845282088320?= X-GMAIL-MSGID: =?utf-8?q?1751477845282088320?= From: Jeff Xu In order to avoid WX mappings, add F_SEAL_WRITE when apply F_SEAL_EXEC to an executable memfd, so W^X from start. This implys application need to fill the content of the memfd first, after F_SEAL_EXEC is applied, application won't be able to modify the content of the memfd. Typically, application seals the memfd right after writing to it. For example: 3> shall be right after 2> in steps below. 1. memfd_create(MFD_EXEC). 2. write() code to the memfd. 3. fcntl(F_ADD_SEALS, F_SEAL_EXEC) to convert the memfd to W^X. 4. call exec() on the memfd. Signed-off-by: Jeff Xu --- mm/memfd.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mm/memfd.c b/mm/memfd.c index ec70675a7069..92f0a5765f7c 100644 --- a/mm/memfd.c +++ b/mm/memfd.c @@ -222,6 +222,12 @@ static int memfd_add_seals(struct file *file, unsigned int seals) } } + /* + * SEAL_EXEC implys SEAL_WRITE, making W^X from the start. + */ + if (seals & F_SEAL_EXEC && inode->i_mode & 0111) + seals |= F_SEAL_SHRINK|F_SEAL_GROW|F_SEAL_WRITE|F_SEAL_FUTURE_WRITE; + *file_seals |= seals; error = 0; From patchwork Tue Dec 6 15:02:32 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Xu X-Patchwork-Id: 30369 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp2876569wrr; Tue, 6 Dec 2022 07:10:29 -0800 (PST) X-Google-Smtp-Source: AA0mqf6YDmOPi9LXZNxpxuguQPhWawmdRd3FUHtf1lbIKvPSsb84Le+LDw15LIv6fV4LZyCEzA9B X-Received: by 2002:a05:6402:1397:b0:467:78f2:d81f with SMTP id b23-20020a056402139700b0046778f2d81fmr59093447edv.88.1670339429460; Tue, 06 Dec 2022 07:10:29 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1670339429; cv=none; d=google.com; s=arc-20160816; b=yg5WfE2gfZ9ZASQcz5ffFSUr8QVHmuBHhU8GPKyqIdSm1DjX1QhkeZDH8LDhs7qKGY 4YlNMqgO7hYGig0vin190Dw6B/ZZiIYaWnhB0jCBYkd/dfZgDetWxqEiVE37fx8Zw19e rq4fkEl0zMpzlX9tX4xlS6oLwI8f8x6Nwdu0iRYaTlzbj/l5M/TmqXD+4yaezEBmoW8I UIY1fJcWiD6FnrMr1Xfqv97uc8YteXpQOXKxoPFrsShO2c0qqCNco6JTPcLnnbh4riDa t74Hxk8Y7kdrXvuVLawn2+uz8Lh6ljHlwGWIxkOhFkbhhss95N1TSbyF0hs9aWOubflE je1g== 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=BMuCN4bdPpTwWJ2iwnu2KEtJZwK23OdE1QXZ74xgH4g=; b=G8fFgoMzAS5MgY6Thh74h2uR8jHVbqK/0qSQFNU4KBcY1bgDJSqxmEAgcaKzeM2So4 4+sz6dvAdH7K/nq6Inanx9brStl/jwTlnmfiZnS+8SVrwLwrKTY6APuFRYNdcJt53TEP ygg9W6lXL6BeqhZhGShBanNkLK+xr1DtXssraDWBTOREG1PWBeYhn1chVRNaxUk/fItb 2mNOnypNTywtoKX0iw7KKUAbsIQpzPkazMzbOGBTbZ5jM2x+R2buCG3ojUNoxn+O13Rt EScwTZBuO0v/u87uJPlfaNQSYq/IuTgHNlHCZRaQt+t2tgwjkV15YaHFEy0geUWcErE1 NhxA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=XJLjuopX; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id o8-20020a170906974800b007c0b6decb95si14526199ejy.739.2022.12.06.07.10.01; Tue, 06 Dec 2022 07:10:29 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=XJLjuopX; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235228AbiLFPII (ORCPT + 99 others); Tue, 6 Dec 2022 10:08:08 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60900 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234171AbiLFPGr (ORCPT ); Tue, 6 Dec 2022 10:06:47 -0500 Received: from mail-pf1-x436.google.com (mail-pf1-x436.google.com [IPv6:2607:f8b0:4864:20::436]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 26B692B18E for ; Tue, 6 Dec 2022 07:02:57 -0800 (PST) Received: by mail-pf1-x436.google.com with SMTP id t18so4427710pfq.13 for ; Tue, 06 Dec 2022 07:02:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; 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=BMuCN4bdPpTwWJ2iwnu2KEtJZwK23OdE1QXZ74xgH4g=; b=XJLjuopX/noBfpUchfjWoYWRDGOau8gDq97AcZA+rWP2IkrKc0qTbaIJxgZr0SCI41 cxlB1zOILdsMJlzP5JvTr5c4JOIVt4CfVlicsOoqf6EC7zkAPENFrXm5FFOptw+FbFmL 8bE++Pk+TZ4th9HxnUGTIPA71o5g5KWeTug14= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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=BMuCN4bdPpTwWJ2iwnu2KEtJZwK23OdE1QXZ74xgH4g=; b=3h+TZ8M8WV9ycRpZkYVjFzH92BwilKanV7vXKvmQ76KgxUjk68OWuAX4TD/y0ykYef XNTw9J77dPxy/jiy5sg/T2i8RRB+eBpkWj3IR2tV2ONHXIOYQ9whNBksAubbyAOFU67I AschRG0EB1HhHohz+uHbjka857Z6SAtSOYmn5IVF532OpeyhBYv2dLG23pSufij1Hp7v YEz2+WnymJBRO0u6FJWwNV8Y16KDENiErCA/xx2wGMaQDc57H5pfjiDrHgwgSO9U0yh1 QVq84O4TyydOiX06kdTomByJuQ3nYCFx4PaAiLPuX0DxaYg0FkTwdbx7V5lba6+6gqCX Bt3Q== X-Gm-Message-State: ANoB5plgF7J0r7fsOUH/snzutV9nj5cj05wFSZ45r6/Xh64a9vNkUa6U J0zBQPbkzXZES3DcQ0rTh1Wueg== X-Received: by 2002:aa7:808b:0:b0:575:71d2:4702 with SMTP id v11-20020aa7808b000000b0057571d24702mr35704594pff.48.1670338976656; Tue, 06 Dec 2022 07:02:56 -0800 (PST) Received: from jeffxud.c.googlers.com.com (30.202.168.34.bc.googleusercontent.com. [34.168.202.30]) by smtp.gmail.com with ESMTPSA id 62-20020a621441000000b00575bab45644sm3343019pfu.61.2022.12.06.07.02.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Dec 2022 07:02:56 -0800 (PST) From: jeffxu@chromium.org To: skhan@linuxfoundation.org, keescook@chromium.org Cc: akpm@linux-foundation.org, dmitry.torokhov@gmail.com, dverkamp@chromium.org, hughd@google.com, jeffxu@google.com, jorgelo@chromium.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-mm@kvack.org, jannh@google.com, linux-hardening@vger.kernel.org, Jeff Xu Subject: [PATCH v4 5/6] selftests/memfd: add tests for MFD_NOEXEC_SEAL MFD_EXEC Date: Tue, 6 Dec 2022 15:02:32 +0000 Message-Id: <20221206150233.1963717-6-jeffxu@google.com> X-Mailer: git-send-email 2.39.0.rc0.267.gcb52ba06e7-goog In-Reply-To: <20221206150233.1963717-1-jeffxu@google.com> References: <20221206150233.1963717-1-jeffxu@google.com> MIME-Version: 1.0 X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1751477837609711169?= X-GMAIL-MSGID: =?utf-8?q?1751477837609711169?= From: Jeff Xu Tests to verify MFD_NOEXEC, MFD_EXEC and vm.memfd_noexec sysctl. Signed-off-by: Jeff Xu Co-developed-by: Daniel Verkamp Signed-off-by: Daniel Verkamp Change-Id: Idccec1141255ca948c849f4efc8ba5e97f78b6eb --- tools/testing/selftests/memfd/fuse_test.c | 1 + tools/testing/selftests/memfd/memfd_test.c | 185 ++++++++++++++++++++- 2 files changed, 181 insertions(+), 5 deletions(-) diff --git a/tools/testing/selftests/memfd/fuse_test.c b/tools/testing/selftests/memfd/fuse_test.c index be675002f918..93798c8c5d54 100644 --- a/tools/testing/selftests/memfd/fuse_test.c +++ b/tools/testing/selftests/memfd/fuse_test.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include diff --git a/tools/testing/selftests/memfd/memfd_test.c b/tools/testing/selftests/memfd/memfd_test.c index 1d7e7b36bbdd..7fc78ff62d40 100644 --- a/tools/testing/selftests/memfd/memfd_test.c +++ b/tools/testing/selftests/memfd/memfd_test.c @@ -32,10 +32,20 @@ #define F_SEAL_EXEC 0x0020 #endif +#define F_WX_SEALS (F_SEAL_SHRINK | \ + F_SEAL_GROW | \ + F_SEAL_WRITE | \ + F_SEAL_FUTURE_WRITE | \ + F_SEAL_EXEC) + #ifndef MAX_PATH #define MAX_PATH 256 #endif +#ifndef MFD_NOEXEC_SEAL +#define MFD_NOEXEC_SEAL 0x0008U +#endif + /* * Default is not to test hugetlbfs */ @@ -86,6 +96,21 @@ static int mfd_assert_new(const char *name, loff_t sz, unsigned int flags) return fd; } +static void sysctl_assert_write(const char *val) +{ + int fd = open("/proc/sys/vm/memfd_noexec", O_WRONLY | O_CLOEXEC); + + if (fd < 0) { + printf("open sysctl failed\n"); + abort(); + } + + if (write(fd, val, strlen(val)) < 0) { + printf("write sysctl failed\n"); + abort(); + } +} + static int mfd_assert_reopen_fd(int fd_in) { int fd; @@ -764,6 +789,9 @@ static void test_create(void) mfd_fail_new("", ~0); mfd_fail_new("", 0x80000000U); + /* verify EXEC and NOEXEC_SEAL can't both be set */ + mfd_fail_new("", MFD_EXEC | MFD_NOEXEC_SEAL); + /* verify MFD_CLOEXEC is allowed */ fd = mfd_assert_new("", 0, MFD_CLOEXEC); close(fd); @@ -975,20 +1003,21 @@ static void test_seal_resize(void) /* * Test SEAL_EXEC - * Test that chmod() cannot change x bits after sealing + * Test fd is created with exec and allow sealing. + * chmod() cannot change x bits after sealing. */ -static void test_seal_exec(void) +static void test_exec_seal(void) { int fd; printf("%s SEAL-EXEC\n", memfd_str); + printf("%s Apply SEAL_EXEC\n", memfd_str); fd = mfd_assert_new("kern_memfd_seal_exec", mfd_def_size, - MFD_CLOEXEC | MFD_ALLOW_SEALING); + MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_EXEC); mfd_assert_mode(fd, 0777); - mfd_assert_chmod(fd, 0644); mfd_assert_has_seals(fd, 0); @@ -1002,10 +1031,152 @@ static void test_seal_exec(void) mfd_fail_chmod(fd, 0700); mfd_fail_chmod(fd, 0100); mfd_assert_chmod(fd, 0666); + mfd_assert_write(fd); + close(fd); + + printf("%s Apply ALL_SEALS\n", memfd_str); + fd = mfd_assert_new("kern_memfd_seal_exec", + mfd_def_size, + MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_EXEC); + + mfd_assert_mode(fd, 0777); + mfd_assert_chmod(fd, 0700); + + mfd_assert_has_seals(fd, 0); + mfd_assert_add_seals(fd, F_SEAL_EXEC); + mfd_assert_has_seals(fd, F_WX_SEALS); + mfd_fail_chmod(fd, 0711); + mfd_fail_chmod(fd, 0600); + mfd_fail_write(fd); close(fd); } +/* + * Test EXEC_NO_SEAL + * Test fd is created with exec and not allow sealing. + */ +static void test_exec_no_seal(void) +{ + int fd; + + printf("%s EXEC_NO_SEAL\n", memfd_str); + + /* Create with EXEC but without ALLOW_SEALING */ + fd = mfd_assert_new("kern_memfd_exec_no_sealing", + mfd_def_size, + MFD_CLOEXEC | MFD_EXEC); + mfd_assert_mode(fd, 0777); + mfd_assert_has_seals(fd, F_SEAL_SEAL); + mfd_assert_chmod(fd, 0666); + close(fd); +} + +/* + * Test memfd_create with MFD_NOEXEC flag + */ +static void test_noexec_seal(void) +{ + int fd; + + printf("%s NOEXEC_SEAL\n", memfd_str); + + /* Create with NOEXEC and ALLOW_SEALING */ + fd = mfd_assert_new("kern_memfd_noexec", + mfd_def_size, + MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_NOEXEC_SEAL); + mfd_assert_mode(fd, 0666); + mfd_assert_has_seals(fd, F_SEAL_EXEC); + mfd_fail_chmod(fd, 0777); + close(fd); + + /* Create with NOEXEC but without ALLOW_SEALING */ + fd = mfd_assert_new("kern_memfd_noexec", + mfd_def_size, + MFD_CLOEXEC | MFD_NOEXEC_SEAL); + mfd_assert_mode(fd, 0666); + mfd_assert_has_seals(fd, F_SEAL_EXEC); + mfd_fail_chmod(fd, 0777); + close(fd); +} + +static void test_sysctl_child(void) +{ + int fd, pid, ret; + + printf("%s sysctl 0\n", memfd_str); + sysctl_assert_write("0"); + fd = mfd_assert_new("kern_memfd_sysctl_0", + mfd_def_size, + MFD_CLOEXEC | MFD_ALLOW_SEALING); + + mfd_assert_mode(fd, 0777); + mfd_assert_has_seals(fd, 0); + mfd_assert_chmod(fd, 0644); + close(fd); + + printf("%s sysctl 1\n", memfd_str); + sysctl_assert_write("1"); + fd = mfd_assert_new("kern_memfd_sysctl_1", + mfd_def_size, + MFD_CLOEXEC | MFD_ALLOW_SEALING); + + mfd_assert_mode(fd, 0666); + mfd_assert_has_seals(fd, F_SEAL_EXEC); + mfd_fail_chmod(fd, 0777); + close(fd); + + printf("%s sysctl 2\n", memfd_str); + sysctl_assert_write("2"); + mfd_fail_new("kern_memfd_sysctl_2", + MFD_CLOEXEC | MFD_ALLOW_SEALING); +} + +static int newpid_thread_fn(void *arg) +{ + test_sysctl_child(); + return 0; +} + +static pid_t spawn_newpid_thread(unsigned int flags) +{ + uint8_t *stack; + pid_t pid; + + stack = malloc(STACK_SIZE); + if (!stack) { + printf("malloc(STACK_SIZE) failed: %m\n"); + abort(); + } + + pid = clone(newpid_thread_fn, + stack + STACK_SIZE, + SIGCHLD | flags, + NULL); + if (pid < 0) { + printf("clone() failed: %m\n"); + abort(); + } + + return pid; +} + +static void join_newpid_thread(pid_t pid) +{ + waitpid(pid, NULL, 0); +} + +/* + * Test sysctl + * A very basic sealing test to see whether setting/retrieving seals works. + */ +static void test_sysctl(void) +{ + int pid = spawn_newpid_thread(CLONE_NEWPID); + + join_newpid_thread(pid); +} + /* * Test sharing via dup() * Test that seals are shared between dupped FDs and they're all equal. @@ -1179,13 +1350,15 @@ int main(int argc, char **argv) test_create(); test_basic(); + test_exec_seal(); + test_exec_no_seal(); + test_noexec_seal(); test_seal_write(); test_seal_future_write(); test_seal_shrink(); test_seal_grow(); test_seal_resize(); - test_seal_exec(); test_share_dup("SHARE-DUP", ""); test_share_mmap("SHARE-MMAP", ""); @@ -1201,6 +1374,8 @@ int main(int argc, char **argv) test_share_fork("SHARE-FORK", SHARED_FT_STR); join_idle_thread(pid); + test_sysctl(); + printf("memfd: DONE\n"); return 0; From patchwork Tue Dec 6 15:02:33 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Xu X-Patchwork-Id: 30372 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp2876742wrr; Tue, 6 Dec 2022 07:10:45 -0800 (PST) X-Google-Smtp-Source: AA0mqf7O9KlZ8vAjX8wrAl0D7FLvni2RWx0X/9udklL6pe14C4Jl2GRj/J2VdPien00Q9fKhbq1i X-Received: by 2002:a17:906:8d7:b0:7c0:efba:b39c with SMTP id o23-20020a17090608d700b007c0efbab39cmr8923078eje.209.1670339444992; Tue, 06 Dec 2022 07:10:44 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1670339444; cv=none; d=google.com; s=arc-20160816; b=JVduWk1IHuL/k53SbJGoAJmLQv4ZgwSfXS8CMmYCuTpU/PnXZGmXTqxZBVAPvBTV4a LTsdzoZea4uVGcsciG3emEYkZz+9E/Kggw7ub/ThztXy8SEdsEJISwbJjbc6s39s8bZn cXo8eZJ+CQZMkgpgqMvavlM04OIeIbHmEcZXs7NiZzEb5JHoR5lMrZSAcnn8N6SY7ob8 0FY7DWLztg9xkmhVbs5GbVJ7FVS3iaZ2dg/KVXJlNR0iQ0aOZ/pYfn0k/xt8WUaMi6SN +HzuEzZ/tgHBaBvd57a8KYkmNPEElb6KOlEIzFCMNHabsL6xXvKf+K6D1IPQ4NrdOvVM rk2w== 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=RP30KXKl/PR6YPpKgU+DDNG5UwR2kZxBVDTlEl1cNxU=; b=wDP9hTOH4A1RSyK+U8P72N1bISIo9uYp6EwKXCZJGZ3J+SJ77gyufOlKscKl+mQKTA Xjy+9R60i3SR6BkzlSMK+D7RMmsRqP0/Fi3PEn7UyWcMC14/CBr2kuwdycGgrijzDjgJ +P14WgYyWZVwPDMe+xbTaa4jgtkksEE+RZGAUnNJZI0PDcLhhRY/lK0+zQfhsu2jXkMB FKNX4zE03s056QlywjNlwYFWGjG3EiGjmWXVBLaDtIycRDSedP7UqWflinycYo/7kH/P QZ0IwjNb5BWV53T6Vk0mEkajGhn3l9FONdaRMEgB3J206z4ie6OD1VNaUNV4T/h+rqPz HQ0A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=HPjs8mhe; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id n14-20020a05640205ce00b0046af790c410si2333925edx.569.2022.12.06.07.10.16; Tue, 06 Dec 2022 07:10:44 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=HPjs8mhe; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235312AbiLFPIR (ORCPT + 99 others); Tue, 6 Dec 2022 10:08:17 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60568 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235323AbiLFPG7 (ORCPT ); Tue, 6 Dec 2022 10:06:59 -0500 Received: from mail-pj1-x102d.google.com (mail-pj1-x102d.google.com [IPv6:2607:f8b0:4864:20::102d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EE0972E9C5 for ; Tue, 6 Dec 2022 07:03:19 -0800 (PST) Received: by mail-pj1-x102d.google.com with SMTP id o12so14676449pjo.4 for ; Tue, 06 Dec 2022 07:03:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; 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=RP30KXKl/PR6YPpKgU+DDNG5UwR2kZxBVDTlEl1cNxU=; b=HPjs8mheLAahBm8OUAn4PnD0Mw9299JNdm/Ya3WP81eG9XgGqqNUb1NxHROe4uAzpa pxH4GbCDjdsUHJZFXJDWpAGkq0hfWPstAQ4vbO8Nd7CmrtGPKaiK0LCfcK9X8GCoRloL pYH55QtHDsWGwxU98YexyagX1ikk0x6JAHEyM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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=RP30KXKl/PR6YPpKgU+DDNG5UwR2kZxBVDTlEl1cNxU=; b=ZPhiAce1AizwA3V2BdjJGENXOaHmfEwE4HW3rn2T0djJb0QEprM/GHlWQNyUeWhsm6 L0ADaJwo1IQcc7xzLMFm6YsKUURmeouFeBtEk+HYs/HLI1M1MvJVZUHJK4SXCO/fMSqd /3+zOA63X69Vtd2UWvtLxn7z6uV0E1F/+rrtSZDIfa/feNFH3WO47mrYzuODjMwS9rZE aJPjzGOnIXgHHH0LKl8plXKK78nPZYBiD+snYsiQm1L0Zqzp2+N3+ChZpIOXa+N96ELk +/oEiXbTcmdeNsJ3VxX8+EtfMQA25HiUbVu8Uwk1Te4mw1IdWswzPKdAl2rCGOtvR5bx DPmw== X-Gm-Message-State: ANoB5pmrjsGx+swgPrcYOsyIIIKIOfOXUyGytAqBdAc5A0DiuuMpscbA Qe0LF2uXM/LxDlHAf6yGy5qiRw== X-Received: by 2002:a17:90a:13c4:b0:219:e3de:53e3 with SMTP id s4-20020a17090a13c400b00219e3de53e3mr7665466pjf.87.1670338978111; Tue, 06 Dec 2022 07:02:58 -0800 (PST) Received: from jeffxud.c.googlers.com.com (30.202.168.34.bc.googleusercontent.com. [34.168.202.30]) by smtp.gmail.com with ESMTPSA id 62-20020a621441000000b00575bab45644sm3343019pfu.61.2022.12.06.07.02.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Dec 2022 07:02:57 -0800 (PST) From: jeffxu@chromium.org To: skhan@linuxfoundation.org, keescook@chromium.org Cc: akpm@linux-foundation.org, dmitry.torokhov@gmail.com, dverkamp@chromium.org, hughd@google.com, jeffxu@google.com, jorgelo@chromium.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-mm@kvack.org, jannh@google.com, linux-hardening@vger.kernel.org, Jeff Xu , kernel test robot Subject: [PATCH v4 6/6] mm/memfd: security hook for memfd_create Date: Tue, 6 Dec 2022 15:02:33 +0000 Message-Id: <20221206150233.1963717-7-jeffxu@google.com> X-Mailer: git-send-email 2.39.0.rc0.267.gcb52ba06e7-goog In-Reply-To: <20221206150233.1963717-1-jeffxu@google.com> References: <20221206150233.1963717-1-jeffxu@google.com> MIME-Version: 1.0 X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1751477853623774608?= X-GMAIL-MSGID: =?utf-8?q?1751477853623774608?= From: Jeff Xu The new security_memfd_create allows lsm to check flags of memfd_create. The security by default system (such as chromeos) can use this to implement system wide lsm to allow only non-executable memfd being created. Signed-off-by: Jeff Xu Reported-by: kernel test robot --- include/linux/lsm_hook_defs.h | 1 + include/linux/lsm_hooks.h | 4 ++++ include/linux/security.h | 6 ++++++ mm/memfd.c | 5 +++++ security/security.c | 13 +++++++++++++ 5 files changed, 29 insertions(+) diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index ec119da1d89b..fd40840927c8 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -164,6 +164,7 @@ LSM_HOOK(int, 0, file_alloc_security, struct file *file) LSM_HOOK(void, LSM_RET_VOID, file_free_security, struct file *file) LSM_HOOK(int, 0, file_ioctl, struct file *file, unsigned int cmd, unsigned long arg) +LSM_HOOK(int, 0, memfd_create, char *name, unsigned int flags) LSM_HOOK(int, 0, mmap_addr, unsigned long addr) LSM_HOOK(int, 0, mmap_file, struct file *file, unsigned long reqprot, unsigned long prot, unsigned long flags) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 4ec80b96c22e..5a18a6552278 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -543,6 +543,10 @@ * simple integer value. When @arg represents a user space pointer, it * should never be used by the security module. * Return 0 if permission is granted. + * @memfd_create: + * @name is the name of memfd file. + * @flags is the flags used in memfd_create. + * Return 0 if permission is granted. * @mmap_addr : * Check permissions for a mmap operation at @addr. * @addr contains virtual address that will be used for the operation. diff --git a/include/linux/security.h b/include/linux/security.h index ca1b7109c0db..5b87a780822a 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -384,6 +384,7 @@ int security_file_permission(struct file *file, int mask); int security_file_alloc(struct file *file); void security_file_free(struct file *file); int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg); +int security_memfd_create(char *name, unsigned int flags); int security_mmap_file(struct file *file, unsigned long prot, unsigned long flags); int security_mmap_addr(unsigned long addr); @@ -963,6 +964,11 @@ static inline int security_file_ioctl(struct file *file, unsigned int cmd, return 0; } +static inline int security_memfd_create(char *name, unsigned int flags) +{ + return 0; +} + static inline int security_mmap_file(struct file *file, unsigned long prot, unsigned long flags) { diff --git a/mm/memfd.c b/mm/memfd.c index 92f0a5765f7c..f04ed5f0474f 100644 --- a/mm/memfd.c +++ b/mm/memfd.c @@ -356,6 +356,11 @@ SYSCALL_DEFINE2(memfd_create, goto err_name; } + /* security hook for memfd_create */ + error = security_memfd_create(name, flags); + if (error) + return error; + if (flags & MFD_HUGETLB) { file = hugetlb_file_setup(name, 0, VM_NORESERVE, HUGETLB_ANONHUGE_INODE, diff --git a/security/security.c b/security/security.c index 79d82cb6e469..5c018e080923 100644 --- a/security/security.c +++ b/security/security.c @@ -1010,6 +1010,19 @@ int security_sb_clone_mnt_opts(const struct super_block *oldsb, } EXPORT_SYMBOL(security_sb_clone_mnt_opts); +int security_add_mnt_opt(const char *option, const char *val, int len, + void **mnt_opts) +{ + return call_int_hook(sb_add_mnt_opt, -EINVAL, + option, val, len, mnt_opts); +} +EXPORT_SYMBOL(security_add_mnt_opt); + +int security_memfd_create(char *name, unsigned int flags) +{ + return call_int_hook(memfd_create, 0, name, flags); +} + int security_move_mount(const struct path *from_path, const struct path *to_path) { return call_int_hook(move_mount, 0, from_path, to_path);