From patchwork Fri Dec 9 16:04:48 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Xu X-Patchwork-Id: 31863 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp860681wrr; Fri, 9 Dec 2022 08:08:04 -0800 (PST) X-Google-Smtp-Source: AA0mqf5a6mmiEtLUiMtZFzaiWedVuFH4kvgvDJQ6FVmGi2mIgyGtnyKCm8hmNGwG8rwhO0Beupsj X-Received: by 2002:a05:6a20:d38e:b0:aa:5c2d:ae2a with SMTP id iq14-20020a056a20d38e00b000aa5c2dae2amr7784826pzb.61.1670602083900; Fri, 09 Dec 2022 08:08:03 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1670602083; cv=none; d=google.com; s=arc-20160816; b=IJYs0v65mPBoPZNKYp7XG1PmCLHtMI0z65RI7XEy9TL/BJUsoQsRkpd0CXPXniAFgA JpzkywFsOuKH+ylp515qEoA4r+ElzN2wqR0SuVynnmsUU9t5fesj1cTobjfWAaEjRjQz VfL7LCZEV7HeDRHHyeAqGtUH5f1zXV5IDZKMROi8jutKPnIbW+pRZGaZG5C6ChaZhQYR q4//yApEAw0xsvk/TWg1nBudPtthl84ygSI4V7H+6k8ndIc4KHUoSstceDrOXyxWtfPm IYK60TE8zuH6BAXdWea2SKwDICP6yrf2r+KIcY1TAQeqPQDtV3lpfdgH0W0tbnFUKedx 9EOA== 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=1Z0pNLRJ0HO6mEsQsP4xR7y3AzecdWz1BUkrTkkGBPM=; b=GhPCNfiAliiIk0hrEuH0udU5rjp6OZPg/X2J0Vlw5gVZAYB55W0ArhTvo4rPbzqzXE aZz1o6AOk54nBi1HGdalJj9s9or3TjPKFaYJ4ViQUVBcSBHvL9l6DgRj1XFnInGdEIlU eMMpFK0KJZWVxkMki9cEGhi7pqhBJUGhCS38mhaFrb+Jr2ego8x3F45WGWTlUYPiSawc xQLDyLTnfN3LeO59r3gOsu/1GbHN4YqhWZrHaqwGD6Z/LPUk/UWlh8Bvehf14UDRAoM/ dEwQm3NlfQjltmQlE9e6Ym/OHcXpDk4RI4iT2F0uqkOAknMfHJtPA6D3t5IVun57RZJ1 gzMQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=NKb1GAp4; 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 e23-20020a656897000000b004772bd28105si1656272pgt.831.2022.12.09.08.07.50; Fri, 09 Dec 2022 08:08:03 -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=NKb1GAp4; 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 S229680AbiLIQFJ (ORCPT + 99 others); Fri, 9 Dec 2022 11:05:09 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49714 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229835AbiLIQFC (ORCPT ); Fri, 9 Dec 2022 11:05:02 -0500 Received: from mail-pg1-x535.google.com (mail-pg1-x535.google.com [IPv6:2607:f8b0:4864:20::535]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2F7A351C04 for ; Fri, 9 Dec 2022 08:05:01 -0800 (PST) Received: by mail-pg1-x535.google.com with SMTP id w37so3822652pga.5 for ; Fri, 09 Dec 2022 08:05:01 -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=1Z0pNLRJ0HO6mEsQsP4xR7y3AzecdWz1BUkrTkkGBPM=; b=NKb1GAp4o6SR8RAwURjuFDuN+zxhqHMcW5ssGhcZ+DU+PFAx+LUcL7yPaq/lio2rqx gsbeokPy4gQONsYdB+99EBxJJNsHClsPC4BjpU3IrUyEzRti9qGuEoFDz7cNCZF8sD6t PVp5eg0FzAb2GvkkjoCUfSPMbbq/LQxGCDCUg= 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=1Z0pNLRJ0HO6mEsQsP4xR7y3AzecdWz1BUkrTkkGBPM=; b=PdeS7xvyNC4mEzyH780yhXUUx3gvCyB/uhzgTiGYlSdy3xLKK7o6r1xuf0G8dxoD3J LVfMKePQV3rB3SH3E5wOSrE4gul6DidMayFJLMqs3WbX+JqkppO7ZRtNIEhD0nDCDiDW D8j6SgnJm8T75i7vSbrEw9+ZcQ+vkhr1qGbFnG75mxWgyEPtK1lvQTTLAJNA+agNg8DL 3SnwflF2eX3qwtpkZaMCqNOPFMEa4cee9hkEeM/wkalPm4/Drkj/8CJY0S3ruN8GV1QH DHdvFCbkmod23vtuBGJDbMpehF+9znGxKugk/hAEwEV+FWVSw3tVZC2EZh4GzN2yq3Z3 /RGA== X-Gm-Message-State: ANoB5pk5d6D10IDWxwCTXXcF2vvclEwSCaG9xxX0YUmvDGlY1GfGe4Vt EQUcigSjiuxAuPmd+yweT+hc6g== X-Received: by 2002:a62:870d:0:b0:576:f02e:d0ef with SMTP id i13-20020a62870d000000b00576f02ed0efmr5609008pfe.4.1670601900690; Fri, 09 Dec 2022 08:05:00 -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 a15-20020aa795af000000b00576670cc170sm1460504pfk.93.2022.12.09.08.04.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 09 Dec 2022 08:05:00 -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, linux-security-module@vger.kernel.org Subject: [PATCH v7 1/6] mm/memfd: add F_SEAL_EXEC Date: Fri, 9 Dec 2022 16:04:48 +0000 Message-Id: <20221209160453.3246150-2-jeffxu@google.com> X-Mailer: git-send-email 2.39.0.rc1.256.g54fd8350bd-goog In-Reply-To: <20221209160453.3246150-1-jeffxu@google.com> References: <20221209160453.3246150-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?1751753250919352668?= X-GMAIL-MSGID: =?utf-8?q?1751753250919352668?= 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 Reviewed-by: Kees Cook --- 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 Fri Dec 9 16:04:49 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Xu X-Patchwork-Id: 31864 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp860715wrr; Fri, 9 Dec 2022 08:08:07 -0800 (PST) X-Google-Smtp-Source: AA0mqf4nD7bDU8rPRENjfg6oWdjhBzCeUqduk0KzwchGh74Lcq406Zz6mmbuYR/Jnqax8sRgL3gi X-Received: by 2002:a05:6a21:6d8d:b0:ab:ee20:b004 with SMTP id wl13-20020a056a216d8d00b000abee20b004mr10038956pzb.28.1670602086969; Fri, 09 Dec 2022 08:08:06 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1670602086; cv=none; d=google.com; s=arc-20160816; b=zPxoFqxnDx6kDDPmuE3SvDTkGkMuqxBHLDJ4/kG/v24Kn1iR2zJyOQsoFE0G1DkQ14 FqbBd4YdH1qzvD7RPtjW9suR5by12G6LEd2+waHLFH5U+sR3Qe+ktl/LAjUV0nQ29Pz8 0v9R5bwOhxdx7WKaYSsyP6OH7iHt66vyPfy8VuIAC3ERM8V86MRsdErOXR0HblWNrNpF bTIj5A57VaJRQ6zfiP4YCT1X+njV3DC0uClPXsbFVs9aETXjDEI5ekq6n+0oHo2uTfdg +5pF+RxliDJoOIliNEZKcTlcZiLUAbQ4jQQyD3AOhuowYWGEsUyTEy1/5YpPDU+zmUxC zr3A== 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=vFajmLWzEheOspCEYhY0eo6ZhecGZeOzelViubfUiKU=; b=U9Zj8WJFZW4/4Wv2JdSzwsDGiTz5Wu/hCRre5FTGIbrFEiB3p9qxlTykbs663iigBQ p9pcaMx1s5XWpGNcJz4o38I9fgBMGMKo0L/I1ep5XIJTioLnOrha3XGsos4U20afVrgk yLKhmzyDKST0UtCnPIk5KHuIcdLIrOJdATC/b14Ndi5CKOn/peDp18YU0NRIZKBd46m+ 8NTErOR5M0hZTqC26HCHpZEHH4tuun7CvTJPB//kNMEPYrw+nSW1Tyw0LbxJoj9ZySjc DuJKc6EHYFZ/4ln1JHz6TcNyVyTwhK3ipBqdoMc1VvY9+tdGOykaLQfUmFGk20bSKnS9 tZBA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=dptKtOCd; 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 i184-20020a6387c1000000b00478d1230674si1638181pge.736.2022.12.09.08.07.53; Fri, 09 Dec 2022 08:08:06 -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=dptKtOCd; 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 S229734AbiLIQF1 (ORCPT + 99 others); Fri, 9 Dec 2022 11:05:27 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49784 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230077AbiLIQFE (ORCPT ); Fri, 9 Dec 2022 11:05:04 -0500 Received: from mail-pf1-x42c.google.com (mail-pf1-x42c.google.com [IPv6:2607:f8b0:4864:20::42c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 834C8554F6 for ; Fri, 9 Dec 2022 08:05:02 -0800 (PST) Received: by mail-pf1-x42c.google.com with SMTP id t18so3978686pfq.13 for ; Fri, 09 Dec 2022 08:05:02 -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=vFajmLWzEheOspCEYhY0eo6ZhecGZeOzelViubfUiKU=; b=dptKtOCdTYDRw1zV2LczU6Mn1xxfY3K7c4rFaFud5vbOoJLbaV53h863pAiKxktADU hrt1ext9eD2TGdU12+Ynlfi3y5U15x8duzI8R0NoHOvfww3B8KJhixGy5q8AKCjevVIp bMEZAl3CbIzNJxQFT7JG1kmnsDBR/bSc/JGm0= 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=vFajmLWzEheOspCEYhY0eo6ZhecGZeOzelViubfUiKU=; b=CiFJjVbpX30oV+BQmuFIxkXNNJYRwQGG+l+eb5P030KEFep/5TyfdVFwjBlxwXk805 HcYJWdb9VNfT/AxqGOvhyy69NlIlkRiuM/SQot+6QqM25LlXxY0X6bshOOSgrIV7hOJV 9n2CyCQhjoPxvRrk96YXTW+wx7+BsIdpUAWxnEiTHzU4w89+v/6c8LU40Q4f4xtYU20x Y2KsoyRSazCg0o3isQo5Ja83oFX4UYT/rPtLTLLd+tsoZteenGhj6TL3I32AlL/UyX1P hYMntKkzghGj42Ra6ZGnNu71+ZlVlvyP2Oyt9Jaf325j58gBNcYmHFCECloc4M1oOoQt psig== X-Gm-Message-State: ANoB5pkuTF48ntkkBtldo1dtYUsmvtoVnpfaxqRtBY2knY5p7A3Gfi30 BRn6+JGsG1x5gxe/7TBVagmdPA== X-Received: by 2002:a05:6a00:1d14:b0:578:1708:6416 with SMTP id a20-20020a056a001d1400b0057817086416mr113562pfx.11.1670601901687; Fri, 09 Dec 2022 08:05:01 -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 a15-20020aa795af000000b00576670cc170sm1460504pfk.93.2022.12.09.08.05.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 09 Dec 2022 08:05:01 -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, linux-security-module@vger.kernel.org Subject: [PATCH v7 2/6] selftests/memfd: add tests for F_SEAL_EXEC Date: Fri, 9 Dec 2022 16:04:49 +0000 Message-Id: <20221209160453.3246150-3-jeffxu@google.com> X-Mailer: git-send-email 2.39.0.rc1.256.g54fd8350bd-goog In-Reply-To: <20221209160453.3246150-1-jeffxu@google.com> References: <20221209160453.3246150-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?1751753254067450940?= X-GMAIL-MSGID: =?utf-8?q?1751753254067450940?= 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 Reviewed-by: Kees Cook --- tools/testing/selftests/memfd/memfd_test.c | 123 ++++++++++++++++++++- 1 file changed, 122 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/memfd/memfd_test.c b/tools/testing/selftests/memfd/memfd_test.c index 94df2692e6e4..f18a15a1f275 100644 --- a/tools/testing/selftests/memfd/memfd_test.c +++ b/tools/testing/selftests/memfd/memfd_test.c @@ -28,12 +28,38 @@ #define MFD_DEF_SIZE 8192 #define STACK_SIZE 65536 +#define F_SEAL_EXEC 0x0020 + /* * 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[PATH_MAX]; + int size; + ssize_t nbytes; + + size = snprintf(buf1, PATH_MAX, "/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 +124,14 @@ static unsigned int mfd_assert_get_seals(int fd) static void mfd_assert_has_seals(int fd, unsigned int seals) { + char buf[PATH_MAX]; + int nbytes; unsigned int s; + fd2name(fd, buf, PATH_MAX); 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 +623,64 @@ static void mfd_fail_grow_write(int fd) } } +static void mfd_assert_mode(int fd, int mode) +{ + struct stat st; + char buf[PATH_MAX]; + int nbytes; + + fd2name(fd, buf, PATH_MAX); + + 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[PATH_MAX]; + int nbytes; + + fd2name(fd, buf, PATH_MAX); + + 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[PATH_MAX]; + int nbytes; + + fd2name(fd, buf, PATH_MAX); + + 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 +967,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 +1179,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 Fri Dec 9 16:04:50 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Xu X-Patchwork-Id: 31866 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp860938wrr; Fri, 9 Dec 2022 08:08:30 -0800 (PST) X-Google-Smtp-Source: AA0mqf6+2pYLKpkKYKwEUtR0blmB+o68HFACTfP+XqncZinUfjSH362OR0DwIsbkOQ3TaNrZK1uV X-Received: by 2002:a05:6a20:690d:b0:9d:efbe:e601 with SMTP id q13-20020a056a20690d00b0009defbee601mr9407893pzj.29.1670602110055; Fri, 09 Dec 2022 08:08:30 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1670602110; cv=none; d=google.com; s=arc-20160816; b=NYD1qEnyIWW6j3ZuWW4gCRKnM87sgk9fKOHC+Sl2CPrdEut7xqNWu/SM8thNHDbEOC 9QczH0XPzbIq0k0tjgxKTCUFKApV49b+lAhb2TztJj5zC47xAh/D/bNbA7UDJEG9xWEa OKv8q3Q+YHYahqqKDkXyn8mhS9YhGvBFU3wH98aYoEML2E9A5U47/zAWYX3z6gJBj9NL PVL/fKEb10Ou/Hv0piYPK9OhjegXK1B/7YBdnk6URCjVCVP/BpUaGyoEB/PHDhpFg0E3 BmXCa5OCgQ28P3UzgpXNRVqK9ZGhNxkdDUXhDIs48fLlJDFAzVU91zUsG/olP2r6B2Fj UeGw== 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=/lNT4C2C35mOy+jPoPmY94wPPGI2c0JAbSMFbo6Kb0w=; b=ICKUe8dwQsfugYC3amakClxViGHxGuYtzEaHdNSj9yoSDvEY0SXpom3IpGigyy0Zjo kTUVEnkvMw5p9R7lWj9oE9ZW/DXO6PrtJ/5FTATANZ+oMwaYD6zLzPV9oIMzejyHlcgM eFm0w48cniskWFRTXITu9qeLNvpMvXB9amuyTlfQnuFN1P/QrhybzWu6icjPGAkvr2w6 bI+yB9PJ0p2EoVZp3z5jAlrmzJSzkA1mX4ARUKj4YvWNFVt9J0RJjWNe2s396EDL70dE FbfOnZx/7RK9xJsljBWVzS6f8S8/MaTsPisRtEHwGS/WPVTgWnfdoI4nuSbDf+3vaQ8x IcHQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=L2iwn1Oo; 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 20-20020a630614000000b00477c217a5eesi1712357pgg.317.2022.12.09.08.08.16; Fri, 09 Dec 2022 08:08:30 -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=L2iwn1Oo; 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 S230094AbiLIQFj (ORCPT + 99 others); Fri, 9 Dec 2022 11:05:39 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49786 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230080AbiLIQFE (ORCPT ); Fri, 9 Dec 2022 11:05:04 -0500 Received: from mail-pf1-x42c.google.com (mail-pf1-x42c.google.com [IPv6:2607:f8b0:4864:20::42c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1E329511F0 for ; Fri, 9 Dec 2022 08:05:03 -0800 (PST) Received: by mail-pf1-x42c.google.com with SMTP id 130so3991410pfu.8 for ; Fri, 09 Dec 2022 08:05:03 -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=/lNT4C2C35mOy+jPoPmY94wPPGI2c0JAbSMFbo6Kb0w=; b=L2iwn1OomYfbP7l4GF464dPsfgipBEVevdZXKRKgHcfV08U1sqYon0o9BlepBzJOYS XTpyig9stj0VQGImyy2Rlx4We3ZlF0GeiEpbp37EUTnoSm4082vtfDY+ET0w+llXm1Nc Gjgj3R+kZut0FdaYdWoxYlvVXfIajYgdHDdqM= 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=/lNT4C2C35mOy+jPoPmY94wPPGI2c0JAbSMFbo6Kb0w=; b=AlpinJNmqJNcnQK7LC+iqdOHZ/YT351shCJlC0FpkjeJQyGC5ApzOPE1pxwFK9GNcV 7w7h+QORVnqTkMx7Qc2PQp059x0zkmUqxRSw2O83Gw28uJDVSWD/nETb/EHCYEu0Ev9T Ap6YVBlf2KpUVttotnobOnq8qxVZYAR4Z8Rv73ZBtBJYBBg9kFevV25vRMT121xXTiv5 MBuRfqyVLtfxpJvITHcXb1/iA/Q6tuCudiCwVoNkoO9Swt/y8J6nlKNu5oMhOjWwlW9w jFZHYVeAXy2Dm+xoNaB8U7zlVPobjsiOphAmoQzbC8uDRObHMcjXt1nlBvlT/wFuZT4g 5AdQ== X-Gm-Message-State: ANoB5pm8OMMEe5HGs8oM2MFm2USbhy9qpGJm7e7txZsankMBZW9Kgxfe Bl+qE4kSrmTxJgnct9xbRjl48g== X-Received: by 2002:a05:6a00:3316:b0:577:151f:3fda with SMTP id cq22-20020a056a00331600b00577151f3fdamr7603327pfb.8.1670601902717; Fri, 09 Dec 2022 08:05:02 -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 a15-20020aa795af000000b00576670cc170sm1460504pfk.93.2022.12.09.08.05.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 09 Dec 2022 08:05:02 -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, linux-security-module@vger.kernel.org, kernel test robot Subject: [PATCH v7 3/6] mm/memfd: add MFD_NOEXEC_SEAL and MFD_EXEC Date: Fri, 9 Dec 2022 16:04:50 +0000 Message-Id: <20221209160453.3246150-4-jeffxu@google.com> X-Mailer: git-send-email 2.39.0.rc1.256.g54fd8350bd-goog In-Reply-To: <20221209160453.3246150-1-jeffxu@google.com> References: <20221209160453.3246150-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?1751753278187224060?= X-GMAIL-MSGID: =?utf-8?q?1751753278187224060?= 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. Also, the value of memfd_noexec is passed to child namespace at creation time. For example, if the init namespace has vm.memfd_noexec=2, all its children namespaces will be created with 2. Signed-off-by: Jeff Xu Co-developed-by: Daniel Verkamp Signed-off-by: Daniel Verkamp Reported-by: kernel test robot Reviewed-by: Kees Cook --- include/linux/pid_namespace.h | 19 +++++++++++ include/uapi/linux/memfd.h | 4 +++ kernel/pid_namespace.c | 5 +++ kernel/pid_sysctl.h | 59 +++++++++++++++++++++++++++++++++++ mm/memfd.c | 48 ++++++++++++++++++++++++++-- 5 files changed, 133 insertions(+), 2 deletions(-) create mode 100644 kernel/pid_sysctl.h diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h index 07481bb87d4e..c758809d5bcf 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..8a98b1af9376 100644 --- a/kernel/pid_namespace.c +++ b/kernel/pid_namespace.c @@ -23,6 +23,7 @@ #include #include #include +#include "pid_sysctl.h" static DEFINE_MUTEX(pid_caches_mutex); static struct kmem_cache *pid_ns_cachep; @@ -110,6 +111,8 @@ static struct pid_namespace *create_pid_namespace(struct user_namespace *user_ns ns->ucounts = ucounts; ns->pid_allocated = PIDNS_ADDING; + initialize_memfd_noexec_scope(ns); + return ns; out_free_idr: @@ -455,6 +458,8 @@ static __init int pid_namespaces_init(void) #ifdef CONFIG_CHECKPOINT_RESTORE register_sysctl_paths(kern_path, pid_ns_ctl_table); #endif + + register_pid_ns_sysctl_table_vm(); return 0; } diff --git a/kernel/pid_sysctl.h b/kernel/pid_sysctl.h new file mode 100644 index 000000000000..90a93161a122 --- /dev/null +++ b/kernel/pid_sysctl.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef LINUX_PID_SYSCTL_H +#define LINUX_PID_SYSCTL_H + +#include + +#if defined(CONFIG_SYSCTL) && defined(CONFIG_MEMFD_CREATE) +static inline void initialize_memfd_noexec_scope(struct pid_namespace *ns) +{ + ns->memfd_noexec_scope = + task_active_pid_ns(current)->memfd_noexec_scope; +} + +static int pid_mfd_noexec_dointvec_minmax(struct ctl_table *table, + int write, void *buf, size_t *lenp, loff_t *ppos) +{ + struct pid_namespace *ns = task_active_pid_ns(current); + struct ctl_table table_copy; + + if (write && !ns_capable(ns->user_ns, 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, buf, 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", }, { } }; +static inline void register_pid_ns_sysctl_table_vm(void) +{ + register_sysctl_paths(vm_path, pid_ns_ctl_table_vm); +} +#else +static inline void set_memfd_noexec_scope(struct pid_namespace *ns) {} +static inline void register_pid_ns_ctl_table_vm(void) {} +#endif + +#endif /* LINUX_PID_SYSCTL_H */ 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 Fri Dec 9 16:04:51 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Xu X-Patchwork-Id: 31865 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp860859wrr; Fri, 9 Dec 2022 08:08:22 -0800 (PST) X-Google-Smtp-Source: AA0mqf4RfvoRaiLg7JUuhmN/0bGGFCFAtpmL5HQjIC6hgIkhnrsoucAcfERuXPKUkVnW7AJMiOe+ X-Received: by 2002:a17:90a:4f0a:b0:219:49d9:ebda with SMTP id p10-20020a17090a4f0a00b0021949d9ebdamr6579187pjh.48.1670602101736; Fri, 09 Dec 2022 08:08:21 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1670602101; cv=none; d=google.com; s=arc-20160816; b=BKZwnrDdEn7wS2nLhj7fIsQ5+l/qenQn4tx9cL1yfwX0OVzzal5tjI7O1MCtmoC+Nk HwURT2XgtJjR3yFU1Gau/cjK64iDM49IOyvzzclhNsDFtQ+OdwJOYhS+4pc8Ns8F1K3l wwMJH6t5Z7sNlo7zda7sRtoN7uMMupA9m6ZSiDiHhISPxCA3pigtRTryxsaMl5/Ykvb/ CGR+/rR6BkJQ+nr0l6LgW77am935m1kKcsnrN4h22lDtw4j91a0Jey576w1xZmGO4pz9 PZDdsMF1AoYdkIkWCiBCinyDzzlsQ0Uf9YQufQ9JPBgS+v8qWbm3+C9n9WGBEaGXOoj7 y7BA== 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=FZNFa0Som2cEXdyImA0PHzAPIxujgLNI2oeSKx5nHZI=; b=EoAnQfODSUzq14lbK91wWZDtwuvvezJ5U+DEMDWv/4/bLCmvo2qjPX0W3M22vBfTjb F7JKWID2Cvq2fFnmc7l9Q8TmfAMNIZbNWEpcNgleOLKMjkapI4poS1nYR45GgbH+F/jp iMFgiGU0eCivp83QqX5Dfp+hxkZ7LJszwG53JCl6+MaS95BaObpaj2ub8Ip2lTM6Cy4/ HbyG6OuNvRiLP/FHSJQ8RPoLJjXdUsUmy8siTSkQGUbAmwMDoNY9Oq4flbZHl/F5Bv7Z 9Sgkk1D+L08nd24+LZLEGVqUeuPNtCJAL10D6TJIMK8mHoB8hVgEGwkA334AHOGPj4c0 JYOg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=h3FquO7M; 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 bc22-20020a656d96000000b0047839aeb6e4si1812211pgb.363.2022.12.09.08.08.08; Fri, 09 Dec 2022 08:08:21 -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=h3FquO7M; 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 S229674AbiLIQFc (ORCPT + 99 others); Fri, 9 Dec 2022 11:05:32 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49710 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229965AbiLIQFF (ORCPT ); Fri, 9 Dec 2022 11:05:05 -0500 Received: from mail-pg1-x531.google.com (mail-pg1-x531.google.com [IPv6:2607:f8b0:4864:20::531]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 670A0554EA for ; Fri, 9 Dec 2022 08:05:04 -0800 (PST) Received: by mail-pg1-x531.google.com with SMTP id h33so3806856pgm.9 for ; Fri, 09 Dec 2022 08:05:04 -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=FZNFa0Som2cEXdyImA0PHzAPIxujgLNI2oeSKx5nHZI=; b=h3FquO7MkL3Xkcl57UR0vuuniHUg5+pjAS+449C9zKHXjh3bfCzGniHHohZYn5ZJxa PimfhG0DETXRYTKLCZGzQghCrFbpOJpZG5Zr0M0bfkbC/VGkO9Ut1cdT7lGwEdufbrrc PnxV8fbesmJTL6d00qwrsh707SkFtLJvebIYI= 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=FZNFa0Som2cEXdyImA0PHzAPIxujgLNI2oeSKx5nHZI=; b=rWb5YHTxV/CX8OVOSMIWSD5cWHmQAu8VAOPIbu1HtNc7MgX2VruOxpyT7RLdBnBogV Wzk9aB3psZ3m8ammypGFmrEQswPPLJCVWrgMgJQpQbHQPNuojhH7A5ly8FAWoFmX2nSk lHeUYHLmHgBEarWhwVp21lRIbmcTOsmPqbjGQFcBfyhbDw02uU4VTB3t9k3GMjxLkRei fQNgXKV6rzMWhsQxWD/l9WNRvp3Sx3wgp5WbIYqYWNl3+W5JrPzONqGRSXx3PRXUO1mN Z5awihCvFtTu+DIT8152N70yyLJg1sENfwgCHACQNN4gIl29obz8WmOO+RhkrjtcWSI7 KMdA== X-Gm-Message-State: ANoB5pncgwk47Cc/7aTOh35/EYGGI5KZmKakVNtmrMMyB193yFsTyrg/ qn5/M2GOLkbLQTrQQawWETho2w== X-Received: by 2002:a05:6a00:a05:b0:566:900d:6396 with SMTP id p5-20020a056a000a0500b00566900d6396mr8624787pfh.22.1670601903758; Fri, 09 Dec 2022 08:05:03 -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 a15-20020aa795af000000b00576670cc170sm1460504pfk.93.2022.12.09.08.05.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 09 Dec 2022 08:05:03 -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, linux-security-module@vger.kernel.org Subject: [PATCH v7 4/6] mm/memfd: Add write seals when apply SEAL_EXEC to executable memfd Date: Fri, 9 Dec 2022 16:04:51 +0000 Message-Id: <20221209160453.3246150-5-jeffxu@google.com> X-Mailer: git-send-email 2.39.0.rc1.256.g54fd8350bd-goog In-Reply-To: <20221209160453.3246150-1-jeffxu@google.com> References: <20221209160453.3246150-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?1751753269110648404?= X-GMAIL-MSGID: =?utf-8?q?1751753269110648404?= 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 can no longer modify the content of the memfd. Typically, application seals the memfd right after writing to it. For example: 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 Reviewed-by: Kees Cook --- 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 Fri Dec 9 16:04:52 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Xu X-Patchwork-Id: 31868 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp861548wrr; Fri, 9 Dec 2022 08:09:26 -0800 (PST) X-Google-Smtp-Source: AA0mqf6OXsMV29BTmeHBUUytW/vxOL9ybDNHm0ByMwclVl7TZYfvlz/7YooCbA69scW3to7NRUz5 X-Received: by 2002:a05:6a20:bf19:b0:ad:2abb:5a5b with SMTP id gc25-20020a056a20bf1900b000ad2abb5a5bmr2140990pzb.9.1670602166356; Fri, 09 Dec 2022 08:09:26 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1670602166; cv=none; d=google.com; s=arc-20160816; b=xmJwK1JoApsxwLxOctwNC1/AeLccGNDaBursL3zLMofAL7s/+9HsuDbdXS8qWyTpw0 xMiLLUi7xfSTrTorBcZXP+gPrDazTkpOWcvMV+LeKveVeLuMGqvWtOlWUejhjgBzZarV nLrfxNWzDzyJHUGRwigg1bpXDLVRdHyyWBEGDflmHt+ShzzAxHFfPnzkfGBhEd4olKo4 emmXKicdUcdbdryKUnCCaMhDFna5VHi2P6ZiPVwQaaXVLhhTcYG1cjr8g7Un7s0mxmBv 98KLcsR/Zk1/naOiQyWZKeVF87pSC7PA1OVLvcRM0A1CGe2dq17KGo4+XI/6RCuxve4X ASNA== 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=Wap6ucoC/WNJsFqIKWfaQDf7c8pQKriu9bpCkWTKgYw=; b=V+BsK157zagp04/jWV6LCkCxH/JnluziASZ+HdIl36ykqvkCEmeK93cUjjQwrbveu3 BNopDwvrIYmsYNb03Kn7vt6bIe8muI12v3y/LHzlT8fYSOy8KFOx7qx/qTFcAOnw8egl x/+Z6fwZzksceajcX8krgyEvvKI6rvg+57awEFqwnDYPuPdALdFbokRlT0Yul5oUZoks mymcq9vWQc17/dI48ZZSTdJyOK1TnAwBkN2zMHzITp7l7yQbbkJtQ3E4bmkIhxIxPflY ODiLJ9N1XmKVXQtBLE1ftWbRDVx5+fwHAJ6FRpvfnf3nlDGzSoZimCLCa9Q3Q6dEoEER 4ApA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=ArLIvu3g; 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 j1-20020a17090a738100b00218792fa2b3si2168179pjg.160.2022.12.09.08.09.08; Fri, 09 Dec 2022 08:09:26 -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=ArLIvu3g; 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 S229605AbiLIQFm (ORCPT + 99 others); Fri, 9 Dec 2022 11:05:42 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49714 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229835AbiLIQFX (ORCPT ); Fri, 9 Dec 2022 11:05:23 -0500 Received: from mail-pf1-x433.google.com (mail-pf1-x433.google.com [IPv6:2607:f8b0:4864:20::433]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0896A7B4DC for ; Fri, 9 Dec 2022 08:05:05 -0800 (PST) Received: by mail-pf1-x433.google.com with SMTP id d82so3984428pfd.11 for ; Fri, 09 Dec 2022 08:05:05 -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=Wap6ucoC/WNJsFqIKWfaQDf7c8pQKriu9bpCkWTKgYw=; b=ArLIvu3gLFPm72bYeNKvt/CrsqiGwjWKD784LRjAjOtXxXPJcZp1GSPF3KJaSJQlmC 7Pq5HdfRBIVQ7cqdlhTtevbqiym7vqydKk1fvUP6v1gD/YSN3G+N0QDIb7er8NSGZ0BK qLGNZG1pYzJPzQjNIWmE8GYmS4c3koFlyz+K8= 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=Wap6ucoC/WNJsFqIKWfaQDf7c8pQKriu9bpCkWTKgYw=; b=AFGNUNowSGPl1riR9/h4KMD77NpwPETtonAjoxnGNJsAgG6M1Bf4m4MmsfsrRU+1tk TD1lN4RVb3Gy0tUDG3lay0e0o99iHe68RalQfCK5/Bg17pc376AP3irWOC5qPjwMqnzD dl0mLb+4txa0xVIYwzsA/4FlE3o4/YN8Q5c9WB+YPSMQyfCeiTVqgfwJh4kI9NaTqeDn GsSUi1PijGYEzA4OxwB9PFRycLGh5upahI+Zst2v3AAfcg2A9LJTbq8zOTgO+wLwcRZS JKzrg952r8BPEPOITxa2sEM7nmX1pxxQk574KOECPN16RYd07+dj7TNpY9xp9bKDrVlF McFQ== X-Gm-Message-State: ANoB5pma0JB947mWzodROcI7ROL6qUeEjA1D5302S/uhmlgw+1E6i/4K YCER8svOFUKg6axscCeuYik9nQ== X-Received: by 2002:a62:1488:0:b0:56b:b890:6ccd with SMTP id 130-20020a621488000000b0056bb8906ccdmr5473086pfu.4.1670601904693; Fri, 09 Dec 2022 08:05:04 -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 a15-20020aa795af000000b00576670cc170sm1460504pfk.93.2022.12.09.08.05.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 09 Dec 2022 08:05:04 -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, linux-security-module@vger.kernel.org Subject: [PATCH v7 5/6] selftests/memfd: add tests for MFD_NOEXEC_SEAL MFD_EXEC Date: Fri, 9 Dec 2022 16:04:52 +0000 Message-Id: <20221209160453.3246150-6-jeffxu@google.com> X-Mailer: git-send-email 2.39.0.rc1.256.g54fd8350bd-goog In-Reply-To: <20221209160453.3246150-1-jeffxu@google.com> References: <20221209160453.3246150-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?1751753337336059626?= X-GMAIL-MSGID: =?utf-8?q?1751753337336059626?= 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 Reviewed-by: Kees Cook --- tools/testing/selftests/memfd/fuse_test.c | 1 + tools/testing/selftests/memfd/memfd_test.c | 228 ++++++++++++++++++++- 2 files changed, 224 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 f18a15a1f275..ae71f15f790d 100644 --- a/tools/testing/selftests/memfd/memfd_test.c +++ b/tools/testing/selftests/memfd/memfd_test.c @@ -30,6 +30,14 @@ #define F_SEAL_EXEC 0x0020 +#define F_WX_SEALS (F_SEAL_SHRINK | \ + F_SEAL_GROW | \ + F_SEAL_WRITE | \ + F_SEAL_FUTURE_WRITE | \ + F_SEAL_EXEC) + +#define MFD_NOEXEC_SEAL 0x0008U + /* * Default is not to test hugetlbfs */ @@ -80,6 +88,37 @@ 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 void sysctl_fail_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 %s succeeded, but failure expected\n", + val); + abort(); + } +} + static int mfd_assert_reopen_fd(int fd_in) { int fd; @@ -758,6 +797,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); @@ -969,20 +1011,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); @@ -996,10 +1039,181 @@ 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; + + 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); + sysctl_fail_write("0"); + 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); + sysctl_fail_write("0"); + sysctl_fail_write("1"); +} + +static int newpid_thread_fn(void *arg) +{ + test_sysctl_child(); + return 0; +} + +static void test_sysctl_child2(void) +{ + int fd; + + sysctl_fail_write("0"); + 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); +} + +static int newpid_thread_fn2(void *arg) +{ + test_sysctl_child2(); + return 0; +} +static pid_t spawn_newpid_thread(unsigned int flags, int (*fn)(void *)) +{ + uint8_t *stack; + pid_t pid; + + stack = malloc(STACK_SIZE); + if (!stack) { + printf("malloc(STACK_SIZE) failed: %m\n"); + abort(); + } + + pid = clone(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, newpid_thread_fn); + + join_newpid_thread(pid); + + printf("%s child ns\n", memfd_str); + sysctl_assert_write("1"); + + pid = spawn_newpid_thread(CLONE_NEWPID, newpid_thread_fn2); + join_newpid_thread(pid); +} + /* * Test sharing via dup() * Test that seals are shared between dupped FDs and they're all equal. @@ -1173,13 +1387,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", ""); @@ -1195,6 +1411,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 Fri Dec 9 16:04:53 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Xu X-Patchwork-Id: 31867 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp861544wrr; Fri, 9 Dec 2022 08:09:26 -0800 (PST) X-Google-Smtp-Source: AA0mqf6TQUln9YI4eCeVuJL8c5U2nfcPZn480V1T2LWPP7bMCV+NCQloWF68OGlzswXM4f1MzvjL X-Received: by 2002:a17:903:1341:b0:189:e4e:792c with SMTP id jl1-20020a170903134100b001890e4e792cmr5826550plb.64.1670602166009; Fri, 09 Dec 2022 08:09:26 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1670602165; cv=none; d=google.com; s=arc-20160816; b=cOiep+Yu4y5N1nzP48TbRa8WEzEgF6N0DZx6N3T9VPg5ovWdAYFaY/lZaC6QRZfvuy gh/DJ5i33MmaT809FLsBBcjVIglLX636Uk8fLaHFJvMMC1q2fMOINKCyk5mcrfGoB/Ee wUnu7e0z65YZhxkUlr6aBIs4GZNYTOzHC2JdIzjVyDMLCQxN10TqGqp0YGf/xsmopzor x/jJ1y9V+JX7nt1SL4gOAy8I2cYFe7H7YpAc+ubydAKsXPlkIpfMmFxSIcu8qsZ0zZ9R oDNZxpkp4nPng2poS9/KUmpx9FrJwKFj42CXtx067idPul1ZhRW4xkwbZSh57tL2qQjJ TRvw== 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=dO2vEZu0Db7wP8hwByIkT/4WBK5RsSRu/0g8CrsVk0Q=; b=j8en01ZeJ10+XP92liu5Qd2QKrfzf/IeFVfLLiAVLcA44luzNxYG02XVec+LHfnlZ2 CiQDySsNjSGnLeSG6NqI8OxTLCWJqpu2nz2Nj/8fX5M/AebKkh7+ZM1MqXcTuD9rnVgk 4mivp66U5avKyH8R9zXBk1tAnQwn02FSadryXhXLdXMJeajUKyvmljLvHuc3x7lfA4NE javfzkMLaMnJdeSxnlO44uOd5124LjFVebt5o9+d/1+ECIwzUP4fRBvXMnJzhfqcr2hZ 5n7rQ0cLqxv2UTFjBfvS6ncUkwX1fITuWtZk6/c92wHchyKnopBVilialgzp9nTNJtzi GVsg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=Nz9hhcL5; 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 u4-20020a170902e5c400b001894d872b14si1836359plf.66.2022.12.09.08.09.12; Fri, 09 Dec 2022 08:09:25 -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=Nz9hhcL5; 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 S230100AbiLIQFq (ORCPT + 99 others); Fri, 9 Dec 2022 11:05:46 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50308 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230161AbiLIQFY (ORCPT ); Fri, 9 Dec 2022 11:05:24 -0500 Received: from mail-pg1-x52e.google.com (mail-pg1-x52e.google.com [IPv6:2607:f8b0:4864:20::52e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2A59359FDD for ; Fri, 9 Dec 2022 08:05:06 -0800 (PST) Received: by mail-pg1-x52e.google.com with SMTP id s196so3827191pgs.3 for ; Fri, 09 Dec 2022 08:05:06 -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=dO2vEZu0Db7wP8hwByIkT/4WBK5RsSRu/0g8CrsVk0Q=; b=Nz9hhcL5VUT1DNeWW7Mvl2m+8tMK4KUW9ZM63sJBU7BZC5BXcP0QrGhhfixxQYFJr6 jaW0mxnuLY9YKm9/eIJoGL3j7a2Nnz/LO5wqZBulnXeLBCJR0YvayQPJuPVgnkWRqUzs VIPCWg63G260HdzCt34cupUwQj6+eayz1j76w= 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=dO2vEZu0Db7wP8hwByIkT/4WBK5RsSRu/0g8CrsVk0Q=; b=o/YGGuR0Rzoid6Z6/N+Sy6HFPP/LsWmjH3NFFSJGjJfD5hPziGtx08BYrSUZcAr8mk fLRd7gcPTdE5D+iN1/kgmVvS2ta96XIVm82mrqrrnhPbj9TMv4Tnkues7X5CrlGaY8wq hv2TITF2PVfTDm9CHV+JRRgS+UZmk3G5a9Lzx9igihIVY6rLvSiUb2fDX81rCuT3YWSp otcoa05Znli1QOGws/XNnnwBAUgLrYZJnqJ2cWvJXp0iTam39BrP5a6+oO2XY0qxH83Z Xa8ClSpyIMgdIHb3K4836RpwnGlIpWdObKwlbXiAnJAyOIGZTL5HF5+Vv6um/mR3pqM3 vgnQ== X-Gm-Message-State: ANoB5pl4/ydI/e9g8Yi0lEVK5xdqJEj36MJEmcZx/txK8r3bT5UIqaGu fxLfh1xsQ71rfcpKXuviYSkncA== X-Received: by 2002:aa7:858a:0:b0:575:de28:b1f4 with SMTP id w10-20020aa7858a000000b00575de28b1f4mr5165976pfn.16.1670601905655; Fri, 09 Dec 2022 08:05:05 -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 a15-20020aa795af000000b00576670cc170sm1460504pfk.93.2022.12.09.08.05.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 09 Dec 2022 08:05:05 -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, linux-security-module@vger.kernel.org, kernel test robot Subject: [PATCH v7 6/6] mm/memfd: security hook for memfd_create Date: Fri, 9 Dec 2022 16:04:53 +0000 Message-Id: <20221209160453.3246150-7-jeffxu@google.com> X-Mailer: git-send-email 2.39.0.rc1.256.g54fd8350bd-goog In-Reply-To: <20221209160453.3246150-1-jeffxu@google.com> References: <20221209160453.3246150-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?1751753336692368982?= X-GMAIL-MSGID: =?utf-8?q?1751753336692368982?= 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 | 5 +++++ 5 files changed, 21 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..57788cf94075 100644 --- a/security/security.c +++ b/security/security.c @@ -1010,6 +1010,11 @@ int security_sb_clone_mnt_opts(const struct super_block *oldsb, } EXPORT_SYMBOL(security_sb_clone_mnt_opts); +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);