1 // Copyright 2016 The Fuchsia 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 <runtime/processargs.h>
6
7 #include <zircon/syscalls.h>
8 #include <string.h>
9
10 // TODO(mcgrathr): Is there a better error code to use for marshalling
11 // protocol violations?
12 #define MALFORMED ZX_ERR_INVALID_ARGS
13
zxr_processargs_read(zx_handle_t bootstrap,void * buffer,uint32_t nbytes,zx_handle_t handles[],uint32_t nhandles,zx_proc_args_t ** pargs,uint32_t ** handle_info)14 zx_status_t zxr_processargs_read(zx_handle_t bootstrap,
15 void* buffer, uint32_t nbytes,
16 zx_handle_t handles[], uint32_t nhandles,
17 zx_proc_args_t** pargs,
18 uint32_t** handle_info) {
19 if (nbytes < sizeof(zx_proc_args_t))
20 return ZX_ERR_INVALID_ARGS;
21 if ((uintptr_t)buffer % alignof(zx_proc_args_t) != 0)
22 return ZX_ERR_INVALID_ARGS;
23
24 uint32_t got_bytes = 0;
25 uint32_t got_handles = 0;
26 zx_status_t status = _zx_channel_read(bootstrap, 0, buffer, handles, nbytes,
27 nhandles, &got_bytes, &got_handles);
28 if (status != ZX_OK)
29 return status;
30 if (got_bytes != nbytes || got_handles != nhandles)
31 return ZX_ERR_INVALID_ARGS;
32
33 zx_proc_args_t* const pa = buffer;
34
35 if (pa->protocol != ZX_PROCARGS_PROTOCOL ||
36 pa->version != ZX_PROCARGS_VERSION)
37 return MALFORMED;
38
39 if (pa->handle_info_off < sizeof(*pa) ||
40 pa->handle_info_off % alignof(uint32_t) != 0 ||
41 pa->handle_info_off > nbytes ||
42 (nbytes - pa->handle_info_off) / sizeof(uint32_t) < nhandles)
43 return MALFORMED;
44
45 if (pa->args_num > 0 && (pa->args_off < sizeof(*pa) ||
46 pa->args_off > nbytes ||
47 (nbytes - pa->args_off) < pa->args_num))
48 return MALFORMED;
49
50 if (pa->environ_num > 0 && (pa->environ_off < sizeof(*pa) ||
51 pa->environ_off > nbytes ||
52 (nbytes - pa->environ_off) < pa->environ_num))
53 return MALFORMED;
54
55 *pargs = pa;
56 *handle_info = (void*)&((uint8_t*)buffer)[pa->handle_info_off];
57 return ZX_OK;
58 }
59
unpack_strings(char * buffer,uint32_t bytes,char * result[],uint32_t off,uint32_t num)60 static zx_status_t unpack_strings(char* buffer, uint32_t bytes, char* result[],
61 uint32_t off, uint32_t num) {
62 char* p = &buffer[off];
63 for (uint32_t i = 0; i < num; ++i) {
64 result[i] = p;
65 do {
66 if (p >= &buffer[bytes])
67 return MALFORMED;
68 } while (*p++ != '\0');
69 }
70 result[num] = NULL;
71 return ZX_OK;
72 }
73
zxr_processargs_strings(void * msg,uint32_t bytes,char * argv[],char * envp[],char * names[])74 zx_status_t zxr_processargs_strings(void* msg, uint32_t bytes,
75 char* argv[], char* envp[], char* names[]) {
76 zx_proc_args_t* const pa = msg;
77 zx_status_t status = ZX_OK;
78 if (argv != NULL) {
79 status = unpack_strings(msg, bytes, argv, pa->args_off, pa->args_num);
80 }
81 if (envp != NULL && status == ZX_OK) {
82 status = unpack_strings(msg, bytes, envp,
83 pa->environ_off, pa->environ_num);
84 }
85 if (names != NULL && status == ZX_OK) {
86 status = unpack_strings(msg, bytes, names, pa->names_off, pa->names_num);
87 }
88 return status;
89 }
90