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