1 /* $NetBSD: genfs_vnops.c,v 1.199 2017/10/25 08:12:39 maya Exp $ */ 2 3 /*- 4 * Copyright (c) 2008 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /* 30 * Copyright (c) 1982, 1986, 1989, 1993 31 * The Regents of the University of California. All rights reserved. 32 * 33 * Redistribution and use in source and binary forms, with or without 34 * modification, are permitted provided that the following conditions 35 * are met: 36 * 1. Redistributions of source code must retain the above copyright 37 * notice, this list of conditions and the following disclaimer. 38 * 2. Redistributions in binary form must reproduce the above copyright 39 * notice, this list of conditions and the following disclaimer in the 40 * documentation and/or other materials provided with the distribution. 41 * 3. Neither the name of the University nor the names of its contributors 42 * may be used to endorse or promote products derived from this software 43 * without specific prior written permission. 44 * 45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 55 * SUCH DAMAGE. 56 * 57 */ 58 59 #include <sys/cdefs.h> 60 __KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.199 2017/10/25 08:12:39 maya Exp $"); 61 62 #include <sys/param.h> 63 #include <sys/systm.h> 64 #include <sys/proc.h> 65 #include <sys/kernel.h> 66 #include <sys/mount.h> 67 #include <sys/fstrans.h> 68 #include <sys/namei.h> 69 #include <sys/vnode_impl.h> 70 #include <sys/fcntl.h> 71 #include <sys/kmem.h> 72 #include <sys/poll.h> 73 #include <sys/mman.h> 74 #include <sys/file.h> 75 #include <sys/kauth.h> 76 #include <sys/stat.h> 77 78 #include <miscfs/genfs/genfs.h> 79 #include <miscfs/genfs/genfs_node.h> 80 #include <miscfs/specfs/specdev.h> 81 82 #include <uvm/uvm.h> 83 #include <uvm/uvm_pager.h> 84 85 static void filt_genfsdetach(struct knote *); 86 static int filt_genfsread(struct knote *, long); 87 static int filt_genfsvnode(struct knote *, long); 88 89 int 90 genfs_poll(void *v) 91 { 92 struct vop_poll_args /* { 93 struct vnode *a_vp; 94 int a_events; 95 struct lwp *a_l; 96 } */ *ap = v; 97 98 return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)); 99 } 100 101 int 102 genfs_seek(void *v) 103 { 104 struct vop_seek_args /* { 105 struct vnode *a_vp; 106 off_t a_oldoff; 107 off_t a_newoff; 108 kauth_cred_t cred; 109 } */ *ap = v; 110 111 if (ap->a_newoff < 0) 112 return (EINVAL); 113 114 return (0); 115 } 116 117 int 118 genfs_abortop(void *v) 119 { 120 struct vop_abortop_args /* { 121 struct vnode *a_dvp; 122 struct componentname *a_cnp; 123 } */ *ap = v; 124 125 (void)ap; 126 127 return (0); 128 } 129 130 int 131 genfs_fcntl(void *v) 132 { 133 struct vop_fcntl_args /* { 134 struct vnode *a_vp; 135 u_int a_command; 136 void *a_data; 137 int a_fflag; 138 kauth_cred_t a_cred; 139 struct lwp *a_l; 140 } */ *ap = v; 141 142 if (ap->a_command == F_SETFL) 143 return (0); 144 else 145 return (EOPNOTSUPP); 146 } 147 148 /*ARGSUSED*/ 149 int 150 genfs_badop(void *v) 151 { 152 153 panic("genfs: bad op"); 154 } 155 156 /*ARGSUSED*/ 157 int 158 genfs_nullop(void *v) 159 { 160 161 return (0); 162 } 163 164 /*ARGSUSED*/ 165 int 166 genfs_einval(void *v) 167 { 168 169 return (EINVAL); 170 } 171 172 /* 173 * Called when an fs doesn't support a particular vop. 174 * This takes care to vrele, vput, or vunlock passed in vnodes 175 * and calls VOP_ABORTOP for a componentname (in non-rename VOP). 176 */ 177 int 178 genfs_eopnotsupp(void *v) 179 { 180 struct vop_generic_args /* 181 struct vnodeop_desc *a_desc; 182 / * other random data follows, presumably * / 183 } */ *ap = v; 184 struct vnodeop_desc *desc = ap->a_desc; 185 struct vnode *vp, *vp_last = NULL; 186 int flags, i, j, offset_cnp, offset_vp; 187 188 KASSERT(desc->vdesc_offset != VOP_LOOKUP_DESCOFFSET); 189 KASSERT(desc->vdesc_offset != VOP_ABORTOP_DESCOFFSET); 190 191 /* 192 * Abort any componentname that lookup potentially left state in. 193 * 194 * As is logical, componentnames for VOP_RENAME are handled by 195 * the caller of VOP_RENAME. Yay, rename! 196 */ 197 if (desc->vdesc_offset != VOP_RENAME_DESCOFFSET && 198 (offset_vp = desc->vdesc_vp_offsets[0]) != VDESC_NO_OFFSET && 199 (offset_cnp = desc->vdesc_componentname_offset) != VDESC_NO_OFFSET){ 200 struct componentname *cnp; 201 struct vnode *dvp; 202 203 dvp = *VOPARG_OFFSETTO(struct vnode **, offset_vp, ap); 204 cnp = *VOPARG_OFFSETTO(struct componentname **, offset_cnp, ap); 205 206 VOP_ABORTOP(dvp, cnp); 207 } 208 209 flags = desc->vdesc_flags; 210 for (i = 0; i < VDESC_MAX_VPS; flags >>=1, i++) { 211 if ((offset_vp = desc->vdesc_vp_offsets[i]) == VDESC_NO_OFFSET) 212 break; /* stop at end of list */ 213 if ((j = flags & VDESC_VP0_WILLPUT)) { 214 vp = *VOPARG_OFFSETTO(struct vnode **, offset_vp, ap); 215 216 /* Skip if NULL */ 217 if (!vp) 218 continue; 219 220 switch (j) { 221 case VDESC_VP0_WILLPUT: 222 /* Check for dvp == vp cases */ 223 if (vp == vp_last) 224 vrele(vp); 225 else { 226 vput(vp); 227 vp_last = vp; 228 } 229 break; 230 case VDESC_VP0_WILLRELE: 231 vrele(vp); 232 break; 233 } 234 } 235 } 236 237 return (EOPNOTSUPP); 238 } 239 240 /*ARGSUSED*/ 241 int 242 genfs_ebadf(void *v) 243 { 244 245 return (EBADF); 246 } 247 248 /* ARGSUSED */ 249 int 250 genfs_enoioctl(void *v) 251 { 252 253 return (EPASSTHROUGH); 254 } 255 256 257 /* 258 * Eliminate all activity associated with the requested vnode 259 * and with all vnodes aliased to the requested vnode. 260 */ 261 int 262 genfs_revoke(void *v) 263 { 264 struct vop_revoke_args /* { 265 struct vnode *a_vp; 266 int a_flags; 267 } */ *ap = v; 268 269 #ifdef DIAGNOSTIC 270 if ((ap->a_flags & REVOKEALL) == 0) 271 panic("genfs_revoke: not revokeall"); 272 #endif 273 vrevoke(ap->a_vp); 274 return (0); 275 } 276 277 /* 278 * Lock the node (for deadfs). 279 */ 280 int 281 genfs_deadlock(void *v) 282 { 283 struct vop_lock_args /* { 284 struct vnode *a_vp; 285 int a_flags; 286 } */ *ap = v; 287 vnode_t *vp = ap->a_vp; 288 vnode_impl_t *vip = VNODE_TO_VIMPL(vp); 289 int flags = ap->a_flags; 290 krw_t op; 291 292 if (! ISSET(flags, LK_RETRY)) 293 return ENOENT; 294 295 op = (ISSET(flags, LK_EXCLUSIVE) ? RW_WRITER : RW_READER); 296 if (ISSET(flags, LK_NOWAIT)) { 297 if (! rw_tryenter(&vip->vi_lock, op)) 298 return EBUSY; 299 } else { 300 rw_enter(&vip->vi_lock, op); 301 } 302 VSTATE_ASSERT_UNLOCKED(vp, VS_RECLAIMED); 303 return 0; 304 } 305 306 /* 307 * Unlock the node (for deadfs). 308 */ 309 int 310 genfs_deadunlock(void *v) 311 { 312 struct vop_unlock_args /* { 313 struct vnode *a_vp; 314 } */ *ap = v; 315 vnode_t *vp = ap->a_vp; 316 vnode_impl_t *vip = VNODE_TO_VIMPL(vp); 317 318 rw_exit(&vip->vi_lock); 319 320 return 0; 321 } 322 323 /* 324 * Lock the node. 325 */ 326 int 327 genfs_lock(void *v) 328 { 329 struct vop_lock_args /* { 330 struct vnode *a_vp; 331 int a_flags; 332 } */ *ap = v; 333 vnode_t *vp = ap->a_vp; 334 vnode_impl_t *vip = VNODE_TO_VIMPL(vp); 335 int flags = ap->a_flags; 336 krw_t op; 337 338 op = (ISSET(flags, LK_EXCLUSIVE) ? RW_WRITER : RW_READER); 339 if (ISSET(flags, LK_NOWAIT)) { 340 if (! rw_tryenter(&vip->vi_lock, op)) 341 return EBUSY; 342 } else { 343 rw_enter(&vip->vi_lock, op); 344 } 345 VSTATE_ASSERT_UNLOCKED(vp, VS_ACTIVE); 346 return 0; 347 } 348 349 /* 350 * Unlock the node. 351 */ 352 int 353 genfs_unlock(void *v) 354 { 355 struct vop_unlock_args /* { 356 struct vnode *a_vp; 357 } */ *ap = v; 358 vnode_t *vp = ap->a_vp; 359 vnode_impl_t *vip = VNODE_TO_VIMPL(vp); 360 361 rw_exit(&vip->vi_lock); 362 363 return 0; 364 } 365 366 /* 367 * Return whether or not the node is locked. 368 */ 369 int 370 genfs_islocked(void *v) 371 { 372 struct vop_islocked_args /* { 373 struct vnode *a_vp; 374 } */ *ap = v; 375 vnode_t *vp = ap->a_vp; 376 vnode_impl_t *vip = VNODE_TO_VIMPL(vp); 377 378 if (rw_write_held(&vip->vi_lock)) 379 return LK_EXCLUSIVE; 380 381 if (rw_read_held(&vip->vi_lock)) 382 return LK_SHARED; 383 384 return 0; 385 } 386 387 /* 388 * Stubs to use when there is no locking to be done on the underlying object. 389 */ 390 int 391 genfs_nolock(void *v) 392 { 393 394 return (0); 395 } 396 397 int 398 genfs_nounlock(void *v) 399 { 400 401 return (0); 402 } 403 404 int 405 genfs_noislocked(void *v) 406 { 407 408 return (0); 409 } 410 411 int 412 genfs_mmap(void *v) 413 { 414 415 return (0); 416 } 417 418 /* 419 * VOP_PUTPAGES() for vnodes which never have pages. 420 */ 421 422 int 423 genfs_null_putpages(void *v) 424 { 425 struct vop_putpages_args /* { 426 struct vnode *a_vp; 427 voff_t a_offlo; 428 voff_t a_offhi; 429 int a_flags; 430 } */ *ap = v; 431 struct vnode *vp = ap->a_vp; 432 433 KASSERT(vp->v_uobj.uo_npages == 0); 434 mutex_exit(vp->v_interlock); 435 return (0); 436 } 437 438 void 439 genfs_node_init(struct vnode *vp, const struct genfs_ops *ops) 440 { 441 struct genfs_node *gp = VTOG(vp); 442 443 rw_init(&gp->g_glock); 444 gp->g_op = ops; 445 } 446 447 void 448 genfs_node_destroy(struct vnode *vp) 449 { 450 struct genfs_node *gp = VTOG(vp); 451 452 rw_destroy(&gp->g_glock); 453 } 454 455 void 456 genfs_size(struct vnode *vp, off_t size, off_t *eobp, int flags) 457 { 458 int bsize; 459 460 bsize = 1 << vp->v_mount->mnt_fs_bshift; 461 *eobp = (size + bsize - 1) & ~(bsize - 1); 462 } 463 464 static void 465 filt_genfsdetach(struct knote *kn) 466 { 467 struct vnode *vp = (struct vnode *)kn->kn_hook; 468 469 mutex_enter(vp->v_interlock); 470 SLIST_REMOVE(&vp->v_klist, kn, knote, kn_selnext); 471 mutex_exit(vp->v_interlock); 472 } 473 474 static int 475 filt_genfsread(struct knote *kn, long hint) 476 { 477 struct vnode *vp = (struct vnode *)kn->kn_hook; 478 int rv; 479 480 /* 481 * filesystem is gone, so set the EOF flag and schedule 482 * the knote for deletion. 483 */ 484 switch (hint) { 485 case NOTE_REVOKE: 486 KASSERT(mutex_owned(vp->v_interlock)); 487 kn->kn_flags |= (EV_EOF | EV_ONESHOT); 488 return (1); 489 case 0: 490 mutex_enter(vp->v_interlock); 491 kn->kn_data = vp->v_size - ((file_t *)kn->kn_obj)->f_offset; 492 rv = (kn->kn_data != 0); 493 mutex_exit(vp->v_interlock); 494 return rv; 495 default: 496 KASSERT(mutex_owned(vp->v_interlock)); 497 kn->kn_data = vp->v_size - ((file_t *)kn->kn_obj)->f_offset; 498 return (kn->kn_data != 0); 499 } 500 } 501 502 static int 503 filt_genfswrite(struct knote *kn, long hint) 504 { 505 struct vnode *vp = (struct vnode *)kn->kn_hook; 506 507 /* 508 * filesystem is gone, so set the EOF flag and schedule 509 * the knote for deletion. 510 */ 511 switch (hint) { 512 case NOTE_REVOKE: 513 KASSERT(mutex_owned(vp->v_interlock)); 514 kn->kn_flags |= (EV_EOF | EV_ONESHOT); 515 return (1); 516 case 0: 517 mutex_enter(vp->v_interlock); 518 kn->kn_data = 0; 519 mutex_exit(vp->v_interlock); 520 return 1; 521 default: 522 KASSERT(mutex_owned(vp->v_interlock)); 523 kn->kn_data = 0; 524 return 1; 525 } 526 } 527 528 static int 529 filt_genfsvnode(struct knote *kn, long hint) 530 { 531 struct vnode *vp = (struct vnode *)kn->kn_hook; 532 int fflags; 533 534 switch (hint) { 535 case NOTE_REVOKE: 536 KASSERT(mutex_owned(vp->v_interlock)); 537 kn->kn_flags |= EV_EOF; 538 if ((kn->kn_sfflags & hint) != 0) 539 kn->kn_fflags |= hint; 540 return (1); 541 case 0: 542 mutex_enter(vp->v_interlock); 543 fflags = kn->kn_fflags; 544 mutex_exit(vp->v_interlock); 545 break; 546 default: 547 KASSERT(mutex_owned(vp->v_interlock)); 548 if ((kn->kn_sfflags & hint) != 0) 549 kn->kn_fflags |= hint; 550 fflags = kn->kn_fflags; 551 break; 552 } 553 554 return (fflags != 0); 555 } 556 557 static const struct filterops genfsread_filtops = { 558 .f_isfd = 1, 559 .f_attach = NULL, 560 .f_detach = filt_genfsdetach, 561 .f_event = filt_genfsread, 562 }; 563 564 static const struct filterops genfswrite_filtops = { 565 .f_isfd = 1, 566 .f_attach = NULL, 567 .f_detach = filt_genfsdetach, 568 .f_event = filt_genfswrite, 569 }; 570 571 static const struct filterops genfsvnode_filtops = { 572 .f_isfd = 1, 573 .f_attach = NULL, 574 .f_detach = filt_genfsdetach, 575 .f_event = filt_genfsvnode, 576 }; 577 578 int 579 genfs_kqfilter(void *v) 580 { 581 struct vop_kqfilter_args /* { 582 struct vnode *a_vp; 583 struct knote *a_kn; 584 } */ *ap = v; 585 struct vnode *vp; 586 struct knote *kn; 587 588 vp = ap->a_vp; 589 kn = ap->a_kn; 590 switch (kn->kn_filter) { 591 case EVFILT_READ: 592 kn->kn_fop = &genfsread_filtops; 593 break; 594 case EVFILT_WRITE: 595 kn->kn_fop = &genfswrite_filtops; 596 break; 597 case EVFILT_VNODE: 598 kn->kn_fop = &genfsvnode_filtops; 599 break; 600 default: 601 return (EINVAL); 602 } 603 604 kn->kn_hook = vp; 605 606 mutex_enter(vp->v_interlock); 607 SLIST_INSERT_HEAD(&vp->v_klist, kn, kn_selnext); 608 mutex_exit(vp->v_interlock); 609 610 return (0); 611 } 612 613 void 614 genfs_node_wrlock(struct vnode *vp) 615 { 616 struct genfs_node *gp = VTOG(vp); 617 618 rw_enter(&gp->g_glock, RW_WRITER); 619 } 620 621 void 622 genfs_node_rdlock(struct vnode *vp) 623 { 624 struct genfs_node *gp = VTOG(vp); 625 626 rw_enter(&gp->g_glock, RW_READER); 627 } 628 629 int 630 genfs_node_rdtrylock(struct vnode *vp) 631 { 632 struct genfs_node *gp = VTOG(vp); 633 634 return rw_tryenter(&gp->g_glock, RW_READER); 635 } 636 637 void 638 genfs_node_unlock(struct vnode *vp) 639 { 640 struct genfs_node *gp = VTOG(vp); 641 642 rw_exit(&gp->g_glock); 643 } 644 645 int 646 genfs_node_wrlocked(struct vnode *vp) 647 { 648 struct genfs_node *gp = VTOG(vp); 649 650 return rw_write_held(&gp->g_glock); 651 } 652 653 /* 654 * Do the usual access checking. 655 * file_mode, uid and gid are from the vnode in question, 656 * while acc_mode and cred are from the VOP_ACCESS parameter list 657 */ 658 int 659 genfs_can_access(enum vtype type, mode_t file_mode, uid_t uid, gid_t gid, 660 mode_t acc_mode, kauth_cred_t cred) 661 { 662 mode_t mask; 663 int error, ismember; 664 665 mask = 0; 666 667 /* Otherwise, check the owner. */ 668 if (kauth_cred_geteuid(cred) == uid) { 669 if (acc_mode & VEXEC) 670 mask |= S_IXUSR; 671 if (acc_mode & VREAD) 672 mask |= S_IRUSR; 673 if (acc_mode & VWRITE) 674 mask |= S_IWUSR; 675 return ((file_mode & mask) == mask ? 0 : EACCES); 676 } 677 678 /* Otherwise, check the groups. */ 679 error = kauth_cred_ismember_gid(cred, gid, &ismember); 680 if (error) 681 return (error); 682 if (kauth_cred_getegid(cred) == gid || ismember) { 683 if (acc_mode & VEXEC) 684 mask |= S_IXGRP; 685 if (acc_mode & VREAD) 686 mask |= S_IRGRP; 687 if (acc_mode & VWRITE) 688 mask |= S_IWGRP; 689 return ((file_mode & mask) == mask ? 0 : EACCES); 690 } 691 692 /* Otherwise, check everyone else. */ 693 if (acc_mode & VEXEC) 694 mask |= S_IXOTH; 695 if (acc_mode & VREAD) 696 mask |= S_IROTH; 697 if (acc_mode & VWRITE) 698 mask |= S_IWOTH; 699 return ((file_mode & mask) == mask ? 0 : EACCES); 700 } 701 702 /* 703 * Common routine to check if chmod() is allowed. 704 * 705 * Policy: 706 * - You must own the file, and 707 * - You must not set the "sticky" bit (meaningless, see chmod(2)) 708 * - You must be a member of the group if you're trying to set the 709 * SGIDf bit 710 * 711 * cred - credentials of the invoker 712 * vp - vnode of the file-system object 713 * cur_uid, cur_gid - current uid/gid of the file-system object 714 * new_mode - new mode for the file-system object 715 * 716 * Returns 0 if the change is allowed, or an error value otherwise. 717 */ 718 int 719 genfs_can_chmod(enum vtype type, kauth_cred_t cred, uid_t cur_uid, 720 gid_t cur_gid, mode_t new_mode) 721 { 722 int error; 723 724 /* The user must own the file. */ 725 if (kauth_cred_geteuid(cred) != cur_uid) 726 return (EPERM); 727 728 /* 729 * Unprivileged users can't set the sticky bit on files. 730 */ 731 if ((type != VDIR) && (new_mode & S_ISTXT)) 732 return (EFTYPE); 733 734 /* 735 * If the invoker is trying to set the SGID bit on the file, 736 * check group membership. 737 */ 738 if (new_mode & S_ISGID) { 739 int ismember; 740 741 error = kauth_cred_ismember_gid(cred, cur_gid, 742 &ismember); 743 if (error || !ismember) 744 return (EPERM); 745 } 746 747 return (0); 748 } 749 750 /* 751 * Common routine to check if chown() is allowed. 752 * 753 * Policy: 754 * - You must own the file, and 755 * - You must not try to change ownership, and 756 * - You must be member of the new group 757 * 758 * cred - credentials of the invoker 759 * cur_uid, cur_gid - current uid/gid of the file-system object 760 * new_uid, new_gid - target uid/gid of the file-system object 761 * 762 * Returns 0 if the change is allowed, or an error value otherwise. 763 */ 764 int 765 genfs_can_chown(kauth_cred_t cred, uid_t cur_uid, 766 gid_t cur_gid, uid_t new_uid, gid_t new_gid) 767 { 768 int error, ismember; 769 770 /* 771 * You can only change ownership of a file if: 772 * You own the file and... 773 */ 774 if (kauth_cred_geteuid(cred) == cur_uid) { 775 /* 776 * You don't try to change ownership, and... 777 */ 778 if (new_uid != cur_uid) 779 return (EPERM); 780 781 /* 782 * You don't try to change group (no-op), or... 783 */ 784 if (new_gid == cur_gid) 785 return (0); 786 787 /* 788 * Your effective gid is the new gid, or... 789 */ 790 if (kauth_cred_getegid(cred) == new_gid) 791 return (0); 792 793 /* 794 * The new gid is one you're a member of. 795 */ 796 ismember = 0; 797 error = kauth_cred_ismember_gid(cred, new_gid, 798 &ismember); 799 if (!error && ismember) 800 return (0); 801 } 802 803 return (EPERM); 804 } 805 806 int 807 genfs_can_chtimes(vnode_t *vp, u_int vaflags, uid_t owner_uid, 808 kauth_cred_t cred) 809 { 810 int error; 811 812 /* Must be owner, or... */ 813 if (kauth_cred_geteuid(cred) == owner_uid) 814 return (0); 815 816 /* set the times to the current time, and... */ 817 if ((vaflags & VA_UTIMES_NULL) == 0) 818 return (EPERM); 819 820 /* have write access. */ 821 error = VOP_ACCESS(vp, VWRITE, cred); 822 if (error) 823 return (error); 824 825 return (0); 826 } 827 828 /* 829 * Common routine to check if chflags() is allowed. 830 * 831 * Policy: 832 * - You must own the file, and 833 * - You must not change system flags, and 834 * - You must not change flags on character/block devices. 835 * 836 * cred - credentials of the invoker 837 * owner_uid - uid of the file-system object 838 * changing_sysflags - true if the invoker wants to change system flags 839 */ 840 int 841 genfs_can_chflags(kauth_cred_t cred, enum vtype type, uid_t owner_uid, 842 bool changing_sysflags) 843 { 844 845 /* The user must own the file. */ 846 if (kauth_cred_geteuid(cred) != owner_uid) { 847 return EPERM; 848 } 849 850 if (changing_sysflags) { 851 return EPERM; 852 } 853 854 /* 855 * Unprivileged users cannot change the flags on devices, even if they 856 * own them. 857 */ 858 if (type == VCHR || type == VBLK) { 859 return EPERM; 860 } 861 862 return 0; 863 } 864 865 /* 866 * Common "sticky" policy. 867 * 868 * When a directory is "sticky" (as determined by the caller), this 869 * function may help implementing the following policy: 870 * - Renaming a file in it is only possible if the user owns the directory 871 * or the file being renamed. 872 * - Deleting a file from it is only possible if the user owns the 873 * directory or the file being deleted. 874 */ 875 int 876 genfs_can_sticky(kauth_cred_t cred, uid_t dir_uid, uid_t file_uid) 877 { 878 if (kauth_cred_geteuid(cred) != dir_uid && 879 kauth_cred_geteuid(cred) != file_uid) 880 return EPERM; 881 882 return 0; 883 } 884 885 int 886 genfs_can_extattr(kauth_cred_t cred, int access_mode, vnode_t *vp, 887 const char *attr) 888 { 889 /* We can't allow privileged namespaces. */ 890 if (strncasecmp(attr, "system", 6) == 0) 891 return EPERM; 892 893 return VOP_ACCESS(vp, access_mode, cred); 894 } 895