1 /* $NetBSD: genfs_vnops.c,v 1.176 2010/01/27 15:52:31 uebayasi 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.176 2010/01/27 15:52:31 uebayasi 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 int 518 genfs_node_rdtrylock(struct vnode *vp) 519 { 520 struct genfs_node *gp = VTOG(vp); 521 522 return rw_tryenter(&gp->g_glock, RW_READER); 523 } 524 525 void 526 genfs_node_unlock(struct vnode *vp) 527 { 528 struct genfs_node *gp = VTOG(vp); 529 530 rw_exit(&gp->g_glock); 531 } 532 533 /* 534 * Do the usual access checking. 535 * file_mode, uid and gid are from the vnode in question, 536 * while acc_mode and cred are from the VOP_ACCESS parameter list 537 */ 538 int 539 genfs_can_access(enum vtype type, mode_t file_mode, uid_t uid, gid_t gid, 540 mode_t acc_mode, kauth_cred_t cred) 541 { 542 mode_t mask; 543 int error, ismember; 544 545 /* 546 * Super-user always gets read/write access, but execute access depends 547 * on at least one execute bit being set. 548 */ 549 if (kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL) == 0) { 550 if ((acc_mode & VEXEC) && type != VDIR && 551 (file_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0) 552 return (EACCES); 553 return (0); 554 } 555 556 mask = 0; 557 558 /* Otherwise, check the owner. */ 559 if (kauth_cred_geteuid(cred) == uid) { 560 if (acc_mode & VEXEC) 561 mask |= S_IXUSR; 562 if (acc_mode & VREAD) 563 mask |= S_IRUSR; 564 if (acc_mode & VWRITE) 565 mask |= S_IWUSR; 566 return ((file_mode & mask) == mask ? 0 : EACCES); 567 } 568 569 /* Otherwise, check the groups. */ 570 error = kauth_cred_ismember_gid(cred, gid, &ismember); 571 if (error) 572 return (error); 573 if (kauth_cred_getegid(cred) == gid || ismember) { 574 if (acc_mode & VEXEC) 575 mask |= S_IXGRP; 576 if (acc_mode & VREAD) 577 mask |= S_IRGRP; 578 if (acc_mode & VWRITE) 579 mask |= S_IWGRP; 580 return ((file_mode & mask) == mask ? 0 : EACCES); 581 } 582 583 /* Otherwise, check everyone else. */ 584 if (acc_mode & VEXEC) 585 mask |= S_IXOTH; 586 if (acc_mode & VREAD) 587 mask |= S_IROTH; 588 if (acc_mode & VWRITE) 589 mask |= S_IWOTH; 590 return ((file_mode & mask) == mask ? 0 : EACCES); 591 } 592 593 /* 594 * Common routine to check if chmod() is allowed. 595 * 596 * Policy: 597 * - You must be root, or 598 * - You must own the file, and 599 * - You must not set the "sticky" bit (meaningless, see chmod(2)) 600 * - You must be a member of the group if you're trying to set the 601 * SGIDf bit 602 * 603 * cred - credentials of the invoker 604 * vp - vnode of the file-system object 605 * cur_uid, cur_gid - current uid/gid of the file-system object 606 * new_mode - new mode for the file-system object 607 * 608 * Returns 0 if the change is allowed, or an error value otherwise. 609 */ 610 int 611 genfs_can_chmod(vnode_t *vp, kauth_cred_t cred, uid_t cur_uid, 612 gid_t cur_gid, mode_t new_mode) 613 { 614 int error; 615 616 /* Superuser can always change mode. */ 617 error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, 618 NULL); 619 if (!error) 620 return (0); 621 622 /* Otherwise, user must own the file. */ 623 if (kauth_cred_geteuid(cred) != cur_uid) 624 return (EPERM); 625 626 /* 627 * Non-root users can't set the sticky bit on files. 628 */ 629 if ((vp->v_type != VDIR) && (new_mode & S_ISTXT)) 630 return (EFTYPE); 631 632 /* 633 * If the invoker is trying to set the SGID bit on the file, 634 * check group membership. 635 */ 636 if (new_mode & S_ISGID) { 637 int ismember; 638 639 error = kauth_cred_ismember_gid(cred, cur_gid, 640 &ismember); 641 if (error || !ismember) 642 return (EPERM); 643 } 644 645 return (0); 646 } 647 648 /* 649 * Common routine to check if chown() is allowed. 650 * 651 * Policy: 652 * - You must be root, or 653 * - You must own the file, and 654 * - You must not try to change ownership, and 655 * - You must be member of the new group 656 * 657 * cred - credentials of the invoker 658 * cur_uid, cur_gid - current uid/gid of the file-system object 659 * new_uid, new_gid - target uid/gid of the file-system object 660 * 661 * Returns 0 if the change is allowed, or an error value otherwise. 662 */ 663 int 664 genfs_can_chown(vnode_t *vp, kauth_cred_t cred, uid_t cur_uid, 665 gid_t cur_gid, uid_t new_uid, gid_t new_gid) 666 { 667 int error, ismember; 668 669 /* 670 * You can only change ownership of a file if: 671 * You are the superuser, or... 672 */ 673 error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, 674 NULL); 675 if (!error) 676 return (0); 677 678 /* 679 * You own the file and... 680 */ 681 if (kauth_cred_geteuid(cred) == cur_uid) { 682 /* 683 * You don't try to change ownership, and... 684 */ 685 if (new_uid != cur_uid) 686 return (EPERM); 687 688 /* 689 * You don't try to change group (no-op), or... 690 */ 691 if (new_gid == cur_gid) 692 return (0); 693 694 /* 695 * Your effective gid is the new gid, or... 696 */ 697 if (kauth_cred_getegid(cred) == new_gid) 698 return (0); 699 700 /* 701 * The new gid is one you're a member of. 702 */ 703 ismember = 0; 704 error = kauth_cred_ismember_gid(cred, new_gid, 705 &ismember); 706 if (!error && ismember) 707 return (0); 708 } 709 710 return (EPERM); 711 } 712 713 /* 714 * Common routine to check if the device can be mounted. 715 * 716 * devvp - the locked vnode of the device 717 * cred - credentials of the invoker 718 * accessmode - the accessmode (VREAD, VWRITE) 719 * 720 * Returns 0 if the mount is allowed, or an error value otherwise. 721 */ 722 int 723 genfs_can_mount(vnode_t *devvp, mode_t accessmode, kauth_cred_t cred) 724 { 725 int error; 726 727 /* Always allow for root. */ 728 error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL); 729 if (!error) 730 return (0); 731 732 error = VOP_ACCESS(devvp, accessmode, cred); 733 734 return (error); 735 } 736 737 int 738 genfs_can_chtimes(vnode_t *vp, u_int vaflags, uid_t owner_uid, 739 kauth_cred_t cred) 740 { 741 int error; 742 743 /* Must be root, or... */ 744 error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL); 745 if (!error) 746 return (0); 747 748 /* must be owner, or... */ 749 if (kauth_cred_geteuid(cred) == owner_uid) 750 return (0); 751 752 /* set the times to the current time, and... */ 753 if ((vaflags & VA_UTIMES_NULL) == 0) 754 return (EPERM); 755 756 /* have write access. */ 757 error = VOP_ACCESS(vp, VWRITE, cred); 758 if (error) 759 return (error); 760 761 return (0); 762 } 763 764