1 /*
2  * Copyright (c) 2012 The Native Client Authors. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  */
6 
7 /*
8  * NaCl Service Runtime.  Directory descriptor abstraction.
9  */
10 
11 #include "native_client/src/include/portability.h"
12 
13 #include <stdlib.h>
14 #include <string.h>
15 
16 #include "native_client/src/shared/imc/nacl_imc_c.h"
17 
18 #include "native_client/src/trusted/desc/nacl_desc_base.h"
19 #include "native_client/src/trusted/desc/nacl_desc_dir.h"
20 
21 #include "native_client/src/shared/platform/nacl_host_dir.h"
22 #include "native_client/src/shared/platform/nacl_log.h"
23 
24 #include "native_client/src/trusted/service_runtime/internal_errno.h"
25 #include "native_client/src/trusted/service_runtime/nacl_config.h"
26 
27 #include "native_client/src/trusted/service_runtime/include/bits/mman.h"
28 #include "native_client/src/trusted/service_runtime/include/sys/dirent.h"
29 #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
30 #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
31 #include "native_client/src/trusted/service_runtime/include/sys/stat.h"
32 
33 
34 /*
35  * This file contains the implementation for the NaClDirDesc subclass
36  * of NaClDesc.
37  *
38  * NaClDescDirDesc is the subclass that wraps host-OS directory information.
39  */
40 
41 static struct NaClDescVtbl const kNaClDescDirDescVtbl;  /* fwd */
42 
43 /*
44  * Takes ownership of hd, will close in Dtor.
45  */
NaClDescDirDescCtor(struct NaClDescDirDesc * self,struct NaClHostDir * hd)46 int NaClDescDirDescCtor(struct NaClDescDirDesc  *self,
47                         struct NaClHostDir      *hd) {
48   struct NaClDesc *basep = (struct NaClDesc *) self;
49 
50   basep->base.vtbl = (struct NaClRefCountVtbl const *) NULL;
51   if (!NaClDescCtor(basep)) {
52     return 0;
53   }
54   self->hd = hd;
55   basep->base.vtbl = (struct NaClRefCountVtbl const *) &kNaClDescDirDescVtbl;
56   return 1;
57 }
58 
NaClDescDirDescDtor(struct NaClRefCount * vself)59 static void NaClDescDirDescDtor(struct NaClRefCount *vself) {
60   struct NaClDescDirDesc *self = (struct NaClDescDirDesc *) vself;
61 
62   NaClHostDirClose(self->hd);
63   free(self->hd);
64   self->hd = NULL;
65   vself->vtbl = (struct NaClRefCountVtbl const *) &kNaClDescVtbl;
66   (*vself->vtbl->Dtor)(vself);
67 }
68 
NaClDescDirDescMake(struct NaClHostDir * nhdp)69 struct NaClDescDirDesc *NaClDescDirDescMake(struct NaClHostDir *nhdp) {
70   struct NaClDescDirDesc *ndp;
71 
72   ndp = malloc(sizeof *ndp);
73   if (NULL == ndp) {
74     NaClLog(LOG_FATAL,
75             "NaClDescDirDescMake: no memory for 0x%08"NACL_PRIxPTR"\n",
76             (uintptr_t) nhdp);
77   }
78   if (!NaClDescDirDescCtor(ndp, nhdp)) {
79     NaClLog(LOG_FATAL,
80             ("NaClDescDirDescMake:"
81              " NaClDescDirDescCtor(0x%08"NACL_PRIxPTR",0x%08"NACL_PRIxPTR
82              ") failed\n"),
83             (uintptr_t) ndp,
84             (uintptr_t) nhdp);
85   }
86   return ndp;
87 }
88 
NaClDescDirDescOpen(char * path)89 struct NaClDescDirDesc *NaClDescDirDescOpen(char *path) {
90   struct NaClHostDir  *nhdp;
91 
92   nhdp = malloc(sizeof *nhdp);
93   if (NULL == nhdp) {
94     NaClLog(LOG_FATAL, "NaClDescDirDescOpen: no memory for %s\n", path);
95   }
96   if (!NaClHostDirOpen(nhdp, path)) {
97     NaClLog(LOG_FATAL, "NaClDescDirDescOpen: NaClHostDirOpen failed for %s\n",
98             path);
99   }
100   return NaClDescDirDescMake(nhdp);
101 }
102 
NaClDescDirDescGetdents(struct NaClDesc * vself,void * dirp,size_t count)103 static ssize_t NaClDescDirDescGetdents(struct NaClDesc         *vself,
104                                        void                    *dirp,
105                                        size_t                  count) {
106   struct NaClDescDirDesc *self = (struct NaClDescDirDesc *) vself;
107 
108   return NaClHostDirGetdents(self->hd, dirp, count);
109 }
110 
NaClDescDirDescRead(struct NaClDesc * vself,void * buf,size_t len)111 static ssize_t NaClDescDirDescRead(struct NaClDesc         *vself,
112                                    void                    *buf,
113                                    size_t                  len) {
114   /* NaClLog(LOG_ERROR, "NaClDescDirDescRead: Read not allowed on dir\n"); */
115   return NaClDescDirDescGetdents(vself, buf, len);
116   /* return -NACL_ABI_EINVAL; */
117 }
118 
NaClDescDirDescSeek(struct NaClDesc * vself,nacl_off64_t offset,int whence)119 static nacl_off64_t NaClDescDirDescSeek(struct NaClDesc *vself,
120                                         nacl_off64_t    offset,
121                                         int             whence) {
122   struct NaClDescDirDesc *self = (struct NaClDescDirDesc *) vself;
123   /* Special case to handle rewinddir() */
124   if (offset == 0 || whence == SEEK_SET) {
125     NaClHostDirRewind(self->hd);
126     return 0;
127   }
128   return -NACL_ABI_EINVAL;
129 }
130 
NaClDescDirDescFstat(struct NaClDesc * vself,struct nacl_abi_stat * statbuf)131 static int NaClDescDirDescFstat(struct NaClDesc          *vself,
132                                 struct nacl_abi_stat     *statbuf) {
133   UNREFERENCED_PARAMETER(vself);
134 
135   memset(statbuf, 0, sizeof *statbuf);
136   /*
137    * TODO(bsy): saying it's executable/searchable might be a lie.
138    */
139   statbuf->nacl_abi_st_mode = (NACL_ABI_S_IFDIR |
140                                NACL_ABI_S_IRUSR |
141                                NACL_ABI_S_IXUSR);
142   return 0;
143 }
144 
NaClDescDirDescFchdir(struct NaClDesc * vself)145 static int NaClDescDirDescFchdir(struct NaClDesc *vself) {
146   struct NaClDescDirDesc *self = (struct NaClDescDirDesc *) vself;
147 
148   return NaClHostDirFchdir(self->hd);
149 }
150 
NaClDescDirDescFchmod(struct NaClDesc * vself,int mode)151 static int NaClDescDirDescFchmod(struct NaClDesc  *vself,
152                                  int              mode) {
153   struct NaClDescDirDesc *self = (struct NaClDescDirDesc *) vself;
154 
155   return NaClHostDirFchmod(self->hd, mode);
156 }
157 
NaClDescDirDescFsync(struct NaClDesc * vself)158 static int NaClDescDirDescFsync(struct NaClDesc *vself) {
159   struct NaClDescDirDesc *self = (struct NaClDescDirDesc *) vself;
160 
161   return NaClHostDirFsync(self->hd);
162 }
163 
NaClDescDirDescFdatasync(struct NaClDesc * vself)164 static int NaClDescDirDescFdatasync(struct NaClDesc *vself) {
165   struct NaClDescDirDesc *self = (struct NaClDescDirDesc *) vself;
166 
167   return NaClHostDirFdatasync(self->hd);
168 }
169 
170 static struct NaClDescVtbl const kNaClDescDirDescVtbl = {
171   {
172     NaClDescDirDescDtor,
173   },
174   NaClDescMapNotImplemented,
175   NaClDescDirDescRead,
176   NaClDescWriteNotImplemented,
177   NaClDescDirDescSeek,
178   NaClDescPReadNotImplemented,
179   NaClDescPWriteNotImplemented,
180   NaClDescDirDescFstat,
181   NaClDescDirDescFchdir,
182   NaClDescDirDescFchmod,
183   NaClDescDirDescFsync,
184   NaClDescDirDescFdatasync,
185   NaClDescFtruncateNotImplemented,
186   NaClDescDirDescGetdents,
187   NaClDescExternalizeSizeNotImplemented,
188   NaClDescExternalizeNotImplemented,
189   NaClDescLockNotImplemented,
190   NaClDescTryLockNotImplemented,
191   NaClDescUnlockNotImplemented,
192   NaClDescWaitNotImplemented,
193   NaClDescTimedWaitAbsNotImplemented,
194   NaClDescSignalNotImplemented,
195   NaClDescBroadcastNotImplemented,
196   NaClDescSendMsgNotImplemented,
197   NaClDescRecvMsgNotImplemented,
198   NaClDescLowLevelSendMsgNotImplemented,
199   NaClDescLowLevelRecvMsgNotImplemented,
200   NaClDescConnectAddrNotImplemented,
201   NaClDescAcceptConnNotImplemented,
202   NaClDescPostNotImplemented,
203   NaClDescSemWaitNotImplemented,
204   NaClDescGetValueNotImplemented,
205   NaClDescSetMetadata,
206   NaClDescGetMetadata,
207   NaClDescSetFlags,
208   NaClDescGetFlags,
209   NaClDescIsattyNotImplemented,
210   NACL_DESC_DIR,
211 };
212