1 /* 2 * Copyright (c) 2007-2009 Google Inc. and Amit Singh 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the following disclaimer 13 * in the documentation and/or other materials provided with the 14 * distribution. 15 * * Neither the name of Google Inc. nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 * Copyright (C) 2005 Csaba Henk. 32 * All rights reserved. 33 * 34 * Redistribution and use in source and binary forms, with or without 35 * modification, are permitted provided that the following conditions 36 * are met: 37 * 1. Redistributions of source code must retain the above copyright 38 * notice, this list of conditions and the following disclaimer. 39 * 2. Redistributions in binary form must reproduce the above copyright 40 * notice, this list of conditions and the following disclaimer in the 41 * documentation and/or other materials provided with the distribution. 42 * 43 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 46 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 53 * SUCH DAMAGE. 54 */ 55 56 #include <sys/cdefs.h> 57 __FBSDID("$FreeBSD$"); 58 59 #include <sys/types.h> 60 #include <sys/module.h> 61 #include <sys/systm.h> 62 #include <sys/errno.h> 63 #include <sys/param.h> 64 #include <sys/kernel.h> 65 #include <sys/conf.h> 66 #include <sys/uio.h> 67 #include <sys/malloc.h> 68 #include <sys/queue.h> 69 #include <sys/lock.h> 70 #include <sys/mutex.h> 71 #include <sys/sx.h> 72 #include <sys/proc.h> 73 #include <sys/mount.h> 74 #include <sys/vnode.h> 75 #include <sys/namei.h> 76 #include <sys/stat.h> 77 #include <sys/unistd.h> 78 #include <sys/filedesc.h> 79 #include <sys/file.h> 80 #include <sys/fcntl.h> 81 #include <sys/dirent.h> 82 #include <sys/bio.h> 83 #include <sys/buf.h> 84 #include <sys/sysctl.h> 85 #include <sys/priv.h> 86 87 #include "fuse.h" 88 #include "fuse_file.h" 89 #include "fuse_internal.h" 90 #include "fuse_ipc.h" 91 #include "fuse_node.h" 92 #include "fuse_file.h" 93 #include "fuse_param.h" 94 95 #define FUSE_DEBUG_MODULE INTERNAL 96 #include "fuse_debug.h" 97 98 #ifdef ZERO_PAD_INCOMPLETE_BUFS 99 static int isbzero(void *buf, size_t len); 100 101 #endif 102 103 /* access */ 104 105 int 106 fuse_internal_access(struct vnode *vp, 107 mode_t mode, 108 struct fuse_access_param *facp, 109 struct thread *td, 110 struct ucred *cred) 111 { 112 int err = 0; 113 uint32_t mask = 0; 114 int dataflags; 115 int vtype; 116 struct mount *mp; 117 struct fuse_dispatcher fdi; 118 struct fuse_access_in *fai; 119 struct fuse_data *data; 120 121 /* NOT YET DONE */ 122 /* 123 * If this vnop gives you trouble, just return 0 here for a lazy 124 * kludge. 125 */ 126 /* return 0;*/ 127 128 fuse_trace_printf_func(); 129 130 mp = vnode_mount(vp); 131 vtype = vnode_vtype(vp); 132 133 data = fuse_get_mpdata(mp); 134 dataflags = data->dataflags; 135 136 if ((mode & VWRITE) && vfs_isrdonly(mp)) { 137 return EACCES; 138 } 139 /* Unless explicitly permitted, deny everyone except the fs owner. */ 140 if (vnode_isvroot(vp) && !(facp->facc_flags & FACCESS_NOCHECKSPY)) { 141 if (!(dataflags & FSESS_DAEMON_CAN_SPY)) { 142 int denied = fuse_match_cred(data->daemoncred, 143 cred); 144 145 if (denied) { 146 return EPERM; 147 } 148 } 149 facp->facc_flags |= FACCESS_NOCHECKSPY; 150 } 151 if (!(facp->facc_flags & FACCESS_DO_ACCESS)) { 152 return 0; 153 } 154 if (((vtype == VREG) && (mode & VEXEC))) { 155 #ifdef NEED_MOUNT_ARGUMENT_FOR_THIS 156 /* Let the kernel handle this through open / close heuristics.*/ 157 return ENOTSUP; 158 #else 159 /* Let the kernel handle this. */ 160 return 0; 161 #endif 162 } 163 if (!fsess_isimpl(mp, FUSE_ACCESS)) { 164 /* Let the kernel handle this. */ 165 return 0; 166 } 167 if (dataflags & FSESS_DEFAULT_PERMISSIONS) { 168 /* Let the kernel handle this. */ 169 return 0; 170 } 171 if ((mode & VADMIN) != 0) { 172 err = priv_check_cred(cred, PRIV_VFS_ADMIN, 0); 173 if (err) { 174 return err; 175 } 176 } 177 if ((mode & (VWRITE | VAPPEND | VADMIN)) != 0) { 178 mask |= W_OK; 179 } 180 if ((mode & VREAD) != 0) { 181 mask |= R_OK; 182 } 183 if ((mode & VEXEC) != 0) { 184 mask |= X_OK; 185 } 186 bzero(&fdi, sizeof(fdi)); 187 188 fdisp_init(&fdi, sizeof(*fai)); 189 fdisp_make_vp(&fdi, FUSE_ACCESS, vp, td, cred); 190 191 fai = fdi.indata; 192 fai->mask = F_OK; 193 fai->mask |= mask; 194 195 err = fdisp_wait_answ(&fdi); 196 fdisp_destroy(&fdi); 197 198 if (err == ENOSYS) { 199 fsess_set_notimpl(mp, FUSE_ACCESS); 200 err = 0; 201 } 202 return err; 203 } 204 205 /* fsync */ 206 207 int 208 fuse_internal_fsync_callback(struct fuse_ticket *tick, struct uio *uio) 209 { 210 fuse_trace_printf_func(); 211 212 if (tick->tk_aw_ohead.error == ENOSYS) { 213 fsess_set_notimpl(tick->tk_data->mp, fticket_opcode(tick)); 214 } 215 return 0; 216 } 217 218 int 219 fuse_internal_fsync(struct vnode *vp, 220 struct thread *td, 221 struct ucred *cred, 222 struct fuse_filehandle *fufh) 223 { 224 int op = FUSE_FSYNC; 225 struct fuse_fsync_in *ffsi; 226 struct fuse_dispatcher fdi; 227 228 fuse_trace_printf_func(); 229 230 if (vnode_isdir(vp)) { 231 op = FUSE_FSYNCDIR; 232 } 233 fdisp_init(&fdi, sizeof(*ffsi)); 234 fdisp_make_vp(&fdi, op, vp, td, cred); 235 ffsi = fdi.indata; 236 ffsi->fh = fufh->fh_id; 237 238 ffsi->fsync_flags = 1; /* datasync */ 239 240 fuse_insert_callback(fdi.tick, fuse_internal_fsync_callback); 241 fuse_insert_message(fdi.tick); 242 243 fdisp_destroy(&fdi); 244 245 return 0; 246 247 } 248 249 /* readdir */ 250 251 int 252 fuse_internal_readdir(struct vnode *vp, 253 struct uio *uio, 254 struct fuse_filehandle *fufh, 255 struct fuse_iov *cookediov) 256 { 257 int err = 0; 258 struct fuse_dispatcher fdi; 259 struct fuse_read_in *fri; 260 261 if (uio_resid(uio) == 0) { 262 return 0; 263 } 264 fdisp_init(&fdi, 0); 265 266 /* 267 * Note that we DO NOT have a UIO_SYSSPACE here (so no need for p2p 268 * I/O). 269 */ 270 271 while (uio_resid(uio) > 0) { 272 273 fdi.iosize = sizeof(*fri); 274 fdisp_make_vp(&fdi, FUSE_READDIR, vp, NULL, NULL); 275 276 fri = fdi.indata; 277 fri->fh = fufh->fh_id; 278 fri->offset = uio_offset(uio); 279 fri->size = min(uio_resid(uio), FUSE_DEFAULT_IOSIZE); 280 /* mp->max_read */ 281 282 if ((err = fdisp_wait_answ(&fdi))) { 283 break; 284 } 285 if ((err = fuse_internal_readdir_processdata(uio, fri->size, fdi.answ, 286 fdi.iosize, cookediov))) { 287 break; 288 } 289 } 290 291 fdisp_destroy(&fdi); 292 return ((err == -1) ? 0 : err); 293 } 294 295 int 296 fuse_internal_readdir_processdata(struct uio *uio, 297 size_t reqsize, 298 void *buf, 299 size_t bufsize, 300 void *param) 301 { 302 int err = 0; 303 int cou = 0; 304 int bytesavail; 305 size_t freclen; 306 307 struct dirent *de; 308 struct fuse_dirent *fudge; 309 struct fuse_iov *cookediov = param; 310 311 if (bufsize < FUSE_NAME_OFFSET) { 312 return -1; 313 } 314 for (;;) { 315 316 if (bufsize < FUSE_NAME_OFFSET) { 317 err = -1; 318 break; 319 } 320 fudge = (struct fuse_dirent *)buf; 321 freclen = FUSE_DIRENT_SIZE(fudge); 322 323 cou++; 324 325 if (bufsize < freclen) { 326 err = ((cou == 1) ? -1 : 0); 327 break; 328 } 329 #ifdef ZERO_PAD_INCOMPLETE_BUFS 330 if (isbzero(buf, FUSE_NAME_OFFSET)) { 331 err = -1; 332 break; 333 } 334 #endif 335 336 if (!fudge->namelen || fudge->namelen > MAXNAMLEN) { 337 err = EINVAL; 338 break; 339 } 340 bytesavail = GENERIC_DIRSIZ((struct pseudo_dirent *) 341 &fudge->namelen); 342 343 if (bytesavail > uio_resid(uio)) { 344 err = -1; 345 break; 346 } 347 fiov_refresh(cookediov); 348 fiov_adjust(cookediov, bytesavail); 349 350 de = (struct dirent *)cookediov->base; 351 de->d_fileno = fudge->ino; /* XXX: truncation */ 352 de->d_reclen = bytesavail; 353 de->d_type = fudge->type; 354 de->d_namlen = fudge->namelen; 355 memcpy((char *)cookediov->base + sizeof(struct dirent) - 356 MAXNAMLEN - 1, 357 (char *)buf + FUSE_NAME_OFFSET, fudge->namelen); 358 ((char *)cookediov->base)[bytesavail] = '\0'; 359 360 err = uiomove(cookediov->base, cookediov->len, uio); 361 if (err) { 362 break; 363 } 364 buf = (char *)buf + freclen; 365 bufsize -= freclen; 366 uio_setoffset(uio, fudge->off); 367 } 368 369 return err; 370 } 371 372 /* remove */ 373 374 #define INVALIDATE_CACHED_VATTRS_UPON_UNLINK 1 375 int 376 fuse_internal_remove(struct vnode *dvp, 377 struct vnode *vp, 378 struct componentname *cnp, 379 enum fuse_opcode op) 380 { 381 struct fuse_dispatcher fdi; 382 383 struct vattr *vap = VTOVA(vp); 384 385 #if INVALIDATE_CACHED_VATTRS_UPON_UNLINK 386 int need_invalidate = 0; 387 uint64_t target_nlink = 0; 388 389 #endif 390 int err = 0; 391 392 debug_printf("dvp=%p, cnp=%p, op=%d\n", vp, cnp, op); 393 394 fdisp_init(&fdi, cnp->cn_namelen + 1); 395 fdisp_make_vp(&fdi, op, dvp, cnp->cn_thread, cnp->cn_cred); 396 397 memcpy(fdi.indata, cnp->cn_nameptr, cnp->cn_namelen); 398 ((char *)fdi.indata)[cnp->cn_namelen] = '\0'; 399 400 #if INVALIDATE_CACHED_VATTRS_UPON_UNLINK 401 if (vap->va_nlink > 1) { 402 need_invalidate = 1; 403 target_nlink = vap->va_nlink; 404 } 405 #endif 406 407 err = fdisp_wait_answ(&fdi); 408 fdisp_destroy(&fdi); 409 return err; 410 } 411 412 /* rename */ 413 414 int 415 fuse_internal_rename(struct vnode *fdvp, 416 struct componentname *fcnp, 417 struct vnode *tdvp, 418 struct componentname *tcnp) 419 { 420 struct fuse_dispatcher fdi; 421 struct fuse_rename_in *fri; 422 int err = 0; 423 424 fdisp_init(&fdi, sizeof(*fri) + fcnp->cn_namelen + tcnp->cn_namelen + 2); 425 fdisp_make_vp(&fdi, FUSE_RENAME, fdvp, tcnp->cn_thread, tcnp->cn_cred); 426 427 fri = fdi.indata; 428 fri->newdir = VTOI(tdvp); 429 memcpy((char *)fdi.indata + sizeof(*fri), fcnp->cn_nameptr, 430 fcnp->cn_namelen); 431 ((char *)fdi.indata)[sizeof(*fri) + fcnp->cn_namelen] = '\0'; 432 memcpy((char *)fdi.indata + sizeof(*fri) + fcnp->cn_namelen + 1, 433 tcnp->cn_nameptr, tcnp->cn_namelen); 434 ((char *)fdi.indata)[sizeof(*fri) + fcnp->cn_namelen + 435 tcnp->cn_namelen + 1] = '\0'; 436 437 err = fdisp_wait_answ(&fdi); 438 fdisp_destroy(&fdi); 439 return err; 440 } 441 442 /* strategy */ 443 444 /* entity creation */ 445 446 void 447 fuse_internal_newentry_makerequest(struct mount *mp, 448 uint64_t dnid, 449 struct componentname *cnp, 450 enum fuse_opcode op, 451 void *buf, 452 size_t bufsize, 453 struct fuse_dispatcher *fdip) 454 { 455 debug_printf("fdip=%p\n", fdip); 456 457 fdip->iosize = bufsize + cnp->cn_namelen + 1; 458 459 fdisp_make(fdip, op, mp, dnid, cnp->cn_thread, cnp->cn_cred); 460 memcpy(fdip->indata, buf, bufsize); 461 memcpy((char *)fdip->indata + bufsize, cnp->cn_nameptr, cnp->cn_namelen); 462 ((char *)fdip->indata)[bufsize + cnp->cn_namelen] = '\0'; 463 } 464 465 int 466 fuse_internal_newentry_core(struct vnode *dvp, 467 struct vnode **vpp, 468 struct componentname *cnp, 469 enum vtype vtyp, 470 struct fuse_dispatcher *fdip) 471 { 472 int err = 0; 473 struct fuse_entry_out *feo; 474 struct mount *mp = vnode_mount(dvp); 475 476 if ((err = fdisp_wait_answ(fdip))) { 477 return err; 478 } 479 feo = fdip->answ; 480 481 if ((err = fuse_internal_checkentry(feo, vtyp))) { 482 return err; 483 } 484 err = fuse_vnode_get(mp, feo->nodeid, dvp, vpp, cnp, vtyp); 485 if (err) { 486 fuse_internal_forget_send(mp, cnp->cn_thread, cnp->cn_cred, 487 feo->nodeid, 1); 488 return err; 489 } 490 cache_attrs(*vpp, feo); 491 492 return err; 493 } 494 495 int 496 fuse_internal_newentry(struct vnode *dvp, 497 struct vnode **vpp, 498 struct componentname *cnp, 499 enum fuse_opcode op, 500 void *buf, 501 size_t bufsize, 502 enum vtype vtype) 503 { 504 int err; 505 struct fuse_dispatcher fdi; 506 struct mount *mp = vnode_mount(dvp); 507 508 fdisp_init(&fdi, 0); 509 fuse_internal_newentry_makerequest(mp, VTOI(dvp), cnp, op, buf, 510 bufsize, &fdi); 511 err = fuse_internal_newentry_core(dvp, vpp, cnp, vtype, &fdi); 512 fdisp_destroy(&fdi); 513 514 return err; 515 } 516 517 /* entity destruction */ 518 519 int 520 fuse_internal_forget_callback(struct fuse_ticket *ftick, struct uio *uio) 521 { 522 fuse_internal_forget_send(ftick->tk_data->mp, curthread, NULL, 523 ((struct fuse_in_header *)ftick->tk_ms_fiov.base)->nodeid, 1); 524 525 return 0; 526 } 527 528 void 529 fuse_internal_forget_send(struct mount *mp, 530 struct thread *td, 531 struct ucred *cred, 532 uint64_t nodeid, 533 uint64_t nlookup) 534 { 535 536 struct fuse_dispatcher fdi; 537 struct fuse_forget_in *ffi; 538 539 debug_printf("mp=%p, nodeid=%ju, nlookup=%ju\n", 540 mp, (uintmax_t)nodeid, (uintmax_t)nlookup); 541 542 /* 543 * KASSERT(nlookup > 0, ("zero-times forget for vp #%llu", 544 * (long long unsigned) nodeid)); 545 */ 546 547 fdisp_init(&fdi, sizeof(*ffi)); 548 fdisp_make(&fdi, FUSE_FORGET, mp, nodeid, td, cred); 549 550 ffi = fdi.indata; 551 ffi->nlookup = nlookup; 552 553 fuse_insert_message(fdi.tick); 554 fdisp_destroy(&fdi); 555 } 556 557 void 558 fuse_internal_vnode_disappear(struct vnode *vp) 559 { 560 struct fuse_vnode_data *fvdat = VTOFUD(vp); 561 562 ASSERT_VOP_ELOCKED(vp, "fuse_internal_vnode_disappear"); 563 fvdat->flag |= FN_REVOKED; 564 cache_purge(vp); 565 } 566 567 /* fuse start/stop */ 568 569 int 570 fuse_internal_init_callback(struct fuse_ticket *tick, struct uio *uio) 571 { 572 int err = 0; 573 struct fuse_data *data = tick->tk_data; 574 struct fuse_init_out *fiio; 575 576 if ((err = tick->tk_aw_ohead.error)) { 577 goto out; 578 } 579 if ((err = fticket_pull(tick, uio))) { 580 goto out; 581 } 582 fiio = fticket_resp(tick)->base; 583 584 /* XXX: Do we want to check anything further besides this? */ 585 if (fiio->major < 7) { 586 debug_printf("userpace version too low\n"); 587 err = EPROTONOSUPPORT; 588 goto out; 589 } 590 data->fuse_libabi_major = fiio->major; 591 data->fuse_libabi_minor = fiio->minor; 592 593 if (fuse_libabi_geq(data, 7, 5)) { 594 if (fticket_resp(tick)->len == sizeof(struct fuse_init_out)) { 595 data->max_write = fiio->max_write; 596 } else { 597 err = EINVAL; 598 } 599 } else { 600 /* Old fix values */ 601 data->max_write = 4096; 602 } 603 604 out: 605 if (err) { 606 fdata_set_dead(data); 607 } 608 FUSE_LOCK(); 609 data->dataflags |= FSESS_INITED; 610 wakeup(&data->ticketer); 611 FUSE_UNLOCK(); 612 613 return 0; 614 } 615 616 void 617 fuse_internal_send_init(struct fuse_data *data, struct thread *td) 618 { 619 struct fuse_init_in *fiii; 620 struct fuse_dispatcher fdi; 621 622 fdisp_init(&fdi, sizeof(*fiii)); 623 fdisp_make(&fdi, FUSE_INIT, data->mp, 0, td, NULL); 624 fiii = fdi.indata; 625 fiii->major = FUSE_KERNEL_VERSION; 626 fiii->minor = FUSE_KERNEL_MINOR_VERSION; 627 fiii->max_readahead = FUSE_DEFAULT_IOSIZE * 16; 628 fiii->flags = 0; 629 630 fuse_insert_callback(fdi.tick, fuse_internal_init_callback); 631 fuse_insert_message(fdi.tick); 632 fdisp_destroy(&fdi); 633 } 634 635 #ifdef ZERO_PAD_INCOMPLETE_BUFS 636 static int 637 isbzero(void *buf, size_t len) 638 { 639 int i; 640 641 for (i = 0; i < len; i++) { 642 if (((char *)buf)[i]) 643 return (0); 644 } 645 646 return (1); 647 } 648 649 #endif 650