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