1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (C) 2017  Red Hat, Inc.
4f08c3bdfSopenharmony_ci */
5f08c3bdfSopenharmony_ci
6f08c3bdfSopenharmony_ci /*
7f08c3bdfSopenharmony_ci  *  Based on Linux/tools/testing/selftests/memfd/memfd_test.c
8f08c3bdfSopenharmony_ci  *  by David Herrmann <dh.herrmann@gmail.com>
9f08c3bdfSopenharmony_ci  *
10f08c3bdfSopenharmony_ci  *  24/02/2017   Port to LTP    <jracek@redhat.com>
11f08c3bdfSopenharmony_ci  */
12f08c3bdfSopenharmony_ci
13f08c3bdfSopenharmony_ci#define _GNU_SOURCE
14f08c3bdfSopenharmony_ci
15f08c3bdfSopenharmony_ci#include <errno.h>
16f08c3bdfSopenharmony_ci#include "memfd_create_common.h"
17f08c3bdfSopenharmony_ci#include "tst_test.h"
18f08c3bdfSopenharmony_ci
19f08c3bdfSopenharmony_cistatic char buf[2048];
20f08c3bdfSopenharmony_cistatic char term_buf[2048];
21f08c3bdfSopenharmony_ci
22f08c3bdfSopenharmony_cistatic int available_flags;
23f08c3bdfSopenharmony_ci
24f08c3bdfSopenharmony_cistatic const struct tcase {
25f08c3bdfSopenharmony_ci	char *descr;
26f08c3bdfSopenharmony_ci	char *memfd_name;
27f08c3bdfSopenharmony_ci	int flags;
28f08c3bdfSopenharmony_ci	int memfd_create_exp_err;
29f08c3bdfSopenharmony_ci} tcases[] = {
30f08c3bdfSopenharmony_ci	/*
31f08c3bdfSopenharmony_ci	 * Test memfd_create() syscall
32f08c3bdfSopenharmony_ci	 * Verify syscall-argument validation, including name checks,
33f08c3bdfSopenharmony_ci	 * flag validation and more.
34f08c3bdfSopenharmony_ci	 */
35f08c3bdfSopenharmony_ci	{"invalid name fail 1",   NULL,     0,                      EFAULT },
36f08c3bdfSopenharmony_ci	{"invalid name fail 2",   buf,      0,                      EINVAL },
37f08c3bdfSopenharmony_ci	{"invalid name fail 3",   term_buf, 0,                      EINVAL },
38f08c3bdfSopenharmony_ci
39f08c3bdfSopenharmony_ci	{"invalid flags fail 1", "test",  -500,                     EINVAL },
40f08c3bdfSopenharmony_ci	{"invalid flags fail 2", "test",  0x0100,                   EINVAL },
41f08c3bdfSopenharmony_ci	{"invalid flags fail 3", "test",  ~MFD_CLOEXEC,             EINVAL },
42f08c3bdfSopenharmony_ci	{"invalid flags fail 4", "test",  ~MFD_ALLOW_SEALING,       EINVAL },
43f08c3bdfSopenharmony_ci	{"invalid flags fail 5", "test",  ~0,                       EINVAL },
44f08c3bdfSopenharmony_ci	{"invalid flags fail 6", "test",  0x80000000U,              EINVAL },
45f08c3bdfSopenharmony_ci
46f08c3bdfSopenharmony_ci	{"valid flags 1 pass", "test",  MFD_CLOEXEC,                     0 },
47f08c3bdfSopenharmony_ci	{"valid flags 2 pass", "test",  MFD_ALLOW_SEALING,               0 },
48f08c3bdfSopenharmony_ci	{"valid flags 3 pass", "test",  MFD_CLOEXEC | MFD_ALLOW_SEALING, 0 },
49f08c3bdfSopenharmony_ci	{"valid flags 4 pass", "test",  0,                               0 },
50f08c3bdfSopenharmony_ci	{"valid flags 5 pass", "",      0,                               0 },
51f08c3bdfSopenharmony_ci};
52f08c3bdfSopenharmony_ci
53f08c3bdfSopenharmony_cistatic void setup(void)
54f08c3bdfSopenharmony_ci{
55f08c3bdfSopenharmony_ci
56f08c3bdfSopenharmony_ci	available_flags = GET_MFD_ALL_AVAILABLE_FLAGS();
57f08c3bdfSopenharmony_ci
58f08c3bdfSopenharmony_ci	memset(buf, 0xff, sizeof(buf));
59f08c3bdfSopenharmony_ci
60f08c3bdfSopenharmony_ci	memset(term_buf, 0xff, sizeof(term_buf));
61f08c3bdfSopenharmony_ci	term_buf[sizeof(term_buf) - 1] = 0;
62f08c3bdfSopenharmony_ci}
63f08c3bdfSopenharmony_ci
64f08c3bdfSopenharmony_cistatic void verify_memfd_create_errno(unsigned int n)
65f08c3bdfSopenharmony_ci{
66f08c3bdfSopenharmony_ci	const struct tcase *tc;
67f08c3bdfSopenharmony_ci	int needed_flags;
68f08c3bdfSopenharmony_ci
69f08c3bdfSopenharmony_ci	tc = &tcases[n];
70f08c3bdfSopenharmony_ci	needed_flags = tc->flags & FLAGS_ALL_MASK;
71f08c3bdfSopenharmony_ci
72f08c3bdfSopenharmony_ci	if ((available_flags & needed_flags) != needed_flags) {
73f08c3bdfSopenharmony_ci		tst_res(TCONF, "test '%s' skipped, flag not implemented",
74f08c3bdfSopenharmony_ci					tc->descr);
75f08c3bdfSopenharmony_ci		return;
76f08c3bdfSopenharmony_ci	}
77f08c3bdfSopenharmony_ci
78f08c3bdfSopenharmony_ci	TEST(sys_memfd_create(tc->memfd_name, tc->flags));
79f08c3bdfSopenharmony_ci	if (TST_ERR != tc->memfd_create_exp_err)
80f08c3bdfSopenharmony_ci		tst_brk(TFAIL, "test '%s'", tc->descr);
81f08c3bdfSopenharmony_ci	else
82f08c3bdfSopenharmony_ci		tst_res(TPASS, "test '%s'", tc->descr);
83f08c3bdfSopenharmony_ci
84f08c3bdfSopenharmony_ci	if (TST_RET > 0)
85f08c3bdfSopenharmony_ci		SAFE_CLOSE(TST_RET);
86f08c3bdfSopenharmony_ci}
87f08c3bdfSopenharmony_ci
88f08c3bdfSopenharmony_cistatic struct tst_test test = {
89f08c3bdfSopenharmony_ci	.test = verify_memfd_create_errno,
90f08c3bdfSopenharmony_ci	.tcnt = ARRAY_SIZE(tcases),
91f08c3bdfSopenharmony_ci	.setup = setup,
92f08c3bdfSopenharmony_ci};
93