| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2009 The Native Client Authors. All rights reserved. | 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 | 3 * Use of this source code is governed by a BSD-style license that can be |
| 4 * be found in the LICENSE file. | 4 * found in the LICENSE file. |
| 5 */ | 5 */ |
| 6 | 6 |
| 7 #include <stdio.h> | 7 #include <stdio.h> |
| 8 #include <stdlib.h> | 8 #include <stdlib.h> |
| 9 #include <string.h> | 9 #include <string.h> |
| 10 | 10 |
| 11 #include "native_client/src/include/portability.h" | 11 #include "native_client/src/include/portability.h" |
| 12 #include "native_client/src/include/nacl_macros.h" | 12 #include "native_client/src/include/nacl_macros.h" |
| 13 | 13 |
| 14 #include "native_client/src/trusted/service_runtime/env_cleanser.h" | 14 #include "native_client/src/trusted/service_runtime/env_cleanser.h" |
| 15 #include "native_client/src/trusted/service_runtime/env_cleanser_test.h" | 15 #include "native_client/src/trusted/service_runtime/env_cleanser_test.h" |
| 16 | 16 |
| 17 void NaClEnvCleanserCtor(struct NaClEnvCleanser *self) { | 17 /* |
| 18 * Everything that starts with this prefix is allowed (but the prefix is |
| 19 * stripped away). |
| 20 */ |
| 21 #define NACL_ENV_PREFIX "NACLENV_" |
| 22 #define NACL_ENV_PREFIX_LENGTH 8 |
| 23 |
| 24 void NaClEnvCleanserCtor(struct NaClEnvCleanser *self, int with_whitelist) { |
| 25 self->with_whitelist = with_whitelist; |
| 18 self->cleansed_environ = (char const **) NULL; | 26 self->cleansed_environ = (char const **) NULL; |
| 19 } | 27 } |
| 20 | 28 |
| 21 /* | 29 /* |
| 22 * Environment variables names are from IEEE Std 1003.1-2001, with | 30 * Environment variables names are from IEEE Std 1003.1-2001, with |
| 23 * additional ones from locale(7) from glibc / linux. The entries | 31 * additional ones from locale(7) from glibc / linux. The entries |
| 24 * must be sorted, in ASCII order, for the bsearch to run correctly. | 32 * must be sorted, in ASCII order, for the bsearch to run correctly. |
| 25 */ | 33 */ |
| 26 /* static -- not static for testing */ | 34 /* static -- not static for testing */ |
| 27 char const *const kNaClEnvWhitelist[] = { | 35 char const *const kNaClEnvWhitelist[] = { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 58 && '\0' != cright) { | 66 && '\0' != cright) { |
| 59 ++left; | 67 ++left; |
| 60 ++right; | 68 ++right; |
| 61 } | 69 } |
| 62 if ('=' == cleft && '\0' == cright) { | 70 if ('=' == cleft && '\0' == cright) { |
| 63 return 0; | 71 return 0; |
| 64 } | 72 } |
| 65 return (0xff & cleft) - (0xff & cright); | 73 return (0xff & cleft) - (0xff & cright); |
| 66 } | 74 } |
| 67 | 75 |
| 76 int NaClEnvIsPassThroughVar(char const *env_entry) { |
| 77 return strlen(env_entry) > NACL_ENV_PREFIX_LENGTH && |
| 78 0 == strncmp(env_entry, NACL_ENV_PREFIX, |
| 79 NACL_ENV_PREFIX_LENGTH); |
| 80 } |
| 81 |
| 68 int NaClEnvInWhitelist(char const *env_entry) { | 82 int NaClEnvInWhitelist(char const *env_entry) { |
| 69 return NULL != bsearch((void const *) &env_entry, | 83 return NULL != bsearch((void const *) &env_entry, |
| 70 (void const *) kNaClEnvWhitelist, | 84 (void const *) kNaClEnvWhitelist, |
| 71 NACL_ARRAY_SIZE(kNaClEnvWhitelist) - 1, /* NULL */ | 85 NACL_ARRAY_SIZE(kNaClEnvWhitelist) - 1, /* NULL */ |
| 72 sizeof kNaClEnvWhitelist[0], | 86 sizeof kNaClEnvWhitelist[0], |
| 73 EnvCmp); | 87 EnvCmp); |
| 74 } | 88 } |
| 75 | 89 |
| 76 /* PRE: sizeof(char *) is a power of 2 */ | 90 /* PRE: sizeof(char *) is a power of 2 */ |
| 77 | 91 |
| 78 /* | 92 /* |
| 79 * Initializes the object with a filtered environment. | 93 * Initializes the object with a filtered environment. |
| 80 * | 94 * |
| 81 * May return false on errors, e.g., out-of-memory. | 95 * May return false on errors, e.g., out-of-memory. |
| 82 */ | 96 */ |
| 83 int NaClEnvCleanserInit(struct NaClEnvCleanser *self, char const *const *envp) { | 97 int NaClEnvCleanserInit(struct NaClEnvCleanser *self, char const *const *envp, |
| 98 char const * const *extra_env) { |
| 84 char const *const *p; | 99 char const *const *p; |
| 85 size_t num_env = 0; | 100 size_t num_env = 0; |
| 86 size_t ptr_bytes = 0; | 101 size_t ptr_bytes = 0; |
| 87 const size_t kMaxSize = ~(size_t) 0; | 102 const size_t kMaxSize = ~(size_t) 0; |
| 88 const size_t ptr_size_mult_overflow_mask = ~(kMaxSize / sizeof *envp); | 103 const size_t ptr_size_mult_overflow_mask = ~(kMaxSize / sizeof *envp); |
| 89 char const **ptr_tbl; | 104 char const **ptr_tbl; |
| 90 size_t env; | 105 size_t env; |
| 91 | 106 |
| 92 /* | 107 /* |
| 93 * let n be a size_t. if n & ptr_size_mult_overflow_mask is set, | 108 * let n be a size_t. if n & ptr_size_mult_overflow_mask is set, |
| 94 * then n*sizeof(void *) will have an arithmetic overflow. | 109 * then n*sizeof(void *) will have an arithmetic overflow. |
| 95 */ | 110 */ |
| 96 | 111 |
| 97 if (NULL == envp || NULL == *envp) { | 112 if (NULL == envp || NULL == *envp) { |
| 98 self->cleansed_environ = NULL; | 113 self->cleansed_environ = NULL; |
| 99 return 1; | 114 return 1; |
| 100 } | 115 } |
| 101 for (p = envp; NULL != *p; ++p) { | 116 for (p = envp; NULL != *p; ++p) { |
| 102 if (!NaClEnvInWhitelist(*p)) { | 117 if (!(self->with_whitelist && NaClEnvInWhitelist(*p)) && |
| 118 !NaClEnvIsPassThroughVar(*p)) { |
| 103 continue; | 119 continue; |
| 104 } | 120 } |
| 105 if (num_env == kMaxSize) { | 121 if (num_env == kMaxSize) { |
| 106 /* would overflow */ | 122 /* would overflow */ |
| 107 return 0; | 123 return 0; |
| 108 } | 124 } |
| 109 ++num_env; | 125 ++num_env; |
| 110 } | 126 } |
| 111 | 127 |
| 128 if (extra_env) { |
| 129 for (p = extra_env; NULL != *p; ++p) { |
| 130 if (num_env == kMaxSize) { |
| 131 /* would overflow */ |
| 132 return 0; |
| 133 } |
| 134 ++num_env; |
| 135 } |
| 136 } |
| 137 |
| 112 /* pointer table -- NULL pointer terminated */ | 138 /* pointer table -- NULL pointer terminated */ |
| 113 if (0 != ((1 + num_env) & ptr_size_mult_overflow_mask)) { | 139 if (0 != ((1 + num_env) & ptr_size_mult_overflow_mask)) { |
| 114 return 0; | 140 return 0; |
| 115 } | 141 } |
| 116 ptr_bytes = (1 + num_env) * sizeof(*envp); | 142 ptr_bytes = (1 + num_env) * sizeof(*envp); |
| 117 | 143 |
| 118 ptr_tbl = (char const **) malloc(ptr_bytes); | 144 ptr_tbl = (char const **) malloc(ptr_bytes); |
| 119 if (NULL == ptr_tbl) { | 145 if (NULL == ptr_tbl) { |
| 120 return 0; | 146 return 0; |
| 121 } | 147 } |
| 122 | 148 |
| 123 /* this assumes no other thread is tweaking envp */ | 149 /* this assumes no other thread is tweaking envp */ |
| 124 for (env = 0, p = envp; NULL != *p; ++p) { | 150 for (env = 0, p = envp; NULL != *p; ++p) { |
| 125 if (!NaClEnvInWhitelist(*p)) { | 151 if (NaClEnvIsPassThroughVar(*p)) { |
| 152 ptr_tbl[env] = *p + NACL_ENV_PREFIX_LENGTH; |
| 153 } else if (self->with_whitelist && NaClEnvInWhitelist(*p)) { |
| 154 ptr_tbl[env] = *p; |
| 155 } else { |
| 126 continue; | 156 continue; |
| 127 } | 157 } |
| 128 ptr_tbl[env] = *p; | |
| 129 ++env; | 158 ++env; |
| 130 } | 159 } |
| 160 if (extra_env) { |
| 161 for (p = extra_env; NULL != *p; ++p) { |
| 162 ptr_tbl[env] = *p; |
| 163 ++env; |
| 164 } |
| 165 } |
| 131 if (num_env != env) { | 166 if (num_env != env) { |
| 132 free((void *) ptr_tbl); | 167 free((void *) ptr_tbl); |
| 133 return 0; | 168 return 0; |
| 134 } | 169 } |
| 135 ptr_tbl[env] = NULL; | 170 ptr_tbl[env] = NULL; |
| 136 self->cleansed_environ = ptr_tbl; | 171 self->cleansed_environ = ptr_tbl; |
| 137 | 172 |
| 138 return 1; | 173 return 1; |
| 139 } | 174 } |
| 140 | 175 |
| 141 char const *const *NaClEnvCleanserEnvironment(struct NaClEnvCleanser *self) { | 176 char const *const *NaClEnvCleanserEnvironment(struct NaClEnvCleanser *self) { |
| 142 return (char const *const *) self->cleansed_environ; | 177 return (char const *const *) self->cleansed_environ; |
| 143 } | 178 } |
| 144 | 179 |
| 145 void NaClEnvCleanserDtor(struct NaClEnvCleanser *self) { | 180 void NaClEnvCleanserDtor(struct NaClEnvCleanser *self) { |
| 146 free((void *) self->cleansed_environ); | 181 free((void *) self->cleansed_environ); |
| 147 self->cleansed_environ = NULL; | 182 self->cleansed_environ = NULL; |
| 148 } | 183 } |
| OLD | NEW |