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. I/O Descriptor / Handle abstraction. Memory
9 : * mapping using descriptors.
10 : */
11 :
12 : #ifndef NATIVE_CLIENT_SRC_TRUSTED_PLATFORM_NACL_HOST_DESC_H__
13 : #define NATIVE_CLIENT_SRC_TRUSTED_PLATFORM_NACL_HOST_DESC_H__
14 :
15 : #include <sys/stat.h>
16 :
17 : #include "native_client/src/include/nacl_compiler_annotations.h"
18 : #include "native_client/src/include/portability.h"
19 : #include "native_client/src/shared/platform/nacl_sync.h"
20 :
21 : #if NACL_LINUX || NACL_OSX
22 : # include "native_client/src/shared/platform/posix/nacl_host_desc_types.h"
23 : #elif NACL_WINDOWS
24 : # include "native_client/src/shared/platform/win/nacl_host_desc_types.h"
25 : #endif
26 :
27 :
28 :
29 : /*
30 : * see NACL_MAP_PAGESIZE from nacl_config.h; map operations must be aligned
31 : */
32 :
33 : EXTERN_C_BEGIN
34 :
35 : struct nacl_abi_stat;
36 : struct NaClDescEffector;
37 : struct NaClHostDesc;
38 :
39 : /*
40 : * off64_t in linux, off_t in osx and __int64_t in win
41 : */
42 : typedef int64_t nacl_off64_t;
43 :
44 : /*
45 : * We do not explicitly provide an abstracted version of a
46 : * host-independent stat64 structure. Instead, it is up to the user
47 : * of the nacl_host_desc code to not use anything but the
48 : * POSIX-blessed fields, to know that the shape/size may differ across
49 : * platforms, and to know that the st_size field is a 64-bit value
50 : * compatible w/ nacl_off64_t above.
51 : */
52 : #if NACL_LINUX
53 : typedef struct stat64 nacl_host_stat_t;
54 : # define NACL_HOST_FSTAT64 fstat64
55 : # define NACL_HOST_STAT64 stat64
56 : # define NACL_HOST_LSTAT64 lstat64
57 : #elif NACL_OSX
58 : typedef struct stat nacl_host_stat_t;
59 : # define NACL_HOST_FSTAT64 fstat
60 : # define NACL_HOST_STAT64 stat
61 : # define NACL_HOST_LSTAT64 lstat
62 : #elif NACL_WINDOWS
63 : typedef struct _stati64 nacl_host_stat_t;
64 : # define NACL_HOST_FSTAT64 _fstat64
65 : # define NACL_HOST_STAT64 _stati64
66 : # define NACL_HOST_LSTAT64 _lstati64
67 : #elif defined __native_client__
68 : /* nacl_host_stat_t not exposed to NaCl module code */
69 : #else
70 : # error "what OS?"
71 : #endif
72 :
73 : /*
74 : * TODO(bsy): it seems like these error functions are useful in more
75 : * places than just the NaClDesc library. Move them to a more central
76 : * header. When that's done, it should be possible to include this
77 : * header *only* from host code, removing the need for the #ifdef
78 : * __native_client__ directives.
79 : *
80 : * Currently that's not possible, unless we want to forego
81 : * NaCl*IsNegErrno in trusted code, and go back to writing if(retval <
82 : * 0) to check for errors.
83 : */
84 :
85 : /*
86 : * On 64-bit Linux, the app has the entire 32-bit address space
87 : * (kernel no longer occupies the top 1G), so what is an errno and
88 : * what is an address is trickier: we require that our NACL_ABI_
89 : * errno values be less than 64K.
90 : *
91 : * NB: The runtime assumes that valid errno values can ALWAYS be
92 : * represented using no more than 16 bits. If this assumption
93 : * changes, all code dealing with error number should be reviewed.
94 : *
95 : * NB 2010-02-03: The original code for this function did not work:
96 : * return ((uint64_t) val) >= ~((uint64_t) 0xffff);
97 : * Macintosh optimized builds were not able to recognize negative values.
98 : * All other platforms as well as Macintosh debug builds worked fine.
99 : *
100 : * NB the 3rd, 2010-10-19: these functions take pointer arguments
101 : * to discourage accidental use of narrowing/widening conversions,
102 : * which have caused problems in the past. We assume without proof
103 : * that the compiler will do the right thing when inlining.
104 : */
105 : static INLINE int NaClPtrIsNegErrno(const uintptr_t *val) {
106 : return (*val & ~((uintptr_t) 0xffff)) == ~((uintptr_t) 0xffff);
107 : }
108 :
109 4 : static INLINE int NaClSSizeIsNegErrno(const ssize_t *val) {
110 4 : return (*val & ~((ssize_t) 0xffff)) == ~((ssize_t) 0xffff);
111 4 : }
112 :
113 : static INLINE int NaClOff64IsNegErrno(const nacl_off64_t *val) {
114 : return (*val & ~((nacl_off64_t) 0xffff)) == ~((nacl_off64_t) 0xffff);
115 : }
116 :
117 : extern int NaClXlateErrno(int errnum);
118 :
119 : extern int NaClXlateNaClSyncStatus(NaClSyncStatus status);
120 :
121 : #ifndef __native_client__ /* these functions are not exposed to NaCl modules
122 : * (see TODO comment above)
123 : */
124 : /*
125 : * Mapping data from a file.
126 : *
127 : * start_addr and len must be multiples of NACL_MAP_PAGESIZE.
128 : *
129 : * Of prot bits, NACL_ABI_PROT_READ, NACL_ABI_PROT_WRITE, and
130 : * NACL_ABI_PROT_WRITE are allowed. Of flags, only
131 : * NACL_ABI_MAP_ANONYMOUS is allowed. start_addr may be NULL when
132 : * NACL_ABI_MAP_FIXED is not set, and in Windows NaClFindAddressSpace
133 : * is used to find a starting address (NB: NaCl module syscall
134 : * handling should always use NACL_ABI_MAP_FIXED to select the
135 : * location to be within the untrusted address space). start_address,
136 : * len, and offset must be a multiple of NACL_MAP_PAGESIZE.
137 : *
138 : * Note that in Windows, in order for the mapping to be coherent (two
139 : * or more shared mappings/views of the file data will show changes
140 : * that are made in another mapping/view), the mappings must use the
141 : * same mapping handle or open file handle. Either may be sent to
142 : * another process to achieve this. Windows does not guarantee
143 : * coherence, however, if a process opened the same file again and
144 : * performed CreateFileMapping / MapViewOfFile using the new file
145 : * handle.
146 : *
147 : * Underlying host-OS syscalls: mmap / MapViewOfFileEx
148 : *
149 : * 4GB file max
150 : */
151 : extern uintptr_t NaClHostDescMap(struct NaClHostDesc *d,
152 : struct NaClDescEffector *effp,
153 : void *start_addr,
154 : size_t len,
155 : int prot,
156 : int flags,
157 : nacl_off64_t offset) NACL_WUR;
158 :
159 : /*
160 : * Undo a file mapping. The memory range specified by start_address,
161 : * len must be memory that came from NaClHostDescMap.
162 : *
163 : * start_addr and len must be multiples of NACL_MAP_PAGESIZE.
164 : *
165 : * Underlying host-OS syscalls: munmap / UnmapViewOfFile
166 : */
167 : extern int NaClHostDescUnmapUnsafe(void *start_addr,
168 : size_t len) NACL_WUR;
169 :
170 :
171 : /*
172 : * These are the flags that are permitted.
173 : */
174 : #define NACL_ALLOWED_OPEN_FLAGS \
175 : (NACL_ABI_O_ACCMODE | NACL_ABI_O_CREAT | NACL_ABI_O_TRUNC | NACL_ABI_O_APPEND)
176 :
177 : /*
178 : * Constructor for a NaClHostDesc object.
179 : *
180 : * |path| should be a host-OS pathname to a file. No validation is
181 : * done. |flags| should contain one of NACL_ABI_O_RDONLY,
182 : * NACL_ABI_O_WRONLY, and NACL_ABI_O_RDWR, and can additionally
183 : * contain NACL_ABI_O_CREAT, NACL_ABI_O_TRUNC, and NACL_ABI_O_APPEND.
184 : *
185 : * Uses raw syscall return convention, so returns 0 for success and
186 : * non-zero (usually -NACL_ABI_EINVAL) for failure.
187 : *
188 : * We cannot return the platform descriptor/handle and be consistent
189 : * with a largely POSIX-ish interface, since e.g. windows handles may
190 : * be negative and might look like negative errno returns. Currently
191 : * we use the posix API on windows, so it could work, but we may need
192 : * to change later.
193 : *
194 : * Underlying host-OS functions: open / _s_open_s
195 : */
196 : extern int NaClHostDescOpen(struct NaClHostDesc *d,
197 : char const *path,
198 : int flags,
199 : int perms) NACL_WUR;
200 :
201 : /*
202 : * Constructor for a NaClHostDesc object.
203 : *
204 : * Uses raw syscall return convention, so returns 0 for success and
205 : * non-zero (usually -NACL_ABI_EINVAL) for failure.
206 : *
207 : * d is a POSIX-interface descriptor
208 : *
209 : * flags may only contain one of NACL_ABI_O_RDONLY, NACL_ABI_O_WRONLY,
210 : * or NACL_ABI_O_RDWR, and must be the NACL_ABI_* versions of the
211 : * actual mode that d was opened with. NACL_ABI_O_CREAT/APPEND are
212 : * permitted, but ignored, so it is safe to pass the same flags value
213 : * used in NaClHostDescOpen and pass it to NaClHostDescPosixDup.
214 : *
215 : * Underlying host-OS functions: dup / _dup; mode is what posix_d was
216 : * opened with
217 : */
218 : extern int NaClHostDescPosixDup(struct NaClHostDesc *d,
219 : int posix_d,
220 : int flags) NACL_WUR;
221 :
222 : /*
223 : * Essentially the same as NaClHostDescPosixDup, but without the dup
224 : * -- takes ownership of the descriptor rather than making a dup.
225 : */
226 : extern int NaClHostDescPosixTake(struct NaClHostDesc *d,
227 : int posix_d,
228 : int flags) NACL_WUR;
229 :
230 :
231 : /*
232 : * Allocates a NaClHostDesc and invokes NaClHostDescPosixTake on it.
233 : * Aborts process if no memory.
234 : */
235 : extern struct NaClHostDesc *NaClHostDescPosixMake(int posix_d,
236 : int flags) NACL_WUR;
237 : /*
238 : * Read data from an opened file into a memory buffer.
239 : *
240 : * buf is not validated.
241 : *
242 : * Underlying host-OS functions: read / FileRead
243 : */
244 : extern ssize_t NaClHostDescRead(struct NaClHostDesc *d,
245 : void *buf,
246 : size_t len) NACL_WUR;
247 :
248 :
249 : /*
250 : * Write data from a memory buffer into an opened file.
251 : *
252 : * buf is not validated.
253 : *
254 : * Underlying host-OS functions: write / FileWrite
255 : */
256 : extern ssize_t NaClHostDescWrite(struct NaClHostDesc *d,
257 : void const *buf,
258 : size_t count) NACL_WUR;
259 :
260 : /*
261 : * Read data from an opened file into a memory buffer from specified
262 : * offset into file.
263 : *
264 : * buf is not validated.
265 : *
266 : * Underlying host-OS functions: pread{,64} / FileRead
267 : */
268 : extern ssize_t NaClHostDescPRead(struct NaClHostDesc *d,
269 : void *buf,
270 : size_t len,
271 : nacl_off64_t offset) NACL_WUR;
272 :
273 :
274 : /*
275 : * Write data from a memory buffer into an opened file at the specific
276 : * offset in the file.
277 : *
278 : * buf is not validated.
279 : *
280 : * Underlying host-OS functions: pwrite{,64} / FileWrite
281 : */
282 : extern ssize_t NaClHostDescPWrite(struct NaClHostDesc *d,
283 : void const *buf,
284 : size_t count,
285 : nacl_off64_t offset) NACL_WUR;
286 :
287 : extern nacl_off64_t NaClHostDescSeek(struct NaClHostDesc *d,
288 : nacl_off64_t offset,
289 : int whence);
290 :
291 : /*
292 : * Fstat.
293 : */
294 : extern int NaClHostDescFstat(struct NaClHostDesc *d,
295 : nacl_host_stat_t *nasp) NACL_WUR;
296 :
297 : /*
298 : * Isatty. Determine if file descriptor is connected to a TTY.
299 : * Returns 1 if the descriptor is a TTY, otherwise returns a negative errno
300 : * value.
301 : */
302 : extern int NaClHostDescIsatty(struct NaClHostDesc *d) NACL_WUR;
303 :
304 : /*
305 : * Dtor for the NaClHostFile object. Close the file.
306 : *
307 : * Underlying host-OS functions: close(2) / _close
308 : */
309 : extern int NaClHostDescClose(struct NaClHostDesc *d) NACL_WUR;
310 :
311 : extern int NaClHostDescStat(char const *host_os_pathname,
312 : nacl_host_stat_t *nasp) NACL_WUR;
313 :
314 : /*
315 : * Create directory
316 : */
317 : extern int NaClHostDescMkdir(const char *path, int mode) NACL_WUR;
318 :
319 : /*
320 : * Remove directory
321 : */
322 : extern int NaClHostDescRmdir(const char *path) NACL_WUR;
323 :
324 : /*
325 : * Change current working directory
326 : */
327 : extern int NaClHostDescChdir(const char *path) NACL_WUR;
328 :
329 : /*
330 : * Get current working directory.
331 : * This works like the POSIX getcwd(3) function except that it returns
332 : * an error code rather than the resulting buffer. The provided path may not
333 : * be NULL.
334 : */
335 : extern int NaClHostDescGetcwd(char *path, size_t len) NACL_WUR;
336 :
337 : /*
338 : * Remove/delete the underlying file.
339 : * Underlying host-OS functions: unlink(2) / _unlink
340 : */
341 : extern int NaClHostDescUnlink(char const *path) NACL_WUR;
342 :
343 : extern int NaClHostDescTruncate(char const *path,
344 : nacl_abi_off_t length) NACL_WUR;
345 :
346 : extern int NaClHostDescLstat(char const *path,
347 : nacl_host_stat_t *nasp) NACL_WUR;
348 :
349 : extern int NaClHostDescLink(const char *oldpath, const char *newpath) NACL_WUR;
350 :
351 : /*
352 : * Rename a file or directory.
353 : */
354 : extern int NaClHostDescRename(const char *oldpath,
355 : const char *newpath) NACL_WUR;
356 :
357 : /*
358 : * Create a new symlink called 'newpath', pointing to 'oldpath'.
359 : */
360 : extern int NaClHostDescSymlink(const char *oldpath, const char *newpath);
361 :
362 : extern int NaClHostDescChmod(const char *path, nacl_abi_mode_t amode);
363 :
364 : extern int NaClHostDescAccess(const char *path, int amode);
365 :
366 : /*
367 : * Find the target of a symlink.
368 : * Like readlink(2) this function writes up to 'bufsize' bytes to 'buf' and
369 : * returns the number of bytes written but never writes the NULL terminator.
370 : * Returns -1 and sets errno on error.
371 : */
372 : extern int NaClHostDescReadlink(const char *path, char *buf, size_t bufsize);
373 :
374 : /*
375 : * Maps NACI_ABI_ versions of the mmap prot argument to host ABI versions
376 : * of the bit values
377 : */
378 : extern int NaClProtMap(int abi_prot);
379 :
380 : /*
381 : * Utility routine. Checks |d| is non-NULL, and that d->d is not -1.
382 : * If either is true, an appropriate LOG_FATAL message with |fn_name|
383 : * interpolated is generated.
384 : */
385 : extern void NaClHostDescCheckValidity(char const *fn_name,
386 : struct NaClHostDesc *d);
387 :
388 : #if NACL_WINDOWS
389 : extern void NaClflProtectAndDesiredAccessMap(int prot,
390 : int is_private,
391 : int accmode,
392 : DWORD *out_flProtect,
393 : DWORD *out_dwDesiredAccess,
394 : DWORD *out_flNewProtect,
395 : char const **out_msg);
396 :
397 : extern DWORD NaClflProtectMap(int prot);
398 : #endif
399 :
400 : EXTERN_C_END
401 :
402 : #endif /* defined __native_client__ */
403 :
404 : #endif /* NATIVE_CLIENT_SRC_TRUSTED_PLATFORM_NACL_HOST_DESC_H__ */
|