diff --git a/node.gyp b/node.gyp index 46dbf396c6..4ee8d04f89 100644 --- a/node.gyp +++ b/node.gyp @@ -101,6 +101,7 @@ 'src/node_javascript.cc', 'src/node_main.cc', 'src/node_os.cc', + 'src/node_revert.cc', 'src/node_v8.cc', 'src/node_stat_watcher.cc', 'src/node_watchdog.cc', @@ -137,6 +138,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/queue.h', diff --git a/src/node.cc b/src/node.cc index 1da83287c1..7055c98603 100644 --- a/src/node.cc +++ b/src/node.cc @@ -26,6 +26,7 @@ #include "node_http_parser.h" #include "node_javascript.h" #include "node_version.h" +#include "node_revert.h" #if defined HAVE_PERFCTR #include "node_counters.h" @@ -2732,6 +2733,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; @@ -3080,6 +3091,9 @@ static void ParseArgs(int* argc, trace_deprecation = 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, "--v8-options") == 0) { new_v8_argv[new_v8_argc] = "--help"; new_v8_argc += 1; diff --git a/src/node_revert.cc b/src/node_revert.cc new file mode 100644 index 0000000000..cba579d9ca --- /dev/null +++ b/src/node_revert.cc @@ -0,0 +1,73 @@ +// Copyright Node Contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. +#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 0000000000..46251f957d --- /dev/null +++ b/src/node_revert.h @@ -0,0 +1,64 @@ +// Copyright Node Contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. +#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_