1 /*- 2 * Copyright (c) 2008-2011 Robert N. M. Watson 3 * Copyright (c) 2010-2011 Jonathan Anderson 4 * All rights reserved. 5 * 6 * This software was developed at the University of Cambridge Computer 7 * Laboratory with support from a grant from Google, Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 /* 32 * FreeBSD kernel capability facility. 33 * 34 * Currently, this file implements only capability mode; capabilities 35 * (rights-refined file descriptors) will follow. 36 * 37 */ 38 39 #include "opt_capsicum.h" 40 41 #include <sys/cdefs.h> 42 __FBSDID("$FreeBSD$"); 43 44 #include <sys/param.h> 45 #include <sys/capability.h> 46 #include <sys/file.h> 47 #include <sys/filedesc.h> 48 #include <sys/kernel.h> 49 #include <sys/lock.h> 50 #include <sys/mutex.h> 51 #include <sys/proc.h> 52 #include <sys/sysproto.h> 53 #include <sys/sysctl.h> 54 #include <sys/systm.h> 55 #include <sys/ucred.h> 56 57 #include <security/audit/audit.h> 58 59 #include <vm/uma.h> 60 #include <vm/vm.h> 61 62 #ifdef CAPABILITY_MODE 63 64 FEATURE(security_capabilities, "Capsicum Capability Mode"); 65 66 /* 67 * System call to enter capability mode for the process. 68 */ 69 int 70 cap_enter(struct thread *td, struct cap_enter_args *uap) 71 { 72 struct ucred *newcred, *oldcred; 73 struct proc *p; 74 75 if (IN_CAPABILITY_MODE(td)) 76 return (0); 77 78 newcred = crget(); 79 p = td->td_proc; 80 PROC_LOCK(p); 81 oldcred = p->p_ucred; 82 crcopy(newcred, oldcred); 83 newcred->cr_flags |= CRED_FLAG_CAPMODE; 84 p->p_ucred = newcred; 85 PROC_UNLOCK(p); 86 crfree(oldcred); 87 return (0); 88 } 89 90 /* 91 * System call to query whether the process is in capability mode. 92 */ 93 int 94 cap_getmode(struct thread *td, struct cap_getmode_args *uap) 95 { 96 u_int i; 97 98 i = (IN_CAPABILITY_MODE(td)) ? 1 : 0; 99 return (copyout(&i, uap->modep, sizeof(i))); 100 } 101 102 #else /* !CAPABILITY_MODE */ 103 104 int 105 cap_enter(struct thread *td, struct cap_enter_args *uap) 106 { 107 108 return (ENOSYS); 109 } 110 111 int 112 cap_getmode(struct thread *td, struct cap_getmode_args *uap) 113 { 114 115 return (ENOSYS); 116 } 117 118 #endif /* CAPABILITY_MODE */ 119 120 #ifdef CAPABILITIES 121 122 /* 123 * struct capability describes a capability, and is hung off of its struct 124 * file f_data field. cap_file and cap_rightss are static once hooked up, as 125 * neither the object it references nor the rights it encapsulates are 126 * permitted to change. 127 */ 128 struct capability { 129 struct file *cap_object; /* Underlying object's file. */ 130 struct file *cap_file; /* Back-pointer to cap's file. */ 131 cap_rights_t cap_rights; /* Mask of rights on object. */ 132 }; 133 134 /* 135 * Capabilities have a fileops vector, but in practice none should ever be 136 * called except for fo_close, as the capability will normally not be 137 * returned during a file descriptor lookup in the system call code. 138 */ 139 static fo_rdwr_t capability_read; 140 static fo_rdwr_t capability_write; 141 static fo_truncate_t capability_truncate; 142 static fo_ioctl_t capability_ioctl; 143 static fo_poll_t capability_poll; 144 static fo_kqfilter_t capability_kqfilter; 145 static fo_stat_t capability_stat; 146 static fo_close_t capability_close; 147 148 static struct fileops capability_ops = { 149 .fo_read = capability_read, 150 .fo_write = capability_write, 151 .fo_truncate = capability_truncate, 152 .fo_ioctl = capability_ioctl, 153 .fo_poll = capability_poll, 154 .fo_kqfilter = capability_kqfilter, 155 .fo_stat = capability_stat, 156 .fo_close = capability_close, 157 .fo_flags = DFLAG_PASSABLE, 158 }; 159 160 static struct fileops capability_ops_unpassable = { 161 .fo_read = capability_read, 162 .fo_write = capability_write, 163 .fo_truncate = capability_truncate, 164 .fo_ioctl = capability_ioctl, 165 .fo_poll = capability_poll, 166 .fo_kqfilter = capability_kqfilter, 167 .fo_stat = capability_stat, 168 .fo_close = capability_close, 169 .fo_flags = 0, 170 }; 171 172 static uma_zone_t capability_zone; 173 174 static void 175 capability_init(void *dummy __unused) 176 { 177 178 capability_zone = uma_zcreate("capability", sizeof(struct capability), 179 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); 180 if (capability_zone == NULL) 181 panic("capability_init: capability_zone not initialized"); 182 } 183 SYSINIT(vfs, SI_SUB_VFS, SI_ORDER_ANY, capability_init, NULL); 184 185 /* 186 * Test whether a capability grants the requested rights. 187 */ 188 static int 189 cap_check(struct capability *c, cap_rights_t rights) 190 { 191 192 if ((c->cap_rights | rights) != c->cap_rights) 193 return (ENOTCAPABLE); 194 return (0); 195 } 196 197 /* 198 * Extract rights from a capability for monitoring purposes -- not for use in 199 * any other way, as we want to keep all capability permission evaluation in 200 * this one file. 201 */ 202 cap_rights_t 203 cap_rights(struct file *fp_cap) 204 { 205 struct capability *c; 206 207 KASSERT(fp_cap->f_type == DTYPE_CAPABILITY, 208 ("cap_rights: !capability")); 209 210 c = fp_cap->f_data; 211 return (c->cap_rights); 212 } 213 214 /* 215 * System call to create a new capability reference to either an existing 216 * file object or an an existing capability. 217 */ 218 int 219 cap_new(struct thread *td, struct cap_new_args *uap) 220 { 221 int error, capfd; 222 int fd = uap->fd; 223 struct file *fp, *fcapp; 224 cap_rights_t rights = uap->rights; 225 226 AUDIT_ARG_FD(fd); 227 AUDIT_ARG_RIGHTS(rights); 228 error = fget(td, fd, &fp); 229 if (error) 230 return (error); 231 AUDIT_ARG_FILE(td->td_proc, fp); 232 error = kern_capwrap(td, fp, rights, &fcapp, &capfd); 233 if (error) 234 return (error); 235 236 /* 237 * Release our reference to the file (kern_capwrap has held a reference 238 * for the filedesc array). 239 */ 240 fdrop(fp, td); 241 td->td_retval[0] = capfd; 242 return (0); 243 } 244 245 /* 246 * System call to query the rights mask associated with a capability. 247 */ 248 int 249 cap_getrights(struct thread *td, struct cap_getrights_args *uap) 250 { 251 struct capability *cp; 252 struct file *fp; 253 int error; 254 255 AUDIT_ARG_FD(uap->fd); 256 error = fgetcap(td, uap->fd, &fp); 257 if (error) 258 return (error); 259 cp = fp->f_data; 260 error = copyout(&cp->cap_rights, uap->rightsp, sizeof(*uap->rightsp)); 261 fdrop(fp, td); 262 return (error); 263 } 264 265 /* 266 * Create a capability to wrap around an existing file. 267 */ 268 int 269 kern_capwrap(struct thread *td, struct file *fp, cap_rights_t rights, 270 struct file **fcappp, int *capfdp) 271 { 272 struct capability *cp, *cp_old; 273 struct file *fp_object; 274 int error; 275 276 if ((rights | CAP_MASK_VALID) != CAP_MASK_VALID) 277 return (EINVAL); 278 279 /* 280 * If a new capability is being derived from an existing capability, 281 * then the new capability rights must be a subset of the existing 282 * rights. 283 */ 284 if (fp->f_type == DTYPE_CAPABILITY) { 285 cp_old = fp->f_data; 286 if ((cp_old->cap_rights | rights) != cp_old->cap_rights) 287 return (ENOTCAPABLE); 288 } 289 290 /* 291 * Allocate a new file descriptor to hang the capability off of. 292 */ 293 error = falloc(td, fcappp, capfdp, fp->f_flag); 294 if (error) 295 return (error); 296 297 /* 298 * Rather than nesting capabilities, directly reference the object an 299 * existing capability references. There's nothing else interesting 300 * to preserve for future use, as we've incorporated the previous 301 * rights mask into the new one. This prevents us from having to 302 * deal with capability chains. 303 */ 304 if (fp->f_type == DTYPE_CAPABILITY) 305 fp_object = ((struct capability *)fp->f_data)->cap_object; 306 else 307 fp_object = fp; 308 fhold(fp_object); 309 cp = uma_zalloc(capability_zone, M_WAITOK | M_ZERO); 310 cp->cap_rights = rights; 311 cp->cap_object = fp_object; 312 cp->cap_file = *fcappp; 313 if (fp->f_flag & DFLAG_PASSABLE) 314 finit(*fcappp, fp->f_flag, DTYPE_CAPABILITY, cp, 315 &capability_ops); 316 else 317 finit(*fcappp, fp->f_flag, DTYPE_CAPABILITY, cp, 318 &capability_ops_unpassable); 319 320 /* 321 * Release our private reference (the proc filedesc still has one). 322 */ 323 fdrop(*fcappp, td); 324 return (0); 325 } 326 327 /* 328 * Given a file descriptor, test it against a capability rights mask and then 329 * return the file descriptor on which to actually perform the requested 330 * operation. As long as the reference to fp_cap remains valid, the returned 331 * pointer in *fp will remain valid, so no extra reference management is 332 * required, and the caller should fdrop() fp_cap as normal when done with 333 * both. 334 */ 335 int 336 cap_funwrap(struct file *fp_cap, cap_rights_t rights, struct file **fpp) 337 { 338 struct capability *c; 339 int error; 340 341 if (fp_cap->f_type != DTYPE_CAPABILITY) { 342 *fpp = fp_cap; 343 return (0); 344 } 345 c = fp_cap->f_data; 346 error = cap_check(c, rights); 347 if (error) 348 return (error); 349 *fpp = c->cap_object; 350 return (0); 351 } 352 353 /* 354 * Slightly different routine for memory mapping file descriptors: unwrap the 355 * capability and check CAP_MMAP, but also return a bitmask representing the 356 * maximum mapping rights the capability allows on the object. 357 */ 358 int 359 cap_funwrap_mmap(struct file *fp_cap, cap_rights_t rights, u_char *maxprotp, 360 struct file **fpp) 361 { 362 struct capability *c; 363 u_char maxprot; 364 int error; 365 366 if (fp_cap->f_type != DTYPE_CAPABILITY) { 367 *fpp = fp_cap; 368 *maxprotp = VM_PROT_ALL; 369 return (0); 370 } 371 c = fp_cap->f_data; 372 error = cap_check(c, rights | CAP_MMAP); 373 if (error) 374 return (error); 375 *fpp = c->cap_object; 376 maxprot = 0; 377 if (c->cap_rights & CAP_READ) 378 maxprot |= VM_PROT_READ; 379 if (c->cap_rights & CAP_WRITE) 380 maxprot |= VM_PROT_WRITE; 381 if (c->cap_rights & CAP_MAPEXEC) 382 maxprot |= VM_PROT_EXECUTE; 383 *maxprotp = maxprot; 384 return (0); 385 } 386 387 /* 388 * When a capability is closed, simply drop the reference on the underlying 389 * object and free the capability. fdrop() will handle the case where the 390 * underlying object also needs to close, and the caller will have already 391 * performed any object-specific lock or mqueue handling. 392 */ 393 static int 394 capability_close(struct file *fp, struct thread *td) 395 { 396 struct capability *c; 397 struct file *fp_object; 398 399 KASSERT(fp->f_type == DTYPE_CAPABILITY, 400 ("capability_close: !capability")); 401 402 c = fp->f_data; 403 fp->f_ops = &badfileops; 404 fp->f_data = NULL; 405 fp_object = c->cap_object; 406 uma_zfree(capability_zone, c); 407 return (fdrop(fp_object, td)); 408 } 409 410 /* 411 * In general, file descriptor operations should never make it to the 412 * capability, only the underlying file descriptor operation vector, so panic 413 * if we do turn up here. 414 */ 415 static int 416 capability_read(struct file *fp, struct uio *uio, struct ucred *active_cred, 417 int flags, struct thread *td) 418 { 419 420 panic("capability_read"); 421 } 422 423 static int 424 capability_write(struct file *fp, struct uio *uio, struct ucred *active_cred, 425 int flags, struct thread *td) 426 { 427 428 panic("capability_write"); 429 } 430 431 static int 432 capability_truncate(struct file *fp, off_t length, struct ucred *active_cred, 433 struct thread *td) 434 { 435 436 panic("capability_truncate"); 437 } 438 439 static int 440 capability_ioctl(struct file *fp, u_long com, void *data, 441 struct ucred *active_cred, struct thread *td) 442 { 443 444 panic("capability_ioctl"); 445 } 446 447 static int 448 capability_poll(struct file *fp, int events, struct ucred *active_cred, 449 struct thread *td) 450 { 451 452 panic("capability_poll"); 453 } 454 455 static int 456 capability_kqfilter(struct file *fp, struct knote *kn) 457 { 458 459 panic("capability_kqfilter"); 460 } 461 462 static int 463 capability_stat(struct file *fp, struct stat *sb, struct ucred *active_cred, 464 struct thread *td) 465 { 466 467 panic("capability_stat"); 468 } 469 470 #else /* !CAPABILITIES */ 471 472 /* 473 * Stub Capability functions for when options CAPABILITIES isn't compiled 474 * into the kernel. 475 */ 476 int 477 cap_new(struct thread *td, struct cap_new_args *uap) 478 { 479 480 return (ENOSYS); 481 } 482 483 int 484 cap_getrights(struct thread *td, struct cap_getrights_args *uap) 485 { 486 487 return (ENOSYS); 488 } 489 490 int 491 cap_funwrap(struct file *fp_cap, cap_rights_t rights, struct file **fpp) 492 { 493 494 KASSERT(fp_cap->f_type != DTYPE_CAPABILITY, 495 ("cap_funwrap: saw capability")); 496 497 *fpp = fp_cap; 498 return (0); 499 } 500 501 int 502 cap_funwrap_mmap(struct file *fp_cap, cap_rights_t rights, u_char *maxprotp, 503 struct file **fpp) 504 { 505 506 KASSERT(fp_cap->f_type != DTYPE_CAPABILITY, 507 ("cap_funwrap_mmap: saw capability")); 508 509 *fpp = fp_cap; 510 *maxprotp = VM_PROT_ALL; 511 return (0); 512 } 513 514 #endif /* CAPABILITIES */ 515 516