On Thu, Jan 02, 2025 at 03:32:51PM -0800, Isaac J. Manjarres wrote: > Add tests to ensure that F_SEAL_FUTURE_EXEC behaves as expected. > > Signed-off-by: Isaac J. Manjarres <isaacmanjarres@xxxxxxxxxx> This looks reasonable, Reviewed-by: Lorenzo Stoakes <lorenzo.stoakes@xxxxxxxxxx> > --- > tools/testing/selftests/memfd/memfd_test.c | 79 ++++++++++++++++++++++ > 1 file changed, 79 insertions(+) > > diff --git a/tools/testing/selftests/memfd/memfd_test.c b/tools/testing/selftests/memfd/memfd_test.c > index c0c53451a16d..abc213a5ce99 100644 > --- a/tools/testing/selftests/memfd/memfd_test.c > +++ b/tools/testing/selftests/memfd/memfd_test.c > @@ -31,6 +31,7 @@ > #define STACK_SIZE 65536 > > #define F_SEAL_EXEC 0x0020 > +#define F_SEAL_FUTURE_EXEC 0x0040 > > #define F_WX_SEALS (F_SEAL_SHRINK | \ > F_SEAL_GROW | \ > @@ -318,6 +319,37 @@ static void *mfd_assert_mmap_private(int fd) > return p; > } > > +static void *mfd_fail_mmap_exec(int fd) > +{ > + void *p; > + > + p = mmap(NULL, > + mfd_def_size, > + PROT_EXEC, > + MAP_SHARED, > + fd, > + 0); > + if (p != MAP_FAILED) { > + printf("mmap() didn't fail as expected\n"); > + abort(); > + } > + > + return p; > +} > + > +static void mfd_fail_mprotect_exec(void *p) > +{ > + int ret; > + > + ret = mprotect(p, > + mfd_def_size, > + PROT_EXEC); > + if (!ret) { > + printf("mprotect didn't fail as expected\n"); > + abort(); > + } > +} > + > static int mfd_assert_open(int fd, int flags, mode_t mode) > { > char buf[512]; > @@ -998,6 +1030,52 @@ static void test_seal_future_write(void) > close(fd); > } > > +/* > + * Test SEAL_FUTURE_EXEC_MAPPING > + * Test whether SEAL_FUTURE_EXEC_MAPPING actually prevents executable mappings. > + */ > +static void test_seal_future_exec_mapping(void) > +{ > + int fd; > + void *p; > + > + > + printf("%s SEAL-FUTURE-EXEC-MAPPING\n", memfd_str); > + > + fd = mfd_assert_new("kern_memfd_seal_future_exec_mapping", > + mfd_def_size, > + MFD_CLOEXEC | MFD_ALLOW_SEALING); > + > + /* > + * PROT_READ | PROT_WRITE mappings create VMAs with VM_MAYEXEC set. > + * However, F_SEAL_FUTURE_EXEC applies to subsequent mappings, > + * so it should still succeed even if this mapping is active when the > + * seal is applied. > + */ > + p = mfd_assert_mmap_shared(fd); > + > + mfd_assert_has_seals(fd, 0); > + > + mfd_assert_add_seals(fd, F_SEAL_FUTURE_EXEC); > + mfd_assert_has_seals(fd, F_SEAL_FUTURE_EXEC); > + > + mfd_fail_mmap_exec(fd); > + > + munmap(p, mfd_def_size); > + > + /* Ensure that new mappings without PROT_EXEC work. */ > + p = mfd_assert_mmap_shared(fd); > + > + /* > + * Ensure that mappings created after the seal was applied cannot be > + * made executable via mprotect(). > + */ > + mfd_fail_mprotect_exec(p); > + > + munmap(p, mfd_def_size); > + close(fd); > +} > + > static void test_seal_write_map_read_shared(void) > { > int fd; > @@ -1639,6 +1717,7 @@ int main(int argc, char **argv) > test_seal_shrink(); > test_seal_grow(); > test_seal_resize(); > + test_seal_future_exec_mapping(); > > if (pid_ns_supported()) { > test_sysctl_simple(); > -- > 2.47.1.613.gc27f4b7a9f-goog >