1 /* $OpenBSD: fuse_device.c,v 1.36 2021/03/11 13:31:35 jsg Exp $ */ 2 /* 3 * Copyright (c) 2012-2013 Sylvestre Gallon <ccna.syl@gmail.com> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/systm.h> 20 #include <sys/fcntl.h> 21 #include <sys/ioctl.h> 22 #include <sys/malloc.h> 23 #include <sys/mount.h> 24 #include <sys/poll.h> 25 #include <sys/stat.h> 26 #include <sys/statvfs.h> 27 #include <sys/vnode.h> 28 #include <sys/fusebuf.h> 29 30 #include "fusefs_node.h" 31 #include "fusefs.h" 32 33 #ifdef FUSE_DEBUG 34 #define DPRINTF(fmt, arg...) printf("%s: " fmt, "fuse", ##arg) 35 #else 36 #define DPRINTF(fmt, arg...) 37 #endif 38 39 SIMPLEQ_HEAD(fusebuf_head, fusebuf); 40 41 struct fuse_d { 42 struct fusefs_mnt *fd_fmp; 43 int fd_unit; 44 45 /*fusebufs queues*/ 46 struct fusebuf_head fd_fbufs_in; 47 struct fusebuf_head fd_fbufs_wait; 48 49 /* kq fields */ 50 struct selinfo fd_rsel; 51 LIST_ENTRY(fuse_d) fd_list; 52 }; 53 54 int stat_fbufs_in = 0; 55 int stat_fbufs_wait = 0; 56 int stat_opened_fusedev = 0; 57 58 LIST_HEAD(, fuse_d) fuse_d_list; 59 struct fuse_d *fuse_lookup(int); 60 61 void fuseattach(int); 62 int fuseopen(dev_t, int, int, struct proc *); 63 int fuseclose(dev_t, int, int, struct proc *); 64 int fuseioctl(dev_t, u_long, caddr_t, int, struct proc *); 65 int fuseread(dev_t, struct uio *, int); 66 int fusewrite(dev_t, struct uio *, int); 67 int fusepoll(dev_t, int, struct proc *); 68 int fusekqfilter(dev_t dev, struct knote *kn); 69 int filt_fuse_read(struct knote *, long); 70 void filt_fuse_rdetach(struct knote *); 71 72 const static struct filterops fuse_rd_filtops = { 73 .f_flags = FILTEROP_ISFD, 74 .f_attach = NULL, 75 .f_detach = filt_fuse_rdetach, 76 .f_event = filt_fuse_read, 77 }; 78 79 #ifdef FUSE_DEBUG 80 static void 81 fuse_dump_buff(char *buff, int len) 82 { 83 char text[17]; 84 int i; 85 86 if (len < 0) { 87 printf("invalid len: %d", len); 88 return; 89 } 90 if (buff == NULL) { 91 printf("invalid buff"); 92 return; 93 } 94 95 memset(text, 0, 17); 96 for (i = 0; i < len; i++) { 97 if (i != 0 && (i % 16) == 0) { 98 printf(": %s\n", text); 99 memset(text, 0, 17); 100 } 101 102 printf("%.2x ", buff[i] & 0xff); 103 104 if (buff[i] > ' ' && buff[i] < '~') 105 text[i%16] = buff[i] & 0xff; 106 else 107 text[i%16] = '.'; 108 } 109 110 if ((i % 16) != 0) 111 while ((i % 16) != 0) { 112 printf(" "); 113 i++; 114 } 115 116 printf(": %s\n", text); 117 } 118 #endif 119 120 struct fuse_d * 121 fuse_lookup(int unit) 122 { 123 struct fuse_d *fd; 124 125 LIST_FOREACH(fd, &fuse_d_list, fd_list) 126 if (fd->fd_unit == unit) 127 return (fd); 128 return (NULL); 129 } 130 131 /* 132 * Cleanup all msgs from sc_fbufs_in and sc_fbufs_wait. 133 */ 134 void 135 fuse_device_cleanup(dev_t dev) 136 { 137 struct fuse_d *fd; 138 struct fusebuf *f, *ftmp, *lprev; 139 140 fd = fuse_lookup(minor(dev)); 141 if (fd == NULL) 142 return; 143 144 /* clear FIFO IN */ 145 lprev = NULL; 146 SIMPLEQ_FOREACH_SAFE(f, &fd->fd_fbufs_in, fb_next, ftmp) { 147 DPRINTF("cleanup unprocessed msg in sc_fbufs_in\n"); 148 if (lprev == NULL) 149 SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_in, fb_next); 150 else 151 SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_in, lprev, 152 fb_next); 153 154 stat_fbufs_in--; 155 f->fb_err = ENXIO; 156 wakeup(f); 157 lprev = f; 158 } 159 160 /* clear FIFO WAIT*/ 161 lprev = NULL; 162 SIMPLEQ_FOREACH_SAFE(f, &fd->fd_fbufs_wait, fb_next, ftmp) { 163 DPRINTF("umount unprocessed msg in sc_fbufs_wait\n"); 164 if (lprev == NULL) 165 SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_wait, fb_next); 166 else 167 SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_wait, lprev, 168 fb_next); 169 170 stat_fbufs_wait--; 171 f->fb_err = ENXIO; 172 wakeup(f); 173 lprev = f; 174 } 175 } 176 177 void 178 fuse_device_queue_fbuf(dev_t dev, struct fusebuf *fbuf) 179 { 180 struct fuse_d *fd; 181 182 fd = fuse_lookup(minor(dev)); 183 if (fd == NULL) 184 return; 185 186 SIMPLEQ_INSERT_TAIL(&fd->fd_fbufs_in, fbuf, fb_next); 187 stat_fbufs_in++; 188 selwakeup(&fd->fd_rsel); 189 } 190 191 void 192 fuse_device_set_fmp(struct fusefs_mnt *fmp, int set) 193 { 194 struct fuse_d *fd; 195 196 fd = fuse_lookup(minor(fmp->dev)); 197 if (fd == NULL) 198 return; 199 200 fd->fd_fmp = set ? fmp : NULL; 201 } 202 203 void 204 fuseattach(int num) 205 { 206 LIST_INIT(&fuse_d_list); 207 } 208 209 int 210 fuseopen(dev_t dev, int flags, int fmt, struct proc * p) 211 { 212 struct fuse_d *fd; 213 int unit = minor(dev); 214 215 if (flags & O_EXCL) 216 return (EBUSY); /* No exclusive opens */ 217 218 if ((fd = fuse_lookup(unit)) != NULL) 219 return (EBUSY); 220 221 fd = malloc(sizeof(*fd), M_DEVBUF, M_WAITOK | M_ZERO); 222 fd->fd_unit = unit; 223 SIMPLEQ_INIT(&fd->fd_fbufs_in); 224 SIMPLEQ_INIT(&fd->fd_fbufs_wait); 225 LIST_INSERT_HEAD(&fuse_d_list, fd, fd_list); 226 227 stat_opened_fusedev++; 228 return (0); 229 } 230 231 int 232 fuseclose(dev_t dev, int flags, int fmt, struct proc *p) 233 { 234 struct fuse_d *fd; 235 int error; 236 237 fd = fuse_lookup(minor(dev)); 238 if (fd == NULL) 239 return (EINVAL); 240 241 if (fd->fd_fmp) { 242 printf("fuse: device close without umount\n"); 243 fd->fd_fmp->sess_init = 0; 244 fuse_device_cleanup(dev); 245 if ((vfs_busy(fd->fd_fmp->mp, VB_WRITE | VB_NOWAIT)) != 0) 246 goto end; 247 error = dounmount(fd->fd_fmp->mp, MNT_FORCE, p); 248 if (error) 249 printf("fuse: unmount failed with error %d\n", error); 250 fd->fd_fmp = NULL; 251 } 252 253 end: 254 LIST_REMOVE(fd, fd_list); 255 free(fd, M_DEVBUF, sizeof(*fd)); 256 stat_opened_fusedev--; 257 return (0); 258 } 259 260 /* 261 * FIOCGETFBDAT Get fusebuf data from kernel to user 262 * FIOCSETFBDAT Set fusebuf data from user to kernel 263 */ 264 int 265 fuseioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) 266 { 267 struct fb_ioctl_xch *ioexch; 268 struct fusebuf *lastfbuf; 269 struct fusebuf *fbuf; 270 struct fuse_d *fd; 271 int error = 0; 272 273 fd = fuse_lookup(minor(dev)); 274 if (fd == NULL) 275 return (ENXIO); 276 277 switch (cmd) { 278 case FIOCGETFBDAT: 279 ioexch = (struct fb_ioctl_xch *)addr; 280 281 /* Looking for uuid in fd_fbufs_in */ 282 SIMPLEQ_FOREACH(fbuf, &fd->fd_fbufs_in, fb_next) { 283 if (fbuf->fb_uuid == ioexch->fbxch_uuid) 284 break; 285 286 lastfbuf = fbuf; 287 } 288 if (fbuf == NULL) { 289 printf("fuse: Cannot find fusebuf\n"); 290 return (EINVAL); 291 } 292 293 /* Remove the fbuf from fd_fbufs_in */ 294 if (fbuf == SIMPLEQ_FIRST(&fd->fd_fbufs_in)) 295 SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_in, fb_next); 296 else 297 SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_in, lastfbuf, 298 fb_next); 299 stat_fbufs_in--; 300 301 /* Do not handle fbufs with bad len */ 302 if (fbuf->fb_len != ioexch->fbxch_len) { 303 printf("fuse: Bad fusebuf len\n"); 304 return (EINVAL); 305 } 306 307 /* Update the userland fbuf */ 308 error = copyout(fbuf->fb_dat, ioexch->fbxch_data, 309 ioexch->fbxch_len); 310 if (error) { 311 printf("fuse: cannot copyout\n"); 312 return (error); 313 } 314 315 #ifdef FUSE_DEBUG 316 fuse_dump_buff(fbuf->fb_dat, fbuf->fb_len); 317 #endif 318 319 /* Adding fbuf in fd_fbufs_wait */ 320 free(fbuf->fb_dat, M_FUSEFS, fbuf->fb_len); 321 fbuf->fb_dat = NULL; 322 SIMPLEQ_INSERT_TAIL(&fd->fd_fbufs_wait, fbuf, fb_next); 323 stat_fbufs_wait++; 324 break; 325 326 case FIOCSETFBDAT: 327 DPRINTF("SET BUFFER\n"); 328 ioexch = (struct fb_ioctl_xch *)addr; 329 330 /* looking for uuid in fd_fbufs_wait */ 331 SIMPLEQ_FOREACH(fbuf, &fd->fd_fbufs_wait, fb_next) { 332 if (fbuf->fb_uuid == ioexch->fbxch_uuid) 333 break; 334 335 lastfbuf = fbuf; 336 } 337 if (fbuf == NULL) { 338 printf("fuse: Cannot find fusebuf\n"); 339 return (EINVAL); 340 } 341 342 /* Do not handle fbufs with bad len */ 343 if (fbuf->fb_len != ioexch->fbxch_len) { 344 printf("fuse: Bad fusebuf size\n"); 345 return (EINVAL); 346 } 347 348 /* fetching data from userland */ 349 fbuf->fb_dat = malloc(ioexch->fbxch_len, M_FUSEFS, 350 M_WAITOK | M_ZERO); 351 error = copyin(ioexch->fbxch_data, fbuf->fb_dat, 352 ioexch->fbxch_len); 353 if (error) { 354 printf("fuse: Cannot copyin\n"); 355 free(fbuf->fb_dat, M_FUSEFS, fbuf->fb_len); 356 fbuf->fb_dat = NULL; 357 return (error); 358 } 359 360 #ifdef FUSE_DEBUG 361 fuse_dump_buff(fbuf->fb_dat, fbuf->fb_len); 362 #endif 363 364 /* Remove fbuf from fd_fbufs_wait */ 365 if (fbuf == SIMPLEQ_FIRST(&fd->fd_fbufs_wait)) 366 SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_wait, fb_next); 367 else 368 SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_wait, lastfbuf, 369 fb_next); 370 stat_fbufs_wait--; 371 wakeup(fbuf); 372 break; 373 default: 374 error = EINVAL; 375 } 376 377 return (error); 378 } 379 380 int 381 fuseread(dev_t dev, struct uio *uio, int ioflag) 382 { 383 struct fuse_d *fd; 384 struct fusebuf *fbuf; 385 struct fb_hdr hdr; 386 void *tmpaddr; 387 int error = 0; 388 389 fd = fuse_lookup(minor(dev)); 390 if (fd == NULL) 391 return (ENXIO); 392 393 if (SIMPLEQ_EMPTY(&fd->fd_fbufs_in)) { 394 if (ioflag & O_NONBLOCK) 395 return (EAGAIN); 396 397 goto end; 398 } 399 fbuf = SIMPLEQ_FIRST(&fd->fd_fbufs_in); 400 401 /* We get the whole fusebuf or nothing */ 402 if (uio->uio_resid != FUSEBUFSIZE) 403 return (EINVAL); 404 405 /* Do not send kernel pointers */ 406 memcpy(&hdr.fh_next, &fbuf->fb_next, sizeof(fbuf->fb_next)); 407 memset(&fbuf->fb_next, 0, sizeof(fbuf->fb_next)); 408 tmpaddr = fbuf->fb_dat; 409 fbuf->fb_dat = NULL; 410 error = uiomove(fbuf, FUSEBUFSIZE, uio); 411 if (error) 412 goto end; 413 414 #ifdef FUSE_DEBUG 415 fuse_dump_buff((char *)fbuf, FUSEBUFSIZE); 416 #endif 417 /* Restore kernel pointers */ 418 memcpy(&fbuf->fb_next, &hdr.fh_next, sizeof(fbuf->fb_next)); 419 fbuf->fb_dat = tmpaddr; 420 421 /* Remove the fbuf if it does not contains data */ 422 if (fbuf->fb_len == 0) { 423 SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_in, fb_next); 424 stat_fbufs_in--; 425 SIMPLEQ_INSERT_TAIL(&fd->fd_fbufs_wait, fbuf, fb_next); 426 stat_fbufs_wait++; 427 } 428 429 end: 430 return (error); 431 } 432 433 int 434 fusewrite(dev_t dev, struct uio *uio, int ioflag) 435 { 436 struct fusebuf *lastfbuf; 437 struct fuse_d *fd; 438 struct fusebuf *fbuf; 439 struct fb_hdr hdr; 440 int error = 0; 441 442 fd = fuse_lookup(minor(dev)); 443 if (fd == NULL) 444 return (ENXIO); 445 446 /* We get the whole fusebuf or nothing */ 447 if (uio->uio_resid != FUSEBUFSIZE) 448 return (EINVAL); 449 450 if ((error = uiomove(&hdr, sizeof(hdr), uio)) != 0) 451 return (error); 452 453 /* looking for uuid in fd_fbufs_wait */ 454 SIMPLEQ_FOREACH(fbuf, &fd->fd_fbufs_wait, fb_next) { 455 if (fbuf->fb_uuid == hdr.fh_uuid) 456 break; 457 458 lastfbuf = fbuf; 459 } 460 if (fbuf == NULL) 461 return (EINVAL); 462 463 /* Update fb_hdr */ 464 fbuf->fb_len = hdr.fh_len; 465 fbuf->fb_err = hdr.fh_err; 466 fbuf->fb_ino = hdr.fh_ino; 467 468 /* Check for corrupted fbufs */ 469 if ((fbuf->fb_len && fbuf->fb_err) || 470 SIMPLEQ_EMPTY(&fd->fd_fbufs_wait)) { 471 printf("fuse: dropping corrupted fusebuf\n"); 472 error = EINVAL; 473 goto end; 474 } 475 476 /* Get the missing data from the fbuf */ 477 error = uiomove(&fbuf->FD, uio->uio_resid, uio); 478 if (error) 479 return error; 480 fbuf->fb_dat = NULL; 481 #ifdef FUSE_DEBUG 482 fuse_dump_buff((char *)fbuf, FUSEBUFSIZE); 483 #endif 484 485 switch (fbuf->fb_type) { 486 case FBT_INIT: 487 fd->fd_fmp->sess_init = 1; 488 break ; 489 case FBT_DESTROY: 490 fd->fd_fmp = NULL; 491 break ; 492 } 493 end: 494 /* Remove the fbuf if it does not contains data */ 495 if (fbuf->fb_len == 0) { 496 if (fbuf == SIMPLEQ_FIRST(&fd->fd_fbufs_wait)) 497 SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_wait, fb_next); 498 else 499 SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_wait, lastfbuf, 500 fb_next); 501 stat_fbufs_wait--; 502 if (fbuf->fb_type == FBT_INIT) 503 fb_delete(fbuf); 504 else 505 wakeup(fbuf); 506 } 507 508 return (error); 509 } 510 511 int 512 fusepoll(dev_t dev, int events, struct proc *p) 513 { 514 struct fuse_d *fd; 515 int revents = 0; 516 517 fd = fuse_lookup(minor(dev)); 518 if (fd == NULL) 519 return (POLLERR); 520 521 if (events & (POLLIN | POLLRDNORM)) 522 if (!SIMPLEQ_EMPTY(&fd->fd_fbufs_in)) 523 revents |= events & (POLLIN | POLLRDNORM); 524 525 if (events & (POLLOUT | POLLWRNORM)) 526 revents |= events & (POLLOUT | POLLWRNORM); 527 528 if (revents == 0) 529 if (events & (POLLIN | POLLRDNORM)) 530 selrecord(p, &fd->fd_rsel); 531 532 return (revents); 533 } 534 535 int 536 fusekqfilter(dev_t dev, struct knote *kn) 537 { 538 struct fuse_d *fd; 539 struct klist *klist; 540 541 fd = fuse_lookup(minor(dev)); 542 if (fd == NULL) 543 return (EINVAL); 544 545 switch (kn->kn_filter) { 546 case EVFILT_READ: 547 klist = &fd->fd_rsel.si_note; 548 kn->kn_fop = &fuse_rd_filtops; 549 break; 550 case EVFILT_WRITE: 551 return (seltrue_kqfilter(dev, kn)); 552 default: 553 return (EINVAL); 554 } 555 556 kn->kn_hook = fd; 557 558 klist_insert_locked(klist, kn); 559 560 return (0); 561 } 562 563 void 564 filt_fuse_rdetach(struct knote *kn) 565 { 566 struct fuse_d *fd = kn->kn_hook; 567 struct klist *klist = &fd->fd_rsel.si_note; 568 569 klist_remove_locked(klist, kn); 570 } 571 572 int 573 filt_fuse_read(struct knote *kn, long hint) 574 { 575 struct fuse_d *fd = kn->kn_hook; 576 int event = 0; 577 578 if (!SIMPLEQ_EMPTY(&fd->fd_fbufs_in)) 579 event = 1; 580 581 return (event); 582 } 583