1 /* $FreeBSD$ */ 2 /*- 3 * Copyright (c) 2010-2013 Hans Petter Selasky. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include "opt_compat.h" 28 29 #include <sys/stdint.h> 30 #include <sys/stddef.h> 31 #include <sys/param.h> 32 #include <sys/types.h> 33 #include <sys/systm.h> 34 #include <sys/conf.h> 35 #include <sys/kernel.h> 36 #include <sys/bus.h> 37 #include <sys/linker_set.h> 38 #include <sys/module.h> 39 #include <sys/lock.h> 40 #include <sys/mutex.h> 41 #include <sys/condvar.h> 42 #include <sys/sysctl.h> 43 #include <sys/unistd.h> 44 #include <sys/malloc.h> 45 #include <sys/priv.h> 46 #include <sys/uio.h> 47 #include <sys/poll.h> 48 #include <sys/sx.h> 49 #include <sys/queue.h> 50 #include <sys/fcntl.h> 51 #include <sys/proc.h> 52 #include <sys/vnode.h> 53 #include <sys/selinfo.h> 54 #include <sys/ptrace.h> 55 56 #include <machine/bus.h> 57 58 #include <vm/vm.h> 59 #include <vm/pmap.h> 60 61 #include <fs/cuse/cuse_defs.h> 62 #include <fs/cuse/cuse_ioctl.h> 63 64 MODULE_VERSION(cuse, 1); 65 66 #define NBUSY ((uint8_t *)1) 67 68 #ifdef FEATURE 69 FEATURE(cuse, "Userspace character devices"); 70 #endif 71 72 struct cuse_command; 73 struct cuse_server; 74 struct cuse_client; 75 76 struct cuse_client_command { 77 TAILQ_ENTRY(cuse_client_command) entry; 78 struct cuse_command sub; 79 struct sx sx; 80 struct cv cv; 81 struct thread *entered; 82 struct cuse_client *client; 83 struct proc *proc_curr; 84 int proc_refs; 85 int got_signal; 86 int error; 87 int command; 88 }; 89 90 struct cuse_memory { 91 struct cuse_server *owner; 92 uint8_t *virtaddr; 93 uint32_t page_count; 94 uint32_t is_allocated; 95 }; 96 97 struct cuse_server_dev { 98 TAILQ_ENTRY(cuse_server_dev) entry; 99 struct cuse_server *server; 100 struct cdev *kern_dev; 101 struct cuse_dev *user_dev; 102 }; 103 104 struct cuse_server { 105 TAILQ_ENTRY(cuse_server) entry; 106 TAILQ_HEAD(, cuse_client_command) head; 107 TAILQ_HEAD(, cuse_server_dev) hdev; 108 TAILQ_HEAD(, cuse_client) hcli; 109 struct cv cv; 110 struct selinfo selinfo; 111 int is_closing; 112 int refs; 113 }; 114 115 struct cuse_client { 116 TAILQ_ENTRY(cuse_client) entry; 117 TAILQ_ENTRY(cuse_client) entry_ref; 118 struct cuse_client_command cmds[CUSE_CMD_MAX]; 119 struct cuse_server *server; 120 struct cuse_server_dev *server_dev; 121 122 uint8_t ioctl_buffer[CUSE_BUFFER_MAX] __aligned(4); 123 124 int fflags; /* file flags */ 125 int cflags; /* client flags */ 126 #define CUSE_CLI_IS_CLOSING 0x01 127 #define CUSE_CLI_KNOTE_NEED_READ 0x02 128 #define CUSE_CLI_KNOTE_NEED_WRITE 0x04 129 #define CUSE_CLI_KNOTE_HAS_READ 0x08 130 #define CUSE_CLI_KNOTE_HAS_WRITE 0x10 131 }; 132 133 #define CUSE_CLIENT_CLOSING(pcc) \ 134 ((pcc)->cflags & CUSE_CLI_IS_CLOSING) 135 136 static MALLOC_DEFINE(M_CUSE, "cuse", "CUSE memory"); 137 138 static TAILQ_HEAD(, cuse_server) cuse_server_head; 139 static struct mtx cuse_mtx; 140 static struct cdev *cuse_dev; 141 static struct cuse_server *cuse_alloc_unit[CUSE_DEVICES_MAX]; 142 static int cuse_alloc_unit_id[CUSE_DEVICES_MAX]; 143 static struct cuse_memory cuse_mem[CUSE_ALLOC_UNIT_MAX]; 144 145 static void cuse_client_kqfilter_read_detach(struct knote *kn); 146 static void cuse_client_kqfilter_write_detach(struct knote *kn); 147 static int cuse_client_kqfilter_read_event(struct knote *kn, long hint); 148 static int cuse_client_kqfilter_write_event(struct knote *kn, long hint); 149 150 static struct filterops cuse_client_kqfilter_read_ops = { 151 .f_isfd = 1, 152 .f_detach = cuse_client_kqfilter_read_detach, 153 .f_event = cuse_client_kqfilter_read_event, 154 }; 155 156 static struct filterops cuse_client_kqfilter_write_ops = { 157 .f_isfd = 1, 158 .f_detach = cuse_client_kqfilter_write_detach, 159 .f_event = cuse_client_kqfilter_write_event, 160 }; 161 162 static d_open_t cuse_client_open; 163 static d_close_t cuse_client_close; 164 static d_ioctl_t cuse_client_ioctl; 165 static d_read_t cuse_client_read; 166 static d_write_t cuse_client_write; 167 static d_poll_t cuse_client_poll; 168 static d_mmap_t cuse_client_mmap; 169 static d_kqfilter_t cuse_client_kqfilter; 170 171 static struct cdevsw cuse_client_devsw = { 172 .d_version = D_VERSION, 173 .d_open = cuse_client_open, 174 .d_close = cuse_client_close, 175 .d_ioctl = cuse_client_ioctl, 176 .d_name = "cuse_client", 177 .d_flags = D_TRACKCLOSE, 178 .d_read = cuse_client_read, 179 .d_write = cuse_client_write, 180 .d_poll = cuse_client_poll, 181 .d_mmap = cuse_client_mmap, 182 .d_kqfilter = cuse_client_kqfilter, 183 }; 184 185 static d_open_t cuse_server_open; 186 static d_close_t cuse_server_close; 187 static d_ioctl_t cuse_server_ioctl; 188 static d_read_t cuse_server_read; 189 static d_write_t cuse_server_write; 190 static d_poll_t cuse_server_poll; 191 static d_mmap_t cuse_server_mmap; 192 193 static struct cdevsw cuse_server_devsw = { 194 .d_version = D_VERSION, 195 .d_open = cuse_server_open, 196 .d_close = cuse_server_close, 197 .d_ioctl = cuse_server_ioctl, 198 .d_name = "cuse_server", 199 .d_flags = D_TRACKCLOSE, 200 .d_read = cuse_server_read, 201 .d_write = cuse_server_write, 202 .d_poll = cuse_server_poll, 203 .d_mmap = cuse_server_mmap, 204 }; 205 206 static void cuse_client_is_closing(struct cuse_client *); 207 static int cuse_free_unit_by_id_locked(struct cuse_server *, int); 208 209 static void 210 cuse_lock(void) 211 { 212 mtx_lock(&cuse_mtx); 213 } 214 215 static void 216 cuse_unlock(void) 217 { 218 mtx_unlock(&cuse_mtx); 219 } 220 221 static void 222 cuse_cmd_lock(struct cuse_client_command *pccmd) 223 { 224 sx_xlock(&pccmd->sx); 225 } 226 227 static void 228 cuse_cmd_unlock(struct cuse_client_command *pccmd) 229 { 230 sx_xunlock(&pccmd->sx); 231 } 232 233 static void 234 cuse_kern_init(void *arg) 235 { 236 TAILQ_INIT(&cuse_server_head); 237 238 mtx_init(&cuse_mtx, "cuse-mtx", NULL, MTX_DEF); 239 240 cuse_dev = make_dev(&cuse_server_devsw, 0, 241 UID_ROOT, GID_OPERATOR, 0600, "cuse"); 242 243 printf("Cuse v%d.%d.%d @ /dev/cuse\n", 244 (CUSE_VERSION >> 16) & 0xFF, (CUSE_VERSION >> 8) & 0xFF, 245 (CUSE_VERSION >> 0) & 0xFF); 246 } 247 248 SYSINIT(cuse_kern_init, SI_SUB_DEVFS, SI_ORDER_ANY, cuse_kern_init, 0); 249 250 static void 251 cuse_kern_uninit(void *arg) 252 { 253 void *ptr; 254 255 while (1) { 256 257 printf("Cuse: Please exit all /dev/cuse instances " 258 "and processes which have used this device.\n"); 259 260 pause("DRAIN", 2 * hz); 261 262 cuse_lock(); 263 ptr = TAILQ_FIRST(&cuse_server_head); 264 cuse_unlock(); 265 266 if (ptr == NULL) 267 break; 268 } 269 270 if (cuse_dev != NULL) 271 destroy_dev(cuse_dev); 272 273 mtx_destroy(&cuse_mtx); 274 } 275 276 SYSUNINIT(cuse_kern_uninit, SI_SUB_DEVFS, SI_ORDER_ANY, cuse_kern_uninit, 0); 277 278 static int 279 cuse_server_get(struct cuse_server **ppcs) 280 { 281 struct cuse_server *pcs; 282 int error; 283 284 error = devfs_get_cdevpriv((void **)&pcs); 285 if (error != 0) { 286 *ppcs = NULL; 287 return (error); 288 } 289 /* check if closing */ 290 cuse_lock(); 291 if (pcs->is_closing) { 292 cuse_unlock(); 293 *ppcs = NULL; 294 return (EINVAL); 295 } 296 cuse_unlock(); 297 *ppcs = pcs; 298 return (0); 299 } 300 301 static void 302 cuse_server_is_closing(struct cuse_server *pcs) 303 { 304 struct cuse_client *pcc; 305 306 if (pcs->is_closing) 307 return; 308 309 pcs->is_closing = 1; 310 311 TAILQ_FOREACH(pcc, &pcs->hcli, entry) { 312 cuse_client_is_closing(pcc); 313 } 314 } 315 316 static struct cuse_client_command * 317 cuse_server_find_command(struct cuse_server *pcs, struct thread *td) 318 { 319 struct cuse_client *pcc; 320 int n; 321 322 if (pcs->is_closing) 323 goto done; 324 325 TAILQ_FOREACH(pcc, &pcs->hcli, entry) { 326 if (CUSE_CLIENT_CLOSING(pcc)) 327 continue; 328 for (n = 0; n != CUSE_CMD_MAX; n++) { 329 if (pcc->cmds[n].entered == td) 330 return (&pcc->cmds[n]); 331 } 332 } 333 done: 334 return (NULL); 335 } 336 337 static void 338 cuse_str_filter(char *ptr) 339 { 340 int c; 341 342 while (((c = *ptr) != 0)) { 343 344 if ((c >= 'a') && (c <= 'z')) { 345 ptr++; 346 continue; 347 } 348 if ((c >= 'A') && (c <= 'Z')) { 349 ptr++; 350 continue; 351 } 352 if ((c >= '0') && (c <= '9')) { 353 ptr++; 354 continue; 355 } 356 if ((c == '.') || (c == '_') || (c == '/')) { 357 ptr++; 358 continue; 359 } 360 *ptr = '_'; 361 362 ptr++; 363 } 364 } 365 366 static int 367 cuse_convert_error(int error) 368 { 369 ; /* indent fix */ 370 switch (error) { 371 case CUSE_ERR_NONE: 372 return (0); 373 case CUSE_ERR_BUSY: 374 return (EBUSY); 375 case CUSE_ERR_WOULDBLOCK: 376 return (EWOULDBLOCK); 377 case CUSE_ERR_INVALID: 378 return (EINVAL); 379 case CUSE_ERR_NO_MEMORY: 380 return (ENOMEM); 381 case CUSE_ERR_FAULT: 382 return (EFAULT); 383 case CUSE_ERR_SIGNAL: 384 return (EINTR); 385 default: 386 return (ENXIO); 387 } 388 } 389 390 static void 391 cuse_server_free_memory(struct cuse_server *pcs) 392 { 393 struct cuse_memory *mem; 394 uint32_t n; 395 396 for (n = 0; n != CUSE_ALLOC_UNIT_MAX; n++) { 397 mem = &cuse_mem[n]; 398 399 /* this memory is never freed */ 400 if (mem->owner == pcs) { 401 mem->owner = NULL; 402 mem->is_allocated = 0; 403 } 404 } 405 } 406 407 static int 408 cuse_server_alloc_memory(struct cuse_server *pcs, 409 struct cuse_memory *mem, uint32_t page_count) 410 { 411 void *ptr; 412 int error; 413 414 cuse_lock(); 415 416 if (mem->virtaddr == NBUSY) { 417 cuse_unlock(); 418 return (EBUSY); 419 } 420 if (mem->virtaddr != NULL) { 421 if (mem->is_allocated != 0) { 422 cuse_unlock(); 423 return (EBUSY); 424 } 425 if (mem->page_count == page_count) { 426 mem->is_allocated = 1; 427 mem->owner = pcs; 428 cuse_unlock(); 429 return (0); 430 } 431 cuse_unlock(); 432 return (EBUSY); 433 } 434 memset(mem, 0, sizeof(*mem)); 435 436 mem->virtaddr = NBUSY; 437 438 cuse_unlock(); 439 440 ptr = malloc(page_count * PAGE_SIZE, M_CUSE, M_WAITOK | M_ZERO); 441 if (ptr == NULL) 442 error = ENOMEM; 443 else 444 error = 0; 445 446 cuse_lock(); 447 448 if (error) { 449 mem->virtaddr = NULL; 450 cuse_unlock(); 451 return (error); 452 } 453 mem->virtaddr = ptr; 454 mem->page_count = page_count; 455 mem->is_allocated = 1; 456 mem->owner = pcs; 457 cuse_unlock(); 458 459 return (0); 460 } 461 462 static int 463 cuse_client_get(struct cuse_client **ppcc) 464 { 465 struct cuse_client *pcc; 466 int error; 467 468 /* try to get private data */ 469 error = devfs_get_cdevpriv((void **)&pcc); 470 if (error != 0) { 471 *ppcc = NULL; 472 return (error); 473 } 474 /* check if closing */ 475 cuse_lock(); 476 if (CUSE_CLIENT_CLOSING(pcc) || pcc->server->is_closing) { 477 cuse_unlock(); 478 *ppcc = NULL; 479 return (EINVAL); 480 } 481 cuse_unlock(); 482 *ppcc = pcc; 483 return (0); 484 } 485 486 static void 487 cuse_client_is_closing(struct cuse_client *pcc) 488 { 489 struct cuse_client_command *pccmd; 490 uint32_t n; 491 492 if (CUSE_CLIENT_CLOSING(pcc)) 493 return; 494 495 pcc->cflags |= CUSE_CLI_IS_CLOSING; 496 pcc->server_dev = NULL; 497 498 for (n = 0; n != CUSE_CMD_MAX; n++) { 499 500 pccmd = &pcc->cmds[n]; 501 502 if (pccmd->entry.tqe_prev != NULL) { 503 TAILQ_REMOVE(&pcc->server->head, pccmd, entry); 504 pccmd->entry.tqe_prev = NULL; 505 } 506 cv_broadcast(&pccmd->cv); 507 } 508 } 509 510 static void 511 cuse_client_send_command_locked(struct cuse_client_command *pccmd, 512 unsigned long data_ptr, unsigned long arg, int fflags, int ioflag) 513 { 514 unsigned long cuse_fflags = 0; 515 struct cuse_server *pcs; 516 517 if (fflags & FREAD) 518 cuse_fflags |= CUSE_FFLAG_READ; 519 520 if (fflags & FWRITE) 521 cuse_fflags |= CUSE_FFLAG_WRITE; 522 523 if (ioflag & IO_NDELAY) 524 cuse_fflags |= CUSE_FFLAG_NONBLOCK; 525 526 pccmd->sub.fflags = cuse_fflags; 527 pccmd->sub.data_pointer = data_ptr; 528 pccmd->sub.argument = arg; 529 530 pcs = pccmd->client->server; 531 532 if ((pccmd->entry.tqe_prev == NULL) && 533 (CUSE_CLIENT_CLOSING(pccmd->client) == 0) && 534 (pcs->is_closing == 0)) { 535 TAILQ_INSERT_TAIL(&pcs->head, pccmd, entry); 536 cv_signal(&pcs->cv); 537 } 538 } 539 540 static void 541 cuse_client_got_signal(struct cuse_client_command *pccmd) 542 { 543 struct cuse_server *pcs; 544 545 pccmd->got_signal = 1; 546 547 pccmd = &pccmd->client->cmds[CUSE_CMD_SIGNAL]; 548 549 pcs = pccmd->client->server; 550 551 if ((pccmd->entry.tqe_prev == NULL) && 552 (CUSE_CLIENT_CLOSING(pccmd->client) == 0) && 553 (pcs->is_closing == 0)) { 554 TAILQ_INSERT_TAIL(&pcs->head, pccmd, entry); 555 cv_signal(&pcs->cv); 556 } 557 } 558 559 static int 560 cuse_client_receive_command_locked(struct cuse_client_command *pccmd, 561 uint8_t *arg_ptr, uint32_t arg_len) 562 { 563 int error; 564 565 error = 0; 566 567 pccmd->proc_curr = curthread->td_proc; 568 569 if (CUSE_CLIENT_CLOSING(pccmd->client) || 570 pccmd->client->server->is_closing) { 571 error = CUSE_ERR_OTHER; 572 goto done; 573 } 574 while (pccmd->command == CUSE_CMD_NONE) { 575 if (error != 0) { 576 cv_wait(&pccmd->cv, &cuse_mtx); 577 } else { 578 error = cv_wait_sig(&pccmd->cv, &cuse_mtx); 579 580 if (error != 0) 581 cuse_client_got_signal(pccmd); 582 } 583 if (CUSE_CLIENT_CLOSING(pccmd->client) || 584 pccmd->client->server->is_closing) { 585 error = CUSE_ERR_OTHER; 586 goto done; 587 } 588 } 589 590 error = pccmd->error; 591 pccmd->command = CUSE_CMD_NONE; 592 cv_signal(&pccmd->cv); 593 594 done: 595 596 /* wait until all process references are gone */ 597 598 pccmd->proc_curr = NULL; 599 600 while (pccmd->proc_refs != 0) 601 cv_wait(&pccmd->cv, &cuse_mtx); 602 603 return (error); 604 } 605 606 /*------------------------------------------------------------------------* 607 * CUSE SERVER PART 608 *------------------------------------------------------------------------*/ 609 610 static void 611 cuse_server_free_dev(struct cuse_server_dev *pcsd) 612 { 613 struct cuse_server *pcs; 614 struct cuse_client *pcc; 615 616 /* get server pointer */ 617 pcs = pcsd->server; 618 619 /* prevent creation of more devices */ 620 cuse_lock(); 621 if (pcsd->kern_dev != NULL) 622 pcsd->kern_dev->si_drv1 = NULL; 623 624 TAILQ_FOREACH(pcc, &pcs->hcli, entry) { 625 if (pcc->server_dev == pcsd) 626 cuse_client_is_closing(pcc); 627 } 628 cuse_unlock(); 629 630 /* destroy device, if any */ 631 if (pcsd->kern_dev != NULL) { 632 /* destroy device synchronously */ 633 destroy_dev(pcsd->kern_dev); 634 } 635 free(pcsd, M_CUSE); 636 } 637 638 static void 639 cuse_server_free(void *arg) 640 { 641 struct cuse_server *pcs = arg; 642 struct cuse_server_dev *pcsd; 643 644 cuse_lock(); 645 pcs->refs--; 646 if (pcs->refs != 0) { 647 cuse_unlock(); 648 return; 649 } 650 cuse_server_is_closing(pcs); 651 652 TAILQ_REMOVE(&cuse_server_head, pcs, entry); 653 654 cuse_free_unit_by_id_locked(pcs, -1); 655 656 while ((pcsd = TAILQ_FIRST(&pcs->hdev)) != NULL) { 657 TAILQ_REMOVE(&pcs->hdev, pcsd, entry); 658 cuse_unlock(); 659 cuse_server_free_dev(pcsd); 660 cuse_lock(); 661 } 662 663 cuse_server_free_memory(pcs); 664 665 knlist_clear(&pcs->selinfo.si_note, 1); 666 knlist_destroy(&pcs->selinfo.si_note); 667 668 cuse_unlock(); 669 670 seldrain(&pcs->selinfo); 671 672 cv_destroy(&pcs->cv); 673 674 free(pcs, M_CUSE); 675 } 676 677 static int 678 cuse_server_open(struct cdev *dev, int fflags, int devtype, struct thread *td) 679 { 680 struct cuse_server *pcs; 681 682 pcs = malloc(sizeof(*pcs), M_CUSE, M_WAITOK | M_ZERO); 683 if (pcs == NULL) 684 return (ENOMEM); 685 686 if (devfs_set_cdevpriv(pcs, &cuse_server_free)) { 687 printf("Cuse: Cannot set cdevpriv.\n"); 688 free(pcs, M_CUSE); 689 return (ENOMEM); 690 } 691 TAILQ_INIT(&pcs->head); 692 TAILQ_INIT(&pcs->hdev); 693 TAILQ_INIT(&pcs->hcli); 694 695 cv_init(&pcs->cv, "cuse-server-cv"); 696 697 knlist_init_mtx(&pcs->selinfo.si_note, &cuse_mtx); 698 699 cuse_lock(); 700 pcs->refs++; 701 TAILQ_INSERT_TAIL(&cuse_server_head, pcs, entry); 702 cuse_unlock(); 703 704 return (0); 705 } 706 707 static int 708 cuse_server_close(struct cdev *dev, int fflag, int devtype, struct thread *td) 709 { 710 struct cuse_server *pcs; 711 int error; 712 713 error = cuse_server_get(&pcs); 714 if (error != 0) 715 goto done; 716 717 cuse_lock(); 718 cuse_server_is_closing(pcs); 719 knlist_clear(&pcs->selinfo.si_note, 1); 720 cuse_unlock(); 721 722 done: 723 return (0); 724 } 725 726 static int 727 cuse_server_read(struct cdev *dev, struct uio *uio, int ioflag) 728 { 729 return (ENXIO); 730 } 731 732 static int 733 cuse_server_write(struct cdev *dev, struct uio *uio, int ioflag) 734 { 735 return (ENXIO); 736 } 737 738 static int 739 cuse_server_ioctl_copy_locked(struct cuse_client_command *pccmd, 740 struct cuse_data_chunk *pchk, int isread) 741 { 742 struct proc *p_proc; 743 uint32_t offset; 744 int error; 745 746 offset = pchk->peer_ptr - CUSE_BUF_MIN_PTR; 747 748 if (pchk->length > CUSE_BUFFER_MAX) 749 return (EFAULT); 750 751 if (offset >= CUSE_BUFFER_MAX) 752 return (EFAULT); 753 754 if ((offset + pchk->length) > CUSE_BUFFER_MAX) 755 return (EFAULT); 756 757 p_proc = pccmd->proc_curr; 758 if (p_proc == NULL) 759 return (ENXIO); 760 761 if (pccmd->proc_refs < 0) 762 return (ENOMEM); 763 764 pccmd->proc_refs++; 765 766 cuse_unlock(); 767 768 if (isread == 0) { 769 error = copyin( 770 (void *)pchk->local_ptr, 771 pccmd->client->ioctl_buffer + offset, 772 pchk->length); 773 } else { 774 error = copyout( 775 pccmd->client->ioctl_buffer + offset, 776 (void *)pchk->local_ptr, 777 pchk->length); 778 } 779 780 cuse_lock(); 781 782 pccmd->proc_refs--; 783 784 if (pccmd->proc_curr == NULL) 785 cv_signal(&pccmd->cv); 786 787 return (error); 788 } 789 790 static int 791 cuse_proc2proc_copy(struct proc *proc_s, vm_offset_t data_s, 792 struct proc *proc_d, vm_offset_t data_d, size_t len) 793 { 794 struct thread *td; 795 struct proc *proc_cur; 796 int error; 797 798 td = curthread; 799 proc_cur = td->td_proc; 800 801 if (proc_cur == proc_d) { 802 struct iovec iov = { 803 .iov_base = (caddr_t)data_d, 804 .iov_len = len, 805 }; 806 struct uio uio = { 807 .uio_iov = &iov, 808 .uio_iovcnt = 1, 809 .uio_offset = (off_t)data_s, 810 .uio_resid = len, 811 .uio_segflg = UIO_USERSPACE, 812 .uio_rw = UIO_READ, 813 .uio_td = td, 814 }; 815 816 PROC_LOCK(proc_s); 817 _PHOLD(proc_s); 818 PROC_UNLOCK(proc_s); 819 820 error = proc_rwmem(proc_s, &uio); 821 822 PROC_LOCK(proc_s); 823 _PRELE(proc_s); 824 PROC_UNLOCK(proc_s); 825 826 } else if (proc_cur == proc_s) { 827 struct iovec iov = { 828 .iov_base = (caddr_t)data_s, 829 .iov_len = len, 830 }; 831 struct uio uio = { 832 .uio_iov = &iov, 833 .uio_iovcnt = 1, 834 .uio_offset = (off_t)data_d, 835 .uio_resid = len, 836 .uio_segflg = UIO_USERSPACE, 837 .uio_rw = UIO_WRITE, 838 .uio_td = td, 839 }; 840 841 PROC_LOCK(proc_d); 842 _PHOLD(proc_d); 843 PROC_UNLOCK(proc_d); 844 845 error = proc_rwmem(proc_d, &uio); 846 847 PROC_LOCK(proc_d); 848 _PRELE(proc_d); 849 PROC_UNLOCK(proc_d); 850 } else { 851 error = EINVAL; 852 } 853 return (error); 854 } 855 856 static int 857 cuse_server_data_copy_locked(struct cuse_client_command *pccmd, 858 struct cuse_data_chunk *pchk, int isread) 859 { 860 struct proc *p_proc; 861 int error; 862 863 p_proc = pccmd->proc_curr; 864 if (p_proc == NULL) 865 return (ENXIO); 866 867 if (pccmd->proc_refs < 0) 868 return (ENOMEM); 869 870 pccmd->proc_refs++; 871 872 cuse_unlock(); 873 874 if (isread == 0) { 875 error = cuse_proc2proc_copy( 876 curthread->td_proc, pchk->local_ptr, 877 p_proc, pchk->peer_ptr, 878 pchk->length); 879 } else { 880 error = cuse_proc2proc_copy( 881 p_proc, pchk->peer_ptr, 882 curthread->td_proc, pchk->local_ptr, 883 pchk->length); 884 } 885 886 cuse_lock(); 887 888 pccmd->proc_refs--; 889 890 if (pccmd->proc_curr == NULL) 891 cv_signal(&pccmd->cv); 892 893 return (error); 894 } 895 896 static int 897 cuse_alloc_unit_by_id_locked(struct cuse_server *pcs, int id) 898 { 899 int n; 900 int x = 0; 901 int match; 902 903 do { 904 for (match = n = 0; n != CUSE_DEVICES_MAX; n++) { 905 if (cuse_alloc_unit[n] != NULL) { 906 if ((cuse_alloc_unit_id[n] ^ id) & CUSE_ID_MASK) 907 continue; 908 if ((cuse_alloc_unit_id[n] & ~CUSE_ID_MASK) == x) { 909 x++; 910 match = 1; 911 } 912 } 913 } 914 } while (match); 915 916 if (x < 256) { 917 for (n = 0; n != CUSE_DEVICES_MAX; n++) { 918 if (cuse_alloc_unit[n] == NULL) { 919 cuse_alloc_unit[n] = pcs; 920 cuse_alloc_unit_id[n] = id | x; 921 return (x); 922 } 923 } 924 } 925 return (-1); 926 } 927 928 static void 929 cuse_server_wakeup_locked(struct cuse_server *pcs) 930 { 931 selwakeup(&pcs->selinfo); 932 KNOTE_LOCKED(&pcs->selinfo.si_note, 0); 933 } 934 935 static int 936 cuse_free_unit_by_id_locked(struct cuse_server *pcs, int id) 937 { 938 int n; 939 int found = 0; 940 941 for (n = 0; n != CUSE_DEVICES_MAX; n++) { 942 if (cuse_alloc_unit[n] == pcs) { 943 if (cuse_alloc_unit_id[n] == id || id == -1) { 944 cuse_alloc_unit[n] = NULL; 945 cuse_alloc_unit_id[n] = 0; 946 found = 1; 947 } 948 } 949 } 950 951 return (found ? 0 : EINVAL); 952 } 953 954 static int 955 cuse_server_ioctl(struct cdev *dev, unsigned long cmd, 956 caddr_t data, int fflag, struct thread *td) 957 { 958 struct cuse_server *pcs; 959 int error; 960 961 error = cuse_server_get(&pcs); 962 if (error != 0) 963 return (error); 964 965 switch (cmd) { 966 struct cuse_client_command *pccmd; 967 struct cuse_client *pcc; 968 struct cuse_command *pcmd; 969 struct cuse_alloc_info *pai; 970 struct cuse_create_dev *pcd; 971 struct cuse_server_dev *pcsd; 972 struct cuse_data_chunk *pchk; 973 int n; 974 975 case CUSE_IOCTL_GET_COMMAND: 976 pcmd = (void *)data; 977 978 cuse_lock(); 979 980 while ((pccmd = TAILQ_FIRST(&pcs->head)) == NULL) { 981 error = cv_wait_sig(&pcs->cv, &cuse_mtx); 982 983 if (pcs->is_closing) 984 error = ENXIO; 985 986 if (error) { 987 cuse_unlock(); 988 return (error); 989 } 990 } 991 992 TAILQ_REMOVE(&pcs->head, pccmd, entry); 993 pccmd->entry.tqe_prev = NULL; 994 995 pccmd->entered = curthread; 996 997 *pcmd = pccmd->sub; 998 999 cuse_unlock(); 1000 1001 break; 1002 1003 case CUSE_IOCTL_SYNC_COMMAND: 1004 1005 cuse_lock(); 1006 while ((pccmd = cuse_server_find_command(pcs, curthread)) != NULL) { 1007 1008 /* send sync command */ 1009 pccmd->entered = NULL; 1010 pccmd->error = *(int *)data; 1011 pccmd->command = CUSE_CMD_SYNC; 1012 1013 /* signal peer, if any */ 1014 cv_signal(&pccmd->cv); 1015 } 1016 cuse_unlock(); 1017 1018 break; 1019 1020 case CUSE_IOCTL_ALLOC_UNIT: 1021 1022 cuse_lock(); 1023 n = cuse_alloc_unit_by_id_locked(pcs, 1024 CUSE_ID_DEFAULT(0)); 1025 cuse_unlock(); 1026 1027 if (n < 0) 1028 error = ENOMEM; 1029 else 1030 *(int *)data = n; 1031 break; 1032 1033 case CUSE_IOCTL_ALLOC_UNIT_BY_ID: 1034 1035 n = *(int *)data; 1036 1037 n = (n & CUSE_ID_MASK); 1038 1039 cuse_lock(); 1040 n = cuse_alloc_unit_by_id_locked(pcs, n); 1041 cuse_unlock(); 1042 1043 if (n < 0) 1044 error = ENOMEM; 1045 else 1046 *(int *)data = n; 1047 break; 1048 1049 case CUSE_IOCTL_FREE_UNIT: 1050 1051 n = *(int *)data; 1052 1053 n = CUSE_ID_DEFAULT(n); 1054 1055 cuse_lock(); 1056 error = cuse_free_unit_by_id_locked(pcs, n); 1057 cuse_unlock(); 1058 break; 1059 1060 case CUSE_IOCTL_FREE_UNIT_BY_ID: 1061 1062 n = *(int *)data; 1063 1064 cuse_lock(); 1065 error = cuse_free_unit_by_id_locked(pcs, n); 1066 cuse_unlock(); 1067 break; 1068 1069 case CUSE_IOCTL_ALLOC_MEMORY: 1070 1071 pai = (void *)data; 1072 1073 if (pai->alloc_nr >= CUSE_ALLOC_UNIT_MAX) { 1074 error = ENOMEM; 1075 break; 1076 } 1077 if (pai->page_count > CUSE_ALLOC_PAGES_MAX) { 1078 error = ENOMEM; 1079 break; 1080 } 1081 error = cuse_server_alloc_memory(pcs, 1082 &cuse_mem[pai->alloc_nr], pai->page_count); 1083 break; 1084 1085 case CUSE_IOCTL_FREE_MEMORY: 1086 pai = (void *)data; 1087 1088 if (pai->alloc_nr >= CUSE_ALLOC_UNIT_MAX) { 1089 error = ENOMEM; 1090 break; 1091 } 1092 /* we trust the character device driver in this case */ 1093 1094 cuse_lock(); 1095 if (cuse_mem[pai->alloc_nr].owner == pcs) { 1096 cuse_mem[pai->alloc_nr].is_allocated = 0; 1097 cuse_mem[pai->alloc_nr].owner = NULL; 1098 } else { 1099 error = EINVAL; 1100 } 1101 cuse_unlock(); 1102 break; 1103 1104 case CUSE_IOCTL_GET_SIG: 1105 1106 cuse_lock(); 1107 pccmd = cuse_server_find_command(pcs, curthread); 1108 1109 if (pccmd != NULL) { 1110 n = pccmd->got_signal; 1111 pccmd->got_signal = 0; 1112 } else { 1113 n = 0; 1114 } 1115 cuse_unlock(); 1116 1117 *(int *)data = n; 1118 1119 break; 1120 1121 case CUSE_IOCTL_SET_PFH: 1122 1123 cuse_lock(); 1124 pccmd = cuse_server_find_command(pcs, curthread); 1125 1126 if (pccmd != NULL) { 1127 pcc = pccmd->client; 1128 for (n = 0; n != CUSE_CMD_MAX; n++) { 1129 pcc->cmds[n].sub.per_file_handle = *(unsigned long *)data; 1130 } 1131 } else { 1132 error = ENXIO; 1133 } 1134 cuse_unlock(); 1135 break; 1136 1137 case CUSE_IOCTL_CREATE_DEV: 1138 1139 error = priv_check(curthread, PRIV_DRIVER); 1140 if (error) 1141 break; 1142 1143 pcd = (void *)data; 1144 1145 /* filter input */ 1146 1147 pcd->devname[sizeof(pcd->devname) - 1] = 0; 1148 1149 if (pcd->devname[0] == 0) { 1150 error = EINVAL; 1151 break; 1152 } 1153 cuse_str_filter(pcd->devname); 1154 1155 pcd->permissions &= 0777; 1156 1157 /* try to allocate a character device */ 1158 1159 pcsd = malloc(sizeof(*pcsd), M_CUSE, M_WAITOK | M_ZERO); 1160 1161 if (pcsd == NULL) { 1162 error = ENOMEM; 1163 break; 1164 } 1165 pcsd->server = pcs; 1166 1167 pcsd->user_dev = pcd->dev; 1168 1169 pcsd->kern_dev = make_dev_credf(MAKEDEV_CHECKNAME, 1170 &cuse_client_devsw, 0, NULL, pcd->user_id, pcd->group_id, 1171 pcd->permissions, "%s", pcd->devname); 1172 1173 if (pcsd->kern_dev == NULL) { 1174 free(pcsd, M_CUSE); 1175 error = ENOMEM; 1176 break; 1177 } 1178 pcsd->kern_dev->si_drv1 = pcsd; 1179 1180 cuse_lock(); 1181 TAILQ_INSERT_TAIL(&pcs->hdev, pcsd, entry); 1182 cuse_unlock(); 1183 1184 break; 1185 1186 case CUSE_IOCTL_DESTROY_DEV: 1187 1188 error = priv_check(curthread, PRIV_DRIVER); 1189 if (error) 1190 break; 1191 1192 cuse_lock(); 1193 1194 error = EINVAL; 1195 1196 pcsd = TAILQ_FIRST(&pcs->hdev); 1197 while (pcsd != NULL) { 1198 if (pcsd->user_dev == *(struct cuse_dev **)data) { 1199 TAILQ_REMOVE(&pcs->hdev, pcsd, entry); 1200 cuse_unlock(); 1201 cuse_server_free_dev(pcsd); 1202 cuse_lock(); 1203 error = 0; 1204 pcsd = TAILQ_FIRST(&pcs->hdev); 1205 } else { 1206 pcsd = TAILQ_NEXT(pcsd, entry); 1207 } 1208 } 1209 1210 cuse_unlock(); 1211 break; 1212 1213 case CUSE_IOCTL_WRITE_DATA: 1214 case CUSE_IOCTL_READ_DATA: 1215 1216 cuse_lock(); 1217 pchk = (struct cuse_data_chunk *)data; 1218 1219 pccmd = cuse_server_find_command(pcs, curthread); 1220 1221 if (pccmd == NULL) { 1222 error = ENXIO; /* invalid request */ 1223 } else if (pchk->peer_ptr < CUSE_BUF_MIN_PTR) { 1224 error = EFAULT; /* NULL pointer */ 1225 } else if (pchk->peer_ptr < CUSE_BUF_MAX_PTR) { 1226 error = cuse_server_ioctl_copy_locked(pccmd, 1227 pchk, cmd == CUSE_IOCTL_READ_DATA); 1228 } else { 1229 error = cuse_server_data_copy_locked(pccmd, 1230 pchk, cmd == CUSE_IOCTL_READ_DATA); 1231 } 1232 cuse_unlock(); 1233 break; 1234 1235 case CUSE_IOCTL_SELWAKEUP: 1236 cuse_lock(); 1237 /* 1238 * We don't know which direction caused the event. 1239 * Wakeup both! 1240 */ 1241 TAILQ_FOREACH(pcc, &pcs->hcli, entry) { 1242 pcc->cflags |= (CUSE_CLI_KNOTE_NEED_READ | 1243 CUSE_CLI_KNOTE_NEED_WRITE); 1244 } 1245 cuse_server_wakeup_locked(pcs); 1246 cuse_unlock(); 1247 break; 1248 1249 default: 1250 error = ENXIO; 1251 break; 1252 } 1253 return (error); 1254 } 1255 1256 static int 1257 cuse_server_poll(struct cdev *dev, int events, struct thread *td) 1258 { 1259 return (events & (POLLHUP | POLLPRI | POLLIN | 1260 POLLRDNORM | POLLOUT | POLLWRNORM)); 1261 } 1262 1263 static int 1264 cuse_server_mmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr, int nprot, vm_memattr_t *memattr) 1265 { 1266 uint32_t page_nr = offset / PAGE_SIZE; 1267 uint32_t alloc_nr = page_nr / CUSE_ALLOC_PAGES_MAX; 1268 struct cuse_memory *mem; 1269 struct cuse_server *pcs; 1270 uint8_t *ptr; 1271 int error; 1272 1273 if (alloc_nr >= CUSE_ALLOC_UNIT_MAX) 1274 return (ENOMEM); 1275 1276 error = cuse_server_get(&pcs); 1277 if (error != 0) 1278 pcs = NULL; 1279 1280 cuse_lock(); 1281 mem = &cuse_mem[alloc_nr]; 1282 1283 /* try to enforce slight ownership */ 1284 if ((pcs != NULL) && (mem->owner != pcs)) { 1285 cuse_unlock(); 1286 return (EINVAL); 1287 } 1288 if (mem->virtaddr == NULL) { 1289 cuse_unlock(); 1290 return (ENOMEM); 1291 } 1292 if (mem->virtaddr == NBUSY) { 1293 cuse_unlock(); 1294 return (ENOMEM); 1295 } 1296 page_nr %= CUSE_ALLOC_PAGES_MAX; 1297 1298 if (page_nr >= mem->page_count) { 1299 cuse_unlock(); 1300 return (ENXIO); 1301 } 1302 ptr = mem->virtaddr + (page_nr * PAGE_SIZE); 1303 cuse_unlock(); 1304 1305 *paddr = vtophys(ptr); 1306 1307 return (0); 1308 } 1309 1310 /*------------------------------------------------------------------------* 1311 * CUSE CLIENT PART 1312 *------------------------------------------------------------------------*/ 1313 static void 1314 cuse_client_free(void *arg) 1315 { 1316 struct cuse_client *pcc = arg; 1317 struct cuse_client_command *pccmd; 1318 struct cuse_server *pcs; 1319 int n; 1320 1321 cuse_lock(); 1322 cuse_client_is_closing(pcc); 1323 TAILQ_REMOVE(&pcc->server->hcli, pcc, entry); 1324 cuse_unlock(); 1325 1326 for (n = 0; n != CUSE_CMD_MAX; n++) { 1327 1328 pccmd = &pcc->cmds[n]; 1329 1330 sx_destroy(&pccmd->sx); 1331 cv_destroy(&pccmd->cv); 1332 } 1333 1334 pcs = pcc->server; 1335 1336 free(pcc, M_CUSE); 1337 1338 /* drop reference on server */ 1339 cuse_server_free(pcs); 1340 } 1341 1342 static int 1343 cuse_client_open(struct cdev *dev, int fflags, int devtype, struct thread *td) 1344 { 1345 struct cuse_client_command *pccmd; 1346 struct cuse_server_dev *pcsd; 1347 struct cuse_client *pcc; 1348 struct cuse_server *pcs; 1349 struct cuse_dev *pcd; 1350 int error; 1351 int n; 1352 1353 cuse_lock(); 1354 pcsd = dev->si_drv1; 1355 if (pcsd != NULL) { 1356 pcs = pcsd->server; 1357 pcd = pcsd->user_dev; 1358 pcs->refs++; 1359 if (pcs->refs < 0) { 1360 /* overflow */ 1361 pcs->refs--; 1362 pcsd = NULL; 1363 } 1364 } else { 1365 pcs = NULL; 1366 pcd = NULL; 1367 } 1368 cuse_unlock(); 1369 1370 if (pcsd == NULL) 1371 return (EINVAL); 1372 1373 pcc = malloc(sizeof(*pcc), M_CUSE, M_WAITOK | M_ZERO); 1374 if (pcc == NULL) { 1375 /* drop reference on server */ 1376 cuse_server_free(pcs); 1377 return (ENOMEM); 1378 } 1379 if (devfs_set_cdevpriv(pcc, &cuse_client_free)) { 1380 printf("Cuse: Cannot set cdevpriv.\n"); 1381 /* drop reference on server */ 1382 cuse_server_free(pcs); 1383 free(pcc, M_CUSE); 1384 return (ENOMEM); 1385 } 1386 pcc->fflags = fflags; 1387 pcc->server_dev = pcsd; 1388 pcc->server = pcs; 1389 1390 for (n = 0; n != CUSE_CMD_MAX; n++) { 1391 1392 pccmd = &pcc->cmds[n]; 1393 1394 pccmd->sub.dev = pcd; 1395 pccmd->sub.command = n; 1396 pccmd->client = pcc; 1397 1398 sx_init(&pccmd->sx, "cuse-client-sx"); 1399 cv_init(&pccmd->cv, "cuse-client-cv"); 1400 } 1401 1402 cuse_lock(); 1403 1404 /* cuse_client_free() assumes that the client is listed somewhere! */ 1405 /* always enqueue */ 1406 1407 TAILQ_INSERT_TAIL(&pcs->hcli, pcc, entry); 1408 1409 /* check if server is closing */ 1410 if ((pcs->is_closing != 0) || (dev->si_drv1 == NULL)) { 1411 error = EINVAL; 1412 } else { 1413 error = 0; 1414 } 1415 cuse_unlock(); 1416 1417 if (error) { 1418 devfs_clear_cdevpriv(); /* XXX bugfix */ 1419 return (error); 1420 } 1421 pccmd = &pcc->cmds[CUSE_CMD_OPEN]; 1422 1423 cuse_cmd_lock(pccmd); 1424 1425 cuse_lock(); 1426 cuse_client_send_command_locked(pccmd, 0, 0, pcc->fflags, 0); 1427 1428 error = cuse_client_receive_command_locked(pccmd, 0, 0); 1429 cuse_unlock(); 1430 1431 if (error < 0) { 1432 error = cuse_convert_error(error); 1433 } else { 1434 error = 0; 1435 } 1436 1437 cuse_cmd_unlock(pccmd); 1438 1439 if (error) 1440 devfs_clear_cdevpriv(); /* XXX bugfix */ 1441 1442 return (error); 1443 } 1444 1445 static int 1446 cuse_client_close(struct cdev *dev, int fflag, int devtype, struct thread *td) 1447 { 1448 struct cuse_client_command *pccmd; 1449 struct cuse_client *pcc; 1450 int error; 1451 1452 error = cuse_client_get(&pcc); 1453 if (error != 0) 1454 return (0); 1455 1456 pccmd = &pcc->cmds[CUSE_CMD_CLOSE]; 1457 1458 cuse_cmd_lock(pccmd); 1459 1460 cuse_lock(); 1461 cuse_client_send_command_locked(pccmd, 0, 0, pcc->fflags, 0); 1462 1463 error = cuse_client_receive_command_locked(pccmd, 0, 0); 1464 cuse_unlock(); 1465 1466 cuse_cmd_unlock(pccmd); 1467 1468 cuse_lock(); 1469 cuse_client_is_closing(pcc); 1470 cuse_unlock(); 1471 1472 return (0); 1473 } 1474 1475 static void 1476 cuse_client_kqfilter_poll(struct cdev *dev, struct cuse_client *pcc) 1477 { 1478 int temp; 1479 1480 cuse_lock(); 1481 temp = (pcc->cflags & (CUSE_CLI_KNOTE_HAS_READ | 1482 CUSE_CLI_KNOTE_HAS_WRITE)); 1483 pcc->cflags &= ~(CUSE_CLI_KNOTE_NEED_READ | 1484 CUSE_CLI_KNOTE_NEED_WRITE); 1485 cuse_unlock(); 1486 1487 if (temp != 0) { 1488 /* get the latest polling state from the server */ 1489 temp = cuse_client_poll(dev, POLLIN | POLLOUT, NULL); 1490 1491 cuse_lock(); 1492 if (temp & (POLLIN | POLLOUT)) { 1493 if (temp & POLLIN) 1494 pcc->cflags |= CUSE_CLI_KNOTE_NEED_READ; 1495 if (temp & POLLOUT) 1496 pcc->cflags |= CUSE_CLI_KNOTE_NEED_WRITE; 1497 1498 /* make sure the "knote" gets woken up */ 1499 cuse_server_wakeup_locked(pcc->server); 1500 } 1501 cuse_unlock(); 1502 } 1503 } 1504 1505 static int 1506 cuse_client_read(struct cdev *dev, struct uio *uio, int ioflag) 1507 { 1508 struct cuse_client_command *pccmd; 1509 struct cuse_client *pcc; 1510 int error; 1511 int len; 1512 1513 error = cuse_client_get(&pcc); 1514 if (error != 0) 1515 return (error); 1516 1517 pccmd = &pcc->cmds[CUSE_CMD_READ]; 1518 1519 if (uio->uio_segflg != UIO_USERSPACE) { 1520 return (EINVAL); 1521 } 1522 uio->uio_segflg = UIO_NOCOPY; 1523 1524 cuse_cmd_lock(pccmd); 1525 1526 while (uio->uio_resid != 0) { 1527 1528 if (uio->uio_iov->iov_len > CUSE_LENGTH_MAX) { 1529 error = ENOMEM; 1530 break; 1531 } 1532 1533 len = uio->uio_iov->iov_len; 1534 1535 cuse_lock(); 1536 cuse_client_send_command_locked(pccmd, 1537 (unsigned long)uio->uio_iov->iov_base, 1538 (unsigned long)(unsigned int)len, pcc->fflags, ioflag); 1539 1540 error = cuse_client_receive_command_locked(pccmd, 0, 0); 1541 cuse_unlock(); 1542 1543 if (error < 0) { 1544 error = cuse_convert_error(error); 1545 break; 1546 } else if (error == len) { 1547 error = uiomove(NULL, error, uio); 1548 if (error) 1549 break; 1550 } else { 1551 error = uiomove(NULL, error, uio); 1552 break; 1553 } 1554 } 1555 cuse_cmd_unlock(pccmd); 1556 1557 uio->uio_segflg = UIO_USERSPACE;/* restore segment flag */ 1558 1559 if (error == EWOULDBLOCK) 1560 cuse_client_kqfilter_poll(dev, pcc); 1561 1562 return (error); 1563 } 1564 1565 static int 1566 cuse_client_write(struct cdev *dev, struct uio *uio, int ioflag) 1567 { 1568 struct cuse_client_command *pccmd; 1569 struct cuse_client *pcc; 1570 int error; 1571 int len; 1572 1573 error = cuse_client_get(&pcc); 1574 if (error != 0) 1575 return (error); 1576 1577 pccmd = &pcc->cmds[CUSE_CMD_WRITE]; 1578 1579 if (uio->uio_segflg != UIO_USERSPACE) { 1580 return (EINVAL); 1581 } 1582 uio->uio_segflg = UIO_NOCOPY; 1583 1584 cuse_cmd_lock(pccmd); 1585 1586 while (uio->uio_resid != 0) { 1587 1588 if (uio->uio_iov->iov_len > CUSE_LENGTH_MAX) { 1589 error = ENOMEM; 1590 break; 1591 } 1592 1593 len = uio->uio_iov->iov_len; 1594 1595 cuse_lock(); 1596 cuse_client_send_command_locked(pccmd, 1597 (unsigned long)uio->uio_iov->iov_base, 1598 (unsigned long)(unsigned int)len, pcc->fflags, ioflag); 1599 1600 error = cuse_client_receive_command_locked(pccmd, 0, 0); 1601 cuse_unlock(); 1602 1603 if (error < 0) { 1604 error = cuse_convert_error(error); 1605 break; 1606 } else if (error == len) { 1607 error = uiomove(NULL, error, uio); 1608 if (error) 1609 break; 1610 } else { 1611 error = uiomove(NULL, error, uio); 1612 break; 1613 } 1614 } 1615 cuse_cmd_unlock(pccmd); 1616 1617 uio->uio_segflg = UIO_USERSPACE;/* restore segment flag */ 1618 1619 if (error == EWOULDBLOCK) 1620 cuse_client_kqfilter_poll(dev, pcc); 1621 1622 return (error); 1623 } 1624 1625 int 1626 cuse_client_ioctl(struct cdev *dev, unsigned long cmd, 1627 caddr_t data, int fflag, struct thread *td) 1628 { 1629 struct cuse_client_command *pccmd; 1630 struct cuse_client *pcc; 1631 int error; 1632 int len; 1633 1634 error = cuse_client_get(&pcc); 1635 if (error != 0) 1636 return (error); 1637 1638 len = IOCPARM_LEN(cmd); 1639 if (len > CUSE_BUFFER_MAX) 1640 return (ENOMEM); 1641 1642 pccmd = &pcc->cmds[CUSE_CMD_IOCTL]; 1643 1644 cuse_cmd_lock(pccmd); 1645 1646 if (cmd & IOC_IN) 1647 memcpy(pcc->ioctl_buffer, data, len); 1648 1649 /* 1650 * When the ioctl-length is zero drivers can pass information 1651 * through the data pointer of the ioctl. Make sure this information 1652 * is forwarded to the driver. 1653 */ 1654 1655 cuse_lock(); 1656 cuse_client_send_command_locked(pccmd, 1657 (len == 0) ? *(long *)data : CUSE_BUF_MIN_PTR, 1658 (unsigned long)cmd, pcc->fflags, 1659 (fflag & O_NONBLOCK) ? IO_NDELAY : 0); 1660 1661 error = cuse_client_receive_command_locked(pccmd, data, len); 1662 cuse_unlock(); 1663 1664 if (error < 0) { 1665 error = cuse_convert_error(error); 1666 } else { 1667 error = 0; 1668 } 1669 1670 if (cmd & IOC_OUT) 1671 memcpy(data, pcc->ioctl_buffer, len); 1672 1673 cuse_cmd_unlock(pccmd); 1674 1675 if (error == EWOULDBLOCK) 1676 cuse_client_kqfilter_poll(dev, pcc); 1677 1678 return (error); 1679 } 1680 1681 static int 1682 cuse_client_poll(struct cdev *dev, int events, struct thread *td) 1683 { 1684 struct cuse_client_command *pccmd; 1685 struct cuse_client *pcc; 1686 unsigned long temp; 1687 int error; 1688 int revents; 1689 1690 error = cuse_client_get(&pcc); 1691 if (error != 0) 1692 return (POLLNVAL); 1693 1694 temp = 0; 1695 1696 if (events & (POLLPRI | POLLIN | POLLRDNORM)) 1697 temp |= CUSE_POLL_READ; 1698 1699 if (events & (POLLOUT | POLLWRNORM)) 1700 temp |= CUSE_POLL_WRITE; 1701 1702 if (events & POLLHUP) 1703 temp |= CUSE_POLL_ERROR; 1704 1705 pccmd = &pcc->cmds[CUSE_CMD_POLL]; 1706 1707 cuse_cmd_lock(pccmd); 1708 1709 /* Need to selrecord() first to not loose any events. */ 1710 if (temp != 0 && td != NULL) 1711 selrecord(td, &pcc->server->selinfo); 1712 1713 cuse_lock(); 1714 cuse_client_send_command_locked(pccmd, 1715 0, temp, pcc->fflags, IO_NDELAY); 1716 1717 error = cuse_client_receive_command_locked(pccmd, 0, 0); 1718 cuse_unlock(); 1719 1720 if (error < 0) { 1721 revents = POLLNVAL; 1722 } else { 1723 revents = 0; 1724 if (error & CUSE_POLL_READ) 1725 revents |= (events & (POLLPRI | POLLIN | POLLRDNORM)); 1726 if (error & CUSE_POLL_WRITE) 1727 revents |= (events & (POLLOUT | POLLWRNORM)); 1728 if (error & CUSE_POLL_ERROR) 1729 revents |= (events & POLLHUP); 1730 } 1731 1732 cuse_cmd_unlock(pccmd); 1733 1734 return (revents); 1735 } 1736 1737 static int 1738 cuse_client_mmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr, int nprot, vm_memattr_t *memattr) 1739 { 1740 uint32_t page_nr = offset / PAGE_SIZE; 1741 uint32_t alloc_nr = page_nr / CUSE_ALLOC_PAGES_MAX; 1742 struct cuse_memory *mem; 1743 struct cuse_server *pcs; 1744 struct cuse_client *pcc; 1745 uint8_t *ptr; 1746 int error; 1747 1748 if (alloc_nr >= CUSE_ALLOC_UNIT_MAX) 1749 return (ENOMEM); 1750 1751 error = cuse_client_get(&pcc); 1752 if (error != 0) 1753 pcs = NULL; 1754 else 1755 pcs = pcc->server; 1756 1757 cuse_lock(); 1758 mem = &cuse_mem[alloc_nr]; 1759 1760 /* try to enforce slight ownership */ 1761 if ((pcs != NULL) && (mem->owner != pcs)) { 1762 cuse_unlock(); 1763 return (EINVAL); 1764 } 1765 if (mem->virtaddr == NULL) { 1766 cuse_unlock(); 1767 return (ENOMEM); 1768 } 1769 if (mem->virtaddr == NBUSY) { 1770 cuse_unlock(); 1771 return (ENOMEM); 1772 } 1773 page_nr %= CUSE_ALLOC_PAGES_MAX; 1774 1775 if (page_nr >= mem->page_count) { 1776 cuse_unlock(); 1777 return (ENXIO); 1778 } 1779 ptr = mem->virtaddr + (page_nr * PAGE_SIZE); 1780 cuse_unlock(); 1781 1782 *paddr = vtophys(ptr); 1783 1784 return (0); 1785 } 1786 1787 static void 1788 cuse_client_kqfilter_read_detach(struct knote *kn) 1789 { 1790 struct cuse_client *pcc; 1791 1792 cuse_lock(); 1793 pcc = kn->kn_hook; 1794 knlist_remove(&pcc->server->selinfo.si_note, kn, 1); 1795 cuse_unlock(); 1796 } 1797 1798 static void 1799 cuse_client_kqfilter_write_detach(struct knote *kn) 1800 { 1801 struct cuse_client *pcc; 1802 1803 cuse_lock(); 1804 pcc = kn->kn_hook; 1805 knlist_remove(&pcc->server->selinfo.si_note, kn, 1); 1806 cuse_unlock(); 1807 } 1808 1809 static int 1810 cuse_client_kqfilter_read_event(struct knote *kn, long hint) 1811 { 1812 struct cuse_client *pcc; 1813 1814 mtx_assert(&cuse_mtx, MA_OWNED); 1815 1816 pcc = kn->kn_hook; 1817 return ((pcc->cflags & CUSE_CLI_KNOTE_NEED_READ) ? 1 : 0); 1818 } 1819 1820 static int 1821 cuse_client_kqfilter_write_event(struct knote *kn, long hint) 1822 { 1823 struct cuse_client *pcc; 1824 1825 mtx_assert(&cuse_mtx, MA_OWNED); 1826 1827 pcc = kn->kn_hook; 1828 return ((pcc->cflags & CUSE_CLI_KNOTE_NEED_WRITE) ? 1 : 0); 1829 } 1830 1831 static int 1832 cuse_client_kqfilter(struct cdev *dev, struct knote *kn) 1833 { 1834 struct cuse_client *pcc; 1835 struct cuse_server *pcs; 1836 int error; 1837 1838 error = cuse_client_get(&pcc); 1839 if (error != 0) 1840 return (error); 1841 1842 cuse_lock(); 1843 pcs = pcc->server; 1844 switch (kn->kn_filter) { 1845 case EVFILT_READ: 1846 pcc->cflags |= CUSE_CLI_KNOTE_HAS_READ; 1847 kn->kn_hook = pcc; 1848 kn->kn_fop = &cuse_client_kqfilter_read_ops; 1849 knlist_add(&pcs->selinfo.si_note, kn, 1); 1850 break; 1851 case EVFILT_WRITE: 1852 pcc->cflags |= CUSE_CLI_KNOTE_HAS_WRITE; 1853 kn->kn_hook = pcc; 1854 kn->kn_fop = &cuse_client_kqfilter_write_ops; 1855 knlist_add(&pcs->selinfo.si_note, kn, 1); 1856 break; 1857 default: 1858 error = EINVAL; 1859 break; 1860 } 1861 cuse_unlock(); 1862 1863 if (error == 0) 1864 cuse_client_kqfilter_poll(dev, pcc); 1865 return (error); 1866 } 1867