1 /*- 2 * Copyright (c) 2006 nCircle Network Security, Inc. 3 * All rights reserved. 4 * 5 * This software was developed by Robert N. M. Watson for the TrustedBSD 6 * Project under contract to nCircle Network Security, Inc. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY, 21 * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 23 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * $FreeBSD$ 30 */ 31 32 /* 33 * This is a joint test of both the read and write privileges with respect to 34 * discretionary file system access control (permissions). Only permissions, 35 * not ACL semantics, and only privilege-related checks are performed. 36 */ 37 38 #include <sys/types.h> 39 #include <sys/stat.h> 40 41 #include <err.h> 42 #include <errno.h> 43 #include <fcntl.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <unistd.h> 47 48 #include "main.h" 49 50 struct test_arguments { 51 int open_flags; 52 uid_t proc_uid; 53 gid_t proc_gid; 54 uid_t file_uid; 55 gid_t file_gid; 56 }; 57 58 /* 59 * Rather special-purpose, don't reuse. Will need updating if anything other 60 * than O_RDONLY and O_WRONLY are to be used in tests. 61 */ 62 static const char * 63 flags_to_string(int flags) 64 { 65 66 switch (flags) { 67 case O_RDONLY: 68 return ("O_RDONLY"); 69 70 case O_WRONLY: 71 return ("O_WRONLY"); 72 73 default: 74 return ("unknown"); 75 } 76 } 77 78 static void 79 test_perm(struct test_arguments ta, mode_t file_mode, int expected) 80 { 81 uid_t proc_uid, file_uid; 82 gid_t proc_gid, file_gid; 83 int fd, open_flags; 84 char fpath[1024]; 85 86 proc_uid = ta.proc_uid; 87 proc_gid = ta.proc_gid; 88 file_uid = ta.file_uid; 89 file_gid = ta.file_gid; 90 open_flags = ta.open_flags; 91 92 setup_file(fpath, file_uid, file_gid, file_mode); 93 set_creds(proc_uid, proc_gid); 94 95 fd = open(fpath, open_flags); 96 97 if (expected == 0) { 98 if (fd <= 0) { 99 warn("test_perm(%s, %d, %d, %d, %d, %04o, %d) " 100 "returned %d instead of %d", 101 flags_to_string(open_flags), proc_uid, proc_gid, 102 file_uid, file_gid, file_mode, expected, 103 errno, expected); 104 restore_creds(); 105 (void)unlink(fpath); 106 exit(-1); 107 } 108 close(fd); 109 } else { 110 if (fd >= 0) { 111 warnx("test_perm(%s, %d, %d, %d, %d, %04o, %d)" 112 " returned 0 instead of %d", 113 flags_to_string(open_flags), proc_uid, proc_gid, 114 file_uid, file_gid, file_mode, expected, 115 expected); 116 close(fd); 117 restore_creds(); 118 (void)unlink(fpath); 119 exit(-1); 120 } else if (errno != expected) { 121 warn("test_perm(%s, %d, %d, %d, %d, %04o, %d)" 122 " returned %d instead of %d", 123 flags_to_string(open_flags), proc_uid, proc_gid, 124 file_uid, file_gid, file_mode, expected, 125 errno, expected); 126 restore_creds(); 127 (void)unlink(fpath); 128 exit(-1); 129 } 130 } 131 132 restore_creds(); 133 (void)unlink(fpath); 134 } 135 136 static const gid_t gidset[] = { GID_WHEEL }; 137 138 static void 139 preamble(void) 140 { 141 142 if (getuid() != UID_ROOT) 143 errx(-1, "must be run as root"); 144 if (setgroups(1, gidset) < 0) 145 err(-1, "setgroups(1, {%d})", GID_WHEEL); 146 } 147 148 void 149 priv_vfs_read(void) 150 { 151 struct test_arguments ta; 152 153 preamble(); 154 155 ta.open_flags = O_RDONLY; 156 157 /* 158 * Privileged user and file owner. All tests should pass. 159 */ 160 ta.proc_uid = UID_ROOT; 161 ta.proc_gid = GID_WHEEL; 162 ta.file_uid = UID_ROOT; 163 ta.file_gid = GID_WHEEL; 164 165 test_perm(ta, 0000, 0); 166 test_perm(ta, 0100, 0); 167 test_perm(ta, 0200, 0); 168 test_perm(ta, 0300, 0); 169 test_perm(ta, 0400, 0); 170 test_perm(ta, 0500, 0); 171 test_perm(ta, 0600, 0); 172 test_perm(ta, 0700, 0); 173 174 /* 175 * Privileged user and file group. All tests should pass. 176 */ 177 ta.proc_uid = UID_ROOT; 178 ta.proc_gid = GID_WHEEL; 179 ta.file_uid = UID_OWNER; 180 ta.file_gid = GID_WHEEL; 181 182 test_perm(ta, 0000, 0); 183 test_perm(ta, 0010, 0); 184 test_perm(ta, 0020, 0); 185 test_perm(ta, 0030, 0); 186 test_perm(ta, 0040, 0); 187 test_perm(ta, 0050, 0); 188 test_perm(ta, 0060, 0); 189 test_perm(ta, 0070, 0); 190 191 /* 192 * Privileged user and file other. All tests should pass. 193 */ 194 ta.proc_uid = UID_ROOT; 195 ta.proc_gid = GID_WHEEL; 196 ta.file_uid = UID_OWNER; 197 ta.file_gid = GID_OWNER; 198 199 test_perm(ta, 0000, 0); 200 test_perm(ta, 0001, 0); 201 test_perm(ta, 0002, 0); 202 test_perm(ta, 0003, 0); 203 test_perm(ta, 0004, 0); 204 test_perm(ta, 0005, 0); 205 test_perm(ta, 0006, 0); 206 test_perm(ta, 0007, 0); 207 208 /* 209 * Unprivileged user and file owner. Various DAC failures. 210 */ 211 ta.proc_uid = UID_OWNER; 212 ta.proc_gid = GID_OWNER; 213 ta.file_uid = UID_OWNER; 214 ta.file_gid = GID_OWNER; 215 216 test_perm(ta, 0000, EACCES); 217 test_perm(ta, 0100, EACCES); 218 test_perm(ta, 0200, EACCES); 219 test_perm(ta, 0300, EACCES); 220 test_perm(ta, 0400, 0); 221 test_perm(ta, 0500, 0); 222 test_perm(ta, 0600, 0); 223 test_perm(ta, 0700, 0); 224 225 /* 226 * Unprivileged user and file group. Various DAC failures. 227 */ 228 ta.proc_uid = UID_OTHER; 229 ta.proc_gid = GID_OWNER; 230 ta.file_uid = UID_OWNER; 231 ta.file_gid = GID_OWNER; 232 233 test_perm(ta, 0000, EACCES); 234 test_perm(ta, 0010, EACCES); 235 test_perm(ta, 0020, EACCES); 236 test_perm(ta, 0030, EACCES); 237 test_perm(ta, 0040, 0); 238 test_perm(ta, 0050, 0); 239 test_perm(ta, 0060, 0); 240 test_perm(ta, 0070, 0); 241 242 /* 243 * Unprivileged user and file other. Various DAC failures. 244 */ 245 ta.proc_uid = UID_OTHER; 246 ta.proc_gid = GID_OTHER; 247 ta.file_uid = UID_OWNER; 248 ta.file_gid = GID_OWNER; 249 250 test_perm(ta, 0000, EACCES); 251 test_perm(ta, 0001, EACCES); 252 test_perm(ta, 0002, EACCES); 253 test_perm(ta, 0003, EACCES); 254 test_perm(ta, 0004, 0); 255 test_perm(ta, 0005, 0); 256 test_perm(ta, 0006, 0); 257 test_perm(ta, 0007, 0); 258 } 259 260 void 261 priv_vfs_write(void) 262 { 263 struct test_arguments ta; 264 265 preamble(); 266 267 ta.open_flags = O_WRONLY; 268 269 /* 270 * Privileged user and file owner. All tests should pass. 271 */ 272 ta.proc_uid = UID_ROOT; 273 ta.proc_gid = GID_WHEEL; 274 ta.file_uid = UID_ROOT; 275 ta.file_gid = GID_WHEEL; 276 277 test_perm(ta, 0000, 0); 278 test_perm(ta, 0100, 0); 279 test_perm(ta, 0200, 0); 280 test_perm(ta, 0300, 0); 281 test_perm(ta, 0400, 0); 282 test_perm(ta, 0500, 0); 283 test_perm(ta, 0600, 0); 284 test_perm(ta, 0700, 0); 285 286 /* 287 * Privileged user and file group. All tests should pass. 288 */ 289 ta.proc_uid = UID_ROOT; 290 ta.proc_gid = GID_WHEEL; 291 ta.file_uid = UID_OWNER; 292 ta.file_gid = GID_WHEEL; 293 294 test_perm(ta, 0000, 0); 295 test_perm(ta, 0010, 0); 296 test_perm(ta, 0020, 0); 297 test_perm(ta, 0030, 0); 298 test_perm(ta, 0040, 0); 299 test_perm(ta, 0050, 0); 300 test_perm(ta, 0060, 0); 301 test_perm(ta, 0070, 0); 302 303 /* 304 * Privileged user and file other. All tests should pass. 305 */ 306 ta.proc_uid = UID_ROOT; 307 ta.proc_gid = GID_WHEEL; 308 ta.file_uid = UID_OWNER; 309 ta.file_gid = GID_OWNER; 310 311 test_perm(ta, 0000, 0); 312 test_perm(ta, 0001, 0); 313 test_perm(ta, 0002, 0); 314 test_perm(ta, 0003, 0); 315 test_perm(ta, 0004, 0); 316 test_perm(ta, 0005, 0); 317 test_perm(ta, 0006, 0); 318 test_perm(ta, 0007, 0); 319 320 /* 321 * Unprivileged user and file owner. Various DAC failures. 322 */ 323 ta.proc_uid = UID_OWNER; 324 ta.proc_gid = GID_OWNER; 325 ta.file_uid = UID_OWNER; 326 ta.file_gid = GID_OWNER; 327 328 test_perm(ta, 0000, EACCES); 329 test_perm(ta, 0100, EACCES); 330 test_perm(ta, 0200, 0); 331 test_perm(ta, 0300, 0); 332 test_perm(ta, 0400, EACCES); 333 test_perm(ta, 0500, EACCES); 334 test_perm(ta, 0600, 0); 335 test_perm(ta, 0700, 0); 336 337 /* 338 * Unprivileged user and file group. Various DAC failures. 339 */ 340 ta.proc_uid = UID_OTHER; 341 ta.proc_gid = GID_OWNER; 342 ta.file_uid = UID_OWNER; 343 ta.file_gid = GID_OWNER; 344 345 test_perm(ta, 0000, EACCES); 346 test_perm(ta, 0010, EACCES); 347 test_perm(ta, 0020, 0); 348 test_perm(ta, 0030, 0); 349 test_perm(ta, 0040, EACCES); 350 test_perm(ta, 0050, EACCES); 351 test_perm(ta, 0060, 0); 352 test_perm(ta, 0070, 0); 353 354 /* 355 * Unprivileged user and file other. Various DAC failures. 356 */ 357 ta.proc_uid = UID_OTHER; 358 ta.proc_gid = GID_OTHER; 359 ta.file_uid = UID_OWNER; 360 ta.file_gid = GID_OWNER; 361 362 test_perm(ta, 0000, EACCES); 363 test_perm(ta, 0001, EACCES); 364 test_perm(ta, 0002, 0); 365 test_perm(ta, 0003, 0); 366 test_perm(ta, 0004, EACCES); 367 test_perm(ta, 0005, EACCES); 368 test_perm(ta, 0006, 0); 369 test_perm(ta, 0007, 0); 370 } 371