From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id ACC2DC00144 for ; Fri, 29 Jul 2022 21:25:02 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id EB32D6B0071; Fri, 29 Jul 2022 17:25:01 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id E631F6B0072; Fri, 29 Jul 2022 17:25:01 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id D2A588E0001; Fri, 29 Jul 2022 17:25:01 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0017.hostedemail.com [216.40.44.17]) by kanga.kvack.org (Postfix) with ESMTP id C1BD96B0071 for ; Fri, 29 Jul 2022 17:25:01 -0400 (EDT) Received: from smtpin11.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay08.hostedemail.com (Postfix) with ESMTP id 9808E140168 for ; Fri, 29 Jul 2022 21:25:01 +0000 (UTC) X-FDA: 79741417602.11.C2CB494 Received: from mail-pj1-f44.google.com (mail-pj1-f44.google.com [209.85.216.44]) by imf16.hostedemail.com (Postfix) with ESMTP id 31F3B180058 for ; Fri, 29 Jul 2022 21:25:01 +0000 (UTC) Received: by mail-pj1-f44.google.com with SMTP id t2-20020a17090a4e4200b001f21572f3a4so6437603pjl.0 for ; Fri, 29 Jul 2022 14:25:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=/7jUURb4Au+aV6G9V1Q591iYS8VKiNaI7Lq+u0Fv1ro=; b=tg8t7DFa2GR5iE4efzwgVUUjlRe8S0unJY5sZ0wltwUUI+PXVjrC4n9vxO/Vr/9S9Z FVNrzxawd/PuYPNKN4AmUPTecdwdaqhVBcglN5n7IOR5T4ad+NpW2oK9kJgHHXsfx+8r THn3tQJAFKGDbDCBHDLyjDhbX3M/hZ4yyKd920u74wxUrwcS/CUWk77nDNuKByTeqs41 DsoMvOEbN8bCr1Ap+9knK6P6i+jNyjxPOh/KsAD5SqAHsqHCd8/0niwII50zEFxTlj1c L93P044BnFuWzWe7yo6WSzDKbWbCLTs6pOxADjb1fvkzpcXx2lMFg3zBVj6w3OVUYGQo 9VSg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=/7jUURb4Au+aV6G9V1Q591iYS8VKiNaI7Lq+u0Fv1ro=; b=5OQgQHOgsO/96Onr2R/xmEJRbXlAdlBrdX1TGSQKia1+anLHzSNAcEwHODKjigTHK6 jArXVrUuebC6jByLtYSRUMVy/vT3230EqbE0bGPM2ROzh9YPZnlcI0tdtU0mASchd8Xk xfvrXucOQp1mNnStQQnvqqx56iYCOflbwGD9Js/xg65Z5rc2ymUe/gBIuUrdVb080ywH m4Owjp5TKgVY94hp8C+ioj5MrufEFjF8OL9c9lKCmN9MSKHBhVoVLqJwvgNfRW1vC2A2 KKc0St3r8l3UW3AqLtFm6PkuyTYnMaHiB9+XelDKRkmqzB60VFYxf+QhL7tyfyqSdAYj 8cfw== X-Gm-Message-State: ACgBeo1vFyVwLqGWvImvFs8gtZpvbuDGNKMytzXm0Az9NWdafrecrAMX cU4OzJKu5qSWAxyDSv2qzs9GirnGg3frmFYuLlEiRw== X-Google-Smtp-Source: AA6agR7ZxLhX5SGu1uAOH1Fw8ZYChERYZ/mqgDcopwgtNrxZyfL1+NLWhnTKgIBkrpu1kCeeLW33A0v65bYhdyxszp8= X-Received: by 2002:a17:90a:7ac4:b0:1ef:a606:4974 with SMTP id b4-20020a17090a7ac400b001efa6064974mr6946724pjl.51.1659129899850; Fri, 29 Jul 2022 14:24:59 -0700 (PDT) MIME-Version: 1.0 References: <6f71a4f3-8f8e-926b-883c-1df630cfc1a0@linuxfoundation.org> <20220729061504.744140-1-jeffxu@google.com> In-Reply-To: <20220729061504.744140-1-jeffxu@google.com> From: Jeff Xu Date: Fri, 29 Jul 2022 14:24:23 -0700 Message-ID: Subject: Re: [PATCH 3/4] selftests/memfd: add tests for F_SEAL_EXEC To: skhan@linuxfoundation.org Cc: akpm@linux-foundation.org, dmitry.torokhov@gmail.com, dverkamp@chromium.org, hughd@google.com, jorgelo@chromium.org, keescook@chromium.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-mm@kvack.org, mnissler@chromium.org Content-Type: multipart/alternative; boundary="00000000000051a9ef05e4f848cd" ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1659129901; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=/7jUURb4Au+aV6G9V1Q591iYS8VKiNaI7Lq+u0Fv1ro=; b=Cp+d5t1zBGiKKMGXxV+h3r3yoVUQ+bQvzJ2FtRMdvKENmhDbRS2enGktGiG0PAMLrdSzMV hQuQ0pGHEgggDVEmdmeupa4Yn+VMc/SY1q5DF3F8vhFtxQ4PLjlfVdBrOtjwjAmzqmGORD 2taV8MYRJo9gBjeoewu/1EBEHZ5qacs= ARC-Authentication-Results: i=1; imf16.hostedemail.com; dkim=pass header.d=google.com header.s=20210112 header.b=tg8t7DFa; spf=pass (imf16.hostedemail.com: domain of jeffxu@google.com designates 209.85.216.44 as permitted sender) smtp.mailfrom=jeffxu@google.com; dmarc=pass (policy=reject) header.from=google.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1659129901; a=rsa-sha256; cv=none; b=fX4vwtkJQMO9riBY0ishXeOod9HQkjBXXCxoXEfMaIuogXIlk08N95znryFaOkQ0G6dxbz X+tAYxFb4FsjVMtEO2jBgGI5Cq2ts/MrcOXbCOZ0x7HmvcEqYOeWypCdOqrviDIdqQDG/r 5cwCEVZmzmCFwpMhmL6QbRPHvt8huOs= X-Rspamd-Server: rspam03 X-Rspamd-Queue-Id: 31F3B180058 X-Rspam-User: Authentication-Results: imf16.hostedemail.com; dkim=pass header.d=google.com header.s=20210112 header.b=tg8t7DFa; spf=pass (imf16.hostedemail.com: domain of jeffxu@google.com designates 209.85.216.44 as permitted sender) smtp.mailfrom=jeffxu@google.com; dmarc=pass (policy=reject) header.from=google.com X-Stat-Signature: 3kj1hkywixw6bwf4egxujwysk56ygh8e X-HE-Tag: 1659129901-906139 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: --00000000000051a9ef05e4f848cd Content-Type: text/plain; charset="UTF-8" Hi Shuah Khan I will continue Daniel Verkamp's work on this patch. Could you please take a look at the new patch to see if all your comments are addressed ? Much appreciated. Best Regards, Jeff. On Thu, Jul 28, 2022 at 11:15 PM Jeff Xu wrote: > From: Daniel Verkamp > > Basic tests to ensure that user/group/other execute bits cannot be > changed after applying F_SEAL_EXEC to a memfd. > > Co-developed-by: Jeff Xu > Signed-off-by: Jeff Xu > Signed-off-by: Daniel Verkamp > --- > 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", ""); > -- > 2.37.1.455.g008518b4e5-goog > > --00000000000051a9ef05e4f848cd Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi Shuah Khan

I will continue Daniel Ve= rkamp's work on this patch.=C2=A0
Could you please take a loo= k at the new=C2=A0patch to see if all your comments are addressed ?=C2=A0

Much appreciated.

= Best Regards,
Jeff.



<= /div>


On Thu, Jul 28, 2022 at 11:15 PM Jeff Xu <jeffxu@google.com> wrote:
From: Daniel Verkamp <dverkamp@chromium.org>

Basic tests to ensure that user/group/other execute bits cannot be
changed after applying F_SEAL_EXEC to a memfd.

Co-developed-by: Jeff Xu <jeffxu@google.com>
Signed-off-by: Jeff Xu <jeffxu@google.com>
Signed-off-by: Daniel Verkamp <dverkamp@chromium.org>
---
=C2=A0tools/testing/selftests/memfd/memfd_test.c | 129 ++++++++++++++++++++= -
=C2=A01 file changed, 128 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/memfd/memfd_test.c b/tools/testing/sel= ftests/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 @@
=C2=A0#define MFD_DEF_SIZE 8192
=C2=A0#define STACK_SIZE 65536

+#ifndef F_SEAL_EXEC
+#define F_SEAL_EXEC=C2=A0 =C2=A0 0x0020
+#endif
+
+#ifndef MAX_PATH
+#define MAX_PATH 256
+#endif
+
=C2=A0/*
=C2=A0 * Default is not to test hugetlbfs
=C2=A0 */
=C2=A0static size_t mfd_def_size =3D MFD_DEF_SIZE;
=C2=A0static const char *memfd_str =3D MEMFD_STR;

+static ssize_t fd2name(int fd, char *buf, size_t bufsize)
+{
+=C2=A0 =C2=A0 =C2=A0 =C2=A0char buf1[MAX_PATH];
+=C2=A0 =C2=A0 =C2=A0 =C2=A0int size;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0ssize_t nbytes;
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0size =3D snprintf(buf1, MAX_PATH, "/proc/s= elf/fd/%d", fd);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0if (size < 0) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0printf("snprin= tf(%d) failed on %m\n", fd);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0abort();
+=C2=A0 =C2=A0 =C2=A0 =C2=A0}
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0/*
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 * reserver one byte for string termination. +=C2=A0 =C2=A0 =C2=A0 =C2=A0 */
+=C2=A0 =C2=A0 =C2=A0 =C2=A0nbytes =3D readlink(buf1, buf, bufsize-1);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0if (nbytes =3D=3D -1) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0printf("readli= nk(%s) failed %m\n", buf1);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0abort();
+=C2=A0 =C2=A0 =C2=A0 =C2=A0}
+=C2=A0 =C2=A0 =C2=A0 =C2=A0buf[nbytes] =3D '\0';
+=C2=A0 =C2=A0 =C2=A0 =C2=A0return nbytes;
+}
+
=C2=A0static int mfd_assert_new(const char *name, loff_t sz, unsigned int f= lags)
=C2=A0{
=C2=A0 =C2=A0 =C2=A0 =C2=A0 int r, fd;
@@ -98,11 +130,14 @@ static unsigned int mfd_assert_get_seals(int fd)

=C2=A0static void mfd_assert_has_seals(int fd, unsigned int seals)
=C2=A0{
+=C2=A0 =C2=A0 =C2=A0 =C2=A0char buf[MAX_PATH];
+=C2=A0 =C2=A0 =C2=A0 =C2=A0int nbytes;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 unsigned int s;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0fd2name(fd, buf, MAX_PATH);

=C2=A0 =C2=A0 =C2=A0 =C2=A0 s =3D mfd_assert_get_seals(fd);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (s !=3D seals) {
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0printf("%u != =3D %u =3D GET_SEALS(%d)\n", seals, s, fd);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0printf("%u != =3D %u =3D GET_SEALS(%s)\n", seals, s, buf);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 abort();
=C2=A0 =C2=A0 =C2=A0 =C2=A0 }
=C2=A0}
@@ -594,6 +629,64 @@ static void mfd_fail_grow_write(int fd)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 }
=C2=A0}

+static void mfd_assert_mode(int fd, int mode)
+{
+=C2=A0 =C2=A0 =C2=A0 =C2=A0struct stat st;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0char buf[MAX_PATH];
+=C2=A0 =C2=A0 =C2=A0 =C2=A0int nbytes;
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0fd2name(fd, buf, MAX_PATH);
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0if (fstat(fd, &st) < 0) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0printf("fstat(= %s) failed: %m\n", buf);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0abort();
+=C2=A0 =C2=A0 =C2=A0 =C2=A0}
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0if ((st.st_mode & 07777) !=3D mode) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0printf("fstat(= %s) wrong file mode 0%04o, but expected 0%04o\n",
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 buf, (int)st.st_mode & 07777, mode);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0abort();
+=C2=A0 =C2=A0 =C2=A0 =C2=A0}
+}
+
+static void mfd_assert_chmod(int fd, int mode)
+{
+=C2=A0 =C2=A0 =C2=A0 =C2=A0char buf[MAX_PATH];
+=C2=A0 =C2=A0 =C2=A0 =C2=A0int nbytes;
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0fd2name(fd, buf, MAX_PATH);
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0if (fchmod(fd, mode) < 0) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0printf("fchmod= (%s, 0%04o) failed: %m\n", buf, mode);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0abort();
+=C2=A0 =C2=A0 =C2=A0 =C2=A0}
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0mfd_assert_mode(fd, mode);
+}
+
+static void mfd_fail_chmod(int fd, int mode)
+{
+=C2=A0 =C2=A0 =C2=A0 =C2=A0struct stat st;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0char buf[MAX_PATH];
+=C2=A0 =C2=A0 =C2=A0 =C2=A0int nbytes;
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0fd2name(fd, buf, MAX_PATH);
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0if (fstat(fd, &st) < 0) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0printf("fstat(= %s) failed: %m\n", buf);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0abort();
+=C2=A0 =C2=A0 =C2=A0 =C2=A0}
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0if (fchmod(fd, mode) =3D=3D 0) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0printf("fchmod= (%s, 0%04o) didn't fail as expected\n",
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 buf, mode);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0abort();
+=C2=A0 =C2=A0 =C2=A0 =C2=A0}
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0/* verify that file mode bits did not change */=
+=C2=A0 =C2=A0 =C2=A0 =C2=A0mfd_assert_mode(fd, st.st_mode & 07777); +}
+
=C2=A0static int idle_thread_fn(void *arg)
=C2=A0{
=C2=A0 =C2=A0 =C2=A0 =C2=A0 sigset_t set;
@@ -880,6 +973,39 @@ static void test_seal_resize(void)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 close(fd);
=C2=A0}

+/*
+ * Test SEAL_EXEC
+ * Test that chmod() cannot change x bits after sealing
+ */
+static void test_seal_exec(void)
+{
+=C2=A0 =C2=A0 =C2=A0 =C2=A0int fd;
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0printf("%s SEAL-EXEC\n", memfd_str);<= br> +
+=C2=A0 =C2=A0 =C2=A0 =C2=A0fd =3D mfd_assert_new("kern_memfd_seal_exe= c",
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0mfd_def_size,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0MFD_CLOEXEC | MFD_ALLOW_SEALING);
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0mfd_assert_mode(fd, 0777);
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0mfd_assert_chmod(fd, 0644);
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0mfd_assert_has_seals(fd, 0);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0mfd_assert_add_seals(fd, F_SEAL_EXEC);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0mfd_assert_has_seals(fd, F_SEAL_EXEC);
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0mfd_assert_chmod(fd, 0600);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0mfd_fail_chmod(fd, 0777);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0mfd_fail_chmod(fd, 0670);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0mfd_fail_chmod(fd, 0605);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0mfd_fail_chmod(fd, 0700);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0mfd_fail_chmod(fd, 0100);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0mfd_assert_chmod(fd, 0666);
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0close(fd);
+}
+
=C2=A0/*
=C2=A0 * Test sharing via dup()
=C2=A0 * Test that seals are shared between dupped FDs and they're all = equal.
@@ -1059,6 +1185,7 @@ int main(int argc, char **argv)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 test_seal_shrink();
=C2=A0 =C2=A0 =C2=A0 =C2=A0 test_seal_grow();
=C2=A0 =C2=A0 =C2=A0 =C2=A0 test_seal_resize();
+=C2=A0 =C2=A0 =C2=A0 =C2=A0test_seal_exec();

=C2=A0 =C2=A0 =C2=A0 =C2=A0 test_share_dup("SHARE-DUP", "&qu= ot;);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 test_share_mmap("SHARE-MMAP", "&= quot;);
--
2.37.1.455.g008518b4e5-goog

--00000000000051a9ef05e4f848cd--