| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2009 The Native Client Authors. All rights reserved. | 2 * Copyright 2009 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 |
| 4 * be found in the LICENSE file. | 4 * be 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)) && !NaClEnvIsPassThrou
ghVar(*p)) { |
| 103 continue; | 118 continue; |
| 104 } | 119 } |
| 105 if (num_env == kMaxSize) { | 120 if (num_env == kMaxSize) { |
| 106 /* would overflow */ | 121 /* would overflow */ |
| 107 return 0; | 122 return 0; |
| 108 } | 123 } |
| 109 ++num_env; | 124 ++num_env; |
| 110 } | 125 } |
| 111 | 126 |
| 127 if (extra_env) { |
| 128 for (p = extra_env; NULL != *p; ++p) { |
| 129 if (num_env == kMaxSize) { |
| 130 /* would overflow */ |
| 131 return 0; |
| 132 } |
| 133 ++num_env; |
| 134 } |
| 135 } |
| 136 |
| 112 /* pointer table -- NULL pointer terminated */ | 137 /* pointer table -- NULL pointer terminated */ |
| 113 if (0 != ((1 + num_env) & ptr_size_mult_overflow_mask)) { | 138 if (0 != ((1 + num_env) & ptr_size_mult_overflow_mask)) { |
| 114 return 0; | 139 return 0; |
| 115 } | 140 } |
| 116 ptr_bytes = (1 + num_env) * sizeof(*envp); | 141 ptr_bytes = (1 + num_env) * sizeof(*envp); |
| 117 | 142 |
| 118 ptr_tbl = (char const **) malloc(ptr_bytes); | 143 ptr_tbl = (char const **) malloc(ptr_bytes); |
| 119 if (NULL == ptr_tbl) { | 144 if (NULL == ptr_tbl) { |
| 120 return 0; | 145 return 0; |
| 121 } | 146 } |
| 122 | 147 |
| 123 /* this assumes no other thread is tweaking envp */ | 148 /* this assumes no other thread is tweaking envp */ |
| 124 for (env = 0, p = envp; NULL != *p; ++p) { | 149 for (env = 0, p = envp; NULL != *p; ++p) { |
| 125 if (!NaClEnvInWhitelist(*p)) { | 150 if (NaClEnvIsPassThroughVar(*p)) { |
| 151 ptr_tbl[env] = *p + NACL_ENV_PREFIX_LENGTH; |
| 152 } else if (self->with_whitelist && NaClEnvInWhitelist(*p)) { |
| 153 ptr_tbl[env] = *p; |
| 154 } else { |
| 126 continue; | 155 continue; |
| 127 } | 156 } |
| 128 ptr_tbl[env] = *p; | |
| 129 ++env; | 157 ++env; |
| 130 } | 158 } |
| 159 if (extra_env) { |
| 160 for (p = extra_env; NULL != *p; ++p) { |
| 161 ptr_tbl[env] = *p; |
| 162 ++env; |
| 163 } |
| 164 } |
| 131 if (num_env != env) { | 165 if (num_env != env) { |
| 132 free((void *) ptr_tbl); | 166 free((void *) ptr_tbl); |
| 133 return 0; | 167 return 0; |
| 134 } | 168 } |
| 135 ptr_tbl[env] = NULL; | 169 ptr_tbl[env] = NULL; |
| 136 self->cleansed_environ = ptr_tbl; | 170 self->cleansed_environ = ptr_tbl; |
| 137 | 171 |
| 138 return 1; | 172 return 1; |
| 139 } | 173 } |
| 140 | 174 |
| 141 char const *const *NaClEnvCleanserEnvironment(struct NaClEnvCleanser *self) { | 175 char const *const *NaClEnvCleanserEnvironment(struct NaClEnvCleanser *self) { |
| 142 return (char const *const *) self->cleansed_environ; | 176 return (char const *const *) self->cleansed_environ; |
| 143 } | 177 } |
| 144 | 178 |
| 145 void NaClEnvCleanserDtor(struct NaClEnvCleanser *self) { | 179 void NaClEnvCleanserDtor(struct NaClEnvCleanser *self) { |
| 146 free((void *) self->cleansed_environ); | 180 free((void *) self->cleansed_environ); |
| 147 self->cleansed_environ = NULL; | 181 self->cleansed_environ = NULL; |
| 148 } | 182 } |
| OLD | NEW |