kernel_proxy.cc revision 3551c9c881056c480085172ff9840cab31610854
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "nacl_io/kernel_proxy.h" 6 7 8#include <assert.h> 9#include <errno.h> 10#include <fcntl.h> 11#include <limits.h> 12#include <poll.h> 13#include <pthread.h> 14#include <stdio.h> 15#include <string.h> 16#include <sys/time.h> 17#include <unistd.h> 18 19#include <iterator> 20#include <string> 21 22#include "nacl_io/dbgprint.h" 23#include "nacl_io/host_resolver.h" 24#include "nacl_io/kernel_handle.h" 25#include "nacl_io/kernel_wrap_real.h" 26#include "nacl_io/mount.h" 27#include "nacl_io/mount_dev.h" 28#include "nacl_io/mount_html5fs.h" 29#include "nacl_io/mount_http.h" 30#include "nacl_io/mount_mem.h" 31#include "nacl_io/mount_node.h" 32#include "nacl_io/mount_node_tcp.h" 33#include "nacl_io/mount_node_udp.h" 34#include "nacl_io/mount_passthrough.h" 35#include "nacl_io/osmman.h" 36#include "nacl_io/ossocket.h" 37#include "nacl_io/osstat.h" 38#include "nacl_io/path.h" 39#include "nacl_io/pepper_interface.h" 40#include "nacl_io/typed_mount_factory.h" 41#include "sdk_util/auto_lock.h" 42#include "sdk_util/ref_object.h" 43 44#ifndef MAXPATHLEN 45#define MAXPATHLEN 256 46#endif 47 48namespace nacl_io { 49 50class SignalEmitter : public EventEmitter { 51 public: 52 // From EventEmitter. The SignalEmitter exists in order 53 // to inturrupt anything waiting in select()/poll() when kill() 54 // is called. It is an edge trigger only and therefore has no 55 // persistent readable/wriable/error state. 56 uint32_t GetEventStatus() { 57 return 0; 58 } 59 60 int GetType() { 61 // For lack of a better type, report socket to signify it can be in an 62 // used to signal. 63 return S_IFSOCK; 64 } 65 66 void SignalOccurred() { 67 RaiseEvent(POLLERR); 68 } 69}; 70 71KernelProxy::KernelProxy() : dev_(0), ppapi_(NULL), 72 sigwinch_handler_(SIG_IGN), 73 signal_emitter_(new SignalEmitter) { 74 75} 76 77KernelProxy::~KernelProxy() { 78 // Clean up the MountFactories. 79 for (MountFactoryMap_t::iterator i = factories_.begin(); 80 i != factories_.end(); 81 ++i) { 82 delete i->second; 83 } 84 85 delete ppapi_; 86} 87 88void KernelProxy::Init(PepperInterface* ppapi) { 89 ppapi_ = ppapi; 90 dev_ = 1; 91 92 factories_["memfs"] = new TypedMountFactory<MountMem>; 93 factories_["dev"] = new TypedMountFactory<MountDev>; 94 factories_["html5fs"] = new TypedMountFactory<MountHtml5Fs>; 95 factories_["httpfs"] = new TypedMountFactory<MountHttp>; 96 factories_["passthroughfs"] = new TypedMountFactory<MountPassthrough>; 97 98 int result; 99 result = mount("", "/", "passthroughfs", 0, NULL); 100 assert(result == 0); 101 102 result = mount("", "/dev", "dev", 0, NULL); 103 assert(result == 0); 104 105 // Open the first three in order to get STDIN, STDOUT, STDERR 106 open("/dev/stdin", O_RDONLY); 107 open("/dev/stdout", O_WRONLY); 108 open("/dev/stderr", O_WRONLY); 109 110#ifdef PROVIDES_SOCKET_API 111 host_resolver_.Init(ppapi_); 112#endif 113 114 StringMap_t args; 115 socket_mount_.reset(new MountSocket()); 116 socket_mount_->Init(0, args, ppapi); 117} 118 119int KernelProxy::open_resource(const char* path) { 120 ScopedMount mnt; 121 Path rel; 122 123 Error error = AcquireMountAndRelPath(path, &mnt, &rel); 124 if (error) { 125 errno = error; 126 return -1; 127 } 128 129 ScopedMountNode node; 130 error = mnt->OpenResource(rel, &node); 131 if (error) { 132 // OpenResource failed, try Open(). 133 error = mnt->Open(rel, O_RDONLY, &node); 134 if (error) { 135 errno = error; 136 return -1; 137 } 138 } 139 140 ScopedKernelHandle handle(new KernelHandle(mnt, node)); 141 error = handle->Init(O_RDONLY); 142 if (error) { 143 errno = error; 144 return -1; 145 } 146 147 return AllocateFD(handle); 148} 149 150int KernelProxy::open(const char* path, int oflags) { 151 ScopedMount mnt; 152 ScopedMountNode node; 153 154 Error error = AcquireMountAndNode(path, oflags, &mnt, &node); 155 if (error) { 156 errno = error; 157 return -1; 158 } 159 160 ScopedKernelHandle handle(new KernelHandle(mnt, node)); 161 error = handle->Init(oflags); 162 if (error) { 163 errno = error; 164 return -1; 165 } 166 167 return AllocateFD(handle); 168} 169 170int KernelProxy::close(int fd) { 171 ScopedKernelHandle handle; 172 Error error = AcquireHandle(fd, &handle); 173 if (error) { 174 errno = error; 175 return -1; 176 } 177 178 // Remove the FD from the process open file descriptor map 179 FreeFD(fd); 180 return 0; 181} 182 183int KernelProxy::dup(int oldfd) { 184 ScopedKernelHandle handle; 185 Error error = AcquireHandle(oldfd, &handle); 186 if (error) { 187 errno = error; 188 return -1; 189 } 190 191 return AllocateFD(handle); 192} 193 194int KernelProxy::dup2(int oldfd, int newfd) { 195 // If it's the same file handle, just return 196 if (oldfd == newfd) 197 return newfd; 198 199 ScopedKernelHandle old_handle; 200 Error error = AcquireHandle(oldfd, &old_handle); 201 if (error) { 202 errno = error; 203 return -1; 204 } 205 206 FreeAndReassignFD(newfd, old_handle); 207 return newfd; 208} 209 210int KernelProxy::chdir(const char* path) { 211 Error error = SetCWD(path); 212 if (error) { 213 errno = error; 214 return -1; 215 } 216 return 0; 217} 218 219char* KernelProxy::getcwd(char* buf, size_t size) { 220 std::string cwd = GetCWD(); 221 222 if (size <= 0) { 223 errno = EINVAL; 224 return NULL; 225 } 226 227 // If size is 0, allocate as much as we need. 228 if (size == 0) { 229 size = cwd.size() + 1; 230 } 231 232 // Verify the buffer is large enough 233 if (size <= cwd.size()) { 234 errno = ERANGE; 235 return NULL; 236 } 237 238 // Allocate the buffer if needed 239 if (buf == NULL) { 240 buf = static_cast<char*>(malloc(size)); 241 } 242 243 strcpy(buf, cwd.c_str()); 244 return buf; 245} 246 247char* KernelProxy::getwd(char* buf) { 248 if (NULL == buf) { 249 errno = EFAULT; 250 return NULL; 251 } 252 return getcwd(buf, MAXPATHLEN); 253} 254 255int KernelProxy::chmod(const char* path, mode_t mode) { 256 int fd = KernelProxy::open(path, O_RDONLY); 257 if (-1 == fd) 258 return -1; 259 260 int result = fchmod(fd, mode); 261 close(fd); 262 return result; 263} 264 265int KernelProxy::chown(const char* path, uid_t owner, gid_t group) { 266 return 0; 267} 268 269int KernelProxy::fchown(int fd, uid_t owner, gid_t group) { 270 return 0; 271} 272 273int KernelProxy::lchown(const char* path, uid_t owner, gid_t group) { 274 return 0; 275} 276 277int KernelProxy::utime(const char* filename, const struct utimbuf* times) { 278 return 0; 279} 280 281int KernelProxy::mkdir(const char* path, mode_t mode) { 282 ScopedMount mnt; 283 Path rel; 284 285 Error error = AcquireMountAndRelPath(path, &mnt, &rel); 286 if (error) { 287 errno = error; 288 return -1; 289 } 290 291 error = mnt->Mkdir(rel, mode); 292 if (error) { 293 errno = error; 294 return -1; 295 } 296 297 return 0; 298} 299 300int KernelProxy::rmdir(const char* path) { 301 ScopedMount mnt; 302 Path rel; 303 304 Error error = AcquireMountAndRelPath(path, &mnt, &rel); 305 if (error) { 306 errno = error; 307 return -1; 308 } 309 310 error = mnt->Rmdir(rel); 311 if (error) { 312 errno = error; 313 return -1; 314 } 315 316 return 0; 317} 318 319int KernelProxy::stat(const char* path, struct stat* buf) { 320 int fd = open(path, O_RDONLY); 321 if (-1 == fd) 322 return -1; 323 324 int result = fstat(fd, buf); 325 close(fd); 326 return result; 327} 328 329 330int KernelProxy::mount(const char* source, 331 const char* target, 332 const char* filesystemtype, 333 unsigned long mountflags, 334 const void* data) { 335 std::string abs_path = GetAbsParts(target).Join(); 336 337 // Find a factory of that type 338 MountFactoryMap_t::iterator factory = factories_.find(filesystemtype); 339 if (factory == factories_.end()) { 340 errno = ENODEV; 341 return -1; 342 } 343 344 // Create a map of settings 345 StringMap_t smap; 346 smap["SOURCE"] = source; 347 smap["TARGET"] = abs_path; 348 349 if (data) { 350 char* str = strdup(static_cast<const char*>(data)); 351 char* ptr = strtok(str, ","); 352 char* val; 353 while (ptr != NULL) { 354 val = strchr(ptr, '='); 355 if (val) { 356 *val = 0; 357 smap[ptr] = val + 1; 358 } else { 359 smap[ptr] = "TRUE"; 360 } 361 ptr = strtok(NULL, ","); 362 } 363 free(str); 364 } 365 366 ScopedMount mnt; 367 Error error = factory->second->CreateMount(dev_++, smap, ppapi_, &mnt); 368 if (error) { 369 errno = error; 370 return -1; 371 } 372 373 error = AttachMountAtPath(mnt, abs_path); 374 if (error) { 375 errno = error; 376 return -1; 377 } 378 379 return 0; 380} 381 382int KernelProxy::umount(const char* path) { 383 Error error = DetachMountAtPath(path); 384 if (error) { 385 errno = error; 386 return -1; 387 } 388 return 0; 389} 390 391ssize_t KernelProxy::read(int fd, void* buf, size_t nbytes) { 392 ScopedKernelHandle handle; 393 Error error = AcquireHandle(fd, &handle); 394 if (error) { 395 errno = error; 396 return -1; 397 } 398 399 int cnt = 0; 400 error = handle->Read(buf, nbytes, &cnt); 401 if (error) { 402 errno = error; 403 return -1; 404 } 405 406 return cnt; 407} 408 409ssize_t KernelProxy::write(int fd, const void* buf, size_t nbytes) { 410 ScopedKernelHandle handle; 411 Error error = AcquireHandle(fd, &handle); 412 if (error) { 413 errno = error; 414 return -1; 415 } 416 417 int cnt = 0; 418 error = handle->Write(buf, nbytes, &cnt); 419 if (error) { 420 errno = error; 421 return -1; 422 } 423 424 return cnt; 425} 426 427int KernelProxy::fstat(int fd, struct stat* buf) { 428 ScopedKernelHandle handle; 429 Error error = AcquireHandle(fd, &handle); 430 if (error) { 431 errno = error; 432 return -1; 433 } 434 435 error = handle->node()->GetStat(buf); 436 if (error) { 437 errno = error; 438 return -1; 439 } 440 441 return 0; 442} 443 444int KernelProxy::getdents(int fd, void* buf, unsigned int count) { 445 ScopedKernelHandle handle; 446 Error error = AcquireHandle(fd, &handle); 447 if (error) { 448 errno = error; 449 return -1; 450 } 451 452 int cnt = 0; 453 error = handle->GetDents(static_cast<dirent*>(buf), count, &cnt); 454 if (error) 455 errno = error; 456 457 return cnt; 458} 459 460int KernelProxy::ftruncate(int fd, off_t length) { 461 ScopedKernelHandle handle; 462 Error error = AcquireHandle(fd, &handle); 463 if (error) { 464 errno = error; 465 return -1; 466 } 467 468 error = handle->node()->FTruncate(length); 469 if (error) { 470 errno = error; 471 return -1; 472 } 473 474 return 0; 475} 476 477int KernelProxy::fsync(int fd) { 478 ScopedKernelHandle handle; 479 Error error = AcquireHandle(fd, &handle); 480 if (error) { 481 errno = error; 482 return -1; 483 } 484 485 error = handle->node()->FSync(); 486 if (error) { 487 errno = error; 488 return -1; 489 } 490 491 return 0; 492} 493 494int KernelProxy::isatty(int fd) { 495 ScopedKernelHandle handle; 496 Error error = AcquireHandle(fd, &handle); 497 if (error) { 498 errno = error; 499 return -1; 500 } 501 502 error = handle->node()->IsaTTY(); 503 if (error) { 504 errno = error; 505 return -1; 506 } 507 508 return 0; 509} 510 511int KernelProxy::ioctl(int fd, int request, char* argp) { 512 ScopedKernelHandle handle; 513 Error error = AcquireHandle(fd, &handle); 514 if (error) { 515 errno = error; 516 return -1; 517 } 518 519 error = handle->node()->Ioctl(request, argp); 520 if (error) { 521 errno = error; 522 return -1; 523 } 524 525 return 0; 526} 527 528off_t KernelProxy::lseek(int fd, off_t offset, int whence) { 529 ScopedKernelHandle handle; 530 Error error = AcquireHandle(fd, &handle); 531 if (error) { 532 errno = error; 533 return -1; 534 } 535 536 off_t new_offset; 537 error = handle->Seek(offset, whence, &new_offset); 538 if (error) { 539 errno = error; 540 return -1; 541 } 542 543 return new_offset; 544} 545 546int KernelProxy::unlink(const char* path) { 547 ScopedMount mnt; 548 Path rel; 549 550 Error error = AcquireMountAndRelPath(path, &mnt, &rel); 551 if (error) { 552 errno = error; 553 return -1; 554 } 555 556 error = mnt->Unlink(rel); 557 if (error) { 558 errno = error; 559 return -1; 560 } 561 562 return 0; 563} 564 565int KernelProxy::remove(const char* path) { 566 ScopedMount mnt; 567 Path rel; 568 569 Error error = AcquireMountAndRelPath(path, &mnt, &rel); 570 if (error) { 571 errno = error; 572 return -1; 573 } 574 575 error = mnt->Remove(rel); 576 if (error) { 577 errno = error; 578 return -1; 579 } 580 581 return 0; 582} 583 584// TODO(noelallen): Needs implementation. 585int KernelProxy::fchmod(int fd, int mode) { 586 ScopedKernelHandle handle; 587 Error error = AcquireHandle(fd, &handle); 588 if (error) { 589 errno = error; 590 return -1; 591 } 592 593 return 0; 594} 595 596int KernelProxy::access(const char* path, int amode) { 597 ScopedMount mnt; 598 Path rel; 599 600 Error error = AcquireMountAndRelPath(path, &mnt, &rel); 601 if (error) { 602 errno = error; 603 return -1; 604 } 605 606 error = mnt->Access(rel, amode); 607 if (error) { 608 errno = error; 609 return -1; 610 } 611 return 0; 612} 613 614// TODO(noelallen): Needs implementation. 615int KernelProxy::link(const char* oldpath, const char* newpath) { 616 errno = EINVAL; 617 return -1; 618} 619 620int KernelProxy::symlink(const char* oldpath, const char* newpath) { 621 errno = EINVAL; 622 return -1; 623} 624 625void* KernelProxy::mmap(void* addr, 626 size_t length, 627 int prot, 628 int flags, 629 int fd, 630 size_t offset) { 631 // We shouldn't be getting anonymous mmaps here. 632 assert((flags & MAP_ANONYMOUS) == 0); 633 assert(fd != -1); 634 635 ScopedKernelHandle handle; 636 Error error = AcquireHandle(fd, &handle); 637 if (error) { 638 errno = error; 639 return MAP_FAILED; 640 } 641 642 void* new_addr; 643 error = handle->node()->MMap(addr, length, prot, flags, offset, &new_addr); 644 if (error) { 645 errno = error; 646 return MAP_FAILED; 647 } 648 649 return new_addr; 650} 651 652int KernelProxy::munmap(void* addr, size_t length) { 653 // NOTE: The comment below is from a previous discarded implementation that 654 // tracks mmap'd regions. For simplicity, we no longer do this; because we 655 // "snapshot" the contents of the file in mmap(), and don't support 656 // write-back or updating the mapped region when the file is written, holding 657 // on to the KernelHandle is pointless. 658 // 659 // If we ever do, these threading issues should be considered. 660 661 // 662 // WARNING: this function may be called by free(). 663 // 664 // There is a potential deadlock scenario: 665 // Thread 1: open() -> takes lock1 -> free() -> takes lock2 666 // Thread 2: free() -> takes lock2 -> munmap() -> takes lock1 667 // 668 // Note that open() above could be any function that takes a lock that is 669 // shared with munmap (this includes munmap!) 670 // 671 // To prevent this, we avoid taking locks in munmap() that are used by other 672 // nacl_io functions that may call free. Specifically, we only take the 673 // mmap_lock, which is only shared with mmap() above. There is still a 674 // possibility of deadlock if mmap() or munmap() calls free(), so this is not 675 // allowed. 676 // 677 // Unfortunately, munmap still needs to acquire other locks; see the call to 678 // ReleaseHandle below which takes the process lock. This is safe as long as 679 // this is never executed from free() -- we can be reasonably sure this is 680 // true, because malloc only makes anonymous mmap() requests, and should only 681 // be munmapping those allocations. We never add to mmap_info_list_ for 682 // anonymous maps, so the unmap_list should always be empty when called from 683 // free(). 684 return 0; 685} 686 687int KernelProxy::tcflush(int fd, int queue_selector) { 688 ScopedKernelHandle handle; 689 Error error = AcquireHandle(fd, &handle); 690 if (error) { 691 errno = error; 692 return -1; 693 } 694 695 error = handle->node()->Tcflush(queue_selector); 696 if (error) { 697 errno = error; 698 return -1; 699 } 700 701 return 0; 702} 703 704int KernelProxy::tcgetattr(int fd, struct termios* termios_p) { 705 ScopedKernelHandle handle; 706 Error error = AcquireHandle(fd, &handle); 707 if (error) { 708 errno = error; 709 return -1; 710 } 711 712 error = handle->node()->Tcgetattr(termios_p); 713 if (error) { 714 errno = error; 715 return -1; 716 } 717 718 return 0; 719} 720 721int KernelProxy::tcsetattr(int fd, int optional_actions, 722 const struct termios *termios_p) { 723 ScopedKernelHandle handle; 724 Error error = AcquireHandle(fd, &handle); 725 if (error) { 726 errno = error; 727 return -1; 728 } 729 730 error = handle->node()->Tcsetattr(optional_actions, termios_p); 731 if (error) { 732 errno = error; 733 return -1; 734 } 735 736 return 0; 737} 738 739int KernelProxy::kill(pid_t pid, int sig) { 740 // Currently we don't even pretend that other processes exist 741 // so we can only send a signal to outselves. For kill(2) 742 // pid 0 means the current process group and -1 means all the 743 // processes we have permission to send signals to. 744 if (pid != getpid() && pid != -1 && pid != 0) { 745 errno = ESRCH; 746 return -1; 747 } 748 749 // Raise an event so that select/poll get interrupted. 750 signal_emitter_->SignalOccurred(); 751 switch (sig) { 752 case SIGWINCH: 753 if (sigwinch_handler_ != SIG_IGN) 754 sigwinch_handler_(SIGWINCH); 755 break; 756 757 case SIGUSR1: 758 case SIGUSR2: 759 break; 760 761 default: 762 errno = EINVAL; 763 return -1; 764 } 765 766 return 0; 767} 768 769sighandler_t KernelProxy::sigset(int signum, sighandler_t handler) { 770 switch (signum) { 771 // Handled signals. 772 case SIGWINCH: { 773 sighandler_t old_value = sigwinch_handler_; 774 if (handler == SIG_DFL) 775 handler = SIG_IGN; 776 sigwinch_handler_ = handler; 777 return old_value; 778 } 779 780 // Known signals 781 case SIGHUP: 782 case SIGINT: 783 case SIGKILL: 784 case SIGPIPE: 785 case SIGPOLL: 786 case SIGPROF: 787 case SIGTERM: 788 case SIGCHLD: 789 case SIGURG: 790 case SIGFPE: 791 case SIGILL: 792 case SIGQUIT: 793 case SIGSEGV: 794 case SIGTRAP: 795 if (handler == SIG_DFL) 796 return SIG_DFL; 797 break; 798 } 799 800 errno = EINVAL; 801 return SIG_ERR; 802} 803 804#ifdef PROVIDES_SOCKET_API 805 806int KernelProxy::select(int nfds, fd_set* readfds, fd_set* writefds, 807 fd_set* exceptfds, struct timeval* timeout) { 808 ScopedEventListener listener(new EventListener); 809 810 std::vector<struct pollfd> fds; 811 812 fd_set readout, writeout, exceptout; 813 814 FD_ZERO(&readout); 815 FD_ZERO(&writeout); 816 FD_ZERO(&exceptout); 817 818 int fd; 819 size_t event_cnt = 0; 820 int event_track = 0; 821 for (fd = 0; fd < nfds; fd++) { 822 int events = 0; 823 824 if (readfds != NULL && FD_ISSET(fd, readfds)) 825 events |= POLLIN; 826 827 if (writefds != NULL && FD_ISSET(fd, writefds)) 828 events |= POLLOUT; 829 830 if (exceptfds != NULL && FD_ISSET(fd, exceptfds)) 831 events |= POLLERR | POLLHUP; 832 833 // If we are not interested in this FD, skip it 834 if (0 == events) continue; 835 836 ScopedKernelHandle handle; 837 Error err = AcquireHandle(fd, &handle); 838 839 // Select will return immediately if there are bad FDs. 840 if (err != 0) { 841 errno = EBADF; 842 return -1; 843 } 844 845 int status = handle->node()->GetEventStatus() & events; 846 if (status & POLLIN) { 847 FD_SET(fd, &readout); 848 event_cnt++; 849 } 850 851 if (status & POLLOUT) { 852 FD_SET(fd, &writeout); 853 event_cnt++; 854 } 855 856 if (status & (POLLERR | POLLHUP)) { 857 FD_SET(fd, &exceptout); 858 event_cnt++; 859 } 860 861 // Otherwise track it. 862 if (0 == status) { 863 err = listener->Track(fd, handle->node(), events, fd); 864 if (err != 0) { 865 errno = EBADF; 866 return -1; 867 } 868 event_track++; 869 } 870 } 871 872 // If nothing is signaled, then we must wait. 873 if (event_cnt == 0) { 874 std::vector<EventData> events; 875 int ready_cnt; 876 int ms_timeout; 877 878 // NULL timeout signals wait forever. 879 if (timeout == NULL) { 880 ms_timeout = -1; 881 } else { 882 int64_t ms = timeout->tv_sec * 1000 + ((timeout->tv_usec + 500) / 1000); 883 884 // If the timeout is invalid or too long (larger than signed 32 bit). 885 if ((timeout->tv_sec < 0) || (timeout->tv_sec >= (INT_MAX / 1000)) || 886 (timeout->tv_usec < 0) || (timeout->tv_usec >= 1000000) || 887 (ms < 0) || (ms >= INT_MAX)) { 888 errno = EINVAL; 889 return -1; 890 } 891 892 ms_timeout = static_cast<int>(ms); 893 } 894 895 // Add a special node to listen for events 896 // coming from the KernelProxy itself (kill will 897 // generated a SIGERR event). 898 listener->Track(-1, signal_emitter_, POLLERR, -1); 899 event_track += 1; 900 901 events.resize(event_track); 902 903 bool interrupted = false; 904 listener->Wait(events.data(), event_track, ms_timeout, &ready_cnt); 905 for (fd = 0; static_cast<int>(fd) < ready_cnt; fd++) { 906 if (events[fd].user_data == static_cast<uint64_t>(-1)) { 907 if (events[fd].events & POLLERR) { 908 interrupted = true; 909 } 910 continue; 911 } 912 913 if (events[fd].events & POLLIN) { 914 FD_SET(events[fd].user_data, &readout); 915 event_cnt++; 916 } 917 918 if (events[fd].events & POLLOUT) { 919 FD_SET(events[fd].user_data, &writeout); 920 event_cnt++; 921 } 922 923 if (events[fd].events & (POLLERR | POLLHUP)) { 924 FD_SET(events[fd].user_data, &exceptout); 925 event_cnt++; 926 } 927 } 928 929 if (0 == event_cnt && interrupted) { 930 errno = EINTR; 931 return -1; 932 } 933 } 934 935 // Copy out the results 936 if (readfds != NULL) 937 *readfds = readout; 938 939 if (writefds != NULL) 940 *writefds = writeout; 941 942 if (exceptfds != NULL) 943 *exceptfds = exceptout; 944 945 return event_cnt; 946} 947 948int KernelProxy::poll(struct pollfd *fds, nfds_t nfds, int timeout) { 949 ScopedEventListener listener(new EventListener); 950 listener->Track(-1, signal_emitter_, POLLERR, 0); 951 952 int index; 953 size_t event_cnt = 0; 954 size_t event_track = 1; 955 for (index = 0; static_cast<nfds_t>(index) < nfds; index++) { 956 ScopedKernelHandle handle; 957 struct pollfd* info = &fds[index]; 958 Error err = AcquireHandle(info->fd, &handle); 959 960 // If the node isn't open, or somehow invalid, mark it so. 961 if (err != 0) { 962 info->revents = POLLNVAL; 963 event_cnt++; 964 continue; 965 } 966 967 // If it's already signaled, then just capture the event 968 if (handle->node()->GetEventStatus() & info->events) { 969 info->revents = info->events & handle->node()->GetEventStatus(); 970 event_cnt++; 971 continue; 972 } 973 974 // Otherwise try to track it. 975 err = listener->Track(info->fd, handle->node(), info->events, index); 976 if (err != 0) { 977 info->revents = POLLNVAL; 978 event_cnt++; 979 continue; 980 } 981 event_track++; 982 } 983 984 // If nothing is signaled, then we must wait. 985 if (0 == event_cnt) { 986 std::vector<EventData> events; 987 int ready_cnt; 988 989 bool interrupted = false; 990 events.resize(event_track); 991 listener->Wait(events.data(), event_track, timeout, &ready_cnt); 992 for (index = 0; index < ready_cnt; index++) { 993 struct pollfd* info = &fds[events[index].user_data]; 994 if (!info) { 995 interrupted = true; 996 continue; 997 } 998 999 info->revents = events[index].events; 1000 event_cnt++; 1001 } 1002 if (0 == event_cnt && interrupted) { 1003 errno = EINTR; 1004 return -1; 1005 } 1006 } 1007 1008 return event_cnt; 1009} 1010 1011 1012 1013// Socket Functions 1014int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) { 1015 if (NULL == addr || NULL == len) { 1016 errno = EFAULT; 1017 return -1; 1018 } 1019 1020 ScopedKernelHandle handle; 1021 if (AcquireSocketHandle(fd, &handle) == -1) 1022 return -1; 1023 1024 errno = EINVAL; 1025 return -1; 1026} 1027 1028int KernelProxy::bind(int fd, const struct sockaddr* addr, socklen_t len) { 1029 if (NULL == addr) { 1030 errno = EFAULT; 1031 return -1; 1032 } 1033 1034 ScopedKernelHandle handle; 1035 if (AcquireSocketHandle(fd, &handle) == -1) 1036 return -1; 1037 1038 Error err = handle->socket_node()->Bind(addr, len); 1039 if (err != 0) { 1040 errno = err; 1041 return -1; 1042 } 1043 1044 return 0; 1045} 1046 1047int KernelProxy::connect(int fd, const struct sockaddr* addr, socklen_t len) { 1048 if (NULL == addr) { 1049 errno = EFAULT; 1050 return -1; 1051 } 1052 1053 ScopedKernelHandle handle; 1054 if (AcquireSocketHandle(fd, &handle) == -1) 1055 return -1; 1056 1057 Error err = handle->socket_node()->Connect(addr, len); 1058 if (err != 0) { 1059 errno = err; 1060 return -1; 1061 } 1062 1063 return 0; 1064} 1065 1066struct hostent* KernelProxy::gethostbyname(const char* name) { 1067 return host_resolver_.gethostbyname(name); 1068} 1069 1070int KernelProxy::getpeername(int fd, struct sockaddr* addr, socklen_t* len) { 1071 if (NULL == addr || NULL == len) { 1072 errno = EFAULT; 1073 return -1; 1074 } 1075 1076 ScopedKernelHandle handle; 1077 if (AcquireSocketHandle(fd, &handle) == -1) 1078 return -1; 1079 1080 Error err = handle->socket_node()->GetPeerName(addr, len); 1081 if (err != 0) { 1082 errno = err; 1083 return -1; 1084 } 1085 1086 return 0; 1087} 1088 1089int KernelProxy::getsockname(int fd, struct sockaddr* addr, socklen_t* len) { 1090 if (NULL == addr || NULL == len) { 1091 errno = EFAULT; 1092 return -1; 1093 } 1094 1095 ScopedKernelHandle handle; 1096 if (AcquireSocketHandle(fd, &handle) == -1) 1097 return -1; 1098 1099 Error err = handle->socket_node()->GetSockName(addr, len); 1100 if (err != 0) { 1101 errno = err; 1102 return -1; 1103 } 1104 1105 return 0; 1106} 1107 1108int KernelProxy::getsockopt(int fd, 1109 int lvl, 1110 int optname, 1111 void* optval, 1112 socklen_t* len) { 1113 if (NULL == optval || NULL == len) { 1114 errno = EFAULT; 1115 return -1; 1116 } 1117 1118 ScopedKernelHandle handle; 1119 if (AcquireSocketHandle(fd, &handle) == -1) 1120 return -1; 1121 1122 errno = EINVAL; 1123 return -1; 1124} 1125 1126int KernelProxy::listen(int fd, int backlog) { 1127 ScopedKernelHandle handle; 1128 if (AcquireSocketHandle(fd, &handle) == -1) 1129 return -1; 1130 1131 errno = EOPNOTSUPP; 1132 return -1; 1133} 1134 1135ssize_t KernelProxy::recv(int fd, 1136 void* buf, 1137 size_t len, 1138 int flags) { 1139 if (NULL == buf) { 1140 errno = EFAULT; 1141 return -1; 1142 } 1143 1144 ScopedKernelHandle handle; 1145 if (AcquireSocketHandle(fd, &handle) == -1) 1146 return -1; 1147 1148 int out_len = 0; 1149 Error err = handle->socket_node()->Recv(buf, len, flags, &out_len); 1150 if (err != 0) { 1151 errno = err; 1152 return -1; 1153 } 1154 1155 return static_cast<ssize_t>(out_len); 1156} 1157 1158ssize_t KernelProxy::recvfrom(int fd, 1159 void* buf, 1160 size_t len, 1161 int flags, 1162 struct sockaddr* addr, 1163 socklen_t* addrlen) { 1164 // According to the manpage, recvfrom with a null addr is identical to recv. 1165 if (NULL == addr) { 1166 return recv(fd, buf, len, flags); 1167 } 1168 1169 if (NULL == buf || NULL == addrlen) { 1170 errno = EFAULT; 1171 return -1; 1172 } 1173 1174 ScopedKernelHandle handle; 1175 if (AcquireSocketHandle(fd, &handle) == -1) 1176 return -1; 1177 1178 int out_len = 0; 1179 Error err = handle->socket_node()->RecvFrom(buf, 1180 len, 1181 flags, 1182 addr, 1183 addrlen, 1184 &out_len); 1185 if (err != 0) { 1186 errno = err; 1187 return -1; 1188 } 1189 1190 return static_cast<ssize_t>(out_len); 1191} 1192 1193ssize_t KernelProxy::recvmsg(int fd, struct msghdr* msg, int flags) { 1194 if (NULL == msg ) { 1195 errno = EFAULT; 1196 return -1; 1197 } 1198 1199 ScopedKernelHandle handle; 1200 if (AcquireSocketHandle(fd, &handle) == -1) 1201 return -1; 1202 1203 errno = EOPNOTSUPP; 1204 return -1; 1205} 1206 1207ssize_t KernelProxy::send(int fd, const void* buf, size_t len, int flags) { 1208 if (NULL == buf) { 1209 errno = EFAULT; 1210 return -1; 1211 } 1212 1213 ScopedKernelHandle handle; 1214 if (AcquireSocketHandle(fd, &handle) == -1) 1215 return -1; 1216 1217 int out_len = 0; 1218 Error err = handle->socket_node()->Send(buf, len, flags, &out_len); 1219 if (err != 0) { 1220 errno = err; 1221 return -1; 1222 } 1223 1224 return static_cast<ssize_t>(out_len); 1225} 1226 1227ssize_t KernelProxy::sendto(int fd, 1228 const void* buf, 1229 size_t len, 1230 int flags, 1231 const struct sockaddr* addr, 1232 socklen_t addrlen) { 1233 // According to the manpage, sendto with a null addr is identical to send. 1234 if (NULL == addr) { 1235 return send(fd, buf, len, flags); 1236 } 1237 1238 if (NULL == buf) { 1239 errno = EFAULT; 1240 return -1; 1241 } 1242 1243 ScopedKernelHandle handle; 1244 if (AcquireSocketHandle(fd, &handle) == -1) 1245 return -1; 1246 1247 int out_len = 0; 1248 Error err = 1249 handle->socket_node()->SendTo(buf, len, flags, addr, addrlen, &out_len); 1250 1251 if (err != 0) { 1252 errno = err; 1253 return -1; 1254 } 1255 1256 return static_cast<ssize_t>(out_len); 1257} 1258 1259ssize_t KernelProxy::sendmsg(int fd, const struct msghdr* msg, int flags) { 1260 if (NULL == msg) { 1261 errno = EFAULT; 1262 return -1; 1263 } 1264 1265 ScopedKernelHandle handle; 1266 if (AcquireSocketHandle(fd, &handle) == -1) 1267 return -1; 1268 1269 errno = EOPNOTSUPP; 1270 return -1; 1271} 1272 1273int KernelProxy::setsockopt(int fd, 1274 int lvl, 1275 int optname, 1276 const void* optval, 1277 socklen_t len) { 1278 if (NULL == optval) { 1279 errno = EFAULT; 1280 return -1; 1281 } 1282 1283 ScopedKernelHandle handle; 1284 if (AcquireSocketHandle(fd, &handle) == -1) 1285 return -1; 1286 1287 errno = EINVAL; 1288 return -1; 1289} 1290 1291int KernelProxy::shutdown(int fd, int how) { 1292 ScopedKernelHandle handle; 1293 if (AcquireSocketHandle(fd, &handle) == -1) 1294 return -1; 1295 1296 Error err = handle->socket_node()->Shutdown(how); 1297 if (err != 0) { 1298 errno = err; 1299 return -1; 1300 } 1301 1302 return 0; 1303} 1304 1305int KernelProxy::socket(int domain, int type, int protocol) { 1306 if (AF_INET != domain && AF_INET6 != domain) { 1307 errno = EAFNOSUPPORT; 1308 return -1; 1309 } 1310 1311 MountNodeSocket* sock = NULL; 1312 switch (type) { 1313 case SOCK_DGRAM: 1314 sock = new MountNodeUDP(socket_mount_.get()); 1315 break; 1316 1317 case SOCK_STREAM: 1318 sock = new MountNodeTCP(socket_mount_.get()); 1319 break; 1320 1321 default: 1322 errno = EPROTONOSUPPORT; 1323 return -1; 1324 } 1325 1326 ScopedMountNode node(sock); 1327 if (sock->Init(S_IREAD | S_IWRITE) == 0) { 1328 ScopedKernelHandle handle(new KernelHandle(socket_mount_, node)); 1329 return AllocateFD(handle); 1330 } 1331 1332 // If we failed to init, assume we don't have access. 1333 return EACCES; 1334} 1335 1336int KernelProxy::socketpair(int domain, int type, int protocol, int* sv) { 1337 if (NULL == sv) { 1338 errno = EFAULT; 1339 return -1; 1340 } 1341 1342 // Catch-22: We don't support AF_UNIX, but any other AF doesn't support 1343 // socket pairs. Thus, this function always fails. 1344 if (AF_UNIX != domain) { 1345 errno = EPROTONOSUPPORT; 1346 return -1; 1347 } 1348 1349 if (AF_INET != domain && AF_INET6 != domain) { 1350 errno = EAFNOSUPPORT; 1351 return -1; 1352 } 1353 1354 // We cannot reach this point. 1355 errno = ENOSYS; 1356 return -1; 1357} 1358 1359int KernelProxy::AcquireSocketHandle(int fd, ScopedKernelHandle* handle) { 1360 Error error = AcquireHandle(fd, handle); 1361 1362 if (error) { 1363 errno = error; 1364 return -1; 1365 } 1366 1367 if ((handle->get()->node_->GetType() & S_IFSOCK) == 0) { 1368 errno = ENOTSOCK; 1369 return -1; 1370 } 1371 1372 return 0; 1373} 1374 1375#endif // PROVIDES_SOCKET_API 1376 1377} // namespace_nacl_io 1378