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