Skip to content

Commit 65c1240

Browse files
bnoordhuisandrew749
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/node#11051 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Sam Roberts <[email protected]>
1 parent 9a22d8c commit 65c1240

File tree

4 files changed

+34
-20
lines changed

4 files changed

+34
-20
lines changed

src/node.cc

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ static node_module* modlist_addon;
167167

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

173173
// used by C++ modules as well
@@ -945,12 +945,21 @@ Local<Value> UVException(Isolate* isolate,
945945

946946

947947
// Look up environment variable unless running as setuid root.
948-
inline const char* secure_getenv(const char* key) {
948+
inline bool SafeGetenv(const char* key, std::string* text) {
949949
#ifndef _WIN32
950-
if (getuid() != geteuid() || getgid() != getegid())
951-
return nullptr;
950+
// TODO(bnoordhuis) Should perhaps also check whether getauxval(AT_SECURE)
951+
// is non-zero on Linux.
952+
if (getuid() != geteuid() || getgid() != getegid()) {
953+
text->clear();
954+
return false;
955+
}
952956
#endif
953-
return getenv(key);
957+
if (const char* value = getenv(key)) {
958+
*text = value;
959+
return true;
960+
}
961+
text->clear();
962+
return false;
954963
}
955964

956965

@@ -3148,11 +3157,11 @@ void SetupProcessObject(Environment* env,
31483157
"icu",
31493158
OneByteString(env->isolate(), U_ICU_VERSION));
31503159

3151-
if (icu_data_dir != nullptr) {
3160+
if (!icu_data_dir.empty()) {
31523161
// Did the user attempt (via env var or parameter) to set an ICU path?
31533162
READONLY_PROPERTY(process,
31543163
"icu_data_dir",
3155-
OneByteString(env->isolate(), icu_data_dir));
3164+
OneByteString(env->isolate(), icu_data_dir.c_str()));
31563165
}
31573166
#endif
31583167

@@ -3873,7 +3882,7 @@ static void ParseArgs(int* argc,
38733882
#endif /* HAVE_OPENSSL */
38743883
#if defined(NODE_HAVE_I18N_SUPPORT)
38753884
} else if (strncmp(arg, "--icu-data-dir=", 15) == 0) {
3876-
icu_data_dir = arg + 15;
3885+
icu_data_dir.assign(arg + 15);
38773886
#endif
38783887
} else if (strcmp(arg, "--expose-internals") == 0 ||
38793888
strcmp(arg, "--expose_internals") == 0) {
@@ -4390,12 +4399,11 @@ void Init(int* argc,
43904399
#endif
43914400

43924401
#if defined(NODE_HAVE_I18N_SUPPORT)
4393-
if (icu_data_dir == nullptr) {
4394-
// if the parameter isn't given, use the env variable.
4395-
icu_data_dir = secure_getenv("NODE_ICU_DATA");
4396-
}
4402+
// If the parameter isn't given, use the env variable.
4403+
if (icu_data_dir.empty())
4404+
SafeGetenv("NODE_ICU_DATA", &icu_data_dir);
43974405
// Initialize ICU.
4398-
// If icu_data_dir is nullptr here, it will load the 'minimal' data.
4406+
// If icu_data_dir is empty here, it will load the 'minimal' data.
43994407
if (!i18n::InitializeICUDirectory(icu_data_dir)) {
44004408
FatalError(nullptr, "Could not initialize ICU "
44014409
"(check NODE_ICU_DATA or --icu-data-dir parameters)");
@@ -4736,8 +4744,11 @@ int Start(int argc, char** argv) {
47364744
Init(&argc, const_cast<const char**>(argv), &exec_argc, &exec_argv);
47374745

47384746
#if HAVE_OPENSSL
4739-
if (const char* extra = secure_getenv("NODE_EXTRA_CA_CERTS"))
4740-
crypto::UseExtraCaCerts(extra);
4747+
{
4748+
std::string extra_ca_certs;
4749+
if (SafeGetenv("NODE_EXTRA_CA_CERTS", &extra_ca_certs))
4750+
crypto::UseExtraCaCerts(extra_ca_certs);
4751+
}
47414752
#ifdef NODE_FIPS_MODE
47424753
// In the case of FIPS builds we should make sure
47434754
// the random source is properly initialized first.
@@ -4746,7 +4757,7 @@ int Start(int argc, char** argv) {
47464757
// V8 on Windows doesn't have a good source of entropy. Seed it from
47474758
// OpenSSL's pool.
47484759
V8::SetEntropySource(crypto::EntropySource);
4749-
#endif
4760+
#endif // HAVE_OPENSSL
47504761

47514762
v8_platform.Initialize(v8_thread_pool_size);
47524763
V8::Initialize();

src/node_i18n.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,10 @@ bool flag_icu_data_dir = false;
6262

6363
namespace i18n {
6464

65-
bool InitializeICUDirectory(const char* icu_data_path) {
66-
if (icu_data_path != nullptr) {
65+
bool InitializeICUDirectory(const std::string& path) {
66+
if (!path.empty()) {
6767
flag_icu_data_dir = true;
68-
u_setDataDirectory(icu_data_path);
68+
u_setDataDirectory(path.c_str());
6969
return true; // no error
7070
} else {
7171
UErrorCode status = U_ZERO_ERROR;

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
} // namespace i18n
1920
} // namespace node

src/node_internals.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#include <stdint.h>
1313
#include <stdlib.h>
1414

15+
#include <string>
16+
1517
struct sockaddr;
1618

1719
// Variation on NODE_DEFINE_CONSTANT that sets a String value.

0 commit comments

Comments
 (0)