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 * Copyright (c) 2019 The FreeBSD Foundation 37 * 38 * Portions of this software were developed by BFF Storage Systems, LLC under 39 * sponsorship from the FreeBSD Foundation. 40 * 41 * Redistribution and use in source and binary forms, with or without 42 * modification, are permitted provided that the following conditions 43 * are met: 44 * 1. Redistributions of source code must retain the above copyright 45 * notice, this list of conditions and the following disclaimer. 46 * 2. Redistributions in binary form must reproduce the above copyright 47 * notice, this list of conditions and the following disclaimer in the 48 * documentation and/or other materials provided with the distribution. 49 * 50 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 51 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 53 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 54 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 58 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 59 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 60 * SUCH DAMAGE. 61 */ 62 63 #include <sys/cdefs.h> 64 __FBSDID("$FreeBSD$"); 65 66 #include <sys/param.h> 67 #include <sys/module.h> 68 #include <sys/systm.h> 69 #include <sys/errno.h> 70 #include <sys/kernel.h> 71 #include <sys/conf.h> 72 #include <sys/uio.h> 73 #include <sys/malloc.h> 74 #include <sys/queue.h> 75 #include <sys/limits.h> 76 #include <sys/lock.h> 77 #include <sys/rwlock.h> 78 #include <sys/sx.h> 79 #include <sys/proc.h> 80 #include <sys/mount.h> 81 #include <sys/vnode.h> 82 #include <sys/namei.h> 83 #include <sys/extattr.h> 84 #include <sys/stat.h> 85 #include <sys/unistd.h> 86 #include <sys/filedesc.h> 87 #include <sys/file.h> 88 #include <sys/fcntl.h> 89 #include <sys/dirent.h> 90 #include <sys/bio.h> 91 #include <sys/buf.h> 92 #include <sys/sysctl.h> 93 #include <sys/vmmeter.h> 94 95 #include <vm/vm.h> 96 #include <vm/vm_extern.h> 97 #include <vm/pmap.h> 98 #include <vm/vm_map.h> 99 #include <vm/vm_page.h> 100 #include <vm/vm_param.h> 101 #include <vm/vm_object.h> 102 #include <vm/vm_pager.h> 103 #include <vm/vnode_pager.h> 104 #include <vm/vm_object.h> 105 106 #include "fuse.h" 107 #include "fuse_file.h" 108 #include "fuse_internal.h" 109 #include "fuse_ipc.h" 110 #include "fuse_node.h" 111 #include "fuse_io.h" 112 113 #include <sys/priv.h> 114 115 /* Maximum number of hardlinks to a single FUSE file */ 116 #define FUSE_LINK_MAX UINT32_MAX 117 118 SDT_PROVIDER_DECLARE(fusefs); 119 /* 120 * Fuse trace probe: 121 * arg0: verbosity. Higher numbers give more verbose messages 122 * arg1: Textual message 123 */ 124 SDT_PROBE_DEFINE2(fusefs, , vnops, trace, "int", "char*"); 125 126 /* vnode ops */ 127 static vop_access_t fuse_vnop_access; 128 static vop_advlock_t fuse_vnop_advlock; 129 static vop_bmap_t fuse_vnop_bmap; 130 static vop_close_t fuse_fifo_close; 131 static vop_close_t fuse_vnop_close; 132 static vop_create_t fuse_vnop_create; 133 static vop_deleteextattr_t fuse_vnop_deleteextattr; 134 static vop_fdatasync_t fuse_vnop_fdatasync; 135 static vop_fsync_t fuse_vnop_fsync; 136 static vop_getattr_t fuse_vnop_getattr; 137 static vop_getextattr_t fuse_vnop_getextattr; 138 static vop_inactive_t fuse_vnop_inactive; 139 static vop_link_t fuse_vnop_link; 140 static vop_listextattr_t fuse_vnop_listextattr; 141 static vop_lookup_t fuse_vnop_lookup; 142 static vop_mkdir_t fuse_vnop_mkdir; 143 static vop_mknod_t fuse_vnop_mknod; 144 static vop_open_t fuse_vnop_open; 145 static vop_pathconf_t fuse_vnop_pathconf; 146 static vop_read_t fuse_vnop_read; 147 static vop_readdir_t fuse_vnop_readdir; 148 static vop_readlink_t fuse_vnop_readlink; 149 static vop_reclaim_t fuse_vnop_reclaim; 150 static vop_remove_t fuse_vnop_remove; 151 static vop_rename_t fuse_vnop_rename; 152 static vop_rmdir_t fuse_vnop_rmdir; 153 static vop_setattr_t fuse_vnop_setattr; 154 static vop_setextattr_t fuse_vnop_setextattr; 155 static vop_strategy_t fuse_vnop_strategy; 156 static vop_symlink_t fuse_vnop_symlink; 157 static vop_write_t fuse_vnop_write; 158 static vop_getpages_t fuse_vnop_getpages; 159 static vop_print_t fuse_vnop_print; 160 static vop_vptofh_t fuse_vnop_vptofh; 161 162 struct vop_vector fuse_fifoops = { 163 .vop_default = &fifo_specops, 164 .vop_access = fuse_vnop_access, 165 .vop_close = fuse_fifo_close, 166 .vop_fsync = fuse_vnop_fsync, 167 .vop_getattr = fuse_vnop_getattr, 168 .vop_inactive = fuse_vnop_inactive, 169 .vop_pathconf = fuse_vnop_pathconf, 170 .vop_print = fuse_vnop_print, 171 .vop_read = VOP_PANIC, 172 .vop_reclaim = fuse_vnop_reclaim, 173 .vop_setattr = fuse_vnop_setattr, 174 .vop_write = VOP_PANIC, 175 .vop_vptofh = fuse_vnop_vptofh, 176 }; 177 VFS_VOP_VECTOR_REGISTER(fuse_fifoops); 178 179 struct vop_vector fuse_vnops = { 180 .vop_allocate = VOP_EINVAL, 181 .vop_default = &default_vnodeops, 182 .vop_access = fuse_vnop_access, 183 .vop_advlock = fuse_vnop_advlock, 184 .vop_bmap = fuse_vnop_bmap, 185 .vop_close = fuse_vnop_close, 186 .vop_create = fuse_vnop_create, 187 .vop_deleteextattr = fuse_vnop_deleteextattr, 188 .vop_fsync = fuse_vnop_fsync, 189 .vop_fdatasync = fuse_vnop_fdatasync, 190 .vop_getattr = fuse_vnop_getattr, 191 .vop_getextattr = fuse_vnop_getextattr, 192 .vop_inactive = fuse_vnop_inactive, 193 /* 194 * TODO: implement vop_ioctl after upgrading to protocol 7.16. 195 * FUSE_IOCTL was added in 7.11, but 32-bit compat is broken until 196 * 7.16. 197 */ 198 .vop_link = fuse_vnop_link, 199 .vop_listextattr = fuse_vnop_listextattr, 200 .vop_lookup = fuse_vnop_lookup, 201 .vop_mkdir = fuse_vnop_mkdir, 202 .vop_mknod = fuse_vnop_mknod, 203 .vop_open = fuse_vnop_open, 204 .vop_pathconf = fuse_vnop_pathconf, 205 /* 206 * TODO: implement vop_poll after upgrading to protocol 7.21. 207 * FUSE_POLL was added in protocol 7.11, but it's kind of broken until 208 * 7.21, which adds the ability for the client to choose which poll 209 * events it wants, and for a client to deregister a file handle 210 */ 211 .vop_read = fuse_vnop_read, 212 .vop_readdir = fuse_vnop_readdir, 213 .vop_readlink = fuse_vnop_readlink, 214 .vop_reclaim = fuse_vnop_reclaim, 215 .vop_remove = fuse_vnop_remove, 216 .vop_rename = fuse_vnop_rename, 217 .vop_rmdir = fuse_vnop_rmdir, 218 .vop_setattr = fuse_vnop_setattr, 219 .vop_setextattr = fuse_vnop_setextattr, 220 .vop_strategy = fuse_vnop_strategy, 221 .vop_symlink = fuse_vnop_symlink, 222 .vop_write = fuse_vnop_write, 223 .vop_getpages = fuse_vnop_getpages, 224 .vop_print = fuse_vnop_print, 225 .vop_vptofh = fuse_vnop_vptofh, 226 }; 227 VFS_VOP_VECTOR_REGISTER(fuse_vnops); 228 229 uma_zone_t fuse_pbuf_zone; 230 231 /* Check permission for extattr operations, much like extattr_check_cred */ 232 static int 233 fuse_extattr_check_cred(struct vnode *vp, int ns, struct ucred *cred, 234 struct thread *td, accmode_t accmode) 235 { 236 struct mount *mp = vnode_mount(vp); 237 struct fuse_data *data = fuse_get_mpdata(mp); 238 239 /* 240 * Kernel-invoked always succeeds. 241 */ 242 if (cred == NOCRED) 243 return (0); 244 245 /* 246 * Do not allow privileged processes in jail to directly manipulate 247 * system attributes. 248 */ 249 switch (ns) { 250 case EXTATTR_NAMESPACE_SYSTEM: 251 if (data->dataflags & FSESS_DEFAULT_PERMISSIONS) { 252 return (priv_check_cred(cred, PRIV_VFS_EXTATTR_SYSTEM)); 253 } 254 /* FALLTHROUGH */ 255 case EXTATTR_NAMESPACE_USER: 256 return (fuse_internal_access(vp, accmode, td, cred)); 257 default: 258 return (EPERM); 259 } 260 } 261 262 /* Get a filehandle for a directory */ 263 static int 264 fuse_filehandle_get_dir(struct vnode *vp, struct fuse_filehandle **fufhp, 265 struct ucred *cred, pid_t pid) 266 { 267 if (fuse_filehandle_get(vp, FREAD, fufhp, cred, pid) == 0) 268 return 0; 269 return fuse_filehandle_get(vp, FEXEC, fufhp, cred, pid); 270 } 271 272 /* Send FUSE_FLUSH for this vnode */ 273 static int 274 fuse_flush(struct vnode *vp, struct ucred *cred, pid_t pid, int fflag) 275 { 276 struct fuse_flush_in *ffi; 277 struct fuse_filehandle *fufh; 278 struct fuse_dispatcher fdi; 279 struct thread *td = curthread; 280 struct mount *mp = vnode_mount(vp); 281 int err; 282 283 if (!fsess_isimpl(vnode_mount(vp), FUSE_FLUSH)) 284 return 0; 285 286 err = fuse_filehandle_getrw(vp, fflag, &fufh, cred, pid); 287 if (err) 288 return err; 289 290 fdisp_init(&fdi, sizeof(*ffi)); 291 fdisp_make_vp(&fdi, FUSE_FLUSH, vp, td, cred); 292 ffi = fdi.indata; 293 ffi->fh = fufh->fh_id; 294 /* 295 * If the file has a POSIX lock then we're supposed to set lock_owner. 296 * If not, then lock_owner is undefined. So we may as well always set 297 * it. 298 */ 299 ffi->lock_owner = td->td_proc->p_pid; 300 301 err = fdisp_wait_answ(&fdi); 302 if (err == ENOSYS) { 303 fsess_set_notimpl(mp, FUSE_FLUSH); 304 err = 0; 305 } 306 fdisp_destroy(&fdi); 307 return err; 308 } 309 310 /* Close wrapper for fifos. */ 311 static int 312 fuse_fifo_close(struct vop_close_args *ap) 313 { 314 return (fifo_specops.vop_close(ap)); 315 } 316 317 /* 318 struct vnop_access_args { 319 struct vnode *a_vp; 320 #if VOP_ACCESS_TAKES_ACCMODE_T 321 accmode_t a_accmode; 322 #else 323 int a_mode; 324 #endif 325 struct ucred *a_cred; 326 struct thread *a_td; 327 }; 328 */ 329 static int 330 fuse_vnop_access(struct vop_access_args *ap) 331 { 332 struct vnode *vp = ap->a_vp; 333 int accmode = ap->a_accmode; 334 struct ucred *cred = ap->a_cred; 335 336 struct fuse_data *data = fuse_get_mpdata(vnode_mount(vp)); 337 338 int err; 339 340 if (fuse_isdeadfs(vp)) { 341 if (vnode_isvroot(vp)) { 342 return 0; 343 } 344 return ENXIO; 345 } 346 if (!(data->dataflags & FSESS_INITED)) { 347 if (vnode_isvroot(vp)) { 348 if (priv_check_cred(cred, PRIV_VFS_ADMIN) || 349 (fuse_match_cred(data->daemoncred, cred) == 0)) { 350 return 0; 351 } 352 } 353 return EBADF; 354 } 355 if (vnode_islnk(vp)) { 356 return 0; 357 } 358 359 err = fuse_internal_access(vp, accmode, ap->a_td, ap->a_cred); 360 return err; 361 } 362 363 /* 364 * struct vop_advlock_args { 365 * struct vop_generic_args a_gen; 366 * struct vnode *a_vp; 367 * void *a_id; 368 * int a_op; 369 * struct flock *a_fl; 370 * int a_flags; 371 * } 372 */ 373 static int 374 fuse_vnop_advlock(struct vop_advlock_args *ap) 375 { 376 struct vnode *vp = ap->a_vp; 377 struct flock *fl = ap->a_fl; 378 struct thread *td = curthread; 379 struct ucred *cred = td->td_ucred; 380 pid_t pid = td->td_proc->p_pid; 381 struct fuse_filehandle *fufh; 382 struct fuse_dispatcher fdi; 383 struct fuse_lk_in *fli; 384 struct fuse_lk_out *flo; 385 enum fuse_opcode op; 386 int dataflags, err; 387 int flags = ap->a_flags; 388 389 dataflags = fuse_get_mpdata(vnode_mount(vp))->dataflags; 390 391 if (fuse_isdeadfs(vp)) { 392 return ENXIO; 393 } 394 395 if (!(dataflags & FSESS_POSIX_LOCKS)) 396 return vop_stdadvlock(ap); 397 /* FUSE doesn't properly support flock until protocol 7.17 */ 398 if (flags & F_FLOCK) 399 return vop_stdadvlock(ap); 400 401 err = fuse_filehandle_get_anyflags(vp, &fufh, cred, pid); 402 if (err) 403 return err; 404 405 fdisp_init(&fdi, sizeof(*fli)); 406 407 switch(ap->a_op) { 408 case F_GETLK: 409 op = FUSE_GETLK; 410 break; 411 case F_SETLK: 412 op = FUSE_SETLK; 413 break; 414 case F_SETLKW: 415 op = FUSE_SETLKW; 416 break; 417 default: 418 return EINVAL; 419 } 420 421 fdisp_make_vp(&fdi, op, vp, td, cred); 422 fli = fdi.indata; 423 fli->fh = fufh->fh_id; 424 fli->owner = fl->l_pid; 425 fli->lk.start = fl->l_start; 426 if (fl->l_len != 0) 427 fli->lk.end = fl->l_start + fl->l_len - 1; 428 else 429 fli->lk.end = INT64_MAX; 430 fli->lk.type = fl->l_type; 431 fli->lk.pid = fl->l_pid; 432 433 err = fdisp_wait_answ(&fdi); 434 fdisp_destroy(&fdi); 435 436 if (err == 0 && op == FUSE_GETLK) { 437 flo = fdi.answ; 438 fl->l_type = flo->lk.type; 439 fl->l_pid = flo->lk.pid; 440 if (flo->lk.type != F_UNLCK) { 441 fl->l_start = flo->lk.start; 442 if (flo->lk.end == INT64_MAX) 443 fl->l_len = 0; 444 else 445 fl->l_len = flo->lk.end - flo->lk.start + 1; 446 fl->l_start = flo->lk.start; 447 } 448 } 449 450 return err; 451 } 452 453 /* { 454 struct vnode *a_vp; 455 daddr_t a_bn; 456 struct bufobj **a_bop; 457 daddr_t *a_bnp; 458 int *a_runp; 459 int *a_runb; 460 } */ 461 static int 462 fuse_vnop_bmap(struct vop_bmap_args *ap) 463 { 464 struct vnode *vp = ap->a_vp; 465 struct bufobj **bo = ap->a_bop; 466 struct thread *td = curthread; 467 struct mount *mp; 468 struct fuse_dispatcher fdi; 469 struct fuse_bmap_in *fbi; 470 struct fuse_bmap_out *fbo; 471 struct fuse_data *data; 472 uint64_t biosize; 473 off_t filesize; 474 daddr_t lbn = ap->a_bn; 475 daddr_t *pbn = ap->a_bnp; 476 int *runp = ap->a_runp; 477 int *runb = ap->a_runb; 478 int error = 0; 479 int maxrun; 480 481 if (fuse_isdeadfs(vp)) { 482 return ENXIO; 483 } 484 485 mp = vnode_mount(vp); 486 data = fuse_get_mpdata(mp); 487 biosize = fuse_iosize(vp); 488 maxrun = MIN(vp->v_mount->mnt_iosize_max / biosize - 1, 489 data->max_readahead_blocks); 490 491 if (bo != NULL) 492 *bo = &vp->v_bufobj; 493 494 /* 495 * The FUSE_BMAP operation does not include the runp and runb 496 * variables, so we must guess. Report nonzero contiguous runs so 497 * cluster_read will combine adjacent reads. It's worthwhile to reduce 498 * upcalls even if we don't know the true physical layout of the file. 499 * 500 * FUSE file systems may opt out of read clustering in two ways: 501 * * mounting with -onoclusterr 502 * * Setting max_readahead <= maxbcachebuf during FUSE_INIT 503 */ 504 if (runb != NULL) 505 *runb = MIN(lbn, maxrun); 506 if (runp != NULL) { 507 error = fuse_vnode_size(vp, &filesize, td->td_ucred, td); 508 if (error == 0) 509 *runp = MIN(MAX(0, filesize / (off_t)biosize - lbn - 1), 510 maxrun); 511 else 512 *runp = 0; 513 } 514 515 if (fsess_isimpl(mp, FUSE_BMAP)) { 516 fdisp_init(&fdi, sizeof(*fbi)); 517 fdisp_make_vp(&fdi, FUSE_BMAP, vp, td, td->td_ucred); 518 fbi = fdi.indata; 519 fbi->block = lbn; 520 fbi->blocksize = biosize; 521 error = fdisp_wait_answ(&fdi); 522 if (error == ENOSYS) { 523 fdisp_destroy(&fdi); 524 fsess_set_notimpl(mp, FUSE_BMAP); 525 error = 0; 526 } else { 527 fbo = fdi.answ; 528 if (error == 0 && pbn != NULL) 529 *pbn = fbo->block; 530 fdisp_destroy(&fdi); 531 return error; 532 } 533 } 534 535 /* If the daemon doesn't support BMAP, make up a sensible default */ 536 if (pbn != NULL) 537 *pbn = lbn * btodb(biosize); 538 return (error); 539 } 540 541 /* 542 struct vop_close_args { 543 struct vnode *a_vp; 544 int a_fflag; 545 struct ucred *a_cred; 546 struct thread *a_td; 547 }; 548 */ 549 static int 550 fuse_vnop_close(struct vop_close_args *ap) 551 { 552 struct vnode *vp = ap->a_vp; 553 struct ucred *cred = ap->a_cred; 554 int fflag = ap->a_fflag; 555 struct thread *td = ap->a_td; 556 pid_t pid = td->td_proc->p_pid; 557 int err = 0; 558 559 if (fuse_isdeadfs(vp)) 560 return 0; 561 if (vnode_isdir(vp)) 562 return 0; 563 if (fflag & IO_NDELAY) 564 return 0; 565 566 err = fuse_flush(vp, cred, pid, fflag); 567 /* TODO: close the file handle, if we're sure it's no longer used */ 568 if ((VTOFUD(vp)->flag & FN_SIZECHANGE) != 0) { 569 fuse_vnode_savesize(vp, cred, td->td_proc->p_pid); 570 } 571 return err; 572 } 573 574 static void 575 fdisp_make_mknod_for_fallback( 576 struct fuse_dispatcher *fdip, 577 struct componentname *cnp, 578 struct vnode *dvp, 579 uint64_t parentnid, 580 struct thread *td, 581 struct ucred *cred, 582 mode_t mode, 583 enum fuse_opcode *op) 584 { 585 struct fuse_mknod_in *fmni; 586 587 fdisp_init(fdip, sizeof(*fmni) + cnp->cn_namelen + 1); 588 *op = FUSE_MKNOD; 589 fdisp_make(fdip, *op, vnode_mount(dvp), parentnid, td, cred); 590 fmni = fdip->indata; 591 fmni->mode = mode; 592 fmni->rdev = 0; 593 memcpy((char *)fdip->indata + sizeof(*fmni), cnp->cn_nameptr, 594 cnp->cn_namelen); 595 ((char *)fdip->indata)[sizeof(*fmni) + cnp->cn_namelen] = '\0'; 596 } 597 /* 598 struct vnop_create_args { 599 struct vnode *a_dvp; 600 struct vnode **a_vpp; 601 struct componentname *a_cnp; 602 struct vattr *a_vap; 603 }; 604 */ 605 static int 606 fuse_vnop_create(struct vop_create_args *ap) 607 { 608 struct vnode *dvp = ap->a_dvp; 609 struct vnode **vpp = ap->a_vpp; 610 struct componentname *cnp = ap->a_cnp; 611 struct vattr *vap = ap->a_vap; 612 struct thread *td = cnp->cn_thread; 613 struct ucred *cred = cnp->cn_cred; 614 615 struct fuse_data *data; 616 struct fuse_create_in *fci; 617 struct fuse_entry_out *feo; 618 struct fuse_open_out *foo; 619 struct fuse_dispatcher fdi, fdi2; 620 struct fuse_dispatcher *fdip = &fdi; 621 struct fuse_dispatcher *fdip2 = NULL; 622 623 int err; 624 625 struct mount *mp = vnode_mount(dvp); 626 data = fuse_get_mpdata(mp); 627 uint64_t parentnid = VTOFUD(dvp)->nid; 628 mode_t mode = MAKEIMODE(vap->va_type, vap->va_mode); 629 enum fuse_opcode op; 630 int flags; 631 632 if (fuse_isdeadfs(dvp)) 633 return ENXIO; 634 635 /* FUSE expects sockets to be created with FUSE_MKNOD */ 636 if (vap->va_type == VSOCK) 637 return fuse_internal_mknod(dvp, vpp, cnp, vap); 638 639 /* 640 * VOP_CREATE doesn't tell us the open(2) flags, so we guess. Only a 641 * writable mode makes sense, and we might as well include readability 642 * too. 643 */ 644 flags = O_RDWR; 645 646 bzero(&fdi, sizeof(fdi)); 647 648 if (vap->va_type != VREG) 649 return (EINVAL); 650 651 if (!fsess_isimpl(mp, FUSE_CREATE) || vap->va_type == VSOCK) { 652 /* Fallback to FUSE_MKNOD/FUSE_OPEN */ 653 fdisp_make_mknod_for_fallback(fdip, cnp, dvp, parentnid, td, 654 cred, mode, &op); 655 } else { 656 /* Use FUSE_CREATE */ 657 size_t insize; 658 659 op = FUSE_CREATE; 660 fdisp_init(fdip, sizeof(*fci) + cnp->cn_namelen + 1); 661 fdisp_make(fdip, op, vnode_mount(dvp), parentnid, td, cred); 662 fci = fdip->indata; 663 fci->mode = mode; 664 fci->flags = O_CREAT | flags; 665 if (fuse_libabi_geq(data, 7, 12)) { 666 insize = sizeof(*fci); 667 fci->umask = td->td_proc->p_fd->fd_cmask; 668 } else { 669 insize = sizeof(struct fuse_open_in); 670 } 671 672 memcpy((char *)fdip->indata + insize, cnp->cn_nameptr, 673 cnp->cn_namelen); 674 ((char *)fdip->indata)[insize + cnp->cn_namelen] = '\0'; 675 } 676 677 err = fdisp_wait_answ(fdip); 678 679 if (err) { 680 if (err == ENOSYS && op == FUSE_CREATE) { 681 fsess_set_notimpl(mp, FUSE_CREATE); 682 fdisp_destroy(fdip); 683 fdisp_make_mknod_for_fallback(fdip, cnp, dvp, 684 parentnid, td, cred, mode, &op); 685 err = fdisp_wait_answ(fdip); 686 } 687 if (err) 688 goto out; 689 } 690 691 feo = fdip->answ; 692 693 if ((err = fuse_internal_checkentry(feo, vap->va_type))) { 694 goto out; 695 } 696 697 if (op == FUSE_CREATE) { 698 foo = (struct fuse_open_out*)(feo + 1); 699 } else { 700 /* Issue a separate FUSE_OPEN */ 701 struct fuse_open_in *foi; 702 703 fdip2 = &fdi2; 704 fdisp_init(fdip2, sizeof(*foi)); 705 fdisp_make(fdip2, FUSE_OPEN, vnode_mount(dvp), feo->nodeid, td, 706 cred); 707 foi = fdip2->indata; 708 foi->flags = flags; 709 err = fdisp_wait_answ(fdip2); 710 if (err) 711 goto out; 712 foo = fdip2->answ; 713 } 714 err = fuse_vnode_get(mp, feo, feo->nodeid, dvp, vpp, cnp, vap->va_type); 715 if (err) { 716 struct fuse_release_in *fri; 717 uint64_t nodeid = feo->nodeid; 718 uint64_t fh_id = foo->fh; 719 720 fdisp_init(fdip, sizeof(*fri)); 721 fdisp_make(fdip, FUSE_RELEASE, mp, nodeid, td, cred); 722 fri = fdip->indata; 723 fri->fh = fh_id; 724 fri->flags = flags; 725 fuse_insert_callback(fdip->tick, fuse_internal_forget_callback); 726 fuse_insert_message(fdip->tick, false); 727 goto out; 728 } 729 ASSERT_VOP_ELOCKED(*vpp, "fuse_vnop_create"); 730 fuse_internal_cache_attrs(*vpp, &feo->attr, feo->attr_valid, 731 feo->attr_valid_nsec, NULL); 732 733 fuse_filehandle_init(*vpp, FUFH_RDWR, NULL, td, cred, foo); 734 fuse_vnode_open(*vpp, foo->open_flags, td); 735 /* 736 * Purge the parent's attribute cache because the daemon should've 737 * updated its mtime and ctime 738 */ 739 fuse_vnode_clear_attr_cache(dvp); 740 cache_purge_negative(dvp); 741 742 out: 743 if (fdip2) 744 fdisp_destroy(fdip2); 745 fdisp_destroy(fdip); 746 return err; 747 } 748 749 /* 750 struct vnop_fdatasync_args { 751 struct vop_generic_args a_gen; 752 struct vnode * a_vp; 753 struct thread * a_td; 754 }; 755 */ 756 static int 757 fuse_vnop_fdatasync(struct vop_fdatasync_args *ap) 758 { 759 struct vnode *vp = ap->a_vp; 760 struct thread *td = ap->a_td; 761 int waitfor = MNT_WAIT; 762 763 int err = 0; 764 765 if (fuse_isdeadfs(vp)) { 766 return 0; 767 } 768 if ((err = vop_stdfdatasync_buf(ap))) 769 return err; 770 771 return fuse_internal_fsync(vp, td, waitfor, true); 772 } 773 774 /* 775 struct vnop_fsync_args { 776 struct vop_generic_args a_gen; 777 struct vnode * a_vp; 778 int a_waitfor; 779 struct thread * a_td; 780 }; 781 */ 782 static int 783 fuse_vnop_fsync(struct vop_fsync_args *ap) 784 { 785 struct vnode *vp = ap->a_vp; 786 struct thread *td = ap->a_td; 787 int waitfor = ap->a_waitfor; 788 int err = 0; 789 790 if (fuse_isdeadfs(vp)) { 791 return 0; 792 } 793 if ((err = vop_stdfsync(ap))) 794 return err; 795 796 return fuse_internal_fsync(vp, td, waitfor, false); 797 } 798 799 /* 800 struct vnop_getattr_args { 801 struct vnode *a_vp; 802 struct vattr *a_vap; 803 struct ucred *a_cred; 804 struct thread *a_td; 805 }; 806 */ 807 static int 808 fuse_vnop_getattr(struct vop_getattr_args *ap) 809 { 810 struct vnode *vp = ap->a_vp; 811 struct vattr *vap = ap->a_vap; 812 struct ucred *cred = ap->a_cred; 813 struct thread *td = curthread; 814 815 int err = 0; 816 int dataflags; 817 818 dataflags = fuse_get_mpdata(vnode_mount(vp))->dataflags; 819 820 /* Note that we are not bailing out on a dead file system just yet. */ 821 822 if (!(dataflags & FSESS_INITED)) { 823 if (!vnode_isvroot(vp)) { 824 fdata_set_dead(fuse_get_mpdata(vnode_mount(vp))); 825 err = ENOTCONN; 826 return err; 827 } else { 828 goto fake; 829 } 830 } 831 err = fuse_internal_getattr(vp, vap, cred, td); 832 if (err == ENOTCONN && vnode_isvroot(vp)) { 833 /* see comment in fuse_vfsop_statfs() */ 834 goto fake; 835 } else { 836 return err; 837 } 838 839 fake: 840 bzero(vap, sizeof(*vap)); 841 vap->va_type = vnode_vtype(vp); 842 843 return 0; 844 } 845 846 /* 847 struct vnop_inactive_args { 848 struct vnode *a_vp; 849 struct thread *a_td; 850 }; 851 */ 852 static int 853 fuse_vnop_inactive(struct vop_inactive_args *ap) 854 { 855 struct vnode *vp = ap->a_vp; 856 struct thread *td = ap->a_td; 857 858 struct fuse_vnode_data *fvdat = VTOFUD(vp); 859 struct fuse_filehandle *fufh, *fufh_tmp; 860 861 int need_flush = 1; 862 863 LIST_FOREACH_SAFE(fufh, &fvdat->handles, next, fufh_tmp) { 864 if (need_flush && vp->v_type == VREG) { 865 if ((VTOFUD(vp)->flag & FN_SIZECHANGE) != 0) { 866 fuse_vnode_savesize(vp, NULL, 0); 867 } 868 if ((fvdat->flag & FN_REVOKED) != 0) 869 fuse_io_invalbuf(vp, td); 870 else 871 fuse_io_flushbuf(vp, MNT_WAIT, td); 872 need_flush = 0; 873 } 874 fuse_filehandle_close(vp, fufh, td, NULL); 875 } 876 877 if ((fvdat->flag & FN_REVOKED) != 0) 878 vrecycle(vp); 879 880 return 0; 881 } 882 883 /* 884 struct vnop_link_args { 885 struct vnode *a_tdvp; 886 struct vnode *a_vp; 887 struct componentname *a_cnp; 888 }; 889 */ 890 static int 891 fuse_vnop_link(struct vop_link_args *ap) 892 { 893 struct vnode *vp = ap->a_vp; 894 struct vnode *tdvp = ap->a_tdvp; 895 struct componentname *cnp = ap->a_cnp; 896 897 struct vattr *vap = VTOVA(vp); 898 899 struct fuse_dispatcher fdi; 900 struct fuse_entry_out *feo; 901 struct fuse_link_in fli; 902 903 int err; 904 905 if (fuse_isdeadfs(vp)) { 906 return ENXIO; 907 } 908 if (vnode_mount(tdvp) != vnode_mount(vp)) { 909 return EXDEV; 910 } 911 912 /* 913 * This is a seatbelt check to protect naive userspace filesystems from 914 * themselves and the limitations of the FUSE IPC protocol. If a 915 * filesystem does not allow attribute caching, assume it is capable of 916 * validating that nlink does not overflow. 917 */ 918 if (vap != NULL && vap->va_nlink >= FUSE_LINK_MAX) 919 return EMLINK; 920 fli.oldnodeid = VTOI(vp); 921 922 fdisp_init(&fdi, 0); 923 fuse_internal_newentry_makerequest(vnode_mount(tdvp), VTOI(tdvp), cnp, 924 FUSE_LINK, &fli, sizeof(fli), &fdi); 925 if ((err = fdisp_wait_answ(&fdi))) { 926 goto out; 927 } 928 feo = fdi.answ; 929 930 err = fuse_internal_checkentry(feo, vnode_vtype(vp)); 931 if (!err) { 932 /* 933 * Purge the parent's attribute cache because the daemon 934 * should've updated its mtime and ctime 935 */ 936 fuse_vnode_clear_attr_cache(tdvp); 937 fuse_internal_cache_attrs(vp, &feo->attr, feo->attr_valid, 938 feo->attr_valid_nsec, NULL); 939 } 940 out: 941 fdisp_destroy(&fdi); 942 return err; 943 } 944 945 struct fuse_lookup_alloc_arg { 946 struct fuse_entry_out *feo; 947 struct componentname *cnp; 948 uint64_t nid; 949 enum vtype vtyp; 950 }; 951 952 /* Callback for vn_get_ino */ 953 static int 954 fuse_lookup_alloc(struct mount *mp, void *arg, int lkflags, struct vnode **vpp) 955 { 956 struct fuse_lookup_alloc_arg *flaa = arg; 957 958 return fuse_vnode_get(mp, flaa->feo, flaa->nid, NULL, vpp, flaa->cnp, 959 flaa->vtyp); 960 } 961 962 SDT_PROBE_DEFINE3(fusefs, , vnops, cache_lookup, 963 "int", "struct timespec*", "struct timespec*"); 964 /* 965 struct vnop_lookup_args { 966 struct vnodeop_desc *a_desc; 967 struct vnode *a_dvp; 968 struct vnode **a_vpp; 969 struct componentname *a_cnp; 970 }; 971 */ 972 int 973 fuse_vnop_lookup(struct vop_lookup_args *ap) 974 { 975 struct vnode *dvp = ap->a_dvp; 976 struct vnode **vpp = ap->a_vpp; 977 struct componentname *cnp = ap->a_cnp; 978 struct thread *td = cnp->cn_thread; 979 struct ucred *cred = cnp->cn_cred; 980 981 int nameiop = cnp->cn_nameiop; 982 int flags = cnp->cn_flags; 983 int wantparent = flags & (LOCKPARENT | WANTPARENT); 984 int islastcn = flags & ISLASTCN; 985 struct mount *mp = vnode_mount(dvp); 986 987 int err = 0; 988 int lookup_err = 0; 989 struct vnode *vp = NULL; 990 991 struct fuse_dispatcher fdi; 992 bool did_lookup = false; 993 struct fuse_entry_out *feo = NULL; 994 enum vtype vtyp; /* vnode type of target */ 995 off_t filesize; /* filesize of target */ 996 997 uint64_t nid; 998 999 if (fuse_isdeadfs(dvp)) { 1000 *vpp = NULL; 1001 return ENXIO; 1002 } 1003 if (!vnode_isdir(dvp)) 1004 return ENOTDIR; 1005 1006 if (islastcn && vfs_isrdonly(mp) && (nameiop != LOOKUP)) 1007 return EROFS; 1008 1009 if ((cnp->cn_flags & NOEXECCHECK) != 0) 1010 cnp->cn_flags &= ~NOEXECCHECK; 1011 else if ((err = fuse_internal_access(dvp, VEXEC, td, cred))) 1012 return err; 1013 1014 if (flags & ISDOTDOT) { 1015 KASSERT(VTOFUD(dvp)->flag & FN_PARENT_NID, 1016 ("Looking up .. is TODO")); 1017 nid = VTOFUD(dvp)->parent_nid; 1018 if (nid == 0) 1019 return ENOENT; 1020 /* .. is obviously a directory */ 1021 vtyp = VDIR; 1022 filesize = 0; 1023 } else if (cnp->cn_namelen == 1 && *(cnp->cn_nameptr) == '.') { 1024 nid = VTOI(dvp); 1025 /* . is obviously a directory */ 1026 vtyp = VDIR; 1027 filesize = 0; 1028 } else { 1029 struct timespec now, timeout; 1030 1031 err = cache_lookup(dvp, vpp, cnp, &timeout, NULL); 1032 getnanouptime(&now); 1033 SDT_PROBE3(fusefs, , vnops, cache_lookup, err, &timeout, &now); 1034 switch (err) { 1035 case -1: /* positive match */ 1036 if (timespeccmp(&timeout, &now, >)) { 1037 counter_u64_add(fuse_lookup_cache_hits, 1); 1038 } else { 1039 /* Cache timeout */ 1040 counter_u64_add(fuse_lookup_cache_misses, 1); 1041 bintime_clear( 1042 &VTOFUD(*vpp)->entry_cache_timeout); 1043 cache_purge(*vpp); 1044 if (dvp != *vpp) 1045 vput(*vpp); 1046 else 1047 vrele(*vpp); 1048 *vpp = NULL; 1049 break; 1050 } 1051 return 0; 1052 1053 case 0: /* no match in cache */ 1054 counter_u64_add(fuse_lookup_cache_misses, 1); 1055 break; 1056 1057 case ENOENT: /* negative match */ 1058 getnanouptime(&now); 1059 if (timespeccmp(&timeout, &now, <=)) { 1060 /* Cache timeout */ 1061 cache_purge_negative(dvp); 1062 break; 1063 } 1064 /* fall through */ 1065 default: 1066 return err; 1067 } 1068 1069 nid = VTOI(dvp); 1070 fdisp_init(&fdi, cnp->cn_namelen + 1); 1071 fdisp_make(&fdi, FUSE_LOOKUP, mp, nid, td, cred); 1072 1073 memcpy(fdi.indata, cnp->cn_nameptr, cnp->cn_namelen); 1074 ((char *)fdi.indata)[cnp->cn_namelen] = '\0'; 1075 lookup_err = fdisp_wait_answ(&fdi); 1076 did_lookup = true; 1077 1078 if (!lookup_err) { 1079 /* lookup call succeeded */ 1080 feo = (struct fuse_entry_out *)fdi.answ; 1081 nid = feo->nodeid; 1082 if (nid == 0) { 1083 /* zero nodeid means ENOENT and cache it */ 1084 struct timespec timeout; 1085 1086 fdi.answ_stat = ENOENT; 1087 lookup_err = ENOENT; 1088 if (cnp->cn_flags & MAKEENTRY) { 1089 fuse_validity_2_timespec(feo, &timeout); 1090 cache_enter_time(dvp, *vpp, cnp, 1091 &timeout, NULL); 1092 } 1093 } else if (nid == FUSE_ROOT_ID) { 1094 lookup_err = EINVAL; 1095 } 1096 vtyp = IFTOVT(feo->attr.mode); 1097 filesize = feo->attr.size; 1098 } 1099 if (lookup_err && (!fdi.answ_stat || lookup_err != ENOENT)) { 1100 fdisp_destroy(&fdi); 1101 return lookup_err; 1102 } 1103 } 1104 /* lookup_err, if non-zero, must be ENOENT at this point */ 1105 1106 if (lookup_err) { 1107 /* Entry not found */ 1108 if ((nameiop == CREATE || nameiop == RENAME) && islastcn) { 1109 err = fuse_internal_access(dvp, VWRITE, td, cred); 1110 if (!err) { 1111 /* 1112 * Set the SAVENAME flag to hold onto the 1113 * pathname for use later in VOP_CREATE or 1114 * VOP_RENAME. 1115 */ 1116 cnp->cn_flags |= SAVENAME; 1117 1118 err = EJUSTRETURN; 1119 } 1120 } else { 1121 err = ENOENT; 1122 } 1123 } else { 1124 /* Entry was found */ 1125 if (flags & ISDOTDOT) { 1126 struct fuse_lookup_alloc_arg flaa; 1127 1128 flaa.nid = nid; 1129 flaa.feo = feo; 1130 flaa.cnp = cnp; 1131 flaa.vtyp = vtyp; 1132 err = vn_vget_ino_gen(dvp, fuse_lookup_alloc, &flaa, 0, 1133 &vp); 1134 *vpp = vp; 1135 } else if (nid == VTOI(dvp)) { 1136 vref(dvp); 1137 *vpp = dvp; 1138 } else { 1139 struct fuse_vnode_data *fvdat; 1140 1141 err = fuse_vnode_get(vnode_mount(dvp), feo, nid, dvp, 1142 &vp, cnp, vtyp); 1143 if (err) 1144 goto out; 1145 *vpp = vp; 1146 1147 /* 1148 * In the case where we are looking up a FUSE node 1149 * represented by an existing cached vnode, and the 1150 * true size reported by FUSE_LOOKUP doesn't match 1151 * the vnode's cached size, then any cached writes 1152 * beyond the file's current size are lost. 1153 * 1154 * We can get here: 1155 * * following attribute cache expiration, or 1156 * * due a bug in the daemon, or 1157 */ 1158 fvdat = VTOFUD(vp); 1159 if (vnode_isreg(vp) && 1160 filesize != fvdat->cached_attrs.va_size && 1161 fvdat->flag & FN_SIZECHANGE) { 1162 /* 1163 * The FN_SIZECHANGE flag reflects a dirty 1164 * append. If userspace lets us know our cache 1165 * is invalid, that write was lost. (Dirty 1166 * writes that do not cause append are also 1167 * lost, but we don't detect them here.) 1168 * 1169 * XXX: Maybe disable WB caching on this mount. 1170 */ 1171 printf("%s: WB cache incoherent on %s!\n", 1172 __func__, 1173 vnode_mount(vp)->mnt_stat.f_mntonname); 1174 1175 fvdat->flag &= ~FN_SIZECHANGE; 1176 } 1177 1178 MPASS(feo != NULL); 1179 fuse_internal_cache_attrs(*vpp, &feo->attr, 1180 feo->attr_valid, feo->attr_valid_nsec, NULL); 1181 fuse_validity_2_bintime(feo->entry_valid, 1182 feo->entry_valid_nsec, 1183 &fvdat->entry_cache_timeout); 1184 1185 if ((nameiop == DELETE || nameiop == RENAME) && 1186 islastcn) 1187 { 1188 struct vattr dvattr; 1189 1190 err = fuse_internal_access(dvp, VWRITE, td, 1191 cred); 1192 if (err != 0) 1193 goto out; 1194 /* 1195 * if the parent's sticky bit is set, check 1196 * whether we're allowed to remove the file. 1197 * Need to figure out the vnode locking to make 1198 * this work. 1199 */ 1200 fuse_internal_getattr(dvp, &dvattr, cred, td); 1201 if ((dvattr.va_mode & S_ISTXT) && 1202 fuse_internal_access(dvp, VADMIN, td, 1203 cred) && 1204 fuse_internal_access(*vpp, VADMIN, td, 1205 cred)) { 1206 err = EPERM; 1207 goto out; 1208 } 1209 } 1210 1211 if (islastcn && ( 1212 (nameiop == DELETE) || 1213 (nameiop == RENAME && wantparent))) { 1214 cnp->cn_flags |= SAVENAME; 1215 } 1216 1217 } 1218 } 1219 out: 1220 if (err) { 1221 if (vp != NULL && dvp != vp) 1222 vput(vp); 1223 else if (vp != NULL) 1224 vrele(vp); 1225 *vpp = NULL; 1226 } 1227 if (did_lookup) 1228 fdisp_destroy(&fdi); 1229 1230 return err; 1231 } 1232 1233 /* 1234 struct vnop_mkdir_args { 1235 struct vnode *a_dvp; 1236 struct vnode **a_vpp; 1237 struct componentname *a_cnp; 1238 struct vattr *a_vap; 1239 }; 1240 */ 1241 static int 1242 fuse_vnop_mkdir(struct vop_mkdir_args *ap) 1243 { 1244 struct vnode *dvp = ap->a_dvp; 1245 struct vnode **vpp = ap->a_vpp; 1246 struct componentname *cnp = ap->a_cnp; 1247 struct vattr *vap = ap->a_vap; 1248 1249 struct fuse_mkdir_in fmdi; 1250 1251 if (fuse_isdeadfs(dvp)) { 1252 return ENXIO; 1253 } 1254 fmdi.mode = MAKEIMODE(vap->va_type, vap->va_mode); 1255 fmdi.umask = curthread->td_proc->p_fd->fd_cmask; 1256 1257 return (fuse_internal_newentry(dvp, vpp, cnp, FUSE_MKDIR, &fmdi, 1258 sizeof(fmdi), VDIR)); 1259 } 1260 1261 /* 1262 struct vnop_mknod_args { 1263 struct vnode *a_dvp; 1264 struct vnode **a_vpp; 1265 struct componentname *a_cnp; 1266 struct vattr *a_vap; 1267 }; 1268 */ 1269 static int 1270 fuse_vnop_mknod(struct vop_mknod_args *ap) 1271 { 1272 1273 struct vnode *dvp = ap->a_dvp; 1274 struct vnode **vpp = ap->a_vpp; 1275 struct componentname *cnp = ap->a_cnp; 1276 struct vattr *vap = ap->a_vap; 1277 1278 if (fuse_isdeadfs(dvp)) 1279 return ENXIO; 1280 1281 return fuse_internal_mknod(dvp, vpp, cnp, vap); 1282 } 1283 1284 /* 1285 struct vop_open_args { 1286 struct vnode *a_vp; 1287 int a_mode; 1288 struct ucred *a_cred; 1289 struct thread *a_td; 1290 int a_fdidx; / struct file *a_fp; 1291 }; 1292 */ 1293 static int 1294 fuse_vnop_open(struct vop_open_args *ap) 1295 { 1296 struct vnode *vp = ap->a_vp; 1297 int a_mode = ap->a_mode; 1298 struct thread *td = ap->a_td; 1299 struct ucred *cred = ap->a_cred; 1300 pid_t pid = td->td_proc->p_pid; 1301 struct fuse_vnode_data *fvdat; 1302 1303 if (fuse_isdeadfs(vp)) 1304 return ENXIO; 1305 if (vp->v_type == VCHR || vp->v_type == VBLK || vp->v_type == VFIFO) 1306 return (EOPNOTSUPP); 1307 if ((a_mode & (FREAD | FWRITE | FEXEC)) == 0) 1308 return EINVAL; 1309 1310 fvdat = VTOFUD(vp); 1311 1312 if (fuse_filehandle_validrw(vp, a_mode, cred, pid)) { 1313 fuse_vnode_open(vp, 0, td); 1314 return 0; 1315 } 1316 1317 return fuse_filehandle_open(vp, a_mode, NULL, td, cred); 1318 } 1319 1320 static int 1321 fuse_vnop_pathconf(struct vop_pathconf_args *ap) 1322 { 1323 1324 switch (ap->a_name) { 1325 case _PC_FILESIZEBITS: 1326 *ap->a_retval = 64; 1327 return (0); 1328 case _PC_NAME_MAX: 1329 *ap->a_retval = NAME_MAX; 1330 return (0); 1331 case _PC_LINK_MAX: 1332 *ap->a_retval = MIN(LONG_MAX, FUSE_LINK_MAX); 1333 return (0); 1334 case _PC_SYMLINK_MAX: 1335 *ap->a_retval = MAXPATHLEN; 1336 return (0); 1337 case _PC_NO_TRUNC: 1338 *ap->a_retval = 1; 1339 return (0); 1340 default: 1341 return (vop_stdpathconf(ap)); 1342 } 1343 } 1344 1345 /* 1346 struct vnop_read_args { 1347 struct vnode *a_vp; 1348 struct uio *a_uio; 1349 int a_ioflag; 1350 struct ucred *a_cred; 1351 }; 1352 */ 1353 static int 1354 fuse_vnop_read(struct vop_read_args *ap) 1355 { 1356 struct vnode *vp = ap->a_vp; 1357 struct uio *uio = ap->a_uio; 1358 int ioflag = ap->a_ioflag; 1359 struct ucred *cred = ap->a_cred; 1360 pid_t pid = curthread->td_proc->p_pid; 1361 1362 if (fuse_isdeadfs(vp)) { 1363 return ENXIO; 1364 } 1365 1366 if (VTOFUD(vp)->flag & FN_DIRECTIO) { 1367 ioflag |= IO_DIRECT; 1368 } 1369 1370 return fuse_io_dispatch(vp, uio, ioflag, cred, pid); 1371 } 1372 1373 /* 1374 struct vnop_readdir_args { 1375 struct vnode *a_vp; 1376 struct uio *a_uio; 1377 struct ucred *a_cred; 1378 int *a_eofflag; 1379 int *a_ncookies; 1380 u_long **a_cookies; 1381 }; 1382 */ 1383 static int 1384 fuse_vnop_readdir(struct vop_readdir_args *ap) 1385 { 1386 struct vnode *vp = ap->a_vp; 1387 struct uio *uio = ap->a_uio; 1388 struct ucred *cred = ap->a_cred; 1389 struct fuse_filehandle *fufh = NULL; 1390 struct fuse_iov cookediov; 1391 int err = 0; 1392 u_long *cookies; 1393 off_t startoff; 1394 ssize_t tresid; 1395 int ncookies; 1396 bool closefufh = false; 1397 pid_t pid = curthread->td_proc->p_pid; 1398 1399 if (ap->a_eofflag) 1400 *ap->a_eofflag = 0; 1401 if (fuse_isdeadfs(vp)) { 1402 return ENXIO; 1403 } 1404 if ( /* XXXIP ((uio_iovcnt(uio) > 1)) || */ 1405 (uio_resid(uio) < sizeof(struct dirent))) { 1406 return EINVAL; 1407 } 1408 1409 tresid = uio->uio_resid; 1410 startoff = uio->uio_offset; 1411 err = fuse_filehandle_get_dir(vp, &fufh, cred, pid); 1412 if (err == EBADF && vnode_mount(vp)->mnt_flag & MNT_EXPORTED) { 1413 /* 1414 * nfsd will do VOP_READDIR without first doing VOP_OPEN. We 1415 * must implicitly open the directory here 1416 */ 1417 err = fuse_filehandle_open(vp, FREAD, &fufh, curthread, cred); 1418 if (err == 0) { 1419 /* 1420 * When a directory is opened, it must be read from 1421 * the beginning. Hopefully, the "startoff" still 1422 * exists as an offset cookie for the directory. 1423 * If not, it will read the entire directory without 1424 * returning any entries and just return eof. 1425 */ 1426 uio->uio_offset = 0; 1427 } 1428 closefufh = true; 1429 } 1430 if (err) 1431 return (err); 1432 if (ap->a_ncookies != NULL) { 1433 ncookies = uio->uio_resid / 1434 (offsetof(struct dirent, d_name) + 4) + 1; 1435 cookies = malloc(ncookies * sizeof(*cookies), M_TEMP, M_WAITOK); 1436 *ap->a_ncookies = ncookies; 1437 *ap->a_cookies = cookies; 1438 } else { 1439 ncookies = 0; 1440 cookies = NULL; 1441 } 1442 #define DIRCOOKEDSIZE FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + MAXNAMLEN + 1) 1443 fiov_init(&cookediov, DIRCOOKEDSIZE); 1444 1445 err = fuse_internal_readdir(vp, uio, startoff, fufh, &cookediov, 1446 &ncookies, cookies); 1447 1448 fiov_teardown(&cookediov); 1449 if (closefufh) 1450 fuse_filehandle_close(vp, fufh, curthread, cred); 1451 1452 if (ap->a_ncookies != NULL) { 1453 if (err == 0) { 1454 *ap->a_ncookies -= ncookies; 1455 } else { 1456 free(*ap->a_cookies, M_TEMP); 1457 *ap->a_ncookies = 0; 1458 *ap->a_cookies = NULL; 1459 } 1460 } 1461 if (err == 0 && tresid == uio->uio_resid) 1462 *ap->a_eofflag = 1; 1463 1464 return err; 1465 } 1466 1467 /* 1468 struct vnop_readlink_args { 1469 struct vnode *a_vp; 1470 struct uio *a_uio; 1471 struct ucred *a_cred; 1472 }; 1473 */ 1474 static int 1475 fuse_vnop_readlink(struct vop_readlink_args *ap) 1476 { 1477 struct vnode *vp = ap->a_vp; 1478 struct uio *uio = ap->a_uio; 1479 struct ucred *cred = ap->a_cred; 1480 1481 struct fuse_dispatcher fdi; 1482 int err; 1483 1484 if (fuse_isdeadfs(vp)) { 1485 return ENXIO; 1486 } 1487 if (!vnode_islnk(vp)) { 1488 return EINVAL; 1489 } 1490 fdisp_init(&fdi, 0); 1491 err = fdisp_simple_putget_vp(&fdi, FUSE_READLINK, vp, curthread, cred); 1492 if (err) { 1493 goto out; 1494 } 1495 if (((char *)fdi.answ)[0] == '/' && 1496 fuse_get_mpdata(vnode_mount(vp))->dataflags & FSESS_PUSH_SYMLINKS_IN) { 1497 char *mpth = vnode_mount(vp)->mnt_stat.f_mntonname; 1498 1499 err = uiomove(mpth, strlen(mpth), uio); 1500 } 1501 if (!err) { 1502 err = uiomove(fdi.answ, fdi.iosize, uio); 1503 } 1504 out: 1505 fdisp_destroy(&fdi); 1506 return err; 1507 } 1508 1509 /* 1510 struct vnop_reclaim_args { 1511 struct vnode *a_vp; 1512 struct thread *a_td; 1513 }; 1514 */ 1515 static int 1516 fuse_vnop_reclaim(struct vop_reclaim_args *ap) 1517 { 1518 struct vnode *vp = ap->a_vp; 1519 struct thread *td = ap->a_td; 1520 struct fuse_vnode_data *fvdat = VTOFUD(vp); 1521 struct fuse_filehandle *fufh, *fufh_tmp; 1522 1523 if (!fvdat) { 1524 panic("FUSE: no vnode data during recycling"); 1525 } 1526 LIST_FOREACH_SAFE(fufh, &fvdat->handles, next, fufh_tmp) { 1527 printf("FUSE: vnode being reclaimed with open fufh " 1528 "(type=%#x)", fufh->fufh_type); 1529 fuse_filehandle_close(vp, fufh, td, NULL); 1530 } 1531 1532 if (!fuse_isdeadfs(vp) && fvdat->nlookup > 0) { 1533 fuse_internal_forget_send(vnode_mount(vp), td, NULL, VTOI(vp), 1534 fvdat->nlookup); 1535 } 1536 cache_purge(vp); 1537 vfs_hash_remove(vp); 1538 fuse_vnode_destroy(vp); 1539 1540 return 0; 1541 } 1542 1543 /* 1544 struct vnop_remove_args { 1545 struct vnode *a_dvp; 1546 struct vnode *a_vp; 1547 struct componentname *a_cnp; 1548 }; 1549 */ 1550 static int 1551 fuse_vnop_remove(struct vop_remove_args *ap) 1552 { 1553 struct vnode *dvp = ap->a_dvp; 1554 struct vnode *vp = ap->a_vp; 1555 struct componentname *cnp = ap->a_cnp; 1556 1557 int err; 1558 1559 if (fuse_isdeadfs(vp)) { 1560 return ENXIO; 1561 } 1562 if (vnode_isdir(vp)) { 1563 return EPERM; 1564 } 1565 1566 err = fuse_internal_remove(dvp, vp, cnp, FUSE_UNLINK); 1567 1568 return err; 1569 } 1570 1571 /* 1572 struct vnop_rename_args { 1573 struct vnode *a_fdvp; 1574 struct vnode *a_fvp; 1575 struct componentname *a_fcnp; 1576 struct vnode *a_tdvp; 1577 struct vnode *a_tvp; 1578 struct componentname *a_tcnp; 1579 }; 1580 */ 1581 static int 1582 fuse_vnop_rename(struct vop_rename_args *ap) 1583 { 1584 struct vnode *fdvp = ap->a_fdvp; 1585 struct vnode *fvp = ap->a_fvp; 1586 struct componentname *fcnp = ap->a_fcnp; 1587 struct vnode *tdvp = ap->a_tdvp; 1588 struct vnode *tvp = ap->a_tvp; 1589 struct componentname *tcnp = ap->a_tcnp; 1590 struct fuse_data *data; 1591 bool newparent = fdvp != tdvp; 1592 bool isdir = fvp->v_type == VDIR; 1593 int err = 0; 1594 1595 if (fuse_isdeadfs(fdvp)) { 1596 return ENXIO; 1597 } 1598 if (fvp->v_mount != tdvp->v_mount || 1599 (tvp && fvp->v_mount != tvp->v_mount)) { 1600 SDT_PROBE2(fusefs, , vnops, trace, 1, "cross-device rename"); 1601 err = EXDEV; 1602 goto out; 1603 } 1604 cache_purge(fvp); 1605 1606 /* 1607 * FUSE library is expected to check if target directory is not 1608 * under the source directory in the file system tree. 1609 * Linux performs this check at VFS level. 1610 */ 1611 /* 1612 * If source is a directory, and it will get a new parent, user must 1613 * have write permission to it, so ".." can be modified. 1614 */ 1615 data = fuse_get_mpdata(vnode_mount(tdvp)); 1616 if (data->dataflags & FSESS_DEFAULT_PERMISSIONS && isdir && newparent) { 1617 err = fuse_internal_access(fvp, VWRITE, 1618 tcnp->cn_thread, tcnp->cn_cred); 1619 if (err) 1620 goto out; 1621 } 1622 sx_xlock(&data->rename_lock); 1623 err = fuse_internal_rename(fdvp, fcnp, tdvp, tcnp); 1624 if (err == 0) { 1625 if (tdvp != fdvp) 1626 fuse_vnode_setparent(fvp, tdvp); 1627 if (tvp != NULL) 1628 fuse_vnode_setparent(tvp, NULL); 1629 } 1630 sx_unlock(&data->rename_lock); 1631 1632 if (tvp != NULL && tvp != fvp) { 1633 cache_purge(tvp); 1634 } 1635 if (vnode_isdir(fvp)) { 1636 if ((tvp != NULL) && vnode_isdir(tvp)) { 1637 cache_purge(tdvp); 1638 } 1639 cache_purge(fdvp); 1640 } 1641 out: 1642 if (tdvp == tvp) { 1643 vrele(tdvp); 1644 } else { 1645 vput(tdvp); 1646 } 1647 if (tvp != NULL) { 1648 vput(tvp); 1649 } 1650 vrele(fdvp); 1651 vrele(fvp); 1652 1653 return err; 1654 } 1655 1656 /* 1657 struct vnop_rmdir_args { 1658 struct vnode *a_dvp; 1659 struct vnode *a_vp; 1660 struct componentname *a_cnp; 1661 } *ap; 1662 */ 1663 static int 1664 fuse_vnop_rmdir(struct vop_rmdir_args *ap) 1665 { 1666 struct vnode *dvp = ap->a_dvp; 1667 struct vnode *vp = ap->a_vp; 1668 1669 int err; 1670 1671 if (fuse_isdeadfs(vp)) { 1672 return ENXIO; 1673 } 1674 if (VTOFUD(vp) == VTOFUD(dvp)) { 1675 return EINVAL; 1676 } 1677 err = fuse_internal_remove(dvp, vp, ap->a_cnp, FUSE_RMDIR); 1678 1679 return err; 1680 } 1681 1682 /* 1683 struct vnop_setattr_args { 1684 struct vnode *a_vp; 1685 struct vattr *a_vap; 1686 struct ucred *a_cred; 1687 struct thread *a_td; 1688 }; 1689 */ 1690 static int 1691 fuse_vnop_setattr(struct vop_setattr_args *ap) 1692 { 1693 struct vnode *vp = ap->a_vp; 1694 struct vattr *vap = ap->a_vap; 1695 struct ucred *cred = ap->a_cred; 1696 struct thread *td = curthread; 1697 struct mount *mp; 1698 struct fuse_data *data; 1699 struct vattr old_va; 1700 int dataflags; 1701 int err = 0, err2; 1702 accmode_t accmode = 0; 1703 bool checkperm; 1704 bool drop_suid = false; 1705 gid_t cr_gid; 1706 1707 mp = vnode_mount(vp); 1708 data = fuse_get_mpdata(mp); 1709 dataflags = data->dataflags; 1710 checkperm = dataflags & FSESS_DEFAULT_PERMISSIONS; 1711 if (cred->cr_ngroups > 0) 1712 cr_gid = cred->cr_groups[0]; 1713 else 1714 cr_gid = 0; 1715 1716 if (fuse_isdeadfs(vp)) { 1717 return ENXIO; 1718 } 1719 1720 if (vap->va_uid != (uid_t)VNOVAL) { 1721 if (checkperm) { 1722 /* Only root may change a file's owner */ 1723 err = priv_check_cred(cred, PRIV_VFS_CHOWN); 1724 if (err) { 1725 /* As a special case, allow the null chown */ 1726 err2 = fuse_internal_getattr(vp, &old_va, cred, 1727 td); 1728 if (err2) 1729 return (err2); 1730 if (vap->va_uid != old_va.va_uid) 1731 return err; 1732 else 1733 accmode |= VADMIN; 1734 drop_suid = true; 1735 } else 1736 accmode |= VADMIN; 1737 } else 1738 accmode |= VADMIN; 1739 } 1740 if (vap->va_gid != (gid_t)VNOVAL) { 1741 if (checkperm && priv_check_cred(cred, PRIV_VFS_CHOWN)) 1742 drop_suid = true; 1743 if (checkperm && !groupmember(vap->va_gid, cred)) 1744 { 1745 /* 1746 * Non-root users may only chgrp to one of their own 1747 * groups 1748 */ 1749 err = priv_check_cred(cred, PRIV_VFS_CHOWN); 1750 if (err) { 1751 /* As a special case, allow the null chgrp */ 1752 err2 = fuse_internal_getattr(vp, &old_va, cred, 1753 td); 1754 if (err2) 1755 return (err2); 1756 if (vap->va_gid != old_va.va_gid) 1757 return err; 1758 accmode |= VADMIN; 1759 } else 1760 accmode |= VADMIN; 1761 } else 1762 accmode |= VADMIN; 1763 } 1764 if (vap->va_size != VNOVAL) { 1765 switch (vp->v_type) { 1766 case VDIR: 1767 return (EISDIR); 1768 case VLNK: 1769 case VREG: 1770 if (vfs_isrdonly(mp)) 1771 return (EROFS); 1772 break; 1773 default: 1774 /* 1775 * According to POSIX, the result is unspecified 1776 * for file types other than regular files, 1777 * directories and shared memory objects. We 1778 * don't support shared memory objects in the file 1779 * system, and have dubious support for truncating 1780 * symlinks. Just ignore the request in other cases. 1781 */ 1782 return (0); 1783 } 1784 /* Don't set accmode. Permission to trunc is checked upstack */ 1785 } 1786 if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { 1787 if (vap->va_vaflags & VA_UTIMES_NULL) 1788 accmode |= VWRITE; 1789 else 1790 accmode |= VADMIN; 1791 } 1792 if (drop_suid) { 1793 if (vap->va_mode != (mode_t)VNOVAL) 1794 vap->va_mode &= ~(S_ISUID | S_ISGID); 1795 else { 1796 err = fuse_internal_getattr(vp, &old_va, cred, td); 1797 if (err) 1798 return (err); 1799 vap->va_mode = old_va.va_mode & ~(S_ISUID | S_ISGID); 1800 } 1801 } 1802 if (vap->va_mode != (mode_t)VNOVAL) { 1803 /* Only root may set the sticky bit on non-directories */ 1804 if (checkperm && vp->v_type != VDIR && (vap->va_mode & S_ISTXT) 1805 && priv_check_cred(cred, PRIV_VFS_STICKYFILE)) 1806 return EFTYPE; 1807 if (checkperm && (vap->va_mode & S_ISGID)) { 1808 err = fuse_internal_getattr(vp, &old_va, cred, td); 1809 if (err) 1810 return (err); 1811 if (!groupmember(old_va.va_gid, cred)) { 1812 err = priv_check_cred(cred, PRIV_VFS_SETGID); 1813 if (err) 1814 return (err); 1815 } 1816 } 1817 accmode |= VADMIN; 1818 } 1819 1820 if (vfs_isrdonly(mp)) 1821 return EROFS; 1822 1823 err = fuse_internal_access(vp, accmode, td, cred); 1824 if (err) 1825 return err; 1826 else 1827 return fuse_internal_setattr(vp, vap, td, cred); 1828 } 1829 1830 /* 1831 struct vnop_strategy_args { 1832 struct vnode *a_vp; 1833 struct buf *a_bp; 1834 }; 1835 */ 1836 static int 1837 fuse_vnop_strategy(struct vop_strategy_args *ap) 1838 { 1839 struct vnode *vp = ap->a_vp; 1840 struct buf *bp = ap->a_bp; 1841 1842 if (!vp || fuse_isdeadfs(vp)) { 1843 bp->b_ioflags |= BIO_ERROR; 1844 bp->b_error = ENXIO; 1845 bufdone(bp); 1846 return 0; 1847 } 1848 1849 /* 1850 * VOP_STRATEGY always returns zero and signals error via bp->b_ioflags. 1851 * fuse_io_strategy sets bp's error fields 1852 */ 1853 (void)fuse_io_strategy(vp, bp); 1854 1855 return 0; 1856 } 1857 1858 1859 /* 1860 struct vnop_symlink_args { 1861 struct vnode *a_dvp; 1862 struct vnode **a_vpp; 1863 struct componentname *a_cnp; 1864 struct vattr *a_vap; 1865 char *a_target; 1866 }; 1867 */ 1868 static int 1869 fuse_vnop_symlink(struct vop_symlink_args *ap) 1870 { 1871 struct vnode *dvp = ap->a_dvp; 1872 struct vnode **vpp = ap->a_vpp; 1873 struct componentname *cnp = ap->a_cnp; 1874 const char *target = ap->a_target; 1875 1876 struct fuse_dispatcher fdi; 1877 1878 int err; 1879 size_t len; 1880 1881 if (fuse_isdeadfs(dvp)) { 1882 return ENXIO; 1883 } 1884 /* 1885 * Unlike the other creator type calls, here we have to create a message 1886 * where the name of the new entry comes first, and the data describing 1887 * the entry comes second. 1888 * Hence we can't rely on our handy fuse_internal_newentry() routine, 1889 * but put together the message manually and just call the core part. 1890 */ 1891 1892 len = strlen(target) + 1; 1893 fdisp_init(&fdi, len + cnp->cn_namelen + 1); 1894 fdisp_make_vp(&fdi, FUSE_SYMLINK, dvp, curthread, NULL); 1895 1896 memcpy(fdi.indata, cnp->cn_nameptr, cnp->cn_namelen); 1897 ((char *)fdi.indata)[cnp->cn_namelen] = '\0'; 1898 memcpy((char *)fdi.indata + cnp->cn_namelen + 1, target, len); 1899 1900 err = fuse_internal_newentry_core(dvp, vpp, cnp, VLNK, &fdi); 1901 fdisp_destroy(&fdi); 1902 return err; 1903 } 1904 1905 /* 1906 struct vnop_write_args { 1907 struct vnode *a_vp; 1908 struct uio *a_uio; 1909 int a_ioflag; 1910 struct ucred *a_cred; 1911 }; 1912 */ 1913 static int 1914 fuse_vnop_write(struct vop_write_args *ap) 1915 { 1916 struct vnode *vp = ap->a_vp; 1917 struct uio *uio = ap->a_uio; 1918 int ioflag = ap->a_ioflag; 1919 struct ucred *cred = ap->a_cred; 1920 pid_t pid = curthread->td_proc->p_pid; 1921 1922 if (fuse_isdeadfs(vp)) { 1923 return ENXIO; 1924 } 1925 1926 if (VTOFUD(vp)->flag & FN_DIRECTIO) { 1927 ioflag |= IO_DIRECT; 1928 } 1929 1930 return fuse_io_dispatch(vp, uio, ioflag, cred, pid); 1931 } 1932 1933 static daddr_t 1934 fuse_gbp_getblkno(struct vnode *vp, vm_ooffset_t off) 1935 { 1936 const int biosize = fuse_iosize(vp); 1937 1938 return (off / biosize); 1939 } 1940 1941 static int 1942 fuse_gbp_getblksz(struct vnode *vp, daddr_t lbn) 1943 { 1944 off_t filesize; 1945 int blksz, err; 1946 const int biosize = fuse_iosize(vp); 1947 1948 err = fuse_vnode_size(vp, &filesize, NULL, NULL); 1949 KASSERT(err == 0, ("vfs_bio_getpages can't handle errors here")); 1950 if (err) 1951 return biosize; 1952 1953 if ((off_t)lbn * biosize >= filesize) { 1954 blksz = 0; 1955 } else if ((off_t)(lbn + 1) * biosize > filesize) { 1956 blksz = filesize - (off_t)lbn *biosize; 1957 } else { 1958 blksz = biosize; 1959 } 1960 return (blksz); 1961 } 1962 1963 /* 1964 struct vnop_getpages_args { 1965 struct vnode *a_vp; 1966 vm_page_t *a_m; 1967 int a_count; 1968 int a_reqpage; 1969 }; 1970 */ 1971 static int 1972 fuse_vnop_getpages(struct vop_getpages_args *ap) 1973 { 1974 struct vnode *vp = ap->a_vp; 1975 1976 if (!fsess_opt_mmap(vnode_mount(vp))) { 1977 SDT_PROBE2(fusefs, , vnops, trace, 1, 1978 "called on non-cacheable vnode??\n"); 1979 return (VM_PAGER_ERROR); 1980 } 1981 1982 return (vfs_bio_getpages(vp, ap->a_m, ap->a_count, ap->a_rbehind, 1983 ap->a_rahead, fuse_gbp_getblkno, fuse_gbp_getblksz)); 1984 } 1985 1986 static const char extattr_namespace_separator = '.'; 1987 1988 /* 1989 struct vop_getextattr_args { 1990 struct vop_generic_args a_gen; 1991 struct vnode *a_vp; 1992 int a_attrnamespace; 1993 const char *a_name; 1994 struct uio *a_uio; 1995 size_t *a_size; 1996 struct ucred *a_cred; 1997 struct thread *a_td; 1998 }; 1999 */ 2000 static int 2001 fuse_vnop_getextattr(struct vop_getextattr_args *ap) 2002 { 2003 struct vnode *vp = ap->a_vp; 2004 struct uio *uio = ap->a_uio; 2005 struct fuse_dispatcher fdi; 2006 struct fuse_getxattr_in *get_xattr_in; 2007 struct fuse_getxattr_out *get_xattr_out; 2008 struct mount *mp = vnode_mount(vp); 2009 struct thread *td = ap->a_td; 2010 struct ucred *cred = ap->a_cred; 2011 char *prefix; 2012 char *attr_str; 2013 size_t len; 2014 int err; 2015 2016 if (fuse_isdeadfs(vp)) 2017 return (ENXIO); 2018 2019 if (!fsess_isimpl(mp, FUSE_GETXATTR)) 2020 return EOPNOTSUPP; 2021 2022 err = fuse_extattr_check_cred(vp, ap->a_attrnamespace, cred, td, VREAD); 2023 if (err) 2024 return err; 2025 2026 /* Default to looking for user attributes. */ 2027 if (ap->a_attrnamespace == EXTATTR_NAMESPACE_SYSTEM) 2028 prefix = EXTATTR_NAMESPACE_SYSTEM_STRING; 2029 else 2030 prefix = EXTATTR_NAMESPACE_USER_STRING; 2031 2032 len = strlen(prefix) + sizeof(extattr_namespace_separator) + 2033 strlen(ap->a_name) + 1; 2034 2035 fdisp_init(&fdi, len + sizeof(*get_xattr_in)); 2036 fdisp_make_vp(&fdi, FUSE_GETXATTR, vp, td, cred); 2037 2038 get_xattr_in = fdi.indata; 2039 /* 2040 * Check to see whether we're querying the available size or 2041 * issuing the actual request. If we pass in 0, we get back struct 2042 * fuse_getxattr_out. If we pass in a non-zero size, we get back 2043 * that much data, without the struct fuse_getxattr_out header. 2044 */ 2045 if (uio == NULL) 2046 get_xattr_in->size = 0; 2047 else 2048 get_xattr_in->size = uio->uio_resid; 2049 2050 attr_str = (char *)fdi.indata + sizeof(*get_xattr_in); 2051 snprintf(attr_str, len, "%s%c%s", prefix, extattr_namespace_separator, 2052 ap->a_name); 2053 2054 err = fdisp_wait_answ(&fdi); 2055 if (err != 0) { 2056 if (err == ENOSYS) { 2057 fsess_set_notimpl(mp, FUSE_GETXATTR); 2058 err = EOPNOTSUPP; 2059 } 2060 goto out; 2061 } 2062 2063 get_xattr_out = fdi.answ; 2064 2065 if (ap->a_size != NULL) 2066 *ap->a_size = get_xattr_out->size; 2067 2068 if (uio != NULL) 2069 err = uiomove(fdi.answ, fdi.iosize, uio); 2070 2071 out: 2072 fdisp_destroy(&fdi); 2073 return (err); 2074 } 2075 2076 /* 2077 struct vop_setextattr_args { 2078 struct vop_generic_args a_gen; 2079 struct vnode *a_vp; 2080 int a_attrnamespace; 2081 const char *a_name; 2082 struct uio *a_uio; 2083 struct ucred *a_cred; 2084 struct thread *a_td; 2085 }; 2086 */ 2087 static int 2088 fuse_vnop_setextattr(struct vop_setextattr_args *ap) 2089 { 2090 struct vnode *vp = ap->a_vp; 2091 struct uio *uio = ap->a_uio; 2092 struct fuse_dispatcher fdi; 2093 struct fuse_setxattr_in *set_xattr_in; 2094 struct mount *mp = vnode_mount(vp); 2095 struct thread *td = ap->a_td; 2096 struct ucred *cred = ap->a_cred; 2097 char *prefix; 2098 size_t len; 2099 char *attr_str; 2100 int err; 2101 2102 if (fuse_isdeadfs(vp)) 2103 return (ENXIO); 2104 2105 if (!fsess_isimpl(mp, FUSE_SETXATTR)) 2106 return EOPNOTSUPP; 2107 2108 if (vfs_isrdonly(mp)) 2109 return EROFS; 2110 2111 /* Deleting xattrs must use VOP_DELETEEXTATTR instead */ 2112 if (ap->a_uio == NULL) { 2113 /* 2114 * If we got here as fallback from VOP_DELETEEXTATTR, then 2115 * return EOPNOTSUPP. 2116 */ 2117 if (!fsess_isimpl(mp, FUSE_REMOVEXATTR)) 2118 return (EOPNOTSUPP); 2119 else 2120 return (EINVAL); 2121 } 2122 2123 err = fuse_extattr_check_cred(vp, ap->a_attrnamespace, cred, td, 2124 VWRITE); 2125 if (err) 2126 return err; 2127 2128 /* Default to looking for user attributes. */ 2129 if (ap->a_attrnamespace == EXTATTR_NAMESPACE_SYSTEM) 2130 prefix = EXTATTR_NAMESPACE_SYSTEM_STRING; 2131 else 2132 prefix = EXTATTR_NAMESPACE_USER_STRING; 2133 2134 len = strlen(prefix) + sizeof(extattr_namespace_separator) + 2135 strlen(ap->a_name) + 1; 2136 2137 fdisp_init(&fdi, len + sizeof(*set_xattr_in) + uio->uio_resid); 2138 fdisp_make_vp(&fdi, FUSE_SETXATTR, vp, td, cred); 2139 2140 set_xattr_in = fdi.indata; 2141 set_xattr_in->size = uio->uio_resid; 2142 2143 attr_str = (char *)fdi.indata + sizeof(*set_xattr_in); 2144 snprintf(attr_str, len, "%s%c%s", prefix, extattr_namespace_separator, 2145 ap->a_name); 2146 2147 err = uiomove((char *)fdi.indata + sizeof(*set_xattr_in) + len, 2148 uio->uio_resid, uio); 2149 if (err != 0) { 2150 goto out; 2151 } 2152 2153 err = fdisp_wait_answ(&fdi); 2154 2155 if (err == ENOSYS) { 2156 fsess_set_notimpl(mp, FUSE_SETXATTR); 2157 err = EOPNOTSUPP; 2158 } 2159 if (err == ERESTART) { 2160 /* Can't restart after calling uiomove */ 2161 err = EINTR; 2162 } 2163 2164 out: 2165 fdisp_destroy(&fdi); 2166 return (err); 2167 } 2168 2169 /* 2170 * The Linux / FUSE extended attribute list is simply a collection of 2171 * NUL-terminated strings. The FreeBSD extended attribute list is a single 2172 * byte length followed by a non-NUL terminated string. So, this allows 2173 * conversion of the Linux / FUSE format to the FreeBSD format in place. 2174 * Linux attribute names are reported with the namespace as a prefix (e.g. 2175 * "user.attribute_name"), but in FreeBSD they are reported without the 2176 * namespace prefix (e.g. "attribute_name"). So, we're going from: 2177 * 2178 * user.attr_name1\0user.attr_name2\0 2179 * 2180 * to: 2181 * 2182 * <num>attr_name1<num>attr_name2 2183 * 2184 * Where "<num>" is a single byte number of characters in the attribute name. 2185 * 2186 * Args: 2187 * prefix - exattr namespace prefix string 2188 * list, list_len - input list with namespace prefixes 2189 * bsd_list, bsd_list_len - output list compatible with bsd vfs 2190 */ 2191 static int 2192 fuse_xattrlist_convert(char *prefix, const char *list, int list_len, 2193 char *bsd_list, int *bsd_list_len) 2194 { 2195 int len, pos, dist_to_next, prefix_len; 2196 2197 pos = 0; 2198 *bsd_list_len = 0; 2199 prefix_len = strlen(prefix); 2200 2201 while (pos < list_len && list[pos] != '\0') { 2202 dist_to_next = strlen(&list[pos]) + 1; 2203 if (bcmp(&list[pos], prefix, prefix_len) == 0 && 2204 list[pos + prefix_len] == extattr_namespace_separator) { 2205 len = dist_to_next - 2206 (prefix_len + sizeof(extattr_namespace_separator)) - 1; 2207 if (len >= EXTATTR_MAXNAMELEN) 2208 return (ENAMETOOLONG); 2209 2210 bsd_list[*bsd_list_len] = len; 2211 memcpy(&bsd_list[*bsd_list_len + 1], 2212 &list[pos + prefix_len + 2213 sizeof(extattr_namespace_separator)], len); 2214 2215 *bsd_list_len += len + 1; 2216 } 2217 2218 pos += dist_to_next; 2219 } 2220 2221 return (0); 2222 } 2223 2224 /* 2225 * List extended attributes 2226 * 2227 * The FUSE_LISTXATTR operation is based on Linux's listxattr(2) syscall, which 2228 * has a number of differences compared to its FreeBSD equivalent, 2229 * extattr_list_file: 2230 * 2231 * - FUSE_LISTXATTR returns all extended attributes across all namespaces, 2232 * whereas listxattr(2) only returns attributes for a single namespace 2233 * - FUSE_LISTXATTR prepends each attribute name with "namespace." 2234 * - If the provided buffer is not large enough to hold the result, 2235 * FUSE_LISTXATTR should return ERANGE, whereas listxattr is expected to 2236 * return as many results as will fit. 2237 */ 2238 /* 2239 struct vop_listextattr_args { 2240 struct vop_generic_args a_gen; 2241 struct vnode *a_vp; 2242 int a_attrnamespace; 2243 struct uio *a_uio; 2244 size_t *a_size; 2245 struct ucred *a_cred; 2246 struct thread *a_td; 2247 }; 2248 */ 2249 static int 2250 fuse_vnop_listextattr(struct vop_listextattr_args *ap) 2251 { 2252 struct vnode *vp = ap->a_vp; 2253 struct uio *uio = ap->a_uio; 2254 struct fuse_dispatcher fdi; 2255 struct fuse_listxattr_in *list_xattr_in; 2256 struct fuse_listxattr_out *list_xattr_out; 2257 struct mount *mp = vnode_mount(vp); 2258 struct thread *td = ap->a_td; 2259 struct ucred *cred = ap->a_cred; 2260 char *prefix; 2261 char *bsd_list = NULL; 2262 char *linux_list; 2263 int bsd_list_len; 2264 int linux_list_len; 2265 int err; 2266 2267 if (fuse_isdeadfs(vp)) 2268 return (ENXIO); 2269 2270 if (!fsess_isimpl(mp, FUSE_LISTXATTR)) 2271 return EOPNOTSUPP; 2272 2273 err = fuse_extattr_check_cred(vp, ap->a_attrnamespace, cred, td, VREAD); 2274 if (err) 2275 return err; 2276 2277 /* 2278 * Add space for a NUL and the period separator if enabled. 2279 * Default to looking for user attributes. 2280 */ 2281 if (ap->a_attrnamespace == EXTATTR_NAMESPACE_SYSTEM) 2282 prefix = EXTATTR_NAMESPACE_SYSTEM_STRING; 2283 else 2284 prefix = EXTATTR_NAMESPACE_USER_STRING; 2285 2286 fdisp_init(&fdi, sizeof(*list_xattr_in)); 2287 fdisp_make_vp(&fdi, FUSE_LISTXATTR, vp, td, cred); 2288 2289 /* 2290 * Retrieve Linux / FUSE compatible list size. 2291 */ 2292 list_xattr_in = fdi.indata; 2293 list_xattr_in->size = 0; 2294 2295 err = fdisp_wait_answ(&fdi); 2296 if (err != 0) { 2297 if (err == ENOSYS) { 2298 fsess_set_notimpl(mp, FUSE_LISTXATTR); 2299 err = EOPNOTSUPP; 2300 } 2301 goto out; 2302 } 2303 2304 list_xattr_out = fdi.answ; 2305 linux_list_len = list_xattr_out->size; 2306 if (linux_list_len == 0) { 2307 if (ap->a_size != NULL) 2308 *ap->a_size = linux_list_len; 2309 goto out; 2310 } 2311 2312 /* 2313 * Retrieve Linux / FUSE compatible list values. 2314 */ 2315 fdisp_refresh_vp(&fdi, FUSE_LISTXATTR, vp, td, cred); 2316 list_xattr_in = fdi.indata; 2317 list_xattr_in->size = linux_list_len; 2318 2319 err = fdisp_wait_answ(&fdi); 2320 if (err == ERANGE) { 2321 /* 2322 * Race detected. The attribute list must've grown since the 2323 * first FUSE_LISTXATTR call. Start over. Go all the way back 2324 * to userland so we can process signals, if necessary, before 2325 * restarting. 2326 */ 2327 err = ERESTART; 2328 goto out; 2329 } else if (err != 0) 2330 goto out; 2331 2332 linux_list = fdi.answ; 2333 /* FUSE doesn't allow the server to return more data than requested */ 2334 if (fdi.iosize > linux_list_len) { 2335 printf("WARNING: FUSE protocol violation. Server returned " 2336 "more extended attribute data than requested; " 2337 "should've returned ERANGE instead"); 2338 } else { 2339 /* But returning less data is fine */ 2340 linux_list_len = fdi.iosize; 2341 } 2342 2343 /* 2344 * Retrieve the BSD compatible list values. 2345 * The Linux / FUSE attribute list format isn't the same 2346 * as FreeBSD's format. So we need to transform it into 2347 * FreeBSD's format before giving it to the user. 2348 */ 2349 bsd_list = malloc(linux_list_len, M_TEMP, M_WAITOK); 2350 err = fuse_xattrlist_convert(prefix, linux_list, linux_list_len, 2351 bsd_list, &bsd_list_len); 2352 if (err != 0) 2353 goto out; 2354 2355 if (ap->a_size != NULL) 2356 *ap->a_size = bsd_list_len; 2357 2358 if (uio != NULL) 2359 err = uiomove(bsd_list, bsd_list_len, uio); 2360 2361 out: 2362 free(bsd_list, M_TEMP); 2363 fdisp_destroy(&fdi); 2364 return (err); 2365 } 2366 2367 /* 2368 struct vop_deleteextattr_args { 2369 struct vop_generic_args a_gen; 2370 struct vnode *a_vp; 2371 int a_attrnamespace; 2372 const char *a_name; 2373 struct ucred *a_cred; 2374 struct thread *a_td; 2375 }; 2376 */ 2377 static int 2378 fuse_vnop_deleteextattr(struct vop_deleteextattr_args *ap) 2379 { 2380 struct vnode *vp = ap->a_vp; 2381 struct fuse_dispatcher fdi; 2382 struct mount *mp = vnode_mount(vp); 2383 struct thread *td = ap->a_td; 2384 struct ucred *cred = ap->a_cred; 2385 char *prefix; 2386 size_t len; 2387 char *attr_str; 2388 int err; 2389 2390 if (fuse_isdeadfs(vp)) 2391 return (ENXIO); 2392 2393 if (!fsess_isimpl(mp, FUSE_REMOVEXATTR)) 2394 return EOPNOTSUPP; 2395 2396 if (vfs_isrdonly(mp)) 2397 return EROFS; 2398 2399 err = fuse_extattr_check_cred(vp, ap->a_attrnamespace, cred, td, 2400 VWRITE); 2401 if (err) 2402 return err; 2403 2404 /* Default to looking for user attributes. */ 2405 if (ap->a_attrnamespace == EXTATTR_NAMESPACE_SYSTEM) 2406 prefix = EXTATTR_NAMESPACE_SYSTEM_STRING; 2407 else 2408 prefix = EXTATTR_NAMESPACE_USER_STRING; 2409 2410 len = strlen(prefix) + sizeof(extattr_namespace_separator) + 2411 strlen(ap->a_name) + 1; 2412 2413 fdisp_init(&fdi, len); 2414 fdisp_make_vp(&fdi, FUSE_REMOVEXATTR, vp, td, cred); 2415 2416 attr_str = fdi.indata; 2417 snprintf(attr_str, len, "%s%c%s", prefix, extattr_namespace_separator, 2418 ap->a_name); 2419 2420 err = fdisp_wait_answ(&fdi); 2421 if (err == ENOSYS) { 2422 fsess_set_notimpl(mp, FUSE_REMOVEXATTR); 2423 err = EOPNOTSUPP; 2424 } 2425 2426 fdisp_destroy(&fdi); 2427 return (err); 2428 } 2429 2430 /* 2431 struct vnop_print_args { 2432 struct vnode *a_vp; 2433 }; 2434 */ 2435 static int 2436 fuse_vnop_print(struct vop_print_args *ap) 2437 { 2438 struct fuse_vnode_data *fvdat = VTOFUD(ap->a_vp); 2439 2440 printf("nodeid: %ju, parent nodeid: %ju, nlookup: %ju, flag: %#x\n", 2441 (uintmax_t)VTOILLU(ap->a_vp), (uintmax_t)fvdat->parent_nid, 2442 (uintmax_t)fvdat->nlookup, 2443 fvdat->flag); 2444 2445 return 0; 2446 } 2447 2448 /* 2449 * Get an NFS filehandle for a FUSE file. 2450 * 2451 * This will only work for FUSE file systems that guarantee the uniqueness of 2452 * nodeid:generation, which most don't. 2453 */ 2454 /* 2455 vop_vptofh { 2456 IN struct vnode *a_vp; 2457 IN struct fid *a_fhp; 2458 }; 2459 */ 2460 static int 2461 fuse_vnop_vptofh(struct vop_vptofh_args *ap) 2462 { 2463 struct vnode *vp = ap->a_vp; 2464 struct fuse_vnode_data *fvdat = VTOFUD(vp); 2465 struct fuse_fid *fhp = (struct fuse_fid *)(ap->a_fhp); 2466 _Static_assert(sizeof(struct fuse_fid) <= sizeof(struct fid), 2467 "FUSE fid type is too big"); 2468 struct mount *mp = vnode_mount(vp); 2469 struct fuse_data *data = fuse_get_mpdata(mp); 2470 struct vattr va; 2471 int err; 2472 2473 if (!(data->dataflags & FSESS_EXPORT_SUPPORT)) 2474 return EOPNOTSUPP; 2475 2476 err = fuse_internal_getattr(vp, &va, curthread->td_ucred, curthread); 2477 if (err) 2478 return err; 2479 2480 /*ip = VTOI(ap->a_vp);*/ 2481 /*ufhp = (struct ufid *)ap->a_fhp;*/ 2482 fhp->len = sizeof(struct fuse_fid); 2483 fhp->nid = fvdat->nid; 2484 if (fvdat->generation <= UINT32_MAX) 2485 fhp->gen = fvdat->generation; 2486 else 2487 return EOVERFLOW; 2488 return (0); 2489 } 2490 2491 2492