Home | History | Annotate | Download | only in memfd_create
      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 (at) gmail.com>
     19  *
     20  *  24/02/2017   Port to LTP    <jracek (at) redhat.com>
     21  */
     22 
     23 #define _GNU_SOURCE
     24 
     25 #include <errno.h>
     26 #include "tst_test.h"
     27 #include "memfd_create_common.h"
     28 
     29 /*
     30  * Do few basic sealing tests to see whether setting/retrieving seals works.
     31  */
     32 static void test_basic(int fd)
     33 {
     34 	/* add basic seals */
     35 	CHECK_MFD_HAS_SEALS(fd, 0);
     36 	CHECK_MFD_ADD_SEALS(fd, F_SEAL_SHRINK | F_SEAL_WRITE);
     37 	CHECK_MFD_HAS_SEALS(fd, F_SEAL_SHRINK | F_SEAL_WRITE);
     38 
     39 	/* add them again */
     40 	CHECK_MFD_ADD_SEALS(fd, F_SEAL_SHRINK | F_SEAL_WRITE);
     41 	CHECK_MFD_HAS_SEALS(fd, F_SEAL_SHRINK | F_SEAL_WRITE);
     42 
     43 	/* add more seals and seal against sealing */
     44 	CHECK_MFD_ADD_SEALS(fd, F_SEAL_GROW | F_SEAL_SEAL);
     45 	CHECK_MFD_HAS_SEALS(fd, F_SEAL_SHRINK | F_SEAL_GROW |
     46 			F_SEAL_WRITE | F_SEAL_SEAL);
     47 
     48 	/* verify that sealing no longer works */
     49 	CHECK_MFD_FAIL_ADD_SEALS(fd, F_SEAL_GROW);
     50 	CHECK_MFD_FAIL_ADD_SEALS(fd, 0);
     51 }
     52 
     53 /*
     54  * Verify that no sealing is possible when memfd is created without
     55  * MFD_ALLOW_SEALING flag.
     56  */
     57 static void test_no_sealing_without_flag(int fd)
     58 {
     59 	CHECK_MFD_HAS_SEALS(fd, F_SEAL_SEAL);
     60 	CHECK_MFD_FAIL_ADD_SEALS(fd,
     61 		F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE);
     62 	CHECK_MFD_HAS_SEALS(fd, F_SEAL_SEAL);
     63 }
     64 
     65 /*
     66  * Test SEAL_WRITE
     67  * Test whether SEAL_WRITE actually prevents modifications.
     68  */
     69 static void test_seal_write(int fd)
     70 {
     71 	CHECK_MFD_HAS_SEALS(fd, 0);
     72 	CHECK_MFD_ADD_SEALS(fd, F_SEAL_WRITE);
     73 	CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE);
     74 
     75 	CHECK_MFD_READABLE(fd);
     76 	CHECK_MFD_NON_WRITEABLE(fd);
     77 	CHECK_MFD_SHRINKABLE(fd);
     78 	CHECK_MFD_GROWABLE(fd);
     79 	CHECK_MFD_NON_GROWABLE_BY_WRITE(fd);
     80 }
     81 
     82 /*
     83  * Test SEAL_SHRINK
     84  * Test whether SEAL_SHRINK actually prevents shrinking
     85  */
     86 static void test_seal_shrink(int fd)
     87 {
     88 	CHECK_MFD_HAS_SEALS(fd, 0);
     89 	CHECK_MFD_ADD_SEALS(fd, F_SEAL_SHRINK);
     90 	CHECK_MFD_HAS_SEALS(fd, F_SEAL_SHRINK);
     91 
     92 	CHECK_MFD_READABLE(fd);
     93 	CHECK_MFD_WRITEABLE(fd);
     94 	CHECK_MFD_NON_SHRINKABLE(fd);
     95 	CHECK_MFD_GROWABLE(fd);
     96 	CHECK_MFD_GROWABLE_BY_WRITE(fd);
     97 }
     98 
     99 /*
    100  * Test SEAL_GROW
    101  * Test whether SEAL_GROW actually prevents growing
    102  */
    103 static void test_seal_grow(int fd)
    104 {
    105 	CHECK_MFD_HAS_SEALS(fd, 0);
    106 	CHECK_MFD_ADD_SEALS(fd, F_SEAL_GROW);
    107 	CHECK_MFD_HAS_SEALS(fd, F_SEAL_GROW);
    108 
    109 	CHECK_MFD_READABLE(fd);
    110 	CHECK_MFD_WRITEABLE(fd);
    111 	CHECK_MFD_SHRINKABLE(fd);
    112 	CHECK_MFD_NON_GROWABLE(fd);
    113 	CHECK_MFD_NON_GROWABLE_BY_WRITE(fd);
    114 }
    115 
    116 /*
    117  * Test SEAL_SHRINK | SEAL_GROW
    118  * Test whether SEAL_SHRINK | SEAL_GROW actually prevents resizing
    119  */
    120 static void test_seal_resize(int fd)
    121 {
    122 	CHECK_MFD_HAS_SEALS(fd, 0);
    123 	CHECK_MFD_ADD_SEALS(fd, F_SEAL_SHRINK | F_SEAL_GROW);
    124 	CHECK_MFD_HAS_SEALS(fd, F_SEAL_SHRINK | F_SEAL_GROW);
    125 
    126 	CHECK_MFD_READABLE(fd);
    127 	CHECK_MFD_WRITEABLE(fd);
    128 	CHECK_MFD_NON_SHRINKABLE(fd);
    129 	CHECK_MFD_NON_GROWABLE(fd);
    130 	CHECK_MFD_NON_GROWABLE_BY_WRITE(fd);
    131 }
    132 
    133 /*
    134  * Test sharing via dup()
    135  * Test that seals are shared between dupped FDs and they're all equal.
    136  */
    137 static void test_share_dup(int fd)
    138 {
    139 	int fd2;
    140 
    141 	CHECK_MFD_HAS_SEALS(fd, 0);
    142 
    143 	fd2 = SAFE_DUP(fd);
    144 	CHECK_MFD_HAS_SEALS(fd2, 0);
    145 
    146 	CHECK_MFD_ADD_SEALS(fd, F_SEAL_WRITE);
    147 	CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE);
    148 	CHECK_MFD_HAS_SEALS(fd2, F_SEAL_WRITE);
    149 
    150 	CHECK_MFD_ADD_SEALS(fd2, F_SEAL_SHRINK);
    151 	CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
    152 	CHECK_MFD_HAS_SEALS(fd2, F_SEAL_WRITE | F_SEAL_SHRINK);
    153 
    154 	CHECK_MFD_ADD_SEALS(fd, F_SEAL_SEAL);
    155 	CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
    156 	CHECK_MFD_HAS_SEALS(fd2, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
    157 
    158 	CHECK_MFD_FAIL_ADD_SEALS(fd, F_SEAL_GROW);
    159 	CHECK_MFD_FAIL_ADD_SEALS(fd2, F_SEAL_GROW);
    160 	CHECK_MFD_FAIL_ADD_SEALS(fd, F_SEAL_SEAL);
    161 	CHECK_MFD_FAIL_ADD_SEALS(fd2, F_SEAL_SEAL);
    162 
    163 	SAFE_CLOSE(fd2);
    164 
    165 	CHECK_MFD_FAIL_ADD_SEALS(fd, F_SEAL_GROW);
    166 }
    167 
    168 /*
    169  * Test sealing with active mmap()s
    170  * Modifying seals is only allowed if no other mmap() refs exist.
    171  */
    172 static void test_share_mmap(int fd)
    173 {
    174 	void *p;
    175 
    176 	CHECK_MFD_HAS_SEALS(fd, 0);
    177 
    178 	/* shared/writable ref prevents sealing WRITE, but allows others */
    179 	p = SAFE_MMAP(NULL, MFD_DEF_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
    180 		fd, 0);
    181 
    182 	CHECK_MFD_FAIL_ADD_SEALS(fd, F_SEAL_WRITE);
    183 	CHECK_MFD_HAS_SEALS(fd, 0);
    184 	CHECK_MFD_ADD_SEALS(fd, F_SEAL_SHRINK);
    185 	CHECK_MFD_HAS_SEALS(fd, F_SEAL_SHRINK);
    186 	SAFE_MUNMAP(p, MFD_DEF_SIZE);
    187 
    188 	/* readable ref allows sealing */
    189 	p = SAFE_MMAP(NULL, MFD_DEF_SIZE, PROT_READ, MAP_PRIVATE, fd, 0);
    190 	CHECK_MFD_ADD_SEALS(fd, F_SEAL_WRITE);
    191 	CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
    192 	SAFE_MUNMAP(p, MFD_DEF_SIZE);
    193 }
    194 
    195 /*
    196  * Test sealing with open(/proc/self/fd/%d)
    197  * Via /proc we can get access to a separate file-context for the same memfd.
    198  * This is *not* like dup(), but like a real separate open(). Make sure the
    199  * semantics are as expected and we correctly check for RDONLY / WRONLY / RDWR.
    200  */
    201 static void test_share_open(int fd)
    202 {
    203 	int fd2;
    204 
    205 	CHECK_MFD_HAS_SEALS(fd, 0);
    206 
    207 	fd2 = CHECK_MFD_OPEN(fd, O_RDWR, 0);
    208 	CHECK_MFD_ADD_SEALS(fd, F_SEAL_WRITE);
    209 	CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE);
    210 	CHECK_MFD_HAS_SEALS(fd2, F_SEAL_WRITE);
    211 
    212 	CHECK_MFD_ADD_SEALS(fd2, F_SEAL_SHRINK);
    213 	CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
    214 	CHECK_MFD_HAS_SEALS(fd2, F_SEAL_WRITE | F_SEAL_SHRINK);
    215 
    216 	SAFE_CLOSE(fd);
    217 	fd = CHECK_MFD_OPEN(fd2, O_RDONLY, 0);
    218 
    219 	CHECK_MFD_FAIL_ADD_SEALS(fd, F_SEAL_SEAL);
    220 	CHECK_MFD_HAS_SEALS(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
    221 	CHECK_MFD_HAS_SEALS(fd2, F_SEAL_WRITE | F_SEAL_SHRINK);
    222 
    223 	SAFE_CLOSE(fd2);
    224 }
    225 
    226 
    227 static const struct tcase {
    228 	int flags;
    229 	void (*func)(int fd);
    230 	const char *desc;
    231 } tcases[] = {
    232 	{MFD_ALLOW_SEALING, &test_basic, "Basic tests + set/get seals"},
    233 	{0,                 &test_no_sealing_without_flag, "Disabled sealing"},
    234 
    235 	{MFD_ALLOW_SEALING, &test_seal_write, "Write seal"},
    236 	{MFD_ALLOW_SEALING, &test_seal_shrink, "Shrink seal"},
    237 	{MFD_ALLOW_SEALING, &test_seal_grow, "Grow seal"},
    238 	{MFD_ALLOW_SEALING, &test_seal_resize, "Resize seal"},
    239 
    240 	{MFD_ALLOW_SEALING, &test_share_dup, "Seals shared for dup"},
    241 	{MFD_ALLOW_SEALING, &test_share_mmap, "Seals shared for mmap"},
    242 	{MFD_ALLOW_SEALING, &test_share_open, "Seals shared for open"},
    243 };
    244 
    245 static void verify_memfd_create(unsigned int n)
    246 {
    247 	int fd;
    248 	const struct tcase *tc;
    249 
    250 	tc = &tcases[n];
    251 
    252 	tst_res(TINFO, "%s", tc->desc);
    253 
    254 	fd = CHECK_MFD_NEW(TCID, MFD_DEF_SIZE, tc->flags);
    255 
    256 	tc->func(fd);
    257 
    258 	SAFE_CLOSE(fd);
    259 }
    260 
    261 static void setup(void)
    262 {
    263 	/*
    264 	 * For now, all tests in this file require MFD_ALLOW_SEALING flag
    265 	 * to be implemented, even though that flag isn't always set when
    266 	 * memfd is created. So don't check anything else and TCONF right away
    267 	 * is this flag is missing.
    268 	 */
    269 	if (!MFD_FLAGS_AVAILABLE(MFD_ALLOW_SEALING)) {
    270 		tst_brk(TCONF | TTERRNO,
    271 			"memfd_create(%u) not implemented", MFD_ALLOW_SEALING);
    272 	}
    273 }
    274 
    275 static struct tst_test test = {
    276 	.test = verify_memfd_create,
    277 	.tcnt = ARRAY_SIZE(tcases),
    278 	.setup = setup,
    279 };
    280