Skip to content

Commit

Permalink
src: make copies of startup environment variables
Browse files Browse the repository at this point in the history
Mutations of the environment can invalidate pointers to environment
variables, so make `secure_getenv()` copy them out instead of returning
pointers.

PR-URL: nodejs#11051
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
  • Loading branch information
bnoordhuis authored and sam-github committed Feb 16, 2017
1 parent fe99edd commit dcdebc3
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 25 deletions.
49 changes: 31 additions & 18 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ static node_module* modlist_addon;

#if defined(NODE_HAVE_I18N_SUPPORT)
// Path to ICU data (for i18n / Intl)
static const char* icu_data_dir = nullptr;
static std::string icu_data_dir; // NOLINT(runtime/string)
#endif

// used by C++ modules as well
Expand Down Expand Up @@ -901,12 +901,21 @@ Local<Value> UVException(Isolate* isolate,


// Look up environment variable unless running as setuid root.
inline const char* secure_getenv(const char* key) {
inline bool SafeGetenv(const char* key, std::string* text) {
#ifndef _WIN32
if (getuid() != geteuid() || getgid() != getegid())
return nullptr;
// TODO(bnoordhuis) Should perhaps also check whether getauxval(AT_SECURE)
// is non-zero on Linux.
if (getuid() != geteuid() || getgid() != getegid()) {
text->clear();
return false;
}
#endif
return getenv(key);
if (const char* value = getenv(key)) {
*text = value;
return true;
}
text->clear();
return false;
}


Expand Down Expand Up @@ -3063,11 +3072,11 @@ void SetupProcessObject(Environment* env,
#if defined(NODE_HAVE_I18N_SUPPORT) && defined(U_ICU_VERSION)
// ICU-related versions are now handled on the js side, see bootstrap_node.js

if (icu_data_dir != nullptr) {
if (!icu_data_dir.empty()) {
// Did the user attempt (via env var or parameter) to set an ICU path?
READONLY_PROPERTY(process,
"icu_data_dir",
OneByteString(env->isolate(), icu_data_dir));
OneByteString(env->isolate(), icu_data_dir.c_str()));
}
#endif

Expand Down Expand Up @@ -3696,7 +3705,7 @@ static void ParseArgs(int* argc,
#endif /* HAVE_OPENSSL */
#if defined(NODE_HAVE_I18N_SUPPORT)
} else if (strncmp(arg, "--icu-data-dir=", 15) == 0) {
icu_data_dir = arg + 15;
icu_data_dir.assign(arg, 15);
#endif
} else if (strcmp(arg, "--expose-internals") == 0 ||
strcmp(arg, "--expose_internals") == 0) {
Expand Down Expand Up @@ -4183,8 +4192,10 @@ void Init(int* argc,
#endif

// Allow for environment set preserving symlinks.
if (auto preserve_symlinks = secure_getenv("NODE_PRESERVE_SYMLINKS")) {
config_preserve_symlinks = (*preserve_symlinks == '1');
{
std::string text;
config_preserve_symlinks =
SafeGetenv("NODE_PRESERVE_SYMLINKS", &text) && text[0] == '1';
}

// Parse a few arguments which are specific to Node.
Expand Down Expand Up @@ -4213,12 +4224,11 @@ void Init(int* argc,
#endif

#if defined(NODE_HAVE_I18N_SUPPORT)
if (icu_data_dir == nullptr) {
// if the parameter isn't given, use the env variable.
icu_data_dir = secure_getenv("NODE_ICU_DATA");
}
// If the parameter isn't given, use the env variable.
if (icu_data_dir.empty())
SafeGetenv("NODE_ICU_DATA", &icu_data_dir);
// Initialize ICU.
// If icu_data_dir is nullptr here, it will load the 'minimal' data.
// If icu_data_dir is empty here, it will load the 'minimal' data.
if (!i18n::InitializeICUDirectory(icu_data_dir)) {
FatalError(nullptr, "Could not initialize ICU "
"(check NODE_ICU_DATA or --icu-data-dir parameters)");
Expand Down Expand Up @@ -4483,8 +4493,11 @@ int Start(int argc, char** argv) {
Init(&argc, const_cast<const char**>(argv), &exec_argc, &exec_argv);

#if HAVE_OPENSSL
if (const char* extra = secure_getenv("NODE_EXTRA_CA_CERTS"))
crypto::UseExtraCaCerts(extra);
{
std::string extra_ca_certs;
if (SafeGetenv("NODE_EXTRA_CA_CERTS", &extra_ca_certs))
crypto::UseExtraCaCerts(extra_ca_certs);
}
#ifdef NODE_FIPS_MODE
// In the case of FIPS builds we should make sure
// the random source is properly initialized first.
Expand All @@ -4493,7 +4506,7 @@ int Start(int argc, char** argv) {
// V8 on Windows doesn't have a good source of entropy. Seed it from
// OpenSSL's pool.
V8::SetEntropySource(crypto::EntropySource);
#endif
#endif // HAVE_OPENSSL

v8_platform.Initialize(v8_thread_pool_size);
V8::Initialize();
Expand Down
12 changes: 6 additions & 6 deletions src/node_i18n.cc
Original file line number Diff line number Diff line change
Expand Up @@ -404,12 +404,8 @@ static void GetVersion(const FunctionCallbackInfo<Value>& args) {
}
}

bool InitializeICUDirectory(const char* icu_data_path) {
if (icu_data_path != nullptr) {
flag_icu_data_dir = true;
u_setDataDirectory(icu_data_path);
return true; // no error
} else {
bool InitializeICUDirectory(const std::string& path) {
if (path.empty()) {
UErrorCode status = U_ZERO_ERROR;
#ifdef NODE_HAVE_SMALL_ICU
// install the 'small' data.
Expand All @@ -418,6 +414,10 @@ bool InitializeICUDirectory(const char* icu_data_path) {
// no small data, so nothing to do.
#endif // !NODE_HAVE_SMALL_ICU
return (status == U_ZERO_ERROR);
} else {
flag_icu_data_dir = true;
u_setDataDirectory(path.c_str());
return true; // No error.
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/node_i18n.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

#include "node.h"
#include <string>

#if defined(NODE_HAVE_I18N_SUPPORT)

Expand All @@ -13,7 +14,7 @@ extern bool flag_icu_data_dir;

namespace i18n {

bool InitializeICUDirectory(const char* icu_data_path);
bool InitializeICUDirectory(const std::string& path);

int32_t ToASCII(MaybeStackBuffer<char>* buf,
const char* input,
Expand Down
2 changes: 2 additions & 0 deletions src/node_internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include <stdint.h>
#include <stdlib.h>

#include <string>

struct sockaddr;

// Variation on NODE_DEFINE_CONSTANT that sets a String value.
Expand Down

0 comments on commit dcdebc3

Please sign in to comment.