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

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

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

~ [ 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