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