1 /* $NetBSD: genfs_vnops.c,v 1.174 2009/11/20 13:42:43 roy 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.174 2009/11/20 13:42:43 roy 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/namei.h> 68 #include <sys/vnode.h> 69 #include <sys/fcntl.h> 70 #include <sys/kmem.h> 71 #include <sys/poll.h> 72 #include <sys/mman.h> 73 #include <sys/file.h> 74 #include <sys/kauth.h> 75 #include <sys/stat.h> 76 77 #include <miscfs/genfs/genfs.h> 78 #include <miscfs/genfs/genfs_node.h> 79 #include <miscfs/specfs/specdev.h> 80 81 #include <uvm/uvm.h> 82 #include <uvm/uvm_pager.h> 83 84 static void filt_genfsdetach(struct knote *); 85 static int filt_genfsread(struct knote *, long); 86 static int filt_genfsvnode(struct knote *, long); 87 88 int 89 genfs_poll(void *v) 90 { 91 struct vop_poll_args /* { 92 struct vnode *a_vp; 93 int a_events; 94 struct lwp *a_l; 95 } */ *ap = v; 96 97 return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)); 98 } 99 100 int 101 genfs_seek(void *v) 102 { 103 struct vop_seek_args /* { 104 struct vnode *a_vp; 105 off_t a_oldoff; 106 off_t a_newoff; 107 kauth_cred_t cred; 108 } */ *ap = v; 109 110 if (ap->a_newoff < 0) 111 return (EINVAL); 112 113 return (0); 114 } 115 116 int 117 genfs_abortop(void *v) 118 { 119 struct vop_abortop_args /* { 120 struct vnode *a_dvp; 121 struct componentname *a_cnp; 122 } */ *ap = v; 123 124 if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF) 125 PNBUF_PUT(ap->a_cnp->cn_pnbuf); 126 return (0); 127 } 128 129 int 130 genfs_fcntl(void *v) 131 { 132 struct vop_fcntl_args /* { 133 struct vnode *a_vp; 134 u_int a_command; 135 void *a_data; 136 int a_fflag; 137 kauth_cred_t a_cred; 138 struct lwp *a_l; 139 } */ *ap = v; 140 141 if (ap->a_command == F_SETFL) 142 return (0); 143 else 144 return (EOPNOTSUPP); 145 } 146 147 /*ARGSUSED*/ 148 int 149 genfs_badop(void *v) 150 { 151 152 panic("genfs: bad op"); 153 } 154 155 /*ARGSUSED*/ 156 int 157 genfs_nullop(void *v) 158 { 159 160 return (0); 161 } 162 163 /*ARGSUSED*/ 164 int 165 genfs_einval(void *v) 166 { 167 168 return (EINVAL); 169 } 170 171 /* 172 * Called when an fs doesn't support a particular vop. 173 * This takes care to vrele, vput, or vunlock passed in vnodes. 174 */ 175 int 176 genfs_eopnotsupp(void *v) 177 { 178 struct vop_generic_args /* 179 struct vnodeop_desc *a_desc; 180 / * other random data follows, presumably * / 181 } */ *ap = v; 182 struct vnodeop_desc *desc = ap->a_desc; 183 struct vnode *vp, *vp_last = NULL; 184 int flags, i, j, offset; 185 186 flags = desc->vdesc_flags; 187 for (i = 0; i < VDESC_MAX_VPS; flags >>=1, i++) { 188 if ((offset = desc->vdesc_vp_offsets[i]) == VDESC_NO_OFFSET) 189 break; /* stop at end of list */ 190 if ((j = flags & VDESC_VP0_WILLPUT)) { 191 vp = *VOPARG_OFFSETTO(struct vnode **, offset, ap); 192 193 /* Skip if NULL */ 194 if (!vp) 195 continue; 196 197 switch (j) { 198 case VDESC_VP0_WILLPUT: 199 /* Check for dvp == vp cases */ 200 if (vp == vp_last) 201 vrele(vp); 202 else { 203 vput(vp); 204 vp_last = vp; 205 } 206 break; 207 case VDESC_VP0_WILLUNLOCK: 208 VOP_UNLOCK(vp, 0); 209 break; 210 case VDESC_VP0_WILLRELE: 211 vrele(vp); 212 break; 213 } 214 } 215 } 216 217 return (EOPNOTSUPP); 218 } 219 220 /*ARGSUSED*/ 221 int 222 genfs_ebadf(void *v) 223 { 224 225 return (EBADF); 226 } 227 228 /* ARGSUSED */ 229 int 230 genfs_enoioctl(void *v) 231 { 232 233 return (EPASSTHROUGH); 234 } 235 236 237 /* 238 * Eliminate all activity associated with the requested vnode 239 * and with all vnodes aliased to the requested vnode. 240 */ 241 int 242 genfs_revoke(void *v) 243 { 244 struct vop_revoke_args /* { 245 struct vnode *a_vp; 246 int a_flags; 247 } */ *ap = v; 248 249 #ifdef DIAGNOSTIC 250 if ((ap->a_flags & REVOKEALL) == 0) 251 panic("genfs_revoke: not revokeall"); 252 #endif 253 vrevoke(ap->a_vp); 254 return (0); 255 } 256 257 /* 258 * Lock the node. 259 */ 260 int 261 genfs_lock(void *v) 262 { 263 struct vop_lock_args /* { 264 struct vnode *a_vp; 265 int a_flags; 266 } */ *ap = v; 267 struct vnode *vp = ap->a_vp; 268 int flags = ap->a_flags; 269 270 if ((flags & LK_INTERLOCK) != 0) { 271 flags &= ~LK_INTERLOCK; 272 mutex_exit(&vp->v_interlock); 273 } 274 275 return (vlockmgr(vp->v_vnlock, flags)); 276 } 277 278 /* 279 * Unlock the node. 280 */ 281 int 282 genfs_unlock(void *v) 283 { 284 struct vop_unlock_args /* { 285 struct vnode *a_vp; 286 int a_flags; 287 } */ *ap = v; 288 struct vnode *vp = ap->a_vp; 289 290 KASSERT(ap->a_flags == 0); 291 292 return (vlockmgr(vp->v_vnlock, LK_RELEASE)); 293 } 294 295 /* 296 * Return whether or not the node is locked. 297 */ 298 int 299 genfs_islocked(void *v) 300 { 301 struct vop_islocked_args /* { 302 struct vnode *a_vp; 303 } */ *ap = v; 304 struct vnode *vp = ap->a_vp; 305 306 return (vlockstatus(vp->v_vnlock)); 307 } 308 309 /* 310 * Stubs to use when there is no locking to be done on the underlying object. 311 */ 312 int 313 genfs_nolock(void *v) 314 { 315 struct vop_lock_args /* { 316 struct vnode *a_vp; 317 int a_flags; 318 struct lwp *a_l; 319 } */ *ap = v; 320 321 /* 322 * Since we are not using the lock manager, we must clear 323 * the interlock here. 324 */ 325 if (ap->a_flags & LK_INTERLOCK) 326 mutex_exit(&ap->a_vp->v_interlock); 327 return (0); 328 } 329 330 int 331 genfs_nounlock(void *v) 332 { 333 334 return (0); 335 } 336 337 int 338 genfs_noislocked(void *v) 339 { 340 341 return (0); 342 } 343 344 int 345 genfs_mmap(void *v) 346 { 347 348 return (0); 349 } 350 351 /* 352 * VOP_PUTPAGES() for vnodes which never have pages. 353 */ 354 355 int 356 genfs_null_putpages(void *v) 357 { 358 struct vop_putpages_args /* { 359 struct vnode *a_vp; 360 voff_t a_offlo; 361 voff_t a_offhi; 362 int a_flags; 363 } */ *ap = v; 364 struct vnode *vp = ap->a_vp; 365 366 KASSERT(vp->v_uobj.uo_npages == 0); 367 mutex_exit(&vp->v_interlock); 368 return (0); 369 } 370 371 void 372 genfs_node_init(struct vnode *vp, const struct genfs_ops *ops) 373 { 374 struct genfs_node *gp = VTOG(vp); 375 376 rw_init(&gp->g_glock); 377 gp->g_op = ops; 378 } 379 380 void 381 genfs_node_destroy(struct vnode *vp) 382 { 383 struct genfs_node *gp = VTOG(vp); 384 385 rw_destroy(&gp->g_glock); 386 } 387 388 void 389 genfs_size(struct vnode *vp, off_t size, off_t *eobp, int flags) 390 { 391 int bsize; 392 393 bsize = 1 << vp->v_mount->mnt_fs_bshift; 394 *eobp = (size + bsize - 1) & ~(bsize - 1); 395 } 396 397 static void 398 filt_genfsdetach(struct knote *kn) 399 { 400 struct vnode *vp = (struct vnode *)kn->kn_hook; 401 402 mutex_enter(&vp->v_interlock); 403 SLIST_REMOVE(&vp->v_klist, kn, knote, kn_selnext); 404 mutex_exit(&vp->v_interlock); 405 } 406 407 static int 408 filt_genfsread(struct knote *kn, long hint) 409 { 410 struct vnode *vp = (struct vnode *)kn->kn_hook; 411 int rv; 412 413 /* 414 * filesystem is gone, so set the EOF flag and schedule 415 * the knote for deletion. 416 */ 417 switch (hint) { 418 case NOTE_REVOKE: 419 KASSERT(mutex_owned(&vp->v_interlock)); 420 kn->kn_flags |= (EV_EOF | EV_ONESHOT); 421 return (1); 422 case 0: 423 mutex_enter(&vp->v_interlock); 424 kn->kn_data = vp->v_size - ((file_t *)kn->kn_obj)->f_offset; 425 rv = (kn->kn_data != 0); 426 mutex_exit(&vp->v_interlock); 427 return rv; 428 default: 429 KASSERT(mutex_owned(&vp->v_interlock)); 430 kn->kn_data = vp->v_size - ((file_t *)kn->kn_obj)->f_offset; 431 return (kn->kn_data != 0); 432 } 433 } 434 435 static int 436 filt_genfsvnode(struct knote *kn, long hint) 437 { 438 struct vnode *vp = (struct vnode *)kn->kn_hook; 439 int fflags; 440 441 switch (hint) { 442 case NOTE_REVOKE: 443 KASSERT(mutex_owned(&vp->v_interlock)); 444 kn->kn_flags |= EV_EOF; 445 if ((kn->kn_sfflags & hint) != 0) 446 kn->kn_fflags |= hint; 447 return (1); 448 case 0: 449 mutex_enter(&vp->v_interlock); 450 fflags = kn->kn_fflags; 451 mutex_exit(&vp->v_interlock); 452 break; 453 default: 454 KASSERT(mutex_owned(&vp->v_interlock)); 455 if ((kn->kn_sfflags & hint) != 0) 456 kn->kn_fflags |= hint; 457 fflags = kn->kn_fflags; 458 break; 459 } 460 461 return (fflags != 0); 462 } 463 464 static const struct filterops genfsread_filtops = 465 { 1, NULL, filt_genfsdetach, filt_genfsread }; 466 static const struct filterops genfsvnode_filtops = 467 { 1, NULL, filt_genfsdetach, filt_genfsvnode }; 468 469 int 470 genfs_kqfilter(void *v) 471 { 472 struct vop_kqfilter_args /* { 473 struct vnode *a_vp; 474 struct knote *a_kn; 475 } */ *ap = v; 476 struct vnode *vp; 477 struct knote *kn; 478 479 vp = ap->a_vp; 480 kn = ap->a_kn; 481 switch (kn->kn_filter) { 482 case EVFILT_READ: 483 kn->kn_fop = &genfsread_filtops; 484 break; 485 case EVFILT_VNODE: 486 kn->kn_fop = &genfsvnode_filtops; 487 break; 488 default: 489 return (EINVAL); 490 } 491 492 kn->kn_hook = vp; 493 494 mutex_enter(&vp->v_interlock); 495 SLIST_INSERT_HEAD(&vp->v_klist, kn, kn_selnext); 496 mutex_exit(&vp->v_interlock); 497 498 return (0); 499 } 500 501 void 502 genfs_node_wrlock(struct vnode *vp) 503 { 504 struct genfs_node *gp = VTOG(vp); 505 506 rw_enter(&gp->g_glock, RW_WRITER); 507 } 508 509 void 510 genfs_node_rdlock(struct vnode *vp) 511 { 512 struct genfs_node *gp = VTOG(vp); 513 514 rw_enter(&gp->g_glock, RW_READER); 515 } 516 517 void 518 genfs_node_unlock(struct vnode *vp) 519 { 520 struct genfs_node *gp = VTOG(vp); 521 522 rw_exit(&gp->g_glock); 523 } 524 525 /* 526 * Do the usual access checking. 527 * file_mode, uid and gid are from the vnode in question, 528 * while acc_mode and cred are from the VOP_ACCESS parameter list 529 */ 530 int 531 genfs_can_access(enum vtype type, mode_t file_mode, uid_t uid, gid_t gid, 532 mode_t acc_mode, kauth_cred_t cred) 533 { 534 mode_t mask; 535 int error, ismember; 536 537 /* 538 * Super-user always gets read/write access, but execute access depends 539 * on at least one execute bit being set. 540 */ 541 if (kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL) == 0) { 542 if ((acc_mode & VEXEC) && type != VDIR && 543 (file_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0) 544 return (EACCES); 545 return (0); 546 } 547 548 mask = 0; 549 550 /* Otherwise, check the owner. */ 551 if (kauth_cred_geteuid(cred) == uid) { 552 if (acc_mode & VEXEC) 553 mask |= S_IXUSR; 554 if (acc_mode & VREAD) 555 mask |= S_IRUSR; 556 if (acc_mode & VWRITE) 557 mask |= S_IWUSR; 558 return ((file_mode & mask) == mask ? 0 : EACCES); 559 } 560 561 /* Otherwise, check the groups. */ 562 error = kauth_cred_ismember_gid(cred, gid, &ismember); 563 if (error) 564 return (error); 565 if (kauth_cred_getegid(cred) == gid || ismember) { 566 if (acc_mode & VEXEC) 567 mask |= S_IXGRP; 568 if (acc_mode & VREAD) 569 mask |= S_IRGRP; 570 if (acc_mode & VWRITE) 571 mask |= S_IWGRP; 572 return ((file_mode & mask) == mask ? 0 : EACCES); 573 } 574 575 /* Otherwise, check everyone else. */ 576 if (acc_mode & VEXEC) 577 mask |= S_IXOTH; 578 if (acc_mode & VREAD) 579 mask |= S_IROTH; 580 if (acc_mode & VWRITE) 581 mask |= S_IWOTH; 582 return ((file_mode & mask) == mask ? 0 : EACCES); 583 } 584 585 /* 586 * Common routine to check if chmod() is allowed. 587 * 588 * Policy: 589 * - You must be root, or 590 * - You must own the file, and 591 * - You must not set the "sticky" bit (meaningless, see chmod(2)) 592 * - You must be a member of the group if you're trying to set the 593 * SGIDf bit 594 * 595 * cred - credentials of the invoker 596 * vp - vnode of the file-system object 597 * cur_uid, cur_gid - current uid/gid of the file-system object 598 * new_mode - new mode for the file-system object 599 * 600 * Returns 0 if the change is allowed, or an error value otherwise. 601 */ 602 int 603 genfs_can_chmod(vnode_t *vp, kauth_cred_t cred, uid_t cur_uid, 604 gid_t cur_gid, mode_t new_mode) 605 { 606 int error; 607 608 /* Superuser can always change mode. */ 609 error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, 610 NULL); 611 if (!error) 612 return (0); 613 614 /* Otherwise, user must own the file. */ 615 if (kauth_cred_geteuid(cred) != cur_uid) 616 return (EPERM); 617 618 /* 619 * Non-root users can't set the sticky bit on files. 620 */ 621 if ((vp->v_type != VDIR) && (new_mode & S_ISTXT)) 622 return (EFTYPE); 623 624 /* 625 * If the invoker is trying to set the SGID bit on the file, 626 * check group membership. 627 */ 628 if (new_mode & S_ISGID) { 629 int ismember; 630 631 error = kauth_cred_ismember_gid(cred, cur_gid, 632 &ismember); 633 if (error || !ismember) 634 return (EPERM); 635 } 636 637 return (0); 638 } 639 640 /* 641 * Common routine to check if chown() is allowed. 642 * 643 * Policy: 644 * - You must be root, or 645 * - You must own the file, and 646 * - You must not try to change ownership, and 647 * - You must be member of the new group 648 * 649 * cred - credentials of the invoker 650 * cur_uid, cur_gid - current uid/gid of the file-system object 651 * new_uid, new_gid - target uid/gid of the file-system object 652 * 653 * Returns 0 if the change is allowed, or an error value otherwise. 654 */ 655 int 656 genfs_can_chown(vnode_t *vp, kauth_cred_t cred, uid_t cur_uid, 657 gid_t cur_gid, uid_t new_uid, gid_t new_gid) 658 { 659 int error, ismember; 660 661 /* 662 * You can only change ownership of a file if: 663 * You are the superuser, or... 664 */ 665 error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, 666 NULL); 667 if (!error) 668 return (0); 669 670 /* 671 * You own the file and... 672 */ 673 if (kauth_cred_geteuid(cred) == cur_uid) { 674 /* 675 * You don't try to change ownership, and... 676 */ 677 if (new_uid != cur_uid) 678 return (EPERM); 679 680 /* 681 * You don't try to change group (no-op), or... 682 */ 683 if (new_gid == cur_gid) 684 return (0); 685 686 /* 687 * Your effective gid is the new gid, or... 688 */ 689 if (kauth_cred_getegid(cred) == new_gid) 690 return (0); 691 692 /* 693 * The new gid is one you're a member of. 694 */ 695 ismember = 0; 696 error = kauth_cred_ismember_gid(cred, new_gid, 697 &ismember); 698 if (!error && ismember) 699 return (0); 700 } 701 702 return (EPERM); 703 } 704 705 /* 706 * Common routine to check if the device can be mounted. 707 * 708 * devvp - the locked vnode of the device 709 * cred - credentials of the invoker 710 * accessmode - the accessmode (VREAD, VWRITE) 711 * 712 * Returns 0 if the mount is allowed, or an error value otherwise. 713 */ 714 int 715 genfs_can_mount(vnode_t *devvp, mode_t accessmode, kauth_cred_t cred) 716 { 717 int error; 718 719 /* Always allow for root. */ 720 error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL); 721 if (!error) 722 return (0); 723 724 error = VOP_ACCESS(devvp, accessmode, cred); 725 726 return (error); 727 } 728 729 int 730 genfs_can_chtimes(vnode_t *vp, u_int vaflags, uid_t owner_uid, 731 kauth_cred_t cred) 732 { 733 int error; 734 735 /* Must be root, or... */ 736 error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL); 737 if (!error) 738 return (0); 739 740 /* must be owner, or... */ 741 if (kauth_cred_geteuid(cred) == owner_uid) 742 return (0); 743 744 /* set the times to the current time, and... */ 745 if ((vaflags & VA_UTIMES_NULL) == 0) 746 return (EPERM); 747 748 /* have write access. */ 749 error = VOP_ACCESS(vp, VWRITE, cred); 750 if (error) 751 return (error); 752 753 return (0); 754 } 755 756