1 /*
2 * Copyright (C) 2017 Red Hat, Inc.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of
7 * the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15
16 /*
17 * Based on Linux/tools/testing/selftests/memfd/memfd_test.c
18 * by David Herrmann <dh.herrmann@gmail.com>
19 *
20 * 24/02/2017 Port to LTP <jracek@redhat.com>
21 */
22
23 #define _GNU_SOURCE
24
25 #include <errno.h>
26
27 #include <tst_test.h>
28
29 #include "memfd_create_common.h"
30
31 static char buf[2048];
32 static char term_buf[2048];
33
34 static int available_flags;
35
36 static const struct tcase {
37 char *descr;
38 char *memfd_name;
39 int flags;
40 int memfd_create_exp_err;
41 } tcases[] = {
42 /*
43 * Test memfd_create() syscall
44 * Verify syscall-argument validation, including name checks,
45 * flag validation and more.
46 */
47 {"invalid name fail 1", NULL, 0, EFAULT },
48 {"invalid name fail 2", buf, 0, EINVAL },
49 {"invalid name fail 3", term_buf, 0, EINVAL },
50
51 {"invalid flags fail 1", "test", -500, EINVAL },
52 {"invalid flags fail 2", "test", 0x0100, EINVAL },
53 {"invalid flags fail 3", "test", ~MFD_CLOEXEC, EINVAL },
54 {"invalid flags fail 4", "test", ~MFD_ALLOW_SEALING, EINVAL },
55 {"invalid flags fail 5", "test", ~0, EINVAL },
56 {"invalid flags fail 6", "test", 0x80000000U, EINVAL },
57
58 {"valid flags 1 pass", "test", MFD_CLOEXEC, 0 },
59 {"valid flags 2 pass", "test", MFD_ALLOW_SEALING, 0 },
60 {"valid flags 3 pass", "test", MFD_CLOEXEC | MFD_ALLOW_SEALING, 0 },
61 {"valid flags 4 pass", "test", 0, 0 },
62 {"valid flags 5 pass", "", 0, 0 },
63 };
64
setup(void)65 static void setup(void)
66 {
67
68 available_flags = GET_MFD_ALL_AVAILABLE_FLAGS();
69
70 memset(buf, 0xff, sizeof(buf));
71
72 memset(term_buf, 0xff, sizeof(term_buf));
73 term_buf[sizeof(term_buf) - 1] = 0;
74 }
75
verify_memfd_create_errno(unsigned int n)76 static void verify_memfd_create_errno(unsigned int n)
77 {
78 const struct tcase *tc;
79 int needed_flags;
80
81 tc = &tcases[n];
82 needed_flags = tc->flags & FLAGS_ALL_MASK;
83
84 if ((available_flags & needed_flags) != needed_flags) {
85 tst_res(TCONF, "test '%s' skipped, flag not implemented",
86 tc->descr);
87 return;
88 }
89
90 TEST(sys_memfd_create(tc->memfd_name, tc->flags));
91 if (TST_ERR != tc->memfd_create_exp_err)
92 tst_brk(TFAIL, "test '%s'", tc->descr);
93 else
94 tst_res(TPASS, "test '%s'", tc->descr);
95
96 if (TST_RET > 0)
97 SAFE_CLOSE(TST_RET);
98 }
99
100 static struct tst_test test = {
101 .test = verify_memfd_create_errno,
102 .tcnt = ARRAY_SIZE(tcases),
103 .setup = setup,
104 };
105