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