diff --git a/node.gyp b/node.gyp index 3fbf912c922b04..dc525e1421333d 100644 --- a/node.gyp +++ b/node.gyp @@ -132,6 +132,7 @@ 'src/node_javascript.cc', 'src/node_main.cc', 'src/node_os.cc', + 'src/node_revert.cc', 'src/node_util.cc', 'src/node_v8.cc', 'src/node_stat_watcher.cc', @@ -171,6 +172,7 @@ 'src/node_version.h', 'src/node_watchdog.h', 'src/node_wrap.h', + 'src/node_revert.h', 'src/node_i18n.h', 'src/pipe_wrap.h', 'src/tty_wrap.h', diff --git a/src/node.cc b/src/node.cc index ab586272d30549..4609422497fe68 100644 --- a/src/node.cc +++ b/src/node.cc @@ -6,6 +6,7 @@ #include "node_javascript.h" #include "node_version.h" #include "node_internals.h" +#include "node_revert.h" #if defined HAVE_PERFCTR #include "node_counters.h" @@ -1864,7 +1865,6 @@ static gid_t gid_by_name(Isolate* isolate, Local value) { } } - static void GetUid(const FunctionCallbackInfo& args) { // uid_t is an uint32_t on all supported platforms. args.GetReturnValue().Set(static_cast(getuid())); @@ -3039,6 +3039,16 @@ void SetupProcessObject(Environment* env, READONLY_PROPERTY(process, "traceDeprecation", True(env->isolate())); } + // --security-revert flags +#define V(code, _, __) \ + do { \ + if (IsReverted(REVERT_ ## code)) { \ + READONLY_PROPERTY(process, "REVERT_" #code, True(env->isolate())); \ + } \ + } while (0); + REVERSIONS(V) +#undef V + size_t exec_path_len = 2 * PATH_MAX; char* exec_path = new char[exec_path_len]; Local exec_path_value; @@ -3288,19 +3298,19 @@ static void PrintHelp() { "\n" "Environment variables:\n" #ifdef _WIN32 - "NODE_PATH ';'-separated list of directories\n" + "NODE_PATH ';'-separated list of directories\n" #else - "NODE_PATH ':'-separated list of directories\n" + "NODE_PATH ':'-separated list of directories\n" #endif - " prefixed to the module search path.\n" - "NODE_DISABLE_COLORS set to 1 to disable colors in the REPL\n" + " prefixed to the module search path.\n" + "NODE_DISABLE_COLORS set to 1 to disable colors in the REPL\n" #if defined(NODE_HAVE_I18N_SUPPORT) - "NODE_ICU_DATA data path for ICU (Intl object) data\n" + "NODE_ICU_DATA data path for ICU (Intl object) data\n" #if !defined(NODE_HAVE_SMALL_ICU) - " (will extend linked-in data)\n" + " (will extend linked-in data)\n" #endif #endif - "NODE_REPL_HISTORY path to the persistent REPL history file\n" + "NODE_REPL_HISTORY path to the persistent REPL history file\n" "\n" "Documentation can be found at https://nodejs.org/\n"); } @@ -3406,6 +3416,9 @@ static void ParseArgs(int* argc, track_heap_objects = true; } else if (strcmp(arg, "--throw-deprecation") == 0) { throw_deprecation = true; + } else if (strncmp(arg, "--security-revert=", 18) == 0) { + const char* cve = arg + 18; + Revert(cve); } else if (strcmp(arg, "--prof-process") == 0) { prof_process = true; short_circuit = true; diff --git a/src/node_revert.cc b/src/node_revert.cc new file mode 100644 index 00000000000000..e62b94ba8a5e04 --- /dev/null +++ b/src/node_revert.cc @@ -0,0 +1,53 @@ +#include "node_revert.h" +#include +#include + +namespace node { + +unsigned int reverted = 0; + +const char* RevertMessage(const unsigned int cve) { +#define V(code, label, msg) case REVERT_ ## code: return label ": " msg; + switch (cve) { + REVERSIONS(V) + default: + return "Unknown"; + } +#undef V +} + +void Revert(const unsigned int cve) { + reverted |= 1 << cve; + printf("SECURITY WARNING: Reverting %s\n", RevertMessage(cve)); +} + +void Revert(const char* cve) { +#define V(code, label, _) \ + do { \ + if (strcmp(cve, label) == 0) { \ + Revert(REVERT_ ## code); \ + return; \ + } \ + } while (0); + REVERSIONS(V) +#undef V + printf("Error: Attempt to revert an unknown CVE [%s]\n", cve); + exit(12); +} + +bool IsReverted(const unsigned int cve) { + return reverted & (1 << cve); +} + +bool IsReverted(const char * cve) { +#define V(code, label, _) \ + do { \ + if (strcmp(cve, label) == 0) \ + return IsReverted(REVERT_ ## code); \ + } while (0); + REVERSIONS(V) + return false; +#undef V +} + +} // namespace node diff --git a/src/node_revert.h b/src/node_revert.h new file mode 100644 index 00000000000000..6a0f9b452eaff4 --- /dev/null +++ b/src/node_revert.h @@ -0,0 +1,44 @@ +#ifndef SRC_NODE_REVERT_H_ +#define SRC_NODE_REVERT_H_ + +#include "node.h" + +/** + * Note that it is expected for this list to vary across specific LTS and + * Stable versions! Only CVE's whose fixes require *breaking* changes within + * a given LTS or Stable may be added to this list, and only with CTC + * consensus. + * + * For *master* this list should always be empty! + * + **/ +#define REVERSIONS(XX) +// XX(CVE_2016_PEND, "CVE-2016-PEND", "Vulnerability Title") + +namespace node { + +typedef enum { +#define V(code, _, __) REVERT_ ## code, + REVERSIONS(V) +#undef V +} reversions_t; + + +/* A bit field for tracking the active reverts */ +extern unsigned int reverted; + +/* Revert the given CVE (see reversions_t enum) */ +void Revert(const unsigned int cve); + +/* Revert the given CVE by label */ +void Revert(const char* cve); + +/* true if the CVE has been reverted **/ +bool IsReverted(const unsigned int cve); + +/* true if the CVE has been reverted **/ +bool IsReverted(const char * cve); + +} // namespace node + +#endif // SRC_NODE_REVERT_H_