kernel_proxy.cc revision 3240926e260ce088908e02ac07a6cf7b0c0cbf44
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 18#include <iterator> 19#include <string> 20 21#include "nacl_io/kernel_handle.h" 22#include "nacl_io/kernel_wrap_real.h" 23#include "nacl_io/mount.h" 24#include "nacl_io/mount_dev.h" 25#include "nacl_io/mount_html5fs.h" 26#include "nacl_io/mount_http.h" 27#include "nacl_io/mount_mem.h" 28#include "nacl_io/mount_node.h" 29#include "nacl_io/mount_passthrough.h" 30#include "nacl_io/osmman.h" 31#include "nacl_io/ossocket.h" 32#include "nacl_io/osstat.h" 33#include "nacl_io/path.h" 34#include "nacl_io/pepper_interface.h" 35#include "nacl_io/typed_mount_factory.h" 36#include "sdk_util/auto_lock.h" 37#include "sdk_util/ref_object.h" 38 39#ifndef MAXPATHLEN 40#define MAXPATHLEN 256 41#endif 42 43namespace nacl_io { 44 45KernelProxy::KernelProxy() : dev_(0), ppapi_(NULL) { 46} 47 48KernelProxy::~KernelProxy() { 49 // Clean up the MountFactories. 50 for (MountFactoryMap_t::iterator i = factories_.begin(); 51 i != factories_.end(); 52 ++i) { 53 delete i->second; 54 } 55 56 delete ppapi_; 57} 58 59void KernelProxy::Init(PepperInterface* ppapi) { 60 ppapi_ = ppapi; 61 dev_ = 1; 62 63 factories_["memfs"] = new TypedMountFactory<MountMem>; 64 factories_["dev"] = new TypedMountFactory<MountDev>; 65 factories_["html5fs"] = new TypedMountFactory<MountHtml5Fs>; 66 factories_["httpfs"] = new TypedMountFactory<MountHttp>; 67 factories_["passthroughfs"] = new TypedMountFactory<MountPassthrough>; 68 69 int result; 70 result = mount("", "/", "passthroughfs", 0, NULL); 71 assert(result == 0); 72 73 result = mount("", "/dev", "dev", 0, NULL); 74 assert(result == 0); 75 76 // Open the first three in order to get STDIN, STDOUT, STDERR 77 open("/dev/stdin", O_RDONLY); 78 open("/dev/stdout", O_WRONLY); 79 open("/dev/stderr", O_WRONLY); 80} 81 82int KernelProxy::open_resource(const char* path) { 83 ScopedMount mnt; 84 Path rel; 85 86 Error error = AcquireMountAndRelPath(path, &mnt, &rel); 87 if (error) { 88 errno = error; 89 return -1; 90 } 91 92 ScopedMountNode node; 93 error = mnt->OpenResource(rel, &node); 94 if (error) { 95 // OpenResource failed, try Open(). 96 error = mnt->Open(rel, O_RDONLY, &node); 97 if (error) { 98 errno = error; 99 return -1; 100 } 101 } 102 103 ScopedKernelHandle handle(new KernelHandle(mnt, node)); 104 error = handle->Init(O_RDONLY); 105 if (error) { 106 errno = error; 107 return -1; 108 } 109 110 return AllocateFD(handle); 111} 112 113int KernelProxy::open(const char* path, int oflags) { 114 ScopedMount mnt; 115 ScopedMountNode node; 116 117 Error error = AcquireMountAndNode(path, oflags, &mnt, &node); 118 if (error) { 119 errno = error; 120 return -1; 121 } 122 123 ScopedKernelHandle handle(new KernelHandle(mnt, node)); 124 error = handle->Init(oflags); 125 if (error) { 126 errno = error; 127 return -1; 128 } 129 130 return AllocateFD(handle); 131} 132 133int KernelProxy::close(int fd) { 134 ScopedKernelHandle handle; 135 Error error = AcquireHandle(fd, &handle); 136 if (error) { 137 errno = error; 138 return -1; 139 } 140 141 // Remove the FD from the process open file descriptor map 142 FreeFD(fd); 143 return 0; 144} 145 146int KernelProxy::dup(int oldfd) { 147 ScopedKernelHandle handle; 148 Error error = AcquireHandle(oldfd, &handle); 149 if (error) { 150 errno = error; 151 return -1; 152 } 153 154 return AllocateFD(handle); 155} 156 157int KernelProxy::dup2(int oldfd, int newfd) { 158 // If it's the same file handle, just return 159 if (oldfd == newfd) 160 return newfd; 161 162 ScopedKernelHandle old_handle; 163 Error error = AcquireHandle(oldfd, &old_handle); 164 if (error) { 165 errno = error; 166 return -1; 167 } 168 169 FreeAndReassignFD(newfd, old_handle); 170 return newfd; 171} 172 173int KernelProxy::chdir(const char* path) { 174 Error error = SetCWD(path); 175 if (error) { 176 errno = error; 177 return -1; 178 } 179 return 0; 180} 181 182char* KernelProxy::getcwd(char* buf, size_t size) { 183 std::string cwd = GetCWD(); 184 185 if (size <= 0) { 186 errno = EINVAL; 187 return NULL; 188 } 189 190 // If size is 0, allocate as much as we need. 191 if (size == 0) { 192 size = cwd.size() + 1; 193 } 194 195 // Verify the buffer is large enough 196 if (size <= cwd.size()) { 197 errno = ERANGE; 198 return NULL; 199 } 200 201 // Allocate the buffer if needed 202 if (buf == NULL) { 203 buf = static_cast<char*>(malloc(size)); 204 } 205 206 strcpy(buf, cwd.c_str()); 207 return buf; 208} 209 210char* KernelProxy::getwd(char* buf) { 211 if (NULL == buf) { 212 errno = EFAULT; 213 return NULL; 214 } 215 return getcwd(buf, MAXPATHLEN); 216} 217 218int KernelProxy::chmod(const char* path, mode_t mode) { 219 int fd = KernelProxy::open(path, O_RDONLY); 220 if (-1 == fd) 221 return -1; 222 223 int result = fchmod(fd, mode); 224 close(fd); 225 return result; 226} 227 228int KernelProxy::chown(const char* path, uid_t owner, gid_t group) { 229 return 0; 230} 231 232int KernelProxy::fchown(int fd, uid_t owner, gid_t group) { 233 return 0; 234} 235 236int KernelProxy::lchown(const char* path, uid_t owner, gid_t group) { 237 return 0; 238} 239 240int KernelProxy::utime(const char* filename, const struct utimbuf* times) { 241 return 0; 242} 243 244int KernelProxy::mkdir(const char* path, mode_t mode) { 245 ScopedMount mnt; 246 Path rel; 247 248 Error error = AcquireMountAndRelPath(path, &mnt, &rel); 249 if (error) { 250 errno = error; 251 return -1; 252 } 253 254 error = mnt->Mkdir(rel, mode); 255 if (error) { 256 errno = error; 257 return -1; 258 } 259 260 return 0; 261} 262 263int KernelProxy::rmdir(const char* path) { 264 ScopedMount mnt; 265 Path rel; 266 267 Error error = AcquireMountAndRelPath(path, &mnt, &rel); 268 if (error) { 269 errno = error; 270 return -1; 271 } 272 273 error = mnt->Rmdir(rel); 274 if (error) { 275 errno = error; 276 return -1; 277 } 278 279 return 0; 280} 281 282int KernelProxy::stat(const char* path, struct stat* buf) { 283 int fd = open(path, O_RDONLY); 284 if (-1 == fd) 285 return -1; 286 287 int result = fstat(fd, buf); 288 close(fd); 289 return result; 290} 291 292 293int KernelProxy::mount(const char* source, 294 const char* target, 295 const char* filesystemtype, 296 unsigned long mountflags, 297 const void* data) { 298 std::string abs_path = GetAbsParts(target).Join(); 299 300 // Find a factory of that type 301 MountFactoryMap_t::iterator factory = factories_.find(filesystemtype); 302 if (factory == factories_.end()) { 303 errno = ENODEV; 304 return -1; 305 } 306 307 // Create a map of settings 308 StringMap_t smap; 309 smap["SOURCE"] = source; 310 smap["TARGET"] = abs_path; 311 312 if (data) { 313 char* str = strdup(static_cast<const char*>(data)); 314 char* ptr = strtok(str, ","); 315 char* val; 316 while (ptr != NULL) { 317 val = strchr(ptr, '='); 318 if (val) { 319 *val = 0; 320 smap[ptr] = val + 1; 321 } else { 322 smap[ptr] = "TRUE"; 323 } 324 ptr = strtok(NULL, ","); 325 } 326 free(str); 327 } 328 329 ScopedMount mnt; 330 Error error = factory->second->CreateMount(dev_++, smap, ppapi_, &mnt); 331 if (error) { 332 errno = error; 333 return -1; 334 } 335 336 error = AttachMountAtPath(mnt, abs_path); 337 if (error) { 338 errno = error; 339 return -1; 340 } 341 342 return 0; 343} 344 345int KernelProxy::umount(const char* path) { 346 Error error = DetachMountAtPath(path); 347 if (error) { 348 errno = error; 349 return -1; 350 } 351 return 0; 352} 353 354ssize_t KernelProxy::read(int fd, void* buf, size_t nbytes) { 355 ScopedKernelHandle handle; 356 Error error = AcquireHandle(fd, &handle); 357 if (error) { 358 errno = error; 359 return -1; 360 } 361 362 int cnt = 0; 363 error = handle->Read(buf, nbytes, &cnt); 364 if (error) { 365 errno = error; 366 return -1; 367 } 368 369 return cnt; 370} 371 372ssize_t KernelProxy::write(int fd, const void* buf, size_t nbytes) { 373 ScopedKernelHandle handle; 374 Error error = AcquireHandle(fd, &handle); 375 if (error) { 376 errno = error; 377 return -1; 378 } 379 380 int cnt = 0; 381 error = handle->Write(buf, nbytes, &cnt); 382 if (error) { 383 errno = error; 384 return -1; 385 } 386 387 return cnt; 388} 389 390int KernelProxy::fstat(int fd, struct stat* buf) { 391 ScopedKernelHandle handle; 392 Error error = AcquireHandle(fd, &handle); 393 if (error) { 394 errno = error; 395 return -1; 396 } 397 398 error = handle->node()->GetStat(buf); 399 if (error) { 400 errno = error; 401 return -1; 402 } 403 404 return 0; 405} 406 407int KernelProxy::getdents(int fd, void* buf, unsigned int count) { 408 ScopedKernelHandle handle; 409 Error error = AcquireHandle(fd, &handle); 410 if (error) { 411 errno = error; 412 return -1; 413 } 414 415 int cnt = 0; 416 error = handle->GetDents(static_cast<dirent*>(buf), count, &cnt); 417 if (error) 418 errno = error; 419 420 return cnt; 421} 422 423int KernelProxy::ftruncate(int fd, off_t length) { 424 ScopedKernelHandle handle; 425 Error error = AcquireHandle(fd, &handle); 426 if (error) { 427 errno = error; 428 return -1; 429 } 430 431 error = handle->node()->FTruncate(length); 432 if (error) { 433 errno = error; 434 return -1; 435 } 436 437 return 0; 438} 439 440int KernelProxy::fsync(int fd) { 441 ScopedKernelHandle handle; 442 Error error = AcquireHandle(fd, &handle); 443 if (error) { 444 errno = error; 445 return -1; 446 } 447 448 error = handle->node()->FSync(); 449 if (error) { 450 errno = error; 451 return -1; 452 } 453 454 return 0; 455} 456 457int KernelProxy::isatty(int fd) { 458 ScopedKernelHandle handle; 459 Error error = AcquireHandle(fd, &handle); 460 if (error) { 461 errno = error; 462 return -1; 463 } 464 465 error = handle->node()->IsaTTY(); 466 if (error) { 467 errno = error; 468 return -1; 469 } 470 471 return 0; 472} 473 474int KernelProxy::ioctl(int d, int request, char* argp) { 475 ScopedKernelHandle handle; 476 Error error = AcquireHandle(d, &handle); 477 if (error) { 478 errno = error; 479 return -1; 480 } 481 482 error = handle->node()->Ioctl(request, argp); 483 if (error) { 484 errno = error; 485 return -1; 486 } 487 488 return 0; 489} 490 491off_t KernelProxy::lseek(int fd, off_t offset, int whence) { 492 ScopedKernelHandle handle; 493 Error error = AcquireHandle(fd, &handle); 494 if (error) { 495 errno = error; 496 return -1; 497 } 498 499 off_t new_offset; 500 error = handle->Seek(offset, whence, &new_offset); 501 if (error) { 502 errno = error; 503 return -1; 504 } 505 506 return new_offset; 507} 508 509int KernelProxy::unlink(const char* path) { 510 ScopedMount mnt; 511 Path rel; 512 513 Error error = AcquireMountAndRelPath(path, &mnt, &rel); 514 if (error) { 515 errno = error; 516 return -1; 517 } 518 519 error = mnt->Unlink(rel); 520 if (error) { 521 errno = error; 522 return -1; 523 } 524 525 return 0; 526} 527 528int KernelProxy::remove(const char* path) { 529 ScopedMount mnt; 530 Path rel; 531 532 Error error = AcquireMountAndRelPath(path, &mnt, &rel); 533 if (error) { 534 errno = error; 535 return -1; 536 } 537 538 error = mnt->Remove(rel); 539 if (error) { 540 errno = error; 541 return -1; 542 } 543 544 return 0; 545} 546 547// TODO(noelallen): Needs implementation. 548int KernelProxy::fchmod(int fd, int mode) { 549 ScopedKernelHandle handle; 550 Error error = AcquireHandle(fd, &handle); 551 if (error) { 552 errno = error; 553 return -1; 554 } 555 556 return 0; 557} 558 559int KernelProxy::access(const char* path, int amode) { 560 ScopedMount mnt; 561 Path rel; 562 563 Error error = AcquireMountAndRelPath(path, &mnt, &rel); 564 if (error) { 565 errno = error; 566 return -1; 567 } 568 569 error = mnt->Access(rel, amode); 570 if (error) { 571 errno = error; 572 return -1; 573 } 574 return 0; 575} 576 577// TODO(noelallen): Needs implementation. 578int KernelProxy::link(const char* oldpath, const char* newpath) { 579 errno = EINVAL; 580 return -1; 581} 582 583int KernelProxy::symlink(const char* oldpath, const char* newpath) { 584 errno = EINVAL; 585 return -1; 586} 587 588void* KernelProxy::mmap(void* addr, 589 size_t length, 590 int prot, 591 int flags, 592 int fd, 593 size_t offset) { 594 // We shouldn't be getting anonymous mmaps here. 595 assert((flags & MAP_ANONYMOUS) == 0); 596 assert(fd != -1); 597 598 ScopedKernelHandle handle; 599 Error error = AcquireHandle(fd, &handle); 600 if (error) { 601 errno = error; 602 return MAP_FAILED; 603 } 604 605 void* new_addr; 606 error = handle->node()->MMap(addr, length, prot, flags, offset, &new_addr); 607 if (error) { 608 errno = error; 609 return MAP_FAILED; 610 } 611 612 return new_addr; 613} 614 615int KernelProxy::munmap(void* addr, size_t length) { 616 // NOTE: The comment below is from a previous discarded implementation that 617 // tracks mmap'd regions. For simplicity, we no longer do this; because we 618 // "snapshot" the contents of the file in mmap(), and don't support 619 // write-back or updating the mapped region when the file is written, holding 620 // on to the KernelHandle is pointless. 621 // 622 // If we ever do, these threading issues should be considered. 623 624 // 625 // WARNING: this function may be called by free(). 626 // 627 // There is a potential deadlock scenario: 628 // Thread 1: open() -> takes lock1 -> free() -> takes lock2 629 // Thread 2: free() -> takes lock2 -> munmap() -> takes lock1 630 // 631 // Note that open() above could be any function that takes a lock that is 632 // shared with munmap (this includes munmap!) 633 // 634 // To prevent this, we avoid taking locks in munmap() that are used by other 635 // nacl_io functions that may call free. Specifically, we only take the 636 // mmap_lock, which is only shared with mmap() above. There is still a 637 // possibility of deadlock if mmap() or munmap() calls free(), so this is not 638 // allowed. 639 // 640 // Unfortunately, munmap still needs to acquire other locks; see the call to 641 // ReleaseHandle below which takes the process lock. This is safe as long as 642 // this is never executed from free() -- we can be reasonably sure this is 643 // true, because malloc only makes anonymous mmap() requests, and should only 644 // be munmapping those allocations. We never add to mmap_info_list_ for 645 // anonymous maps, so the unmap_list should always be empty when called from 646 // free(). 647 return 0; 648} 649 650#ifdef PROVIDES_SOCKET_API 651 652int KernelProxy::select(int nfds, fd_set* readfds, fd_set* writefds, 653 fd_set* exceptfds, struct timeval* timeout) { 654 ScopedEventListener listener(new EventListener); 655 std::vector<struct pollfd> fds; 656 657 fd_set readout, writeout, exceptout; 658 659 FD_ZERO(&readout); 660 FD_ZERO(&writeout); 661 FD_ZERO(&exceptout); 662 663 int fd; 664 size_t event_cnt = 0; 665 int event_track = 0; 666 for (fd = 0; fd < nfds; fd++) { 667 int events = 0; 668 669 if (readfds != NULL && FD_ISSET(fd, readfds)) 670 events |= POLLIN; 671 672 if (writefds != NULL && FD_ISSET(fd, writefds)) 673 events |= POLLOUT; 674 675 if (exceptfds != NULL && FD_ISSET(fd, exceptfds)) 676 events |= POLLERR | POLLHUP; 677 678 // If we are not interested in this FD, skip it 679 if (0 == events) continue; 680 681 ScopedKernelHandle handle; 682 Error err = AcquireHandle(fd, &handle); 683 684 // Select will return immediately if there are bad FDs. 685 if (err != 0) { 686 errno = EBADF; 687 return -1; 688 } 689 690 int status = handle->node()->GetEventStatus() & events; 691 if (status & POLLIN) { 692 FD_SET(fd, &readout); 693 event_cnt++; 694 } 695 696 if (status & POLLOUT) { 697 FD_SET(fd, &writeout); 698 event_cnt++; 699 } 700 701 if (status & (POLLERR | POLLHUP)) { 702 FD_SET(fd, &exceptout); 703 event_cnt++; 704 } 705 706 // Otherwise track it. 707 if (0 == status) { 708 err = listener->Track(fd, handle->node(), events, fd); 709 if (err != 0) { 710 errno = EBADF; 711 return -1; 712 } 713 event_track++; 714 } 715 } 716 717 // If nothing is signaled, then we must wait. 718 if (event_cnt == 0) { 719 std::vector<EventData> events; 720 int ready_cnt; 721 int ms_timeout; 722 723 // NULL timeout signals wait forever. 724 if (timeout == NULL) { 725 ms_timeout = -1; 726 } else { 727 int64_t ms = timeout->tv_sec * 1000 + ((timeout->tv_usec + 500) / 1000); 728 729 // If the timeout is invalid or too long (larger than signed 32 bit). 730 if ((timeout->tv_sec < 0) || (timeout->tv_sec >= (INT_MAX / 1000)) || 731 (timeout->tv_usec < 0) || (timeout->tv_usec >= 1000) || 732 (ms < 0) || (ms >= INT_MAX)) { 733 errno = EINVAL; 734 return -1; 735 } 736 737 ms_timeout = static_cast<int>(ms); 738 } 739 740 events.resize(event_track); 741 listener->Wait(events.data(), event_track, ms_timeout, &ready_cnt); 742 for (fd = 0; static_cast<int>(fd) < ready_cnt; fd++) { 743 if (events[fd].events & POLLIN) { 744 FD_SET(events[fd].user_data, &readout); 745 event_cnt++; 746 } 747 748 if (events[fd].events & POLLOUT) { 749 FD_SET(events[fd].user_data, &writeout); 750 event_cnt++; 751 } 752 753 if (events[fd].events & (POLLERR | POLLHUP)) { 754 FD_SET(events[fd].user_data, &exceptout); 755 event_cnt++; 756 } 757 } 758 } 759 760 // Copy out the results 761 if (readfds != NULL) 762 *readfds = readout; 763 764 if (writefds != NULL) 765 *writefds = writeout; 766 767 if (exceptfds != NULL) 768 *exceptfds = exceptout; 769 770 return event_cnt; 771} 772 773int KernelProxy::poll(struct pollfd *fds, nfds_t nfds, int timeout) { 774 ScopedEventListener listener(new EventListener); 775 776 int index; 777 size_t event_cnt = 0; 778 size_t event_track = 0; 779 for (index = 0; static_cast<nfds_t>(index) < nfds; index++) { 780 ScopedKernelHandle handle; 781 struct pollfd* info = &fds[index]; 782 Error err = AcquireHandle(info->fd, &handle); 783 784 // If the node isn't open, or somehow invalid, mark it so. 785 if (err != 0) { 786 info->revents = POLLNVAL; 787 event_cnt++; 788 continue; 789 } 790 791 // If it's already signaled, then just capture the event 792 if (handle->node()->GetEventStatus() & info->events) { 793 info->revents = info->events & handle->node()->GetEventStatus(); 794 event_cnt++; 795 continue; 796 } 797 798 // Otherwise try to track it. 799 err = listener->Track(info->fd, handle->node(), info->events, index); 800 if (err != 0) { 801 info->revents = POLLNVAL; 802 event_cnt++; 803 continue; 804 } 805 event_track++; 806 } 807 808 // If nothing is signaled, then we must wait. 809 if (0 == event_cnt) { 810 std::vector<EventData> events; 811 int ready_cnt; 812 813 events.resize(event_track); 814 listener->Wait(events.data(), event_track, timeout, &ready_cnt); 815 for (index = 0; index < ready_cnt; index++) { 816 struct pollfd* info = &fds[events[index].user_data]; 817 818 info->revents = events[index].events; 819 event_cnt++; 820 } 821 } 822 823 return event_cnt; 824} 825 826 827 828// Socket Functions 829int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) { 830 if (NULL == addr || NULL == len) { 831 errno = EFAULT; 832 return -1; 833 } 834 835 ScopedKernelHandle handle; 836 if (AcquireSocketHandle(fd, &handle) == -1) 837 return -1; 838 839 errno = EINVAL; 840 return -1; 841} 842 843int KernelProxy::bind(int fd, const struct sockaddr* addr, socklen_t len) { 844 if (NULL == addr) { 845 errno = EFAULT; 846 return -1; 847 } 848 849 ScopedKernelHandle handle; 850 if (AcquireSocketHandle(fd, &handle) == -1) 851 return -1; 852 853 errno = EINVAL; 854 return -1; 855} 856 857int KernelProxy::connect(int fd, const struct sockaddr* addr, socklen_t len) { 858 if (NULL == addr) { 859 errno = EFAULT; 860 return -1; 861 } 862 863 ScopedKernelHandle handle; 864 if (AcquireSocketHandle(fd, &handle) == -1) 865 return -1; 866 867 errno = EACCES; 868 return -1; 869} 870 871int KernelProxy::getpeername(int fd, struct sockaddr* addr, socklen_t* len) { 872 if (NULL == addr || NULL == len) { 873 errno = EFAULT; 874 return -1; 875 } 876 877 ScopedKernelHandle handle; 878 if (AcquireSocketHandle(fd, &handle) == -1) 879 return -1; 880 881 errno = EINVAL; 882 return -1; 883} 884 885int KernelProxy::getsockname(int fd, struct sockaddr* addr, socklen_t* len) { 886 if (NULL == addr || NULL == len) { 887 errno = EFAULT; 888 return -1; 889 } 890 891 ScopedKernelHandle handle; 892 if (AcquireSocketHandle(fd, &handle) == -1) 893 return -1; 894 895 errno = EINVAL; 896 return -1; 897} 898 899int KernelProxy::getsockopt(int fd, 900 int lvl, 901 int optname, 902 void* optval, 903 socklen_t* len) { 904 if (NULL == optval || NULL == len) { 905 errno = EFAULT; 906 return -1; 907 } 908 909 ScopedKernelHandle handle; 910 if (AcquireSocketHandle(fd, &handle) == -1) 911 return -1; 912 913 errno = EINVAL; 914 return -1; 915} 916 917int KernelProxy::listen(int fd, int backlog) { 918 ScopedKernelHandle handle; 919 if (AcquireSocketHandle(fd, &handle) == -1) 920 return -1; 921 922 errno = EOPNOTSUPP; 923 return -1; 924} 925 926ssize_t KernelProxy::recv(int fd, 927 void* buf, 928 size_t len, 929 int flags) { 930 if (NULL == buf) { 931 errno = EFAULT; 932 return -1; 933 } 934 935 ScopedKernelHandle handle; 936 if (AcquireSocketHandle(fd, &handle) == -1) 937 return -1; 938 939 errno = EINVAL; 940 return -1; 941} 942 943ssize_t KernelProxy::recvfrom(int fd, 944 void* buf, 945 size_t len, 946 int flags, 947 struct sockaddr* addr, 948 socklen_t* addrlen) { 949 // According to the manpage, recvfrom with a null addr is identical to recv. 950 if (NULL == addr) { 951 return recv(fd, buf, len, flags); 952 } 953 954 if (NULL == buf || NULL == addrlen) { 955 errno = EFAULT; 956 return -1; 957 } 958 959 ScopedKernelHandle handle; 960 if (AcquireSocketHandle(fd, &handle) == -1) 961 return -1; 962 963 errno = EINVAL; 964 return -1; 965} 966 967ssize_t KernelProxy::recvmsg(int fd, struct msghdr* msg, int flags) { 968 if (NULL == msg ) { 969 errno = EFAULT; 970 return -1; 971 } 972 973 ScopedKernelHandle handle; 974 if (AcquireSocketHandle(fd, &handle) == -1) 975 return -1; 976 977 errno = EOPNOTSUPP; 978 return -1; 979} 980 981ssize_t KernelProxy::send(int fd, const void* buf, size_t len, int flags) { 982 if (NULL == buf) { 983 errno = EFAULT; 984 return -1; 985 } 986 987 ScopedKernelHandle handle; 988 if (AcquireSocketHandle(fd, &handle) == -1) 989 return -1; 990 991 errno = EINVAL; 992 return -1; 993} 994 995ssize_t KernelProxy::sendto(int fd, 996 const void* buf, 997 size_t len, 998 int flags, 999 const struct sockaddr* addr, 1000 socklen_t addrlen) { 1001 // According to the manpage, sendto with a null addr is identical to send. 1002 if (NULL == addr) { 1003 return send(fd, buf, len, flags); 1004 } 1005 1006 if (NULL == buf) { 1007 errno = EFAULT; 1008 return -1; 1009 } 1010 1011 ScopedKernelHandle handle; 1012 if (AcquireSocketHandle(fd, &handle) == -1) 1013 return -1; 1014 1015 errno = EINVAL; 1016 return -1; 1017} 1018 1019ssize_t KernelProxy::sendmsg(int fd, const struct msghdr* msg, int flags) { 1020 if (NULL == msg) { 1021 errno = EFAULT; 1022 return -1; 1023 } 1024 1025 ScopedKernelHandle handle; 1026 if (AcquireSocketHandle(fd, &handle) == -1) 1027 return -1; 1028 1029 errno = EOPNOTSUPP; 1030 return -1; 1031} 1032 1033int KernelProxy::setsockopt(int fd, 1034 int lvl, 1035 int optname, 1036 const void* optval, 1037 socklen_t len) { 1038 if (NULL == optval) { 1039 errno = EFAULT; 1040 return -1; 1041 } 1042 1043 ScopedKernelHandle handle; 1044 if (AcquireSocketHandle(fd, &handle) == -1) 1045 return -1; 1046 1047 errno = EINVAL; 1048 return -1; 1049} 1050 1051int KernelProxy::shutdown(int fd, int how) { 1052 ScopedKernelHandle handle; 1053 if (AcquireSocketHandle(fd, &handle) == -1) 1054 return -1; 1055 1056 errno = EINVAL; 1057 return -1; 1058} 1059 1060int KernelProxy::socket(int domain, int type, int protocol) { 1061 if (AF_INET != domain && AF_INET6 != domain) { 1062 errno = EAFNOSUPPORT; 1063 return -1; 1064 } 1065 1066 if (SOCK_STREAM != type && SOCK_DGRAM != type) { 1067 errno = EPROTONOSUPPORT; 1068 return -1; 1069 } 1070 1071 errno = EACCES; 1072 return -1; 1073} 1074 1075int KernelProxy::socketpair(int domain, int type, int protocol, int* sv) { 1076 if (NULL == sv) { 1077 errno = EFAULT; 1078 return -1; 1079 } 1080 1081 // Catch-22: We don't support AF_UNIX, but any other AF doesn't support 1082 // socket pairs. Thus, this function always fails. 1083 if (AF_UNIX != domain) { 1084 errno = EPROTONOSUPPORT; 1085 return -1; 1086 } 1087 1088 if (AF_INET != domain && AF_INET6 != domain) { 1089 errno = EAFNOSUPPORT; 1090 return -1; 1091 } 1092 1093 // We cannot reach this point. 1094 errno = ENOSYS; 1095 return -1; 1096} 1097 1098int KernelProxy::AcquireSocketHandle(int fd, ScopedKernelHandle* handle) { 1099 Error error = AcquireHandle(fd, handle); 1100 1101 if (error) { 1102 errno = error; 1103 return -1; 1104 } 1105 1106 if ((handle->get()->node_->GetType() & S_IFSOCK) == 0) { 1107 errno = ENOTSOCK; 1108 return -1; 1109 } 1110 1111 return 0; 1112} 1113 1114#endif // PROVIDES_SOCKET_API 1115 1116} // namespace_nacl_io 1117