~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/memfd/memfd_test.c

Version: ~ [ linux-5.19-rc8 ] ~ [ linux-5.18.14 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.57 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.133 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.207 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.253 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.289 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.324 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.302 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 #define _GNU_SOURCE
  2 #define __EXPORTED_HEADERS__
  3 
  4 #include <errno.h>
  5 #include <inttypes.h>
  6 #include <limits.h>
  7 #include <linux/falloc.h>
  8 #include <linux/fcntl.h>
  9 #include <linux/memfd.h>
 10 #include <sched.h>
 11 #include <stdio.h>
 12 #include <stdlib.h>
 13 #include <signal.h>
 14 #include <string.h>
 15 #include <sys/mman.h>
 16 #include <sys/stat.h>
 17 #include <sys/syscall.h>
 18 #include <sys/wait.h>
 19 #include <unistd.h>
 20 
 21 #define MFD_DEF_SIZE 8192
 22 #define STACK_SIZE 65536
 23 
 24 static int sys_memfd_create(const char *name,
 25                             unsigned int flags)
 26 {
 27         return syscall(__NR_memfd_create, name, flags);
 28 }
 29 
 30 static int mfd_assert_new(const char *name, loff_t sz, unsigned int flags)
 31 {
 32         int r, fd;
 33 
 34         fd = sys_memfd_create(name, flags);
 35         if (fd < 0) {
 36                 printf("memfd_create(\"%s\", %u) failed: %m\n",
 37                        name, flags);
 38                 abort();
 39         }
 40 
 41         r = ftruncate(fd, sz);
 42         if (r < 0) {
 43                 printf("ftruncate(%llu) failed: %m\n", (unsigned long long)sz);
 44                 abort();
 45         }
 46 
 47         return fd;
 48 }
 49 
 50 static void mfd_fail_new(const char *name, unsigned int flags)
 51 {
 52         int r;
 53 
 54         r = sys_memfd_create(name, flags);
 55         if (r >= 0) {
 56                 printf("memfd_create(\"%s\", %u) succeeded, but failure expected\n",
 57                        name, flags);
 58                 close(r);
 59                 abort();
 60         }
 61 }
 62 
 63 static unsigned int mfd_assert_get_seals(int fd)
 64 {
 65         int r;
 66 
 67         r = fcntl(fd, F_GET_SEALS);
 68         if (r < 0) {
 69                 printf("GET_SEALS(%d) failed: %m\n", fd);
 70                 abort();
 71         }
 72 
 73         return (unsigned int)r;
 74 }
 75 
 76 static void mfd_assert_has_seals(int fd, unsigned int seals)
 77 {
 78         unsigned int s;
 79 
 80         s = mfd_assert_get_seals(fd);
 81         if (s != seals) {
 82                 printf("%u != %u = GET_SEALS(%d)\n", seals, s, fd);
 83                 abort();
 84         }
 85 }
 86 
 87 static void mfd_assert_add_seals(int fd, unsigned int seals)
 88 {
 89         int r;
 90         unsigned int s;
 91 
 92         s = mfd_assert_get_seals(fd);
 93         r = fcntl(fd, F_ADD_SEALS, seals);
 94         if (r < 0) {
 95                 printf("ADD_SEALS(%d, %u -> %u) failed: %m\n", fd, s, seals);
 96                 abort();
 97         }
 98 }
 99 
100 static void mfd_fail_add_seals(int fd, unsigned int seals)
101 {
102         int r;
103         unsigned int s;
104 
105         r = fcntl(fd, F_GET_SEALS);
106         if (r < 0)
107                 s = 0;
108         else
109                 s = (unsigned int)r;
110 
111         r = fcntl(fd, F_ADD_SEALS, seals);
112         if (r >= 0) {
113                 printf("ADD_SEALS(%d, %u -> %u) didn't fail as expected\n",
114                                 fd, s, seals);
115                 abort();
116         }
117 }
118 
119 static void mfd_assert_size(int fd, size_t size)
120 {
121         struct stat st;
122         int r;
123 
124         r = fstat(fd, &st);
125         if (r < 0) {
126                 printf("fstat(%d) failed: %m\n", fd);
127                 abort();
128         } else if (st.st_size != size) {
129                 printf("wrong file size %lld, but expected %lld\n",
130                        (long long)st.st_size, (long long)size);
131                 abort();
132         }
133 }
134 
135 static int mfd_assert_dup(int fd)
136 {
137         int r;
138 
139         r = dup(fd);
140         if (r < 0) {
141                 printf("dup(%d) failed: %m\n", fd);
142                 abort();
143         }
144 
145         return r;
146 }
147 
148 static void *mfd_assert_mmap_shared(int fd)
149 {
150         void *p;
151 
152         p = mmap(NULL,
153                  MFD_DEF_SIZE,
154                  PROT_READ | PROT_WRITE,
155                  MAP_SHARED,
156                  fd,
157                  0);
158         if (p == MAP_FAILED) {
159                 printf("mmap() failed: %m\n");
160                 abort();
161         }
162 
163         return p;
164 }
165 
166 static void *mfd_assert_mmap_private(int fd)
167 {
168         void *p;
169 
170         p = mmap(NULL,
171                  MFD_DEF_SIZE,
172                  PROT_READ,
173                  MAP_PRIVATE,
174                  fd,
175                  0);
176         if (p == MAP_FAILED) {
177                 printf("mmap() failed: %m\n");
178                 abort();
179         }
180 
181         return p;
182 }
183 
184 static int mfd_assert_open(int fd, int flags, mode_t mode)
185 {
186         char buf[512];
187         int r;
188 
189         sprintf(buf, "/proc/self/fd/%d", fd);
190         r = open(buf, flags, mode);
191         if (r < 0) {
192                 printf("open(%s) failed: %m\n", buf);
193                 abort();
194         }
195 
196         return r;
197 }
198 
199 static void mfd_fail_open(int fd, int flags, mode_t mode)
200 {
201         char buf[512];
202         int r;
203 
204         sprintf(buf, "/proc/self/fd/%d", fd);
205         r = open(buf, flags, mode);
206         if (r >= 0) {
207                 printf("open(%s) didn't fail as expected\n", buf);
208                 abort();
209         }
210 }
211 
212 static void mfd_assert_read(int fd)
213 {
214         char buf[16];
215         void *p;
216         ssize_t l;
217 
218         l = read(fd, buf, sizeof(buf));
219         if (l != sizeof(buf)) {
220                 printf("read() failed: %m\n");
221                 abort();
222         }
223 
224         /* verify PROT_READ *is* allowed */
225         p = mmap(NULL,
226                  MFD_DEF_SIZE,
227                  PROT_READ,
228                  MAP_PRIVATE,
229                  fd,
230                  0);
231         if (p == MAP_FAILED) {
232                 printf("mmap() failed: %m\n");
233                 abort();
234         }
235         munmap(p, MFD_DEF_SIZE);
236 
237         /* verify MAP_PRIVATE is *always* allowed (even writable) */
238         p = mmap(NULL,
239                  MFD_DEF_SIZE,
240                  PROT_READ | PROT_WRITE,
241                  MAP_PRIVATE,
242                  fd,
243                  0);
244         if (p == MAP_FAILED) {
245                 printf("mmap() failed: %m\n");
246                 abort();
247         }
248         munmap(p, MFD_DEF_SIZE);
249 }
250 
251 static void mfd_assert_write(int fd)
252 {
253         ssize_t l;
254         void *p;
255         int r;
256 
257         /* verify write() succeeds */
258         l = write(fd, "\0\0\0\0", 4);
259         if (l != 4) {
260                 printf("write() failed: %m\n");
261                 abort();
262         }
263 
264         /* verify PROT_READ | PROT_WRITE is allowed */
265         p = mmap(NULL,
266                  MFD_DEF_SIZE,
267                  PROT_READ | PROT_WRITE,
268                  MAP_SHARED,
269                  fd,
270                  0);
271         if (p == MAP_FAILED) {
272                 printf("mmap() failed: %m\n");
273                 abort();
274         }
275         *(char *)p = 0;
276         munmap(p, MFD_DEF_SIZE);
277 
278         /* verify PROT_WRITE is allowed */
279         p = mmap(NULL,
280                  MFD_DEF_SIZE,
281                  PROT_WRITE,
282                  MAP_SHARED,
283                  fd,
284                  0);
285         if (p == MAP_FAILED) {
286                 printf("mmap() failed: %m\n");
287                 abort();
288         }
289         *(char *)p = 0;
290         munmap(p, MFD_DEF_SIZE);
291 
292         /* verify PROT_READ with MAP_SHARED is allowed and a following
293          * mprotect(PROT_WRITE) allows writing */
294         p = mmap(NULL,
295                  MFD_DEF_SIZE,
296                  PROT_READ,
297                  MAP_SHARED,
298                  fd,
299                  0);
300         if (p == MAP_FAILED) {
301                 printf("mmap() failed: %m\n");
302                 abort();
303         }
304 
305         r = mprotect(p, MFD_DEF_SIZE, PROT_READ | PROT_WRITE);
306         if (r < 0) {
307                 printf("mprotect() failed: %m\n");
308                 abort();
309         }
310 
311         *(char *)p = 0;
312         munmap(p, MFD_DEF_SIZE);
313 
314         /* verify PUNCH_HOLE works */
315         r = fallocate(fd,
316                       FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
317                       0,
318                       MFD_DEF_SIZE);
319         if (r < 0) {
320                 printf("fallocate(PUNCH_HOLE) failed: %m\n");
321                 abort();
322         }
323 }
324 
325 static void mfd_fail_write(int fd)
326 {
327         ssize_t l;
328         void *p;
329         int r;
330 
331         /* verify write() fails */
332         l = write(fd, "data", 4);
333         if (l != -EPERM) {
334                 printf("expected EPERM on write(), but got %d: %m\n", (int)l);
335                 abort();
336         }
337 
338         /* verify PROT_READ | PROT_WRITE is not allowed */
339         p = mmap(NULL,
340                  MFD_DEF_SIZE,
341                  PROT_READ | PROT_WRITE,
342                  MAP_SHARED,
343                  fd,
344                  0);
345         if (p != MAP_FAILED) {
346                 printf("mmap() didn't fail as expected\n");
347                 abort();
348         }
349 
350         /* verify PROT_WRITE is not allowed */
351         p = mmap(NULL,
352                  MFD_DEF_SIZE,
353                  PROT_WRITE,
354                  MAP_SHARED,
355                  fd,
356                  0);
357         if (p != MAP_FAILED) {
358                 printf("mmap() didn't fail as expected\n");
359                 abort();
360         }
361 
362         /* Verify PROT_READ with MAP_SHARED with a following mprotect is not
363          * allowed. Note that for r/w the kernel already prevents the mmap. */
364         p = mmap(NULL,
365                  MFD_DEF_SIZE,
366                  PROT_READ,
367                  MAP_SHARED,
368                  fd,
369                  0);
370         if (p != MAP_FAILED) {
371                 r = mprotect(p, MFD_DEF_SIZE, PROT_READ | PROT_WRITE);
372                 if (r >= 0) {
373                         printf("mmap()+mprotect() didn't fail as expected\n");
374                         abort();
375                 }
376         }
377 
378         /* verify PUNCH_HOLE fails */
379         r = fallocate(fd,
380                       FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
381                       0,
382                       MFD_DEF_SIZE);
383         if (r >= 0) {
384                 printf("fallocate(PUNCH_HOLE) didn't fail as expected\n");
385                 abort();
386         }
387 }
388 
389 static void mfd_assert_shrink(int fd)
390 {
391         int r, fd2;
392 
393         r = ftruncate(fd, MFD_DEF_SIZE / 2);
394         if (r < 0) {
395                 printf("ftruncate(SHRINK) failed: %m\n");
396                 abort();
397         }
398 
399         mfd_assert_size(fd, MFD_DEF_SIZE / 2);
400 
401         fd2 = mfd_assert_open(fd,
402                               O_RDWR | O_CREAT | O_TRUNC,
403                               S_IRUSR | S_IWUSR);
404         close(fd2);
405 
406         mfd_assert_size(fd, 0);
407 }
408 
409 static void mfd_fail_shrink(int fd)
410 {
411         int r;
412 
413         r = ftruncate(fd, MFD_DEF_SIZE / 2);
414         if (r >= 0) {
415                 printf("ftruncate(SHRINK) didn't fail as expected\n");
416                 abort();
417         }
418 
419         mfd_fail_open(fd,
420                       O_RDWR | O_CREAT | O_TRUNC,
421                       S_IRUSR | S_IWUSR);
422 }
423 
424 static void mfd_assert_grow(int fd)
425 {
426         int r;
427 
428         r = ftruncate(fd, MFD_DEF_SIZE * 2);
429         if (r < 0) {
430                 printf("ftruncate(GROW) failed: %m\n");
431                 abort();
432         }
433 
434         mfd_assert_size(fd, MFD_DEF_SIZE * 2);
435 
436         r = fallocate(fd,
437                       0,
438                       0,
439                       MFD_DEF_SIZE * 4);
440         if (r < 0) {
441                 printf("fallocate(ALLOC) failed: %m\n");
442                 abort();
443         }
444 
445         mfd_assert_size(fd, MFD_DEF_SIZE * 4);
446 }
447 
448 static void mfd_fail_grow(int fd)
449 {
450         int r;
451 
452         r = ftruncate(fd, MFD_DEF_SIZE * 2);
453         if (r >= 0) {
454                 printf("ftruncate(GROW) didn't fail as expected\n");
455                 abort();
456         }
457 
458         r = fallocate(fd,
459                       0,
460                       0,
461                       MFD_DEF_SIZE * 4);
462         if (r >= 0) {
463                 printf("fallocate(ALLOC) didn't fail as expected\n");
464                 abort();
465         }
466 }
467 
468 static void mfd_assert_grow_write(int fd)
469 {
470         static char buf[MFD_DEF_SIZE * 8];
471         ssize_t l;
472 
473         l = pwrite(fd, buf, sizeof(buf), 0);
474         if (l != sizeof(buf)) {
475                 printf("pwrite() failed: %m\n");
476                 abort();
477         }
478 
479         mfd_assert_size(fd, MFD_DEF_SIZE * 8);
480 }
481 
482 static void mfd_fail_grow_write(int fd)
483 {
484         static char buf[MFD_DEF_SIZE * 8];
485         ssize_t l;
486 
487         l = pwrite(fd, buf, sizeof(buf), 0);
488         if (l == sizeof(buf)) {
489                 printf("pwrite() didn't fail as expected\n");
490                 abort();
491         }
492 }
493 
494 static int idle_thread_fn(void *arg)
495 {
496         sigset_t set;
497         int sig;
498 
499         /* dummy waiter; SIGTERM terminates us anyway */
500         sigemptyset(&set);
501         sigaddset(&set, SIGTERM);
502         sigwait(&set, &sig);
503 
504         return 0;
505 }
506 
507 static pid_t spawn_idle_thread(unsigned int flags)
508 {
509         uint8_t *stack;
510         pid_t pid;
511 
512         stack = malloc(STACK_SIZE);
513         if (!stack) {
514                 printf("malloc(STACK_SIZE) failed: %m\n");
515                 abort();
516         }
517 
518         pid = clone(idle_thread_fn,
519                     stack + STACK_SIZE,
520                     SIGCHLD | flags,
521                     NULL);
522         if (pid < 0) {
523                 printf("clone() failed: %m\n");
524                 abort();
525         }
526 
527         return pid;
528 }
529 
530 static void join_idle_thread(pid_t pid)
531 {
532         kill(pid, SIGTERM);
533         waitpid(pid, NULL, 0);
534 }
535 
536 /*
537  * Test memfd_create() syscall
538  * Verify syscall-argument validation, including name checks, flag validation
539  * and more.
540  */
541 static void test_create(void)
542 {
543         char buf[2048];
544         int fd;
545 
546         /* test NULL name */
547         mfd_fail_new(NULL, 0);
548 
549         /* test over-long name (not zero-terminated) */
550         memset(buf, 0xff, sizeof(buf));
551         mfd_fail_new(buf, 0);
552 
553         /* test over-long zero-terminated name */
554         memset(buf, 0xff, sizeof(buf));
555         buf[sizeof(buf) - 1] = 0;
556         mfd_fail_new(buf, 0);
557 
558         /* verify "" is a valid name */
559         fd = mfd_assert_new("", 0, 0);
560         close(fd);
561 
562         /* verify invalid O_* open flags */
563         mfd_fail_new("", 0x0100);
564         mfd_fail_new("", ~MFD_CLOEXEC);
565         mfd_fail_new("", ~MFD_ALLOW_SEALING);
566         mfd_fail_new("", ~0);
567         mfd_fail_new("", 0x80000000U);
568 
569         /* verify MFD_CLOEXEC is allowed */
570         fd = mfd_assert_new("", 0, MFD_CLOEXEC);
571         close(fd);
572 
573         /* verify MFD_ALLOW_SEALING is allowed */
574         fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING);
575         close(fd);
576 
577         /* verify MFD_ALLOW_SEALING | MFD_CLOEXEC is allowed */
578         fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING | MFD_CLOEXEC);
579         close(fd);
580 }
581 
582 /*
583  * Test basic sealing
584  * A very basic sealing test to see whether setting/retrieving seals works.
585  */
586 static void test_basic(void)
587 {
588         int fd;
589 
590         fd = mfd_assert_new("kern_memfd_basic",
591                             MFD_DEF_SIZE,
592                             MFD_CLOEXEC | MFD_ALLOW_SEALING);
593 
594         /* add basic seals */
595         mfd_assert_has_seals(fd, 0);
596         mfd_assert_add_seals(fd, F_SEAL_SHRINK |
597                                  F_SEAL_WRITE);
598         mfd_assert_has_seals(fd, F_SEAL_SHRINK |
599                                  F_SEAL_WRITE);
600 
601         /* add them again */
602         mfd_assert_add_seals(fd, F_SEAL_SHRINK |
603                                  F_SEAL_WRITE);
604         mfd_assert_has_seals(fd, F_SEAL_SHRINK |
605                                  F_SEAL_WRITE);
606 
607         /* add more seals and seal against sealing */
608         mfd_assert_add_seals(fd, F_SEAL_GROW | F_SEAL_SEAL);
609         mfd_assert_has_seals(fd, F_SEAL_SHRINK |
610                                  F_SEAL_GROW |
611                                  F_SEAL_WRITE |
612                                  F_SEAL_SEAL);
613 
614         /* verify that sealing no longer works */
615         mfd_fail_add_seals(fd, F_SEAL_GROW);
616         mfd_fail_add_seals(fd, 0);
617 
618         close(fd);
619 
620         /* verify sealing does not work without MFD_ALLOW_SEALING */
621         fd = mfd_assert_new("kern_memfd_basic",
622                             MFD_DEF_SIZE,
623                             MFD_CLOEXEC);
624         mfd_assert_has_seals(fd, F_SEAL_SEAL);
625         mfd_fail_add_seals(fd, F_SEAL_SHRINK |
626                                F_SEAL_GROW |
627                                F_SEAL_WRITE);
628         mfd_assert_has_seals(fd, F_SEAL_SEAL);
629         close(fd);
630 }
631 
632 /*
633  * Test SEAL_WRITE
634  * Test whether SEAL_WRITE actually prevents modifications.
635  */
636 static void test_seal_write(void)
637 {
638         int fd;
639 
640         fd = mfd_assert_new("kern_memfd_seal_write",
641                             MFD_DEF_SIZE,
642                             MFD_CLOEXEC | MFD_ALLOW_SEALING);
643         mfd_assert_has_seals(fd, 0);
644         mfd_assert_add_seals(fd, F_SEAL_WRITE);
645         mfd_assert_has_seals(fd, F_SEAL_WRITE);
646 
647         mfd_assert_read(fd);
648         mfd_fail_write(fd);
649         mfd_assert_shrink(fd);
650         mfd_assert_grow(fd);
651         mfd_fail_grow_write(fd);
652 
653         close(fd);
654 }
655 
656 /*
657  * Test SEAL_SHRINK
658  * Test whether SEAL_SHRINK actually prevents shrinking
659  */
660 static void test_seal_shrink(void)
661 {
662         int fd;
663 
664         fd = mfd_assert_new("kern_memfd_seal_shrink",
665                             MFD_DEF_SIZE,
666                             MFD_CLOEXEC | MFD_ALLOW_SEALING);
667         mfd_assert_has_seals(fd, 0);
668         mfd_assert_add_seals(fd, F_SEAL_SHRINK);
669         mfd_assert_has_seals(fd, F_SEAL_SHRINK);
670 
671         mfd_assert_read(fd);
672         mfd_assert_write(fd);
673         mfd_fail_shrink(fd);
674         mfd_assert_grow(fd);
675         mfd_assert_grow_write(fd);
676 
677         close(fd);
678 }
679 
680 /*
681  * Test SEAL_GROW
682  * Test whether SEAL_GROW actually prevents growing
683  */
684 static void test_seal_grow(void)
685 {
686         int fd;
687 
688         fd = mfd_assert_new("kern_memfd_seal_grow",
689                             MFD_DEF_SIZE,
690                             MFD_CLOEXEC | MFD_ALLOW_SEALING);
691         mfd_assert_has_seals(fd, 0);
692         mfd_assert_add_seals(fd, F_SEAL_GROW);
693         mfd_assert_has_seals(fd, F_SEAL_GROW);
694 
695         mfd_assert_read(fd);
696         mfd_assert_write(fd);
697         mfd_assert_shrink(fd);
698         mfd_fail_grow(fd);
699         mfd_fail_grow_write(fd);
700 
701         close(fd);
702 }
703 
704 /*
705  * Test SEAL_SHRINK | SEAL_GROW
706  * Test whether SEAL_SHRINK | SEAL_GROW actually prevents resizing
707  */
708 static void test_seal_resize(void)
709 {
710         int fd;
711 
712         fd = mfd_assert_new("kern_memfd_seal_resize",
713                             MFD_DEF_SIZE,
714                             MFD_CLOEXEC | MFD_ALLOW_SEALING);
715         mfd_assert_has_seals(fd, 0);
716         mfd_assert_add_seals(fd, F_SEAL_SHRINK | F_SEAL_GROW);
717         mfd_assert_has_seals(fd, F_SEAL_SHRINK | F_SEAL_GROW);
718 
719         mfd_assert_read(fd);
720         mfd_assert_write(fd);
721         mfd_fail_shrink(fd);
722         mfd_fail_grow(fd);
723         mfd_fail_grow_write(fd);
724 
725         close(fd);
726 }
727 
728 /*
729  * Test sharing via dup()
730  * Test that seals are shared between dupped FDs and they're all equal.
731  */
732 static void test_share_dup(void)
733 {
734         int fd, fd2;
735 
736         fd = mfd_assert_new("kern_memfd_share_dup",
737                             MFD_DEF_SIZE,
738                             MFD_CLOEXEC | MFD_ALLOW_SEALING);
739         mfd_assert_has_seals(fd, 0);
740 
741         fd2 = mfd_assert_dup(fd);
742         mfd_assert_has_seals(fd2, 0);
743 
744         mfd_assert_add_seals(fd, F_SEAL_WRITE);
745         mfd_assert_has_seals(fd, F_SEAL_WRITE);
746         mfd_assert_has_seals(fd2, F_SEAL_WRITE);
747 
748         mfd_assert_add_seals(fd2, F_SEAL_SHRINK);
749         mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
750         mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK);
751 
752         mfd_assert_add_seals(fd, F_SEAL_SEAL);
753         mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
754         mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
755 
756         mfd_fail_add_seals(fd, F_SEAL_GROW);
757         mfd_fail_add_seals(fd2, F_SEAL_GROW);
758         mfd_fail_add_seals(fd, F_SEAL_SEAL);
759         mfd_fail_add_seals(fd2, F_SEAL_SEAL);
760 
761         close(fd2);
762 
763         mfd_fail_add_seals(fd, F_SEAL_GROW);
764         close(fd);
765 }
766 
767 /*
768  * Test sealing with active mmap()s
769  * Modifying seals is only allowed if no other mmap() refs exist.
770  */
771 static void test_share_mmap(void)
772 {
773         int fd;
774         void *p;
775 
776         fd = mfd_assert_new("kern_memfd_share_mmap",
777                             MFD_DEF_SIZE,
778                             MFD_CLOEXEC | MFD_ALLOW_SEALING);
779         mfd_assert_has_seals(fd, 0);
780 
781         /* shared/writable ref prevents sealing WRITE, but allows others */
782         p = mfd_assert_mmap_shared(fd);
783         mfd_fail_add_seals(fd, F_SEAL_WRITE);
784         mfd_assert_has_seals(fd, 0);
785         mfd_assert_add_seals(fd, F_SEAL_SHRINK);
786         mfd_assert_has_seals(fd, F_SEAL_SHRINK);
787         munmap(p, MFD_DEF_SIZE);
788 
789         /* readable ref allows sealing */
790         p = mfd_assert_mmap_private(fd);
791         mfd_assert_add_seals(fd, F_SEAL_WRITE);
792         mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
793         munmap(p, MFD_DEF_SIZE);
794 
795         close(fd);
796 }
797 
798 /*
799  * Test sealing with open(/proc/self/fd/%d)
800  * Via /proc we can get access to a separate file-context for the same memfd.
801  * This is *not* like dup(), but like a real separate open(). Make sure the
802  * semantics are as expected and we correctly check for RDONLY / WRONLY / RDWR.
803  */
804 static void test_share_open(void)
805 {
806         int fd, fd2;
807 
808         fd = mfd_assert_new("kern_memfd_share_open",
809                             MFD_DEF_SIZE,
810                             MFD_CLOEXEC | MFD_ALLOW_SEALING);
811         mfd_assert_has_seals(fd, 0);
812 
813         fd2 = mfd_assert_open(fd, O_RDWR, 0);
814         mfd_assert_add_seals(fd, F_SEAL_WRITE);
815         mfd_assert_has_seals(fd, F_SEAL_WRITE);
816         mfd_assert_has_seals(fd2, F_SEAL_WRITE);
817 
818         mfd_assert_add_seals(fd2, F_SEAL_SHRINK);
819         mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
820         mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK);
821 
822         close(fd);
823         fd = mfd_assert_open(fd2, O_RDONLY, 0);
824 
825         mfd_fail_add_seals(fd, F_SEAL_SEAL);
826         mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
827         mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK);
828 
829         close(fd2);
830         fd2 = mfd_assert_open(fd, O_RDWR, 0);
831 
832         mfd_assert_add_seals(fd2, F_SEAL_SEAL);
833         mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
834         mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
835 
836         close(fd2);
837         close(fd);
838 }
839 
840 /*
841  * Test sharing via fork()
842  * Test whether seal-modifications work as expected with forked childs.
843  */
844 static void test_share_fork(void)
845 {
846         int fd;
847         pid_t pid;
848 
849         fd = mfd_assert_new("kern_memfd_share_fork",
850                             MFD_DEF_SIZE,
851                             MFD_CLOEXEC | MFD_ALLOW_SEALING);
852         mfd_assert_has_seals(fd, 0);
853 
854         pid = spawn_idle_thread(0);
855         mfd_assert_add_seals(fd, F_SEAL_SEAL);
856         mfd_assert_has_seals(fd, F_SEAL_SEAL);
857 
858         mfd_fail_add_seals(fd, F_SEAL_WRITE);
859         mfd_assert_has_seals(fd, F_SEAL_SEAL);
860 
861         join_idle_thread(pid);
862 
863         mfd_fail_add_seals(fd, F_SEAL_WRITE);
864         mfd_assert_has_seals(fd, F_SEAL_SEAL);
865 
866         close(fd);
867 }
868 
869 int main(int argc, char **argv)
870 {
871         pid_t pid;
872 
873         printf("memfd: CREATE\n");
874         test_create();
875         printf("memfd: BASIC\n");
876         test_basic();
877 
878         printf("memfd: SEAL-WRITE\n");
879         test_seal_write();
880         printf("memfd: SEAL-SHRINK\n");
881         test_seal_shrink();
882         printf("memfd: SEAL-GROW\n");
883         test_seal_grow();
884         printf("memfd: SEAL-RESIZE\n");
885         test_seal_resize();
886 
887         printf("memfd: SHARE-DUP\n");
888         test_share_dup();
889         printf("memfd: SHARE-MMAP\n");
890         test_share_mmap();
891         printf("memfd: SHARE-OPEN\n");
892         test_share_open();
893         printf("memfd: SHARE-FORK\n");
894         test_share_fork();
895 
896         /* Run test-suite in a multi-threaded environment with a shared
897          * file-table. */
898         pid = spawn_idle_thread(CLONE_FILES | CLONE_FS | CLONE_VM);
899         printf("memfd: SHARE-DUP (shared file-table)\n");
900         test_share_dup();
901         printf("memfd: SHARE-MMAP (shared file-table)\n");
902         test_share_mmap();
903         printf("memfd: SHARE-OPEN (shared file-table)\n");
904         test_share_open();
905         printf("memfd: SHARE-FORK (shared file-table)\n");
906         test_share_fork();
907         join_idle_thread(pid);
908 
909         printf("memfd: DONE\n");
910 
911         return 0;
912 }
913 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp