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