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 PHOLD(proc_s); 817 error = proc_rwmem(proc_s, &uio); 818 PRELE(proc_s); 819 820 } else if (proc_cur == proc_s) { 821 struct iovec iov = { 822 .iov_base = (caddr_t)data_s, 823 .iov_len = len, 824 }; 825 struct uio uio = { 826 .uio_iov = &iov, 827 .uio_iovcnt = 1, 828 .uio_offset = (off_t)data_d, 829 .uio_resid = len, 830 .uio_segflg = UIO_USERSPACE, 831 .uio_rw = UIO_WRITE, 832 .uio_td = td, 833 }; 834 835 PHOLD(proc_d); 836 error = proc_rwmem(proc_d, &uio); 837 PRELE(proc_d); 838 } else { 839 error = EINVAL; 840 } 841 return (error); 842 } 843 844 static int 845 cuse_server_data_copy_locked(struct cuse_client_command *pccmd, 846 struct cuse_data_chunk *pchk, int isread) 847 { 848 struct proc *p_proc; 849 int error; 850 851 p_proc = pccmd->proc_curr; 852 if (p_proc == NULL) 853 return (ENXIO); 854 855 if (pccmd->proc_refs < 0) 856 return (ENOMEM); 857 858 pccmd->proc_refs++; 859 860 cuse_unlock(); 861 862 if (isread == 0) { 863 error = cuse_proc2proc_copy( 864 curthread->td_proc, pchk->local_ptr, 865 p_proc, pchk->peer_ptr, 866 pchk->length); 867 } else { 868 error = cuse_proc2proc_copy( 869 p_proc, pchk->peer_ptr, 870 curthread->td_proc, pchk->local_ptr, 871 pchk->length); 872 } 873 874 cuse_lock(); 875 876 pccmd->proc_refs--; 877 878 if (pccmd->proc_curr == NULL) 879 cv_signal(&pccmd->cv); 880 881 return (error); 882 } 883 884 static int 885 cuse_alloc_unit_by_id_locked(struct cuse_server *pcs, int id) 886 { 887 int n; 888 int x = 0; 889 int match; 890 891 do { 892 for (match = n = 0; n != CUSE_DEVICES_MAX; n++) { 893 if (cuse_alloc_unit[n] != NULL) { 894 if ((cuse_alloc_unit_id[n] ^ id) & CUSE_ID_MASK) 895 continue; 896 if ((cuse_alloc_unit_id[n] & ~CUSE_ID_MASK) == x) { 897 x++; 898 match = 1; 899 } 900 } 901 } 902 } while (match); 903 904 if (x < 256) { 905 for (n = 0; n != CUSE_DEVICES_MAX; n++) { 906 if (cuse_alloc_unit[n] == NULL) { 907 cuse_alloc_unit[n] = pcs; 908 cuse_alloc_unit_id[n] = id | x; 909 return (x); 910 } 911 } 912 } 913 return (-1); 914 } 915 916 static void 917 cuse_server_wakeup_locked(struct cuse_server *pcs) 918 { 919 selwakeup(&pcs->selinfo); 920 KNOTE_LOCKED(&pcs->selinfo.si_note, 0); 921 } 922 923 static int 924 cuse_free_unit_by_id_locked(struct cuse_server *pcs, int id) 925 { 926 int n; 927 int found = 0; 928 929 for (n = 0; n != CUSE_DEVICES_MAX; n++) { 930 if (cuse_alloc_unit[n] == pcs) { 931 if (cuse_alloc_unit_id[n] == id || id == -1) { 932 cuse_alloc_unit[n] = NULL; 933 cuse_alloc_unit_id[n] = 0; 934 found = 1; 935 } 936 } 937 } 938 939 return (found ? 0 : EINVAL); 940 } 941 942 static int 943 cuse_server_ioctl(struct cdev *dev, unsigned long cmd, 944 caddr_t data, int fflag, struct thread *td) 945 { 946 struct cuse_server *pcs; 947 int error; 948 949 error = cuse_server_get(&pcs); 950 if (error != 0) 951 return (error); 952 953 switch (cmd) { 954 struct cuse_client_command *pccmd; 955 struct cuse_client *pcc; 956 struct cuse_command *pcmd; 957 struct cuse_alloc_info *pai; 958 struct cuse_create_dev *pcd; 959 struct cuse_server_dev *pcsd; 960 struct cuse_data_chunk *pchk; 961 int n; 962 963 case CUSE_IOCTL_GET_COMMAND: 964 pcmd = (void *)data; 965 966 cuse_lock(); 967 968 while ((pccmd = TAILQ_FIRST(&pcs->head)) == NULL) { 969 error = cv_wait_sig(&pcs->cv, &cuse_mtx); 970 971 if (pcs->is_closing) 972 error = ENXIO; 973 974 if (error) { 975 cuse_unlock(); 976 return (error); 977 } 978 } 979 980 TAILQ_REMOVE(&pcs->head, pccmd, entry); 981 pccmd->entry.tqe_prev = NULL; 982 983 pccmd->entered = curthread; 984 985 *pcmd = pccmd->sub; 986 987 cuse_unlock(); 988 989 break; 990 991 case CUSE_IOCTL_SYNC_COMMAND: 992 993 cuse_lock(); 994 while ((pccmd = cuse_server_find_command(pcs, curthread)) != NULL) { 995 996 /* send sync command */ 997 pccmd->entered = NULL; 998 pccmd->error = *(int *)data; 999 pccmd->command = CUSE_CMD_SYNC; 1000 1001 /* signal peer, if any */ 1002 cv_signal(&pccmd->cv); 1003 } 1004 cuse_unlock(); 1005 1006 break; 1007 1008 case CUSE_IOCTL_ALLOC_UNIT: 1009 1010 cuse_lock(); 1011 n = cuse_alloc_unit_by_id_locked(pcs, 1012 CUSE_ID_DEFAULT(0)); 1013 cuse_unlock(); 1014 1015 if (n < 0) 1016 error = ENOMEM; 1017 else 1018 *(int *)data = n; 1019 break; 1020 1021 case CUSE_IOCTL_ALLOC_UNIT_BY_ID: 1022 1023 n = *(int *)data; 1024 1025 n = (n & CUSE_ID_MASK); 1026 1027 cuse_lock(); 1028 n = cuse_alloc_unit_by_id_locked(pcs, n); 1029 cuse_unlock(); 1030 1031 if (n < 0) 1032 error = ENOMEM; 1033 else 1034 *(int *)data = n; 1035 break; 1036 1037 case CUSE_IOCTL_FREE_UNIT: 1038 1039 n = *(int *)data; 1040 1041 n = CUSE_ID_DEFAULT(n); 1042 1043 cuse_lock(); 1044 error = cuse_free_unit_by_id_locked(pcs, n); 1045 cuse_unlock(); 1046 break; 1047 1048 case CUSE_IOCTL_FREE_UNIT_BY_ID: 1049 1050 n = *(int *)data; 1051 1052 cuse_lock(); 1053 error = cuse_free_unit_by_id_locked(pcs, n); 1054 cuse_unlock(); 1055 break; 1056 1057 case CUSE_IOCTL_ALLOC_MEMORY: 1058 1059 pai = (void *)data; 1060 1061 if (pai->alloc_nr >= CUSE_ALLOC_UNIT_MAX) { 1062 error = ENOMEM; 1063 break; 1064 } 1065 if (pai->page_count > CUSE_ALLOC_PAGES_MAX) { 1066 error = ENOMEM; 1067 break; 1068 } 1069 error = cuse_server_alloc_memory(pcs, 1070 &cuse_mem[pai->alloc_nr], pai->page_count); 1071 break; 1072 1073 case CUSE_IOCTL_FREE_MEMORY: 1074 pai = (void *)data; 1075 1076 if (pai->alloc_nr >= CUSE_ALLOC_UNIT_MAX) { 1077 error = ENOMEM; 1078 break; 1079 } 1080 /* we trust the character device driver in this case */ 1081 1082 cuse_lock(); 1083 if (cuse_mem[pai->alloc_nr].owner == pcs) { 1084 cuse_mem[pai->alloc_nr].is_allocated = 0; 1085 cuse_mem[pai->alloc_nr].owner = NULL; 1086 } else { 1087 error = EINVAL; 1088 } 1089 cuse_unlock(); 1090 break; 1091 1092 case CUSE_IOCTL_GET_SIG: 1093 1094 cuse_lock(); 1095 pccmd = cuse_server_find_command(pcs, curthread); 1096 1097 if (pccmd != NULL) { 1098 n = pccmd->got_signal; 1099 pccmd->got_signal = 0; 1100 } else { 1101 n = 0; 1102 } 1103 cuse_unlock(); 1104 1105 *(int *)data = n; 1106 1107 break; 1108 1109 case CUSE_IOCTL_SET_PFH: 1110 1111 cuse_lock(); 1112 pccmd = cuse_server_find_command(pcs, curthread); 1113 1114 if (pccmd != NULL) { 1115 pcc = pccmd->client; 1116 for (n = 0; n != CUSE_CMD_MAX; n++) { 1117 pcc->cmds[n].sub.per_file_handle = *(unsigned long *)data; 1118 } 1119 } else { 1120 error = ENXIO; 1121 } 1122 cuse_unlock(); 1123 break; 1124 1125 case CUSE_IOCTL_CREATE_DEV: 1126 1127 error = priv_check(curthread, PRIV_DRIVER); 1128 if (error) 1129 break; 1130 1131 pcd = (void *)data; 1132 1133 /* filter input */ 1134 1135 pcd->devname[sizeof(pcd->devname) - 1] = 0; 1136 1137 if (pcd->devname[0] == 0) { 1138 error = EINVAL; 1139 break; 1140 } 1141 cuse_str_filter(pcd->devname); 1142 1143 pcd->permissions &= 0777; 1144 1145 /* try to allocate a character device */ 1146 1147 pcsd = malloc(sizeof(*pcsd), M_CUSE, M_WAITOK | M_ZERO); 1148 1149 if (pcsd == NULL) { 1150 error = ENOMEM; 1151 break; 1152 } 1153 pcsd->server = pcs; 1154 1155 pcsd->user_dev = pcd->dev; 1156 1157 pcsd->kern_dev = make_dev_credf(MAKEDEV_CHECKNAME, 1158 &cuse_client_devsw, 0, NULL, pcd->user_id, pcd->group_id, 1159 pcd->permissions, "%s", pcd->devname); 1160 1161 if (pcsd->kern_dev == NULL) { 1162 free(pcsd, M_CUSE); 1163 error = ENOMEM; 1164 break; 1165 } 1166 pcsd->kern_dev->si_drv1 = pcsd; 1167 1168 cuse_lock(); 1169 TAILQ_INSERT_TAIL(&pcs->hdev, pcsd, entry); 1170 cuse_unlock(); 1171 1172 break; 1173 1174 case CUSE_IOCTL_DESTROY_DEV: 1175 1176 error = priv_check(curthread, PRIV_DRIVER); 1177 if (error) 1178 break; 1179 1180 cuse_lock(); 1181 1182 error = EINVAL; 1183 1184 pcsd = TAILQ_FIRST(&pcs->hdev); 1185 while (pcsd != NULL) { 1186 if (pcsd->user_dev == *(struct cuse_dev **)data) { 1187 TAILQ_REMOVE(&pcs->hdev, pcsd, entry); 1188 cuse_unlock(); 1189 cuse_server_free_dev(pcsd); 1190 cuse_lock(); 1191 error = 0; 1192 pcsd = TAILQ_FIRST(&pcs->hdev); 1193 } else { 1194 pcsd = TAILQ_NEXT(pcsd, entry); 1195 } 1196 } 1197 1198 cuse_unlock(); 1199 break; 1200 1201 case CUSE_IOCTL_WRITE_DATA: 1202 case CUSE_IOCTL_READ_DATA: 1203 1204 cuse_lock(); 1205 pchk = (struct cuse_data_chunk *)data; 1206 1207 pccmd = cuse_server_find_command(pcs, curthread); 1208 1209 if (pccmd == NULL) { 1210 error = ENXIO; /* invalid request */ 1211 } else if (pchk->peer_ptr < CUSE_BUF_MIN_PTR) { 1212 error = EFAULT; /* NULL pointer */ 1213 } else if (pchk->peer_ptr < CUSE_BUF_MAX_PTR) { 1214 error = cuse_server_ioctl_copy_locked(pccmd, 1215 pchk, cmd == CUSE_IOCTL_READ_DATA); 1216 } else { 1217 error = cuse_server_data_copy_locked(pccmd, 1218 pchk, cmd == CUSE_IOCTL_READ_DATA); 1219 } 1220 cuse_unlock(); 1221 break; 1222 1223 case CUSE_IOCTL_SELWAKEUP: 1224 cuse_lock(); 1225 /* 1226 * We don't know which direction caused the event. 1227 * Wakeup both! 1228 */ 1229 TAILQ_FOREACH(pcc, &pcs->hcli, entry) { 1230 pcc->cflags |= (CUSE_CLI_KNOTE_NEED_READ | 1231 CUSE_CLI_KNOTE_NEED_WRITE); 1232 } 1233 cuse_server_wakeup_locked(pcs); 1234 cuse_unlock(); 1235 break; 1236 1237 default: 1238 error = ENXIO; 1239 break; 1240 } 1241 return (error); 1242 } 1243 1244 static int 1245 cuse_server_poll(struct cdev *dev, int events, struct thread *td) 1246 { 1247 return (events & (POLLHUP | POLLPRI | POLLIN | 1248 POLLRDNORM | POLLOUT | POLLWRNORM)); 1249 } 1250 1251 static int 1252 cuse_server_mmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr, int nprot, vm_memattr_t *memattr) 1253 { 1254 uint32_t page_nr = offset / PAGE_SIZE; 1255 uint32_t alloc_nr = page_nr / CUSE_ALLOC_PAGES_MAX; 1256 struct cuse_memory *mem; 1257 struct cuse_server *pcs; 1258 uint8_t *ptr; 1259 int error; 1260 1261 if (alloc_nr >= CUSE_ALLOC_UNIT_MAX) 1262 return (ENOMEM); 1263 1264 error = cuse_server_get(&pcs); 1265 if (error != 0) 1266 pcs = NULL; 1267 1268 cuse_lock(); 1269 mem = &cuse_mem[alloc_nr]; 1270 1271 /* try to enforce slight ownership */ 1272 if ((pcs != NULL) && (mem->owner != pcs)) { 1273 cuse_unlock(); 1274 return (EINVAL); 1275 } 1276 if (mem->virtaddr == NULL) { 1277 cuse_unlock(); 1278 return (ENOMEM); 1279 } 1280 if (mem->virtaddr == NBUSY) { 1281 cuse_unlock(); 1282 return (ENOMEM); 1283 } 1284 page_nr %= CUSE_ALLOC_PAGES_MAX; 1285 1286 if (page_nr >= mem->page_count) { 1287 cuse_unlock(); 1288 return (ENXIO); 1289 } 1290 ptr = mem->virtaddr + (page_nr * PAGE_SIZE); 1291 cuse_unlock(); 1292 1293 *paddr = vtophys(ptr); 1294 1295 return (0); 1296 } 1297 1298 /*------------------------------------------------------------------------* 1299 * CUSE CLIENT PART 1300 *------------------------------------------------------------------------*/ 1301 static void 1302 cuse_client_free(void *arg) 1303 { 1304 struct cuse_client *pcc = arg; 1305 struct cuse_client_command *pccmd; 1306 struct cuse_server *pcs; 1307 int n; 1308 1309 cuse_lock(); 1310 cuse_client_is_closing(pcc); 1311 TAILQ_REMOVE(&pcc->server->hcli, pcc, entry); 1312 cuse_unlock(); 1313 1314 for (n = 0; n != CUSE_CMD_MAX; n++) { 1315 1316 pccmd = &pcc->cmds[n]; 1317 1318 sx_destroy(&pccmd->sx); 1319 cv_destroy(&pccmd->cv); 1320 } 1321 1322 pcs = pcc->server; 1323 1324 free(pcc, M_CUSE); 1325 1326 /* drop reference on server */ 1327 cuse_server_free(pcs); 1328 } 1329 1330 static int 1331 cuse_client_open(struct cdev *dev, int fflags, int devtype, struct thread *td) 1332 { 1333 struct cuse_client_command *pccmd; 1334 struct cuse_server_dev *pcsd; 1335 struct cuse_client *pcc; 1336 struct cuse_server *pcs; 1337 struct cuse_dev *pcd; 1338 int error; 1339 int n; 1340 1341 cuse_lock(); 1342 pcsd = dev->si_drv1; 1343 if (pcsd != NULL) { 1344 pcs = pcsd->server; 1345 pcd = pcsd->user_dev; 1346 pcs->refs++; 1347 if (pcs->refs < 0) { 1348 /* overflow */ 1349 pcs->refs--; 1350 pcsd = NULL; 1351 } 1352 } else { 1353 pcs = NULL; 1354 pcd = NULL; 1355 } 1356 cuse_unlock(); 1357 1358 if (pcsd == NULL) 1359 return (EINVAL); 1360 1361 pcc = malloc(sizeof(*pcc), M_CUSE, M_WAITOK | M_ZERO); 1362 if (pcc == NULL) { 1363 /* drop reference on server */ 1364 cuse_server_free(pcs); 1365 return (ENOMEM); 1366 } 1367 if (devfs_set_cdevpriv(pcc, &cuse_client_free)) { 1368 printf("Cuse: Cannot set cdevpriv.\n"); 1369 /* drop reference on server */ 1370 cuse_server_free(pcs); 1371 free(pcc, M_CUSE); 1372 return (ENOMEM); 1373 } 1374 pcc->fflags = fflags; 1375 pcc->server_dev = pcsd; 1376 pcc->server = pcs; 1377 1378 for (n = 0; n != CUSE_CMD_MAX; n++) { 1379 1380 pccmd = &pcc->cmds[n]; 1381 1382 pccmd->sub.dev = pcd; 1383 pccmd->sub.command = n; 1384 pccmd->client = pcc; 1385 1386 sx_init(&pccmd->sx, "cuse-client-sx"); 1387 cv_init(&pccmd->cv, "cuse-client-cv"); 1388 } 1389 1390 cuse_lock(); 1391 1392 /* cuse_client_free() assumes that the client is listed somewhere! */ 1393 /* always enqueue */ 1394 1395 TAILQ_INSERT_TAIL(&pcs->hcli, pcc, entry); 1396 1397 /* check if server is closing */ 1398 if ((pcs->is_closing != 0) || (dev->si_drv1 == NULL)) { 1399 error = EINVAL; 1400 } else { 1401 error = 0; 1402 } 1403 cuse_unlock(); 1404 1405 if (error) { 1406 devfs_clear_cdevpriv(); /* XXX bugfix */ 1407 return (error); 1408 } 1409 pccmd = &pcc->cmds[CUSE_CMD_OPEN]; 1410 1411 cuse_cmd_lock(pccmd); 1412 1413 cuse_lock(); 1414 cuse_client_send_command_locked(pccmd, 0, 0, pcc->fflags, 0); 1415 1416 error = cuse_client_receive_command_locked(pccmd, 0, 0); 1417 cuse_unlock(); 1418 1419 if (error < 0) { 1420 error = cuse_convert_error(error); 1421 } else { 1422 error = 0; 1423 } 1424 1425 cuse_cmd_unlock(pccmd); 1426 1427 if (error) 1428 devfs_clear_cdevpriv(); /* XXX bugfix */ 1429 1430 return (error); 1431 } 1432 1433 static int 1434 cuse_client_close(struct cdev *dev, int fflag, int devtype, struct thread *td) 1435 { 1436 struct cuse_client_command *pccmd; 1437 struct cuse_client *pcc; 1438 int error; 1439 1440 error = cuse_client_get(&pcc); 1441 if (error != 0) 1442 return (0); 1443 1444 pccmd = &pcc->cmds[CUSE_CMD_CLOSE]; 1445 1446 cuse_cmd_lock(pccmd); 1447 1448 cuse_lock(); 1449 cuse_client_send_command_locked(pccmd, 0, 0, pcc->fflags, 0); 1450 1451 error = cuse_client_receive_command_locked(pccmd, 0, 0); 1452 cuse_unlock(); 1453 1454 cuse_cmd_unlock(pccmd); 1455 1456 cuse_lock(); 1457 cuse_client_is_closing(pcc); 1458 cuse_unlock(); 1459 1460 return (0); 1461 } 1462 1463 static void 1464 cuse_client_kqfilter_poll(struct cdev *dev, struct cuse_client *pcc) 1465 { 1466 int temp; 1467 1468 cuse_lock(); 1469 temp = (pcc->cflags & (CUSE_CLI_KNOTE_HAS_READ | 1470 CUSE_CLI_KNOTE_HAS_WRITE)); 1471 pcc->cflags &= ~(CUSE_CLI_KNOTE_NEED_READ | 1472 CUSE_CLI_KNOTE_NEED_WRITE); 1473 cuse_unlock(); 1474 1475 if (temp != 0) { 1476 /* get the latest polling state from the server */ 1477 temp = cuse_client_poll(dev, POLLIN | POLLOUT, NULL); 1478 1479 cuse_lock(); 1480 if (temp & (POLLIN | POLLOUT)) { 1481 if (temp & POLLIN) 1482 pcc->cflags |= CUSE_CLI_KNOTE_NEED_READ; 1483 if (temp & POLLOUT) 1484 pcc->cflags |= CUSE_CLI_KNOTE_NEED_WRITE; 1485 1486 /* make sure the "knote" gets woken up */ 1487 cuse_server_wakeup_locked(pcc->server); 1488 } 1489 cuse_unlock(); 1490 } 1491 } 1492 1493 static int 1494 cuse_client_read(struct cdev *dev, struct uio *uio, int ioflag) 1495 { 1496 struct cuse_client_command *pccmd; 1497 struct cuse_client *pcc; 1498 int error; 1499 int len; 1500 1501 error = cuse_client_get(&pcc); 1502 if (error != 0) 1503 return (error); 1504 1505 pccmd = &pcc->cmds[CUSE_CMD_READ]; 1506 1507 if (uio->uio_segflg != UIO_USERSPACE) { 1508 return (EINVAL); 1509 } 1510 uio->uio_segflg = UIO_NOCOPY; 1511 1512 cuse_cmd_lock(pccmd); 1513 1514 while (uio->uio_resid != 0) { 1515 1516 if (uio->uio_iov->iov_len > CUSE_LENGTH_MAX) { 1517 error = ENOMEM; 1518 break; 1519 } 1520 1521 len = uio->uio_iov->iov_len; 1522 1523 cuse_lock(); 1524 cuse_client_send_command_locked(pccmd, 1525 (unsigned long)uio->uio_iov->iov_base, 1526 (unsigned long)(unsigned int)len, pcc->fflags, ioflag); 1527 1528 error = cuse_client_receive_command_locked(pccmd, 0, 0); 1529 cuse_unlock(); 1530 1531 if (error < 0) { 1532 error = cuse_convert_error(error); 1533 break; 1534 } else if (error == len) { 1535 error = uiomove(NULL, error, uio); 1536 if (error) 1537 break; 1538 } else { 1539 error = uiomove(NULL, error, uio); 1540 break; 1541 } 1542 } 1543 cuse_cmd_unlock(pccmd); 1544 1545 uio->uio_segflg = UIO_USERSPACE;/* restore segment flag */ 1546 1547 if (error == EWOULDBLOCK) 1548 cuse_client_kqfilter_poll(dev, pcc); 1549 1550 return (error); 1551 } 1552 1553 static int 1554 cuse_client_write(struct cdev *dev, struct uio *uio, int ioflag) 1555 { 1556 struct cuse_client_command *pccmd; 1557 struct cuse_client *pcc; 1558 int error; 1559 int len; 1560 1561 error = cuse_client_get(&pcc); 1562 if (error != 0) 1563 return (error); 1564 1565 pccmd = &pcc->cmds[CUSE_CMD_WRITE]; 1566 1567 if (uio->uio_segflg != UIO_USERSPACE) { 1568 return (EINVAL); 1569 } 1570 uio->uio_segflg = UIO_NOCOPY; 1571 1572 cuse_cmd_lock(pccmd); 1573 1574 while (uio->uio_resid != 0) { 1575 1576 if (uio->uio_iov->iov_len > CUSE_LENGTH_MAX) { 1577 error = ENOMEM; 1578 break; 1579 } 1580 1581 len = uio->uio_iov->iov_len; 1582 1583 cuse_lock(); 1584 cuse_client_send_command_locked(pccmd, 1585 (unsigned long)uio->uio_iov->iov_base, 1586 (unsigned long)(unsigned int)len, pcc->fflags, ioflag); 1587 1588 error = cuse_client_receive_command_locked(pccmd, 0, 0); 1589 cuse_unlock(); 1590 1591 if (error < 0) { 1592 error = cuse_convert_error(error); 1593 break; 1594 } else if (error == len) { 1595 error = uiomove(NULL, error, uio); 1596 if (error) 1597 break; 1598 } else { 1599 error = uiomove(NULL, error, uio); 1600 break; 1601 } 1602 } 1603 cuse_cmd_unlock(pccmd); 1604 1605 uio->uio_segflg = UIO_USERSPACE;/* restore segment flag */ 1606 1607 if (error == EWOULDBLOCK) 1608 cuse_client_kqfilter_poll(dev, pcc); 1609 1610 return (error); 1611 } 1612 1613 int 1614 cuse_client_ioctl(struct cdev *dev, unsigned long cmd, 1615 caddr_t data, int fflag, struct thread *td) 1616 { 1617 struct cuse_client_command *pccmd; 1618 struct cuse_client *pcc; 1619 int error; 1620 int len; 1621 1622 error = cuse_client_get(&pcc); 1623 if (error != 0) 1624 return (error); 1625 1626 len = IOCPARM_LEN(cmd); 1627 if (len > CUSE_BUFFER_MAX) 1628 return (ENOMEM); 1629 1630 pccmd = &pcc->cmds[CUSE_CMD_IOCTL]; 1631 1632 cuse_cmd_lock(pccmd); 1633 1634 if (cmd & IOC_IN) 1635 memcpy(pcc->ioctl_buffer, data, len); 1636 1637 /* 1638 * When the ioctl-length is zero drivers can pass information 1639 * through the data pointer of the ioctl. Make sure this information 1640 * is forwarded to the driver. 1641 */ 1642 1643 cuse_lock(); 1644 cuse_client_send_command_locked(pccmd, 1645 (len == 0) ? *(long *)data : CUSE_BUF_MIN_PTR, 1646 (unsigned long)cmd, pcc->fflags, 1647 (fflag & O_NONBLOCK) ? IO_NDELAY : 0); 1648 1649 error = cuse_client_receive_command_locked(pccmd, data, len); 1650 cuse_unlock(); 1651 1652 if (error < 0) { 1653 error = cuse_convert_error(error); 1654 } else { 1655 error = 0; 1656 } 1657 1658 if (cmd & IOC_OUT) 1659 memcpy(data, pcc->ioctl_buffer, len); 1660 1661 cuse_cmd_unlock(pccmd); 1662 1663 if (error == EWOULDBLOCK) 1664 cuse_client_kqfilter_poll(dev, pcc); 1665 1666 return (error); 1667 } 1668 1669 static int 1670 cuse_client_poll(struct cdev *dev, int events, struct thread *td) 1671 { 1672 struct cuse_client_command *pccmd; 1673 struct cuse_client *pcc; 1674 unsigned long temp; 1675 int error; 1676 int revents; 1677 1678 error = cuse_client_get(&pcc); 1679 if (error != 0) 1680 return (POLLNVAL); 1681 1682 temp = 0; 1683 1684 if (events & (POLLPRI | POLLIN | POLLRDNORM)) 1685 temp |= CUSE_POLL_READ; 1686 1687 if (events & (POLLOUT | POLLWRNORM)) 1688 temp |= CUSE_POLL_WRITE; 1689 1690 if (events & POLLHUP) 1691 temp |= CUSE_POLL_ERROR; 1692 1693 pccmd = &pcc->cmds[CUSE_CMD_POLL]; 1694 1695 cuse_cmd_lock(pccmd); 1696 1697 /* Need to selrecord() first to not loose any events. */ 1698 if (temp != 0 && td != NULL) 1699 selrecord(td, &pcc->server->selinfo); 1700 1701 cuse_lock(); 1702 cuse_client_send_command_locked(pccmd, 1703 0, temp, pcc->fflags, IO_NDELAY); 1704 1705 error = cuse_client_receive_command_locked(pccmd, 0, 0); 1706 cuse_unlock(); 1707 1708 if (error < 0) { 1709 revents = POLLNVAL; 1710 } else { 1711 revents = 0; 1712 if (error & CUSE_POLL_READ) 1713 revents |= (events & (POLLPRI | POLLIN | POLLRDNORM)); 1714 if (error & CUSE_POLL_WRITE) 1715 revents |= (events & (POLLOUT | POLLWRNORM)); 1716 if (error & CUSE_POLL_ERROR) 1717 revents |= (events & POLLHUP); 1718 } 1719 1720 cuse_cmd_unlock(pccmd); 1721 1722 return (revents); 1723 } 1724 1725 static int 1726 cuse_client_mmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr, int nprot, vm_memattr_t *memattr) 1727 { 1728 uint32_t page_nr = offset / PAGE_SIZE; 1729 uint32_t alloc_nr = page_nr / CUSE_ALLOC_PAGES_MAX; 1730 struct cuse_memory *mem; 1731 struct cuse_server *pcs; 1732 struct cuse_client *pcc; 1733 uint8_t *ptr; 1734 int error; 1735 1736 if (alloc_nr >= CUSE_ALLOC_UNIT_MAX) 1737 return (ENOMEM); 1738 1739 error = cuse_client_get(&pcc); 1740 if (error != 0) 1741 pcs = NULL; 1742 else 1743 pcs = pcc->server; 1744 1745 cuse_lock(); 1746 mem = &cuse_mem[alloc_nr]; 1747 1748 /* try to enforce slight ownership */ 1749 if ((pcs != NULL) && (mem->owner != pcs)) { 1750 cuse_unlock(); 1751 return (EINVAL); 1752 } 1753 if (mem->virtaddr == NULL) { 1754 cuse_unlock(); 1755 return (ENOMEM); 1756 } 1757 if (mem->virtaddr == NBUSY) { 1758 cuse_unlock(); 1759 return (ENOMEM); 1760 } 1761 page_nr %= CUSE_ALLOC_PAGES_MAX; 1762 1763 if (page_nr >= mem->page_count) { 1764 cuse_unlock(); 1765 return (ENXIO); 1766 } 1767 ptr = mem->virtaddr + (page_nr * PAGE_SIZE); 1768 cuse_unlock(); 1769 1770 *paddr = vtophys(ptr); 1771 1772 return (0); 1773 } 1774 1775 static void 1776 cuse_client_kqfilter_read_detach(struct knote *kn) 1777 { 1778 struct cuse_client *pcc; 1779 1780 cuse_lock(); 1781 pcc = kn->kn_hook; 1782 knlist_remove(&pcc->server->selinfo.si_note, kn, 1); 1783 cuse_unlock(); 1784 } 1785 1786 static void 1787 cuse_client_kqfilter_write_detach(struct knote *kn) 1788 { 1789 struct cuse_client *pcc; 1790 1791 cuse_lock(); 1792 pcc = kn->kn_hook; 1793 knlist_remove(&pcc->server->selinfo.si_note, kn, 1); 1794 cuse_unlock(); 1795 } 1796 1797 static int 1798 cuse_client_kqfilter_read_event(struct knote *kn, long hint) 1799 { 1800 struct cuse_client *pcc; 1801 1802 mtx_assert(&cuse_mtx, MA_OWNED); 1803 1804 pcc = kn->kn_hook; 1805 return ((pcc->cflags & CUSE_CLI_KNOTE_NEED_READ) ? 1 : 0); 1806 } 1807 1808 static int 1809 cuse_client_kqfilter_write_event(struct knote *kn, long hint) 1810 { 1811 struct cuse_client *pcc; 1812 1813 mtx_assert(&cuse_mtx, MA_OWNED); 1814 1815 pcc = kn->kn_hook; 1816 return ((pcc->cflags & CUSE_CLI_KNOTE_NEED_WRITE) ? 1 : 0); 1817 } 1818 1819 static int 1820 cuse_client_kqfilter(struct cdev *dev, struct knote *kn) 1821 { 1822 struct cuse_client *pcc; 1823 struct cuse_server *pcs; 1824 int error; 1825 1826 error = cuse_client_get(&pcc); 1827 if (error != 0) 1828 return (error); 1829 1830 cuse_lock(); 1831 pcs = pcc->server; 1832 switch (kn->kn_filter) { 1833 case EVFILT_READ: 1834 pcc->cflags |= CUSE_CLI_KNOTE_HAS_READ; 1835 kn->kn_hook = pcc; 1836 kn->kn_fop = &cuse_client_kqfilter_read_ops; 1837 knlist_add(&pcs->selinfo.si_note, kn, 1); 1838 break; 1839 case EVFILT_WRITE: 1840 pcc->cflags |= CUSE_CLI_KNOTE_HAS_WRITE; 1841 kn->kn_hook = pcc; 1842 kn->kn_fop = &cuse_client_kqfilter_write_ops; 1843 knlist_add(&pcs->selinfo.si_note, kn, 1); 1844 break; 1845 default: 1846 error = EINVAL; 1847 break; 1848 } 1849 cuse_unlock(); 1850 1851 if (error == 0) 1852 cuse_client_kqfilter_poll(dev, pcc); 1853 return (error); 1854 } 1855