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