2 * Copyright (c) 2011 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.
11 #include "native_client/src/include/portability.h"
12 #include "native_client/src/include/nacl_macros.h"
14 #include "native_client/src/trusted/service_runtime/env_cleanser.h"
15 #include "native_client/src/trusted/service_runtime/env_cleanser_test.h"
18 * Everything that starts with this prefix is allowed (but the prefix is
21 #define NACL_ENV_PREFIX "NACLENV_"
22 #define NACL_ENV_PREFIX_LENGTH 8
24 void NaClEnvCleanserCtor(struct NaClEnvCleanser *self, int with_whitelist) {
25 self->with_whitelist = with_whitelist;
26 self->cleansed_environ = (char const **) NULL;
30 * Environment variables names are from IEEE Std 1003.1-2001, with
31 * additional ones from locale(7) from glibc / linux. The entries
32 * must be sorted, in ASCII order, for the bsearch to run correctly.
34 /* static -- not static for testing */
35 char const *const kNaClEnvWhitelist[] = {
51 "NACL_PLUGIN_DEBUG", /* src/trusted/plugin/srpc/utility.cc */
52 "NACL_SRPC_DEBUG", /* src/shared/srpc/utility.c */
56 /* left arg is key, right arg is table entry */
57 static int EnvCmp(void const *vleft, void const *vright) {
58 char const *left = *(char const *const *) vleft;
59 char const *right = *(char const *const *) vright;
62 while ((cleft = *left) == (cright = *right)
68 if ('=' == cleft && '\0' == cright) {
71 return (0xff & cleft) - (0xff & cright);
74 int NaClEnvIsPassThroughVar(char const *env_entry) {
75 return strlen(env_entry) > NACL_ENV_PREFIX_LENGTH &&
76 0 == strncmp(env_entry, NACL_ENV_PREFIX,
77 NACL_ENV_PREFIX_LENGTH);
80 int NaClEnvInWhitelist(char const *env_entry) {
81 return NULL != bsearch((void const *) &env_entry,
82 (void const *) kNaClEnvWhitelist,
83 NACL_ARRAY_SIZE(kNaClEnvWhitelist) - 1, /* NULL */
84 sizeof kNaClEnvWhitelist[0],
88 /* PRE: sizeof(char *) is a power of 2 */
91 * Initializes the object with a filtered environment.
93 * May return false on errors, e.g., out-of-memory.
95 int NaClEnvCleanserInit(struct NaClEnvCleanser *self, char const *const *envp,
96 char const * const *extra_env) {
100 const size_t kMaxSize = ~(size_t) 0;
101 const size_t ptr_size_mult_overflow_mask = ~(kMaxSize / sizeof *envp);
102 char const **ptr_tbl;
106 * let n be a size_t. if n & ptr_size_mult_overflow_mask is set,
107 * then n*sizeof(void *) will have an arithmetic overflow.
110 if (NULL == envp || NULL == *envp) {
111 self->cleansed_environ = NULL;
114 for (p = envp; NULL != *p; ++p) {
115 if (!(self->with_whitelist && NaClEnvInWhitelist(*p)) &&
116 !NaClEnvIsPassThroughVar(*p)) {
119 if (num_env == kMaxSize) {
127 for (p = extra_env; NULL != *p; ++p) {
128 if (num_env == kMaxSize) {
136 /* pointer table -- NULL pointer terminated */
137 if (0 != ((1 + num_env) & ptr_size_mult_overflow_mask)) {
140 ptr_bytes = (1 + num_env) * sizeof(*envp);
142 ptr_tbl = (char const **) malloc(ptr_bytes);
143 if (NULL == ptr_tbl) {
147 /* this assumes no other thread is tweaking envp */
148 for (env = 0, p = envp; NULL != *p; ++p) {
149 if (NaClEnvIsPassThroughVar(*p)) {
150 ptr_tbl[env] = *p + NACL_ENV_PREFIX_LENGTH;
151 } else if (self->with_whitelist && NaClEnvInWhitelist(*p)) {
159 for (p = extra_env; NULL != *p; ++p) {
164 if (num_env != env) {
165 free((void *) ptr_tbl);
169 self->cleansed_environ = ptr_tbl;
174 char const *const *NaClEnvCleanserEnvironment(struct NaClEnvCleanser *self) {
175 return (char const *const *) self->cleansed_environ;
178 void NaClEnvCleanserDtor(struct NaClEnvCleanser *self) {
179 free((void *) self->cleansed_environ);
180 self->cleansed_environ = NULL;