1 /* Test for the memfd_create system call.
2    Copyright (C) 2017-2021 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <stdbool.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <support/check.h>
26 #include <support/support.h>
27 #include <support/test-driver.h>
28 #include <support/xunistd.h>
29 #include <sys/mman.h>
30 
31 /* Return true if the descriptor has the FD_CLOEXEC flag set.  */
32 static bool
is_cloexec(int fd)33 is_cloexec (int fd)
34 {
35   int flags = fcntl (fd, F_GETFD);
36   TEST_VERIFY (flags >= 0);
37   return flags & FD_CLOEXEC;
38 }
39 
40 /* Return the seals set on FD.  */
41 static int
get_seals(int fd)42 get_seals (int fd)
43 {
44   int flags = fcntl (fd, F_GET_SEALS);
45   TEST_VERIFY (flags >= 0);
46   return flags;
47 }
48 
49 /* Return true if the F_SEAL_SEAL flag is set on the descriptor.  */
50 static bool
is_sealed(int fd)51 is_sealed (int fd)
52 {
53   return get_seals (fd) & F_SEAL_SEAL;
54 }
55 
56 static int
do_test(void)57 do_test (void)
58 {
59   /* Initialized by the first call to memfd_create to 0 (memfd_create
60      unsupported) or 1 (memfd_create is implemented in the kernel).
61      Subsequent iterations check that the success/failure state is
62      consistent.  */
63   int supported = -1;
64 
65   for (int do_cloexec = 0; do_cloexec < 2; ++do_cloexec)
66     for (int do_sealing = 0; do_sealing < 2; ++do_sealing)
67       {
68         int flags = 0;
69         if (do_cloexec)
70           flags |= MFD_CLOEXEC;
71         if (do_sealing)
72           flags |= MFD_ALLOW_SEALING;
73         if  (test_verbose > 0)
74           printf ("info: memfd_create with flags=0x%x\n", flags);
75         int fd = memfd_create ("tst-memfd_create", flags);
76         if (fd < 0)
77           {
78             if (errno == ENOSYS)
79               {
80                 if (supported < 0)
81                   {
82                     printf ("warning: memfd_create is unsupported\n");
83                     supported = 0;
84                     continue;
85                   }
86                 TEST_VERIFY (supported == 0);
87                 continue;
88               }
89             else
90               FAIL_EXIT1 ("memfd_create: %m");
91           }
92         if (supported < 0)
93           supported = 1;
94         TEST_VERIFY (supported > 0);
95 
96         char *fd_path = xasprintf ("/proc/self/fd/%d", fd);
97         char *link = xreadlink (fd_path);
98         if (test_verbose > 0)
99           printf ("info: memfd link: %s\n", link);
100         TEST_VERIFY (strcmp (link, "memfd:tst-memfd_create (deleted)"));
101         TEST_VERIFY (is_cloexec (fd) == do_cloexec);
102         TEST_VERIFY (is_sealed (fd) == !do_sealing);
103         if (do_sealing)
104           {
105             TEST_VERIFY (fcntl (fd, F_ADD_SEALS, F_SEAL_WRITE) == 0);
106             TEST_VERIFY (!is_sealed (fd));
107             TEST_VERIFY (get_seals (fd) & F_SEAL_WRITE);
108             TEST_VERIFY (fcntl (fd, F_ADD_SEALS, F_SEAL_SEAL) == 0);
109             TEST_VERIFY (is_sealed (fd));
110           }
111         xclose (fd);
112         free (fd_path);
113         free (link);
114       }
115 
116   if (supported == 0)
117     return EXIT_UNSUPPORTED;
118   return 0;
119 }
120 
121 #include <support/test-driver.c>
122