kernel_proxy.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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#include <assert.h> 8#include <errno.h> 9#include <fcntl.h> 10#include <limits.h> 11#include <poll.h> 12#include <pthread.h> 13#include <stdio.h> 14#include <string.h> 15#include <sys/time.h> 16#include <unistd.h> 17 18#include <iterator> 19#include <string> 20 21#include "nacl_io/devfs/dev_fs.h" 22#include "nacl_io/filesystem.h" 23#include "nacl_io/fusefs/fuse_fs_factory.h" 24#include "nacl_io/host_resolver.h" 25#include "nacl_io/html5fs/html5_fs.h" 26#include "nacl_io/httpfs/http_fs.h" 27#include "nacl_io/kernel_handle.h" 28#include "nacl_io/kernel_wrap_real.h" 29#include "nacl_io/memfs/mem_fs.h" 30#include "nacl_io/node.h" 31#include "nacl_io/osmman.h" 32#include "nacl_io/ossocket.h" 33#include "nacl_io/osstat.h" 34#include "nacl_io/passthroughfs/passthrough_fs.h" 35#include "nacl_io/path.h" 36#include "nacl_io/pepper_interface.h" 37#include "nacl_io/pipe/pipe_node.h" 38#include "nacl_io/socket/tcp_node.h" 39#include "nacl_io/socket/udp_node.h" 40#include "nacl_io/stream/stream_fs.h" 41#include "nacl_io/typed_fs_factory.h" 42#include "sdk_util/auto_lock.h" 43#include "sdk_util/ref_object.h" 44#include "sdk_util/string_util.h" 45 46#ifndef MAXPATHLEN 47#define MAXPATHLEN 256 48#endif 49 50namespace nacl_io { 51 52 53KernelProxy::KernelProxy() : dev_(0), ppapi_(NULL), 54 signal_emitter_(new EventEmitter) { 55 memset(&sigwinch_handler_, 0, sizeof(sigwinch_handler_)); 56 sigwinch_handler_.sa_handler = SIG_DFL; 57} 58 59KernelProxy::~KernelProxy() { 60 // Clean up the MountFactories. 61 for (FsFactoryMap_t::iterator i = factories_.begin(); i != factories_.end(); 62 ++i) { 63 delete i->second; 64 } 65 66 delete ppapi_; 67} 68 69Error KernelProxy::Init(PepperInterface* ppapi) { 70 Error rtn = 0; 71 ppapi_ = ppapi; 72 dev_ = 1; 73 74 factories_["memfs"] = new TypedFsFactory<MemFs>; 75 factories_["dev"] = new TypedFsFactory<DevFs>; 76 factories_["html5fs"] = new TypedFsFactory<Html5Fs>; 77 factories_["httpfs"] = new TypedFsFactory<HttpFs>; 78 factories_["passthroughfs"] = new TypedFsFactory<PassthroughFs>; 79 80 int result; 81 result = mount("", "/", "passthroughfs", 0, NULL); 82 if (result != 0) { 83 assert(false); 84 rtn = errno; 85 } 86 87 result = mount("", "/dev", "dev", 0, NULL); 88 if (result != 0) { 89 assert(false); 90 rtn = errno; 91 } 92 93 // Open the first three in order to get STDIN, STDOUT, STDERR 94 int fd; 95 fd = open("/dev/stdin", O_RDONLY); 96 assert(fd == 0); 97 if (fd < 0) 98 rtn = errno; 99 100 fd = open("/dev/stdout", O_WRONLY); 101 assert(fd == 1); 102 if (fd < 0) 103 rtn = errno; 104 105 fd = open("/dev/stderr", O_WRONLY); 106 assert(fd == 2); 107 if (fd < 0) 108 rtn = errno; 109 110#ifdef PROVIDES_SOCKET_API 111 host_resolver_.Init(ppapi_); 112#endif 113 114 FsInitArgs args; 115 args.dev = dev_++; 116 args.ppapi = ppapi_; 117 stream_mount_.reset(new StreamFs()); 118 result = stream_mount_->Init(args); 119 if (result != 0) { 120 assert(false); 121 rtn = result; 122 } 123 124 return rtn; 125} 126 127bool KernelProxy::RegisterFsType(const char* fs_type, 128 fuse_operations* fuse_ops) { 129 FsFactoryMap_t::iterator iter = factories_.find(fs_type); 130 if (iter != factories_.end()) 131 return false; 132 133 factories_[fs_type] = new FuseFsFactory(fuse_ops); 134 return true; 135} 136 137bool KernelProxy::UnregisterFsType(const char* fs_type) { 138 FsFactoryMap_t::iterator iter = factories_.find(fs_type); 139 if (iter == factories_.end()) 140 return false; 141 142 delete iter->second; 143 factories_.erase(iter); 144 return true; 145} 146 147int KernelProxy::open_resource(const char* path) { 148 ScopedFilesystem fs; 149 Path rel; 150 151 Error error = AcquireFsAndRelPath(path, &fs, &rel); 152 if (error) { 153 errno = error; 154 return -1; 155 } 156 157 ScopedNode node; 158 error = fs->OpenResource(rel, &node); 159 if (error) { 160 // OpenResource failed, try Open(). 161 error = fs->Open(rel, O_RDONLY, &node); 162 if (error) { 163 errno = error; 164 return -1; 165 } 166 } 167 168 ScopedKernelHandle handle(new KernelHandle(fs, node)); 169 error = handle->Init(O_RDONLY); 170 if (error) { 171 errno = error; 172 return -1; 173 } 174 175 return AllocateFD(handle, path); 176} 177 178int KernelProxy::open(const char* path, int open_flags) { 179 ScopedFilesystem fs; 180 ScopedNode node; 181 182 Error error = AcquireFsAndNode(path, open_flags, &fs, &node); 183 if (error) { 184 errno = error; 185 return -1; 186 } 187 188 ScopedKernelHandle handle(new KernelHandle(fs, node)); 189 error = handle->Init(open_flags); 190 if (error) { 191 errno = error; 192 return -1; 193 } 194 195 return AllocateFD(handle, path); 196} 197 198int KernelProxy::pipe(int pipefds[2]) { 199 PipeNode* pipe = new PipeNode(stream_mount_.get()); 200 ScopedNode node(pipe); 201 202 if (pipe->Init(O_RDWR) == 0) { 203 ScopedKernelHandle handle0(new KernelHandle(stream_mount_, node)); 204 ScopedKernelHandle handle1(new KernelHandle(stream_mount_, node)); 205 206 // Should never fail, but... 207 if (handle0->Init(O_RDONLY) || handle1->Init(O_WRONLY)) { 208 errno = EACCES; 209 return -1; 210 } 211 212 pipefds[0] = AllocateFD(handle0); 213 pipefds[1] = AllocateFD(handle1); 214 return 0; 215 } 216 217 errno = ENOSYS; 218 return -1; 219} 220 221int KernelProxy::close(int fd) { 222 ScopedKernelHandle handle; 223 Error error = AcquireHandle(fd, &handle); 224 if (error) { 225 errno = error; 226 return -1; 227 } 228 229 // Remove the FD from the process open file descriptor map 230 FreeFD(fd); 231 return 0; 232} 233 234int KernelProxy::dup(int oldfd) { 235 ScopedKernelHandle handle; 236 std::string path; 237 Error error = AcquireHandleAndPath(oldfd, &handle, &path); 238 if (error) { 239 errno = error; 240 return -1; 241 } 242 return AllocateFD(handle, path); 243} 244 245int KernelProxy::dup2(int oldfd, int newfd) { 246 // If it's the same file handle, just return 247 if (oldfd == newfd) 248 return newfd; 249 250 ScopedKernelHandle old_handle; 251 std::string old_path; 252 Error error = AcquireHandleAndPath(oldfd, &old_handle, &old_path); 253 if (error) { 254 errno = error; 255 return -1; 256 } 257 258 FreeAndReassignFD(newfd, old_handle, old_path); 259 return newfd; 260} 261 262int KernelProxy::chdir(const char* path) { 263 Error error = SetCWD(path); 264 if (error) { 265 errno = error; 266 return -1; 267 } 268 return 0; 269} 270 271char* KernelProxy::getcwd(char* buf, size_t size) { 272 if (NULL == buf) { 273 errno = EFAULT; 274 return NULL; 275 } 276 277 std::string cwd = GetCWD(); 278 279 // Verify the buffer is large enough 280 if (size <= cwd.size()) { 281 errno = ERANGE; 282 return NULL; 283 } 284 285 strcpy(buf, cwd.c_str()); 286 return buf; 287} 288 289char* KernelProxy::getwd(char* buf) { 290 if (NULL == buf) { 291 errno = EFAULT; 292 return NULL; 293 } 294 return getcwd(buf, MAXPATHLEN); 295} 296 297int KernelProxy::chmod(const char* path, mode_t mode) { 298 int fd = KernelProxy::open(path, O_RDONLY); 299 if (-1 == fd) 300 return -1; 301 302 int result = fchmod(fd, mode); 303 close(fd); 304 return result; 305} 306 307int KernelProxy::chown(const char* path, uid_t owner, gid_t group) { 308 return 0; 309} 310 311int KernelProxy::fchown(int fd, uid_t owner, gid_t group) { 312 return 0; 313} 314 315int KernelProxy::lchown(const char* path, uid_t owner, gid_t group) { 316 return 0; 317} 318 319int KernelProxy::utime(const char* filename, const struct utimbuf* times) { 320 return 0; 321} 322 323int KernelProxy::mkdir(const char* path, mode_t mode) { 324 ScopedFilesystem fs; 325 Path rel; 326 327 Error error = AcquireFsAndRelPath(path, &fs, &rel); 328 if (error) { 329 errno = error; 330 return -1; 331 } 332 333 error = fs->Mkdir(rel, mode); 334 if (error) { 335 errno = error; 336 return -1; 337 } 338 339 return 0; 340} 341 342int KernelProxy::rmdir(const char* path) { 343 ScopedFilesystem fs; 344 Path rel; 345 346 Error error = AcquireFsAndRelPath(path, &fs, &rel); 347 if (error) { 348 errno = error; 349 return -1; 350 } 351 352 error = fs->Rmdir(rel); 353 if (error) { 354 errno = error; 355 return -1; 356 } 357 358 return 0; 359} 360 361int KernelProxy::stat(const char* path, struct stat* buf) { 362 int fd = open(path, O_RDONLY); 363 if (-1 == fd) 364 return -1; 365 366 int result = fstat(fd, buf); 367 close(fd); 368 return result; 369} 370 371 372int KernelProxy::mount(const char* source, 373 const char* target, 374 const char* filesystemtype, 375 unsigned long mountflags, 376 const void* data) { 377 std::string abs_path = GetAbsParts(target).Join(); 378 379 // Find a factory of that type 380 FsFactoryMap_t::iterator factory = factories_.find(filesystemtype); 381 if (factory == factories_.end()) { 382 errno = ENODEV; 383 return -1; 384 } 385 386 // Create a map of settings 387 StringMap_t smap; 388 smap["SOURCE"] = source; 389 smap["TARGET"] = abs_path; 390 391 if (data) { 392 std::vector<std::string> elements; 393 sdk_util::SplitString(static_cast<const char*>(data), ',', &elements); 394 395 for (std::vector<std::string>::const_iterator it = elements.begin(); 396 it != elements.end(); ++it) { 397 size_t location = it->find('='); 398 if (location != std::string::npos) { 399 std::string key = it->substr(0, location); 400 std::string val = it->substr(location + 1); 401 smap[key] = val; 402 } else { 403 smap[*it] = "TRUE"; 404 } 405 } 406 } 407 408 FsInitArgs args; 409 args.dev = dev_++; 410 args.string_map = smap; 411 args.ppapi = ppapi_; 412 413 ScopedFilesystem fs; 414 Error error = factory->second->CreateFilesystem(args, &fs); 415 if (error) { 416 errno = error; 417 return -1; 418 } 419 420 error = AttachFsAtPath(fs, abs_path); 421 if (error) { 422 errno = error; 423 return -1; 424 } 425 426 return 0; 427} 428 429int KernelProxy::umount(const char* path) { 430 Error error = DetachFsAtPath(path); 431 if (error) { 432 errno = error; 433 return -1; 434 } 435 return 0; 436} 437 438ssize_t KernelProxy::read(int fd, void* buf, size_t nbytes) { 439 ScopedKernelHandle handle; 440 Error error = AcquireHandle(fd, &handle); 441 if (error) { 442 errno = error; 443 return -1; 444 } 445 446 int cnt = 0; 447 error = handle->Read(buf, nbytes, &cnt); 448 if (error) { 449 errno = error; 450 return -1; 451 } 452 453 return cnt; 454} 455 456ssize_t KernelProxy::write(int fd, const void* buf, size_t nbytes) { 457 ScopedKernelHandle handle; 458 Error error = AcquireHandle(fd, &handle); 459 if (error) { 460 errno = error; 461 return -1; 462 } 463 464 int cnt = 0; 465 error = handle->Write(buf, nbytes, &cnt); 466 if (error) { 467 errno = error; 468 return -1; 469 } 470 471 return cnt; 472} 473 474int KernelProxy::fstat(int fd, struct stat* buf) { 475 ScopedKernelHandle handle; 476 Error error = AcquireHandle(fd, &handle); 477 if (error) { 478 errno = error; 479 return -1; 480 } 481 482 error = handle->node()->GetStat(buf); 483 if (error) { 484 errno = error; 485 return -1; 486 } 487 488 return 0; 489} 490 491int KernelProxy::getdents(int fd, void* buf, unsigned int count) { 492 ScopedKernelHandle handle; 493 Error error = AcquireHandle(fd, &handle); 494 if (error) { 495 errno = error; 496 return -1; 497 } 498 499 int cnt = 0; 500 error = handle->GetDents(static_cast<dirent*>(buf), count, &cnt); 501 if (error) 502 errno = error; 503 504 return cnt; 505} 506 507int KernelProxy::fchdir(int fd) { 508 ScopedKernelHandle handle; 509 std::string path; 510 Error error = AcquireHandleAndPath(fd, &handle, &path); 511 if (error) { 512 errno = error; 513 return -1; 514 } 515 516 if (!handle->node()->IsaDir()) { 517 errno = ENOTDIR; 518 return -1; 519 } 520 521 if (path.empty()) { 522 errno = EBADF; 523 return -1; 524 } 525 526 error = SetCWD(path); 527 if (error) { 528 // errno is return value from SetCWD 529 errno = error; 530 return -1; 531 } 532 return 0; 533} 534 535int KernelProxy::ftruncate(int fd, off_t length) { 536 ScopedKernelHandle handle; 537 Error error = AcquireHandle(fd, &handle); 538 if (error) { 539 errno = error; 540 return -1; 541 } 542 543 error = handle->node()->FTruncate(length); 544 if (error) { 545 errno = error; 546 return -1; 547 } 548 549 return 0; 550} 551 552int KernelProxy::fsync(int fd) { 553 ScopedKernelHandle handle; 554 Error error = AcquireHandle(fd, &handle); 555 if (error) { 556 errno = error; 557 return -1; 558 } 559 560 error = handle->node()->FSync(); 561 if (error) { 562 errno = error; 563 return -1; 564 } 565 566 return 0; 567} 568 569int KernelProxy::fdatasync(int fd) { 570 errno = ENOSYS; 571 return -1; 572} 573 574int KernelProxy::isatty(int fd) { 575 ScopedKernelHandle handle; 576 Error error = AcquireHandle(fd, &handle); 577 if (error) { 578 errno = error; 579 return -1; 580 } 581 582 error = handle->node()->IsaTTY(); 583 if (error) { 584 errno = error; 585 return -1; 586 } 587 588 return 0; 589} 590 591int KernelProxy::ioctl(int fd, int request, va_list args) { 592 ScopedKernelHandle handle; 593 Error error = AcquireHandle(fd, &handle); 594 if (error) { 595 errno = error; 596 return -1; 597 } 598 599 error = handle->node()->VIoctl(request, args); 600 if (error) { 601 errno = error; 602 return -1; 603 } 604 605 return 0; 606} 607 608off_t KernelProxy::lseek(int fd, off_t offset, int whence) { 609 ScopedKernelHandle handle; 610 Error error = AcquireHandle(fd, &handle); 611 if (error) { 612 errno = error; 613 return -1; 614 } 615 616 off_t new_offset; 617 error = handle->Seek(offset, whence, &new_offset); 618 if (error) { 619 errno = error; 620 return -1; 621 } 622 623 return new_offset; 624} 625 626int KernelProxy::unlink(const char* path) { 627 ScopedFilesystem fs; 628 Path rel; 629 630 Error error = AcquireFsAndRelPath(path, &fs, &rel); 631 if (error) { 632 errno = error; 633 return -1; 634 } 635 636 error = fs->Unlink(rel); 637 if (error) { 638 errno = error; 639 return -1; 640 } 641 642 return 0; 643} 644 645int KernelProxy::truncate(const char* path, off_t len) { 646 int fd = KernelProxy::open(path, O_WRONLY); 647 if (-1 == fd) 648 return -1; 649 650 int result = ftruncate(fd, len); 651 close(fd); 652 return result; 653} 654 655int KernelProxy::lstat(const char* path, struct stat* buf) { 656 return stat(path, buf); 657} 658 659int KernelProxy::rename(const char* path, const char* newpath) { 660 ScopedFilesystem fs; 661 Path rel; 662 Error error = AcquireFsAndRelPath(path, &fs, &rel); 663 if (error) { 664 errno = error; 665 return -1; 666 } 667 668 ScopedFilesystem newfs; 669 Path newrel; 670 error = AcquireFsAndRelPath(newpath, &newfs, &newrel); 671 if (error) { 672 errno = error; 673 return -1; 674 } 675 676 if (newfs.get() != fs.get()) { 677 // Renaming accross mountpoints is not allowed 678 errno = EXDEV; 679 return -1; 680 } 681 682 // They already point to the same path 683 if (rel == newrel) 684 return 0; 685 686 error = fs->Rename(rel, newrel); 687 if (error) { 688 errno = error; 689 return -1; 690 } 691 692 return 0; 693} 694 695int KernelProxy::remove(const char* path) { 696 ScopedFilesystem fs; 697 Path rel; 698 699 Error error = AcquireFsAndRelPath(path, &fs, &rel); 700 if (error) { 701 errno = error; 702 return -1; 703 } 704 705 error = fs->Remove(rel); 706 if (error) { 707 errno = error; 708 return -1; 709 } 710 711 return 0; 712} 713 714// TODO(noelallen): Needs implementation. 715int KernelProxy::fchmod(int fd, int mode) { 716 ScopedKernelHandle handle; 717 Error error = AcquireHandle(fd, &handle); 718 if (error) { 719 errno = error; 720 return -1; 721 } 722 723 return 0; 724} 725 726int KernelProxy::fcntl(int fd, int request, va_list args) { 727 Error error = 0; 728 729 // F_GETFD and F_SETFD are descirptor specific flags that 730 // are stored in the KernelObject's decriptor map unlink 731 // F_GETFL and F_SETFL which are handle specific. 732 switch (request) { 733 case F_GETFD: { 734 int rtn = -1; 735 error = GetFDFlags(fd, &rtn); 736 if (error) { 737 errno = error; 738 return -1; 739 } 740 return rtn; 741 } 742 case F_SETFD: { 743 int flags = va_arg(args, int); 744 error = SetFDFlags(fd, flags); 745 if (error) { 746 errno = error; 747 return -1; 748 } 749 return 0; 750 } 751 } 752 753 ScopedKernelHandle handle; 754 error = AcquireHandle(fd, &handle); 755 if (error) { 756 errno = error; 757 return -1; 758 } 759 760 int rtn = 0; 761 error = handle->VFcntl(request, &rtn, args); 762 if (error) { 763 errno = error; 764 return -1; 765 } 766 767 return rtn; 768} 769 770int KernelProxy::access(const char* path, int amode) { 771 ScopedFilesystem fs; 772 Path rel; 773 774 Error error = AcquireFsAndRelPath(path, &fs, &rel); 775 if (error) { 776 errno = error; 777 return -1; 778 } 779 780 error = fs->Access(rel, amode); 781 if (error) { 782 errno = error; 783 return -1; 784 } 785 return 0; 786} 787 788int KernelProxy::readlink(const char *path, char *buf, size_t count) { 789 errno = EINVAL; 790 return -1; 791} 792 793int KernelProxy::utimes(const char *filename, const struct timeval times[2]) { 794 errno = EINVAL; 795 return -1; 796} 797 798// TODO(noelallen): Needs implementation. 799int KernelProxy::link(const char* oldpath, const char* newpath) { 800 errno = EINVAL; 801 return -1; 802} 803 804int KernelProxy::symlink(const char* oldpath, const char* newpath) { 805 errno = EINVAL; 806 return -1; 807} 808 809void* KernelProxy::mmap(void* addr, 810 size_t length, 811 int prot, 812 int flags, 813 int fd, 814 size_t offset) { 815 // We shouldn't be getting anonymous mmaps here. 816 assert((flags & MAP_ANONYMOUS) == 0); 817 assert(fd != -1); 818 819 ScopedKernelHandle handle; 820 Error error = AcquireHandle(fd, &handle); 821 if (error) { 822 errno = error; 823 return MAP_FAILED; 824 } 825 826 void* new_addr; 827 error = handle->node()->MMap(addr, length, prot, flags, offset, &new_addr); 828 if (error) { 829 errno = error; 830 return MAP_FAILED; 831 } 832 833 return new_addr; 834} 835 836int KernelProxy::munmap(void* addr, size_t length) { 837 // NOTE: The comment below is from a previous discarded implementation that 838 // tracks mmap'd regions. For simplicity, we no longer do this; because we 839 // "snapshot" the contents of the file in mmap(), and don't support 840 // write-back or updating the mapped region when the file is written, holding 841 // on to the KernelHandle is pointless. 842 // 843 // If we ever do, these threading issues should be considered. 844 845 // 846 // WARNING: this function may be called by free(). 847 // 848 // There is a potential deadlock scenario: 849 // Thread 1: open() -> takes lock1 -> free() -> takes lock2 850 // Thread 2: free() -> takes lock2 -> munmap() -> takes lock1 851 // 852 // Note that open() above could be any function that takes a lock that is 853 // shared with munmap (this includes munmap!) 854 // 855 // To prevent this, we avoid taking locks in munmap() that are used by other 856 // nacl_io functions that may call free. Specifically, we only take the 857 // mmap_lock, which is only shared with mmap() above. There is still a 858 // possibility of deadlock if mmap() or munmap() calls free(), so this is not 859 // allowed. 860 // 861 // Unfortunately, munmap still needs to acquire other locks; see the call to 862 // ReleaseHandle below which takes the process lock. This is safe as long as 863 // this is never executed from free() -- we can be reasonably sure this is 864 // true, because malloc only makes anonymous mmap() requests, and should only 865 // be munmapping those allocations. We never add to mmap_info_list_ for 866 // anonymous maps, so the unmap_list should always be empty when called from 867 // free(). 868 return 0; 869} 870 871int KernelProxy::tcflush(int fd, int queue_selector) { 872 ScopedKernelHandle handle; 873 Error error = AcquireHandle(fd, &handle); 874 if (error) { 875 errno = error; 876 return -1; 877 } 878 879 error = handle->node()->Tcflush(queue_selector); 880 if (error) { 881 errno = error; 882 return -1; 883 } 884 885 return 0; 886} 887 888int KernelProxy::tcgetattr(int fd, struct termios* termios_p) { 889 ScopedKernelHandle handle; 890 Error error = AcquireHandle(fd, &handle); 891 if (error) { 892 errno = error; 893 return -1; 894 } 895 896 error = handle->node()->Tcgetattr(termios_p); 897 if (error) { 898 errno = error; 899 return -1; 900 } 901 902 return 0; 903} 904 905int KernelProxy::tcsetattr(int fd, int optional_actions, 906 const struct termios *termios_p) { 907 ScopedKernelHandle handle; 908 Error error = AcquireHandle(fd, &handle); 909 if (error) { 910 errno = error; 911 return -1; 912 } 913 914 error = handle->node()->Tcsetattr(optional_actions, termios_p); 915 if (error) { 916 errno = error; 917 return -1; 918 } 919 920 return 0; 921} 922 923int KernelProxy::kill(pid_t pid, int sig) { 924 // Currently we don't even pretend that other processes exist 925 // so we can only send a signal to outselves. For kill(2) 926 // pid 0 means the current process group and -1 means all the 927 // processes we have permission to send signals to. 928 if (pid != getpid() && pid != -1 && pid != 0) { 929 errno = ESRCH; 930 return -1; 931 } 932 933 // Raise an event so that select/poll get interrupted. 934 AUTO_LOCK(signal_emitter_->GetLock()) 935 signal_emitter_->RaiseEvents_Locked(POLLERR); 936 switch (sig) { 937 case SIGWINCH: 938 if (sigwinch_handler_.sa_handler != SIG_IGN && 939 sigwinch_handler_.sa_handler != SIG_DFL) { 940 sigwinch_handler_.sa_handler(SIGWINCH); 941 } 942 break; 943 944 case SIGUSR1: 945 case SIGUSR2: 946 break; 947 948 default: 949 errno = EINVAL; 950 return -1; 951 } 952 return 0; 953} 954 955int KernelProxy::sigaction(int signum, const struct sigaction* action, 956 struct sigaction* oaction) { 957 if (action && action->sa_flags & SA_SIGINFO) { 958 // We don't support SA_SIGINFO (sa_sigaction field) yet 959 errno = EINVAL; 960 return -1; 961 } 962 963 switch (signum) { 964 // Handled signals. 965 case SIGWINCH: { 966 if (oaction) 967 *oaction = sigwinch_handler_; 968 if (action) { 969 sigwinch_handler_ = *action; 970 } 971 return 0; 972 } 973 974 // Known signals 975 case SIGHUP: 976 case SIGINT: 977 case SIGPIPE: 978 case SIGPOLL: 979 case SIGPROF: 980 case SIGTERM: 981 case SIGCHLD: 982 case SIGURG: 983 case SIGFPE: 984 case SIGILL: 985 case SIGQUIT: 986 case SIGSEGV: 987 case SIGTRAP: 988 if (action && action->sa_handler != SIG_DFL) { 989 // Trying to set this action to anything other than SIG_DFL 990 // is not yet supported. 991 errno = EINVAL; 992 return -1; 993 } 994 995 if (oaction) { 996 memset(oaction, 0, sizeof(*oaction)); 997 oaction->sa_handler = SIG_DFL; 998 } 999 return 0; 1000 1001 // KILL and STOP cannot be handled 1002 case SIGKILL: 1003 case SIGSTOP: 1004 errno = EINVAL; 1005 return -1; 1006 } 1007 1008 // Unknown signum 1009 errno = EINVAL; 1010 return -1; 1011} 1012 1013#ifdef PROVIDES_SOCKET_API 1014 1015int KernelProxy::select(int nfds, fd_set* readfds, fd_set* writefds, 1016 fd_set* exceptfds, struct timeval* timeout) { 1017 fd_set ignore; 1018 std::vector<pollfd> pollfds; 1019 1020 // Simplify logic, by using an IGNORE set for any undefined set 1021 FD_ZERO(&ignore); 1022 if (NULL == readfds) 1023 readfds = &ignore; 1024 if (NULL == writefds) 1025 writefds = &ignore; 1026 if (NULL == exceptfds) 1027 exceptfds = &ignore; 1028 1029 for (int fd = 0; fd < nfds; fd++) { 1030 int events = 0; 1031 if (FD_ISSET(fd, readfds)) 1032 events |= POLLIN; 1033 1034 if (FD_ISSET(fd, writefds)) 1035 events |= POLLOUT; 1036 1037 if (FD_ISSET(fd, exceptfds)) 1038 events |= POLLERR | POLLHUP; 1039 1040 if (events) { 1041 pollfd info; 1042 info.fd = fd; 1043 info.events = events; 1044 pollfds.push_back(info); 1045 } 1046 } 1047 1048 FD_ZERO(readfds); 1049 FD_ZERO(writefds); 1050 FD_ZERO(exceptfds); 1051 1052 // NULL timeout signals wait forever. 1053 int ms_timeout = -1; 1054 if (timeout != NULL) { 1055 int64_t ms = timeout->tv_sec * 1000 + ((timeout->tv_usec + 500) / 1000); 1056 1057 // If the timeout is invalid or too long (larger than signed 32 bit). 1058 if ((timeout->tv_sec < 0) || (timeout->tv_sec >= (INT_MAX / 1000)) || 1059 (timeout->tv_usec < 0) || (timeout->tv_usec >= 1000000) || 1060 (ms < 0) || (ms >= INT_MAX)) { 1061 errno = EINVAL; 1062 return -1; 1063 } 1064 1065 ms_timeout = static_cast<int>(ms); 1066 } 1067 1068 int result = poll(&pollfds[0], pollfds.size(), ms_timeout); 1069 if (result == -1) 1070 return -1; 1071 1072 int event_cnt = 0; 1073 for (size_t index = 0; index < pollfds.size(); index++) { 1074 pollfd* info = &pollfds[index]; 1075 if (info->revents & POLLIN) { 1076 FD_SET(info->fd, readfds); 1077 event_cnt++; 1078 } 1079 if (info->revents & POLLOUT) { 1080 FD_SET(info->fd, writefds); 1081 event_cnt++; 1082 } 1083 if (info->revents & (POLLHUP | POLLERR)) { 1084 FD_SET(info->fd, exceptfds); 1085 event_cnt++; 1086 } 1087 } 1088 1089 return event_cnt; 1090} 1091 1092struct PollInfo { 1093 PollInfo() : index(-1) {}; 1094 1095 std::vector<struct pollfd*> fds; 1096 int index; 1097}; 1098 1099typedef std::map<EventEmitter*, PollInfo> EventPollMap_t; 1100 1101int KernelProxy::poll(struct pollfd *fds, nfds_t nfds, int timeout) { 1102 EventPollMap_t event_map; 1103 1104 std::vector<EventRequest> requests; 1105 size_t event_cnt = 0; 1106 1107 for (int index = 0; static_cast<nfds_t>(index) < nfds; index++) { 1108 ScopedKernelHandle handle; 1109 struct pollfd* fd_info = &fds[index]; 1110 Error err = AcquireHandle(fd_info->fd, &handle); 1111 1112 fd_info->revents = 0; 1113 1114 // If the node isn't open, or somehow invalid, mark it so. 1115 if (err != 0) { 1116 fd_info->revents = POLLNVAL; 1117 event_cnt++; 1118 continue; 1119 } 1120 1121 // If it's already signaled, then just capture the event 1122 ScopedEventEmitter emitter(handle->node()->GetEventEmitter()); 1123 int events = POLLIN | POLLOUT; 1124 if (emitter) 1125 events = emitter->GetEventStatus(); 1126 1127 if (events & fd_info->events) { 1128 fd_info->revents = events & fd_info->events; 1129 event_cnt++; 1130 continue; 1131 } 1132 1133 if (NULL == emitter) { 1134 fd_info->revents = POLLNVAL; 1135 event_cnt++; 1136 continue; 1137 } 1138 1139 // Otherwise try to track it. 1140 PollInfo* info = &event_map[emitter.get()]; 1141 if (info->index == -1) { 1142 EventRequest request; 1143 request.emitter = emitter; 1144 request.filter = fd_info->events; 1145 request.events = 0; 1146 1147 info->index = requests.size(); 1148 requests.push_back(request); 1149 } 1150 info->fds.push_back(fd_info); 1151 requests[info->index].filter |= fd_info->events; 1152 } 1153 1154 // If nothing is signaled, then we must wait on the event map 1155 if (0 == event_cnt) { 1156 EventListenerPoll wait; 1157 Error err = wait.WaitOnAny(&requests[0], requests.size(), timeout); 1158 if ((err != 0) && (err != ETIMEDOUT)) { 1159 errno = err; 1160 return -1; 1161 } 1162 1163 for (size_t rindex = 0; rindex < requests.size(); rindex++) { 1164 EventRequest* request = &requests[rindex]; 1165 if (request->events) { 1166 PollInfo* poll_info = &event_map[request->emitter.get()]; 1167 for (size_t findex = 0; findex < poll_info->fds.size(); findex++) { 1168 struct pollfd* fd_info = poll_info->fds[findex]; 1169 uint32_t events = fd_info->events & request->events; 1170 if (events) { 1171 fd_info->revents = events; 1172 event_cnt++; 1173 } 1174 } 1175 } 1176 } 1177 } 1178 1179 return event_cnt; 1180} 1181 1182 1183// Socket Functions 1184int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) { 1185 if (NULL == addr || NULL == len) { 1186 errno = EFAULT; 1187 return -1; 1188 } 1189 1190 ScopedKernelHandle handle; 1191 Error error = AcquireHandle(fd, &handle); 1192 if (error) { 1193 errno = error; 1194 return -1; 1195 } 1196 1197 PP_Resource new_sock = 0; 1198 error = handle->Accept(&new_sock, addr, len); 1199 if (error != 0) { 1200 errno = error; 1201 return -1; 1202 } 1203 1204 SocketNode* sock = new TcpNode(stream_mount_.get(), new_sock); 1205 1206 // The SocketNode now holds a reference to the new socket 1207 // so we release ours. 1208 ppapi_->ReleaseResource(new_sock); 1209 error = sock->Init(O_RDWR); 1210 if (error != 0) { 1211 errno = error; 1212 return -1; 1213 } 1214 1215 ScopedNode node(sock); 1216 ScopedKernelHandle new_handle(new KernelHandle(stream_mount_, node)); 1217 error = new_handle->Init(O_RDWR); 1218 if (error != 0) { 1219 errno = error; 1220 return -1; 1221 } 1222 1223 return AllocateFD(new_handle); 1224} 1225 1226int KernelProxy::bind(int fd, const struct sockaddr* addr, socklen_t len) { 1227 if (NULL == addr) { 1228 errno = EFAULT; 1229 return -1; 1230 } 1231 1232 ScopedKernelHandle handle; 1233 if (AcquireSocketHandle(fd, &handle) == -1) 1234 return -1; 1235 1236 Error err = handle->socket_node()->Bind(addr, len); 1237 if (err != 0) { 1238 errno = err; 1239 return -1; 1240 } 1241 1242 return 0; 1243} 1244 1245int KernelProxy::connect(int fd, const struct sockaddr* addr, socklen_t len) { 1246 if (NULL == addr) { 1247 errno = EFAULT; 1248 return -1; 1249 } 1250 1251 ScopedKernelHandle handle; 1252 Error error = AcquireHandle(fd, &handle); 1253 if (error) { 1254 errno = error; 1255 return -1; 1256 } 1257 1258 error = handle->Connect(addr, len); 1259 if (error != 0) { 1260 errno = error; 1261 return -1; 1262 } 1263 1264 return 0; 1265} 1266 1267void KernelProxy::freeaddrinfo(struct addrinfo *res) { 1268 return host_resolver_.freeaddrinfo(res); 1269} 1270 1271int KernelProxy::getaddrinfo(const char* node, const char* service, 1272 const struct addrinfo* hints, 1273 struct addrinfo** res) { 1274 return host_resolver_.getaddrinfo(node, service, hints, res); 1275} 1276 1277struct hostent* KernelProxy::gethostbyname(const char* name) { 1278 return host_resolver_.gethostbyname(name); 1279} 1280 1281int KernelProxy::getpeername(int fd, struct sockaddr* addr, socklen_t* len) { 1282 if (NULL == addr || NULL == len) { 1283 errno = EFAULT; 1284 return -1; 1285 } 1286 1287 ScopedKernelHandle handle; 1288 if (AcquireSocketHandle(fd, &handle) == -1) 1289 return -1; 1290 1291 Error err = handle->socket_node()->GetPeerName(addr, len); 1292 if (err != 0) { 1293 errno = err; 1294 return -1; 1295 } 1296 1297 return 0; 1298} 1299 1300int KernelProxy::getsockname(int fd, struct sockaddr* addr, socklen_t* len) { 1301 if (NULL == addr || NULL == len) { 1302 errno = EFAULT; 1303 return -1; 1304 } 1305 1306 ScopedKernelHandle handle; 1307 if (AcquireSocketHandle(fd, &handle) == -1) 1308 return -1; 1309 1310 Error err = handle->socket_node()->GetSockName(addr, len); 1311 if (err != 0) { 1312 errno = err; 1313 return -1; 1314 } 1315 1316 return 0; 1317} 1318 1319int KernelProxy::getsockopt(int fd, 1320 int lvl, 1321 int optname, 1322 void* optval, 1323 socklen_t* len) { 1324 if (NULL == optval || NULL == len) { 1325 errno = EFAULT; 1326 return -1; 1327 } 1328 1329 ScopedKernelHandle handle; 1330 if (AcquireSocketHandle(fd, &handle) == -1) 1331 return -1; 1332 1333 Error err = handle->socket_node()->GetSockOpt(lvl, optname, optval, len); 1334 if (err != 0) { 1335 errno = err; 1336 return -1; 1337 } 1338 1339 return 0; 1340} 1341 1342int KernelProxy::listen(int fd, int backlog) { 1343 ScopedKernelHandle handle; 1344 if (AcquireSocketHandle(fd, &handle) == -1) 1345 return -1; 1346 1347 Error err = handle->socket_node()->Listen(backlog); 1348 if (err != 0) { 1349 errno = err; 1350 return -1; 1351 } 1352 1353 return 0; 1354} 1355 1356ssize_t KernelProxy::recv(int fd, 1357 void* buf, 1358 size_t len, 1359 int flags) { 1360 if (NULL == buf) { 1361 errno = EFAULT; 1362 return -1; 1363 } 1364 1365 ScopedKernelHandle handle; 1366 Error error = AcquireHandle(fd, &handle); 1367 if (error) { 1368 errno = error; 1369 return -1; 1370 } 1371 1372 int out_len = 0; 1373 error = handle->Recv(buf, len, flags, &out_len); 1374 if (error != 0) { 1375 errno = error; 1376 return -1; 1377 } 1378 1379 return static_cast<ssize_t>(out_len); 1380} 1381 1382ssize_t KernelProxy::recvfrom(int fd, 1383 void* buf, 1384 size_t len, 1385 int flags, 1386 struct sockaddr* addr, 1387 socklen_t* addrlen) { 1388 // According to the manpage, recvfrom with a null addr is identical to recv. 1389 if (NULL == addr) { 1390 return recv(fd, buf, len, flags); 1391 } 1392 1393 if (NULL == buf || NULL == addrlen) { 1394 errno = EFAULT; 1395 return -1; 1396 } 1397 1398 ScopedKernelHandle handle; 1399 Error error = AcquireHandle(fd, &handle); 1400 if (error) { 1401 errno = error; 1402 return -1; 1403 } 1404 1405 int out_len = 0; 1406 error = handle->RecvFrom(buf, len, flags, addr, addrlen, &out_len); 1407 if (error != 0) { 1408 errno = error; 1409 return -1; 1410 } 1411 1412 return static_cast<ssize_t>(out_len); 1413} 1414 1415ssize_t KernelProxy::recvmsg(int fd, struct msghdr* msg, int flags) { 1416 if (NULL == msg ) { 1417 errno = EFAULT; 1418 return -1; 1419 } 1420 1421 ScopedKernelHandle handle; 1422 if (AcquireSocketHandle(fd, &handle) == -1) 1423 return -1; 1424 1425 errno = EOPNOTSUPP; 1426 return -1; 1427} 1428 1429ssize_t KernelProxy::send(int fd, const void* buf, size_t len, int flags) { 1430 if (NULL == buf) { 1431 errno = EFAULT; 1432 return -1; 1433 } 1434 1435 ScopedKernelHandle handle; 1436 Error error = AcquireHandle(fd, &handle); 1437 if (error) { 1438 errno = error; 1439 return -1; 1440 } 1441 1442 int out_len = 0; 1443 error = handle->Send(buf, len, flags, &out_len); 1444 if (error != 0) { 1445 errno = error; 1446 return -1; 1447 } 1448 1449 return static_cast<ssize_t>(out_len); 1450} 1451 1452ssize_t KernelProxy::sendto(int fd, 1453 const void* buf, 1454 size_t len, 1455 int flags, 1456 const struct sockaddr* addr, 1457 socklen_t addrlen) { 1458 // According to the manpage, sendto with a null addr is identical to send. 1459 if (NULL == addr) { 1460 return send(fd, buf, len, flags); 1461 } 1462 1463 if (NULL == buf) { 1464 errno = EFAULT; 1465 return -1; 1466 } 1467 1468 ScopedKernelHandle handle; 1469 Error error = AcquireHandle(fd, &handle); 1470 if (error) { 1471 errno = error; 1472 return -1; 1473 } 1474 1475 int out_len = 0; 1476 error = handle->SendTo(buf, len, flags, addr, addrlen, &out_len); 1477 if (error != 0) { 1478 errno = error; 1479 return -1; 1480 } 1481 1482 return static_cast<ssize_t>(out_len); 1483} 1484 1485ssize_t KernelProxy::sendmsg(int fd, const struct msghdr* msg, int flags) { 1486 if (NULL == msg) { 1487 errno = EFAULT; 1488 return -1; 1489 } 1490 1491 ScopedKernelHandle handle; 1492 if (AcquireSocketHandle(fd, &handle) == -1) 1493 return -1; 1494 1495 errno = EOPNOTSUPP; 1496 return -1; 1497} 1498 1499int KernelProxy::setsockopt(int fd, 1500 int lvl, 1501 int optname, 1502 const void* optval, 1503 socklen_t len) { 1504 if (NULL == optval) { 1505 errno = EFAULT; 1506 return -1; 1507 } 1508 1509 ScopedKernelHandle handle; 1510 if (AcquireSocketHandle(fd, &handle) == -1) 1511 return -1; 1512 1513 Error err = handle->socket_node()->SetSockOpt(lvl, optname, optval, len); 1514 if (err != 0) { 1515 errno = err; 1516 return -1; 1517 } 1518 1519 return 0; 1520} 1521 1522int KernelProxy::shutdown(int fd, int how) { 1523 ScopedKernelHandle handle; 1524 if (AcquireSocketHandle(fd, &handle) == -1) 1525 return -1; 1526 1527 Error err = handle->socket_node()->Shutdown(how); 1528 if (err != 0) { 1529 errno = err; 1530 return -1; 1531 } 1532 1533 return 0; 1534} 1535 1536int KernelProxy::socket(int domain, int type, int protocol) { 1537 if (AF_INET != domain && AF_INET6 != domain) { 1538 errno = EAFNOSUPPORT; 1539 return -1; 1540 } 1541 1542 int open_flags = O_RDWR; 1543 1544 if (type & SOCK_CLOEXEC) { 1545#ifdef O_CLOEXEC 1546 // The NaCl newlib version of fcntl.h doesn't currently define 1547 // O_CLOEXEC. 1548 // TODO(sbc): remove this guard once it gets added. 1549 open_flags |= O_CLOEXEC; 1550#endif 1551 type &= ~SOCK_CLOEXEC; 1552 } 1553 1554 if (type & SOCK_NONBLOCK) { 1555 open_flags |= O_NONBLOCK; 1556 type &= ~SOCK_NONBLOCK; 1557 } 1558 1559 SocketNode* sock = NULL; 1560 switch (type) { 1561 case SOCK_DGRAM: 1562 sock = new UdpNode(stream_mount_.get()); 1563 break; 1564 1565 case SOCK_STREAM: 1566 sock = new TcpNode(stream_mount_.get()); 1567 break; 1568 1569 case SOCK_SEQPACKET: 1570 case SOCK_RDM: 1571 case SOCK_RAW: 1572 errno = EPROTONOSUPPORT; 1573 return -1; 1574 1575 default: 1576 errno = EINVAL; 1577 return -1; 1578 } 1579 1580 ScopedNode node(sock); 1581 Error rtn = sock->Init(O_RDWR); 1582 if (rtn != 0) { 1583 errno = rtn; 1584 return -1; 1585 } 1586 1587 ScopedKernelHandle handle(new KernelHandle(stream_mount_, node)); 1588 rtn = handle->Init(open_flags); 1589 if (rtn != 0) { 1590 errno = rtn; 1591 return -1; 1592 } 1593 1594 return AllocateFD(handle); 1595} 1596 1597int KernelProxy::socketpair(int domain, int type, int protocol, int* sv) { 1598 if (NULL == sv) { 1599 errno = EFAULT; 1600 return -1; 1601 } 1602 1603 // Catch-22: We don't support AF_UNIX, but any other AF doesn't support 1604 // socket pairs. Thus, this function always fails. 1605 if (AF_UNIX != domain) { 1606 errno = EPROTONOSUPPORT; 1607 return -1; 1608 } 1609 1610 if (AF_INET != domain && AF_INET6 != domain) { 1611 errno = EAFNOSUPPORT; 1612 return -1; 1613 } 1614 1615 // We cannot reach this point. 1616 errno = ENOSYS; 1617 return -1; 1618} 1619 1620int KernelProxy::AcquireSocketHandle(int fd, ScopedKernelHandle* handle) { 1621 Error error = AcquireHandle(fd, handle); 1622 1623 if (error) { 1624 errno = error; 1625 return -1; 1626 } 1627 1628 if ((handle->get()->node_->GetType() & S_IFSOCK) == 0) { 1629 errno = ENOTSOCK; 1630 return -1; 1631 } 1632 1633 return 0; 1634} 1635 1636#endif // PROVIDES_SOCKET_API 1637 1638} // namespace_nacl_io 1639