Skip to content

Commit eff4477

Browse files
bnoordhuiskrydos
authored andcommitted
src: make copies of startup environment variables
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 <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Sam Roberts <[email protected]>
1 parent 5b91db4 commit eff4477

File tree

5 files changed

+49
-33
lines changed

5 files changed

+49
-33
lines changed

src/node.cc

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ static const char* trace_enabled_categories = nullptr;
156156

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

162162
// used by C++ modules as well
@@ -189,7 +189,7 @@ bool trace_warnings = false;
189189
bool config_preserve_symlinks = false;
190190

191191
// Set in node.cc by ParseArgs when --redirect-warnings= is used.
192-
const char* config_warning_file;
192+
std::string config_warning_file; // NOLINT(runtime/string)
193193

194194
bool v8_initialized = false;
195195

@@ -924,12 +924,21 @@ Local<Value> UVException(Isolate* isolate,
924924

925925

926926
// Look up environment variable unless running as setuid root.
927-
inline const char* secure_getenv(const char* key) {
927+
inline bool SafeGetenv(const char* key, std::string* text) {
928928
#ifndef _WIN32
929-
if (getuid() != geteuid() || getgid() != getegid())
930-
return nullptr;
929+
// TODO(bnoordhuis) Should perhaps also check whether getauxval(AT_SECURE)
930+
// is non-zero on Linux.
931+
if (getuid() != geteuid() || getgid() != getegid()) {
932+
text->clear();
933+
return false;
934+
}
931935
#endif
932-
return getenv(key);
936+
if (const char* value = getenv(key)) {
937+
*text = value;
938+
return true;
939+
}
940+
text->clear();
941+
return false;
933942
}
934943

935944

@@ -3089,11 +3098,11 @@ void SetupProcessObject(Environment* env,
30893098
#if defined(NODE_HAVE_I18N_SUPPORT) && defined(U_ICU_VERSION)
30903099
// ICU-related versions are now handled on the js side, see bootstrap_node.js
30913100

3092-
if (icu_data_dir != nullptr) {
3101+
if (!icu_data_dir.empty()) {
30933102
// Did the user attempt (via env var or parameter) to set an ICU path?
30943103
READONLY_PROPERTY(process,
30953104
"icu_data_dir",
3096-
OneByteString(env->isolate(), icu_data_dir));
3105+
OneByteString(env->isolate(), icu_data_dir.c_str()));
30973106
}
30983107
#endif
30993108

@@ -3741,7 +3750,7 @@ static void ParseArgs(int* argc,
37413750
#endif /* HAVE_OPENSSL */
37423751
#if defined(NODE_HAVE_I18N_SUPPORT)
37433752
} else if (strncmp(arg, "--icu-data-dir=", 15) == 0) {
3744-
icu_data_dir = arg + 15;
3753+
icu_data_dir.assign(arg, 15);
37453754
#endif
37463755
} else if (strcmp(arg, "--expose-internals") == 0 ||
37473756
strcmp(arg, "--expose_internals") == 0) {
@@ -4228,13 +4237,14 @@ void Init(int* argc,
42284237
#endif
42294238

42304239
// Allow for environment set preserving symlinks.
4231-
if (auto preserve_symlinks = secure_getenv("NODE_PRESERVE_SYMLINKS")) {
4232-
config_preserve_symlinks = (*preserve_symlinks == '1');
4240+
{
4241+
std::string text;
4242+
config_preserve_symlinks =
4243+
SafeGetenv("NODE_PRESERVE_SYMLINKS", &text) && text[0] == '1';
42334244
}
42344245

4235-
if (auto redirect_warnings = secure_getenv("NODE_REDIRECT_WARNINGS")) {
4236-
config_warning_file = redirect_warnings;
4237-
}
4246+
if (config_warning_file.empty())
4247+
SafeGetenv("NODE_REDIRECT_WARNINGS", &config_warning_file);
42384248

42394249
// Parse a few arguments which are specific to Node.
42404250
int v8_argc;
@@ -4262,12 +4272,11 @@ void Init(int* argc,
42624272
#endif
42634273

42644274
#if defined(NODE_HAVE_I18N_SUPPORT)
4265-
if (icu_data_dir == nullptr) {
4266-
// if the parameter isn't given, use the env variable.
4267-
icu_data_dir = secure_getenv("NODE_ICU_DATA");
4268-
}
4275+
// If the parameter isn't given, use the env variable.
4276+
if (icu_data_dir.empty())
4277+
SafeGetenv("NODE_ICU_DATA", &icu_data_dir);
42694278
// Initialize ICU.
4270-
// If icu_data_dir is nullptr here, it will load the 'minimal' data.
4279+
// If icu_data_dir is empty here, it will load the 'minimal' data.
42714280
if (!i18n::InitializeICUDirectory(icu_data_dir)) {
42724281
FatalError(nullptr, "Could not initialize ICU "
42734282
"(check NODE_ICU_DATA or --icu-data-dir parameters)");
@@ -4532,8 +4541,11 @@ int Start(int argc, char** argv) {
45324541
Init(&argc, const_cast<const char**>(argv), &exec_argc, &exec_argv);
45334542

45344543
#if HAVE_OPENSSL
4535-
if (const char* extra = secure_getenv("NODE_EXTRA_CA_CERTS"))
4536-
crypto::UseExtraCaCerts(extra);
4544+
{
4545+
std::string extra_ca_certs;
4546+
if (SafeGetenv("NODE_EXTRA_CA_CERTS", &extra_ca_certs))
4547+
crypto::UseExtraCaCerts(extra_ca_certs);
4548+
}
45374549
#ifdef NODE_FIPS_MODE
45384550
// In the case of FIPS builds we should make sure
45394551
// the random source is properly initialized first.
@@ -4542,7 +4554,7 @@ int Start(int argc, char** argv) {
45424554
// V8 on Windows doesn't have a good source of entropy. Seed it from
45434555
// OpenSSL's pool.
45444556
V8::SetEntropySource(crypto::EntropySource);
4545-
#endif
4557+
#endif // HAVE_OPENSSL
45464558

45474559
v8_platform.Initialize(v8_thread_pool_size);
45484560
// Enable tracing when argv has --trace-events-enabled.

src/node_config.cc

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,12 @@ void InitConfig(Local<Object> target,
4646
if (config_preserve_symlinks)
4747
READONLY_BOOLEAN_PROPERTY("preserveSymlinks");
4848

49-
if (config_warning_file != nullptr) {
49+
if (!config_warning_file.empty()) {
5050
Local<String> name = OneByteString(env->isolate(), "warningFile");
5151
Local<String> value = String::NewFromUtf8(env->isolate(),
52-
config_warning_file,
53-
v8::NewStringType::kNormal)
52+
config_warning_file.data(),
53+
v8::NewStringType::kNormal,
54+
config_warning_file.size())
5455
.ToLocalChecked();
5556
target->DefineOwnProperty(env->context(), name, value).FromJust();
5657
}

src/node_i18n.cc

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -404,12 +404,8 @@ static void GetVersion(const FunctionCallbackInfo<Value>& args) {
404404
}
405405
}
406406

407-
bool InitializeICUDirectory(const char* icu_data_path) {
408-
if (icu_data_path != nullptr) {
409-
flag_icu_data_dir = true;
410-
u_setDataDirectory(icu_data_path);
411-
return true; // no error
412-
} else {
407+
bool InitializeICUDirectory(const std::string& path) {
408+
if (path.empty()) {
413409
UErrorCode status = U_ZERO_ERROR;
414410
#ifdef NODE_HAVE_SMALL_ICU
415411
// install the 'small' data.
@@ -418,6 +414,10 @@ bool InitializeICUDirectory(const char* icu_data_path) {
418414
// no small data, so nothing to do.
419415
#endif // !NODE_HAVE_SMALL_ICU
420416
return (status == U_ZERO_ERROR);
417+
} else {
418+
flag_icu_data_dir = true;
419+
u_setDataDirectory(path.c_str());
420+
return true; // No error.
421421
}
422422
}
423423

src/node_i18n.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
55

66
#include "node.h"
7+
#include <string>
78

89
#if defined(NODE_HAVE_I18N_SUPPORT)
910

@@ -13,7 +14,7 @@ extern bool flag_icu_data_dir;
1314

1415
namespace i18n {
1516

16-
bool InitializeICUDirectory(const char* icu_data_path);
17+
bool InitializeICUDirectory(const std::string& path);
1718

1819
int32_t ToASCII(MaybeStackBuffer<char>* buf,
1920
const char* input,

src/node_internals.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#include <stdint.h>
1414
#include <stdlib.h>
1515

16+
#include <string>
17+
1618
struct sockaddr;
1719

1820
// Variation on NODE_DEFINE_CONSTANT that sets a String value.
@@ -45,7 +47,7 @@ extern bool config_preserve_symlinks;
4547
// Set in node.cc by ParseArgs when --redirect-warnings= is used.
4648
// Used to redirect warning output to a file rather than sending
4749
// it to stderr.
48-
extern const char* config_warning_file;
50+
extern std::string config_warning_file; // NOLINT(runtime/string)
4951

5052
// Tells whether it is safe to call v8::Isolate::GetCurrent().
5153
extern bool v8_initialized;

0 commit comments

Comments
 (0)