GeezerVison is showing github.com — src: add option to disable loading native addons · nodejs/node@b050c65
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: doc/api/cli.md +10Lines changed: 10 additions & 0 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -587,6 +587,15 @@ added: v7.10.0 | 587 | 587 |
| 588 | 588 | This option is a no-op. It is kept for compatibility. | 589 | 589 |
| | 590 | +### `--no-addons` | | 591 | +<!-- YAML | | 592 | +added: REPLACEME | | 593 | +--> | | 594 | + | | 595 | +Disable the `node-addons` exports condition as well as disable loading | | 596 | +native addons. When `--no-addons` is specified, calling `process.dlopen` or | | 597 | +requiring a native C++ addon will fail and throw an exception. | | 598 | + | 590 | 599 | ### `--no-deprecation` | 591 | 600 | <!-- YAML | 592 | 601 | added: v0.8.0 | @@ -1357,6 +1366,7 @@ Node.js options that are allowed are: | 1357 | 1366 | * `--inspect` | 1358 | 1367 | * `--max-http-header-size` | 1359 | 1368 | * `--napi-modules` | | 1369 | +* `--no-addons` | 1360 | 1370 | * `--no-deprecation` | 1361 | 1371 | * `--no-force-async-hooks-checks` | 1362 | 1372 | * `--no-warnings` | |
Collapse file Copy file name to clipboardExpand all lines: doc/api/errors.md +9Lines changed: 9 additions & 0 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -876,6 +876,14 @@ An unknown cipher was specified. | 876 | 876 | An unknown Diffie-Hellman group name was given. See | 877 | 877 | [`crypto.getDiffieHellman()`][] for a list of valid group names. | 878 | 878 |
| | 879 | +<a id="ERR_DLOPEN_DISABLED"></a> | | 880 | +### `ERR_DLOPEN_DISABLED` | | 881 | +<!-- YAML | | 882 | +added: REPLACEME | | 883 | +--> | | 884 | + | | 885 | +Loading native addons has been disabled using [`--no-addons`][]. | | 886 | + | 879 | 887 | <a id="ERR_DLOPEN_FAILED"></a> | 880 | 888 | ### `ERR_DLOPEN_FAILED` | 881 | 889 | <!-- YAML | @@ -2599,6 +2607,7 @@ closed. | 2599 | 2607 | [`'uncaughtException'`]: process.md#process_event_uncaughtexception | 2600 | 2608 | [`--disable-proto=throw`]: cli.md#cli_disable_proto_mode | 2601 | 2609 | [`--force-fips`]: cli.md#cli_force_fips | | 2610 | +[`--no-addons`]: cli.md#cli_no_addons | 2602 | 2611 | [`Class: assert.AssertionError`]: assert.md#assert_class_assert_assertionerror | 2603 | 2612 | [`ERR_INVALID_ARG_TYPE`]: #ERR_INVALID_ARG_TYPE | 2604 | 2613 | [`EventEmitter`]: events.md#events_class_eventemitter | |
Collapse file Copy file name to clipboardExpand all lines: doc/api/packages.md +16-4Lines changed: 16 additions & 4 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -477,6 +477,11 @@ Node.js implements the following conditions: | 477 | 477 | * `"node"` - matches for any Node.js environment. Can be a CommonJS or ES | 478 | 478 | module file. _This condition should always come after `"import"` or | 479 | 479 | `"require"`._ | | 480 | +* `"node-addons"` - similar to `"node"` and matches for any Node.js environment. | | 481 | + This condition can be used to provide an entry point which uses native C++ | | 482 | + addons as opposed to an entry point which is more universal and doesn't rely | | 483 | + on native addons. This condition can be disabled via the | | 484 | + [`--no-addons` flag][]. | 480 | 485 | * `"default"` - the generic fallback that always matches. Can be a CommonJS | 481 | 486 | or ES module file. _This condition should always come last._ | 482 | 487 |
| @@ -555,17 +560,23 @@ node --conditions=development main.js | 555 | 560 | ``` | 556 | 561 |
| 557 | 562 | which would then resolve the `"development"` condition in package imports and | 558 | | -exports, while resolving the existing `"node"`, `"default"`, `"import"`, and | 559 | | -`"require"` conditions as appropriate. | | 563 | +exports, while resolving the existing `"node"`, `"node-addons"`, `"default"`, | | 564 | +`"import"`, and `"require"` conditions as appropriate. | 560 | 565 |
| 561 | 566 | Any number of custom conditions can be set with repeat flags. | 562 | 567 |
| 563 | 568 | ### Conditions Definitions | 564 | 569 |
| 565 | | -The `"import"`, `"require"`, `"node"` and `"default"` conditions are defined | 566 | | -and implemented in Node.js core, | | 570 | +The `"import"`, `"require"`, `"node"`, `"node-addons"` and `"default"` | | 571 | +conditions are defined and implemented in Node.js core, | 567 | 572 | [as specified above](#packages_conditional_exports). | 568 | 573 |
| | 574 | +The `"node-addons"` condition can be used to provide an entry point which | | 575 | +uses native C++ addons. However, this condition can be disabled via the | | 576 | +[`--no-addons` flag][]. When using `"node-addons"`, it's recommended to treat | | 577 | +`"default"` as an enhancement that provides a more universal entry point, e.g. | | 578 | +using WebAssembly instead of a native addon. | | 579 | + | 569 | 580 | Other condition strings are unknown to Node.js and thus ignored by default. | 570 | 581 | Runtimes or tools other than Node.js can use them at their discretion. | 571 | 582 |
| @@ -1161,6 +1172,7 @@ This field defines [subpath imports][] for the current package. | 1161 | 1172 | [`"main"`]: #packages_main | 1162 | 1173 | [`"name"`]: #packages_name | 1163 | 1174 | [`"type"`]: #packages_type | | 1175 | +[`--no-addons` flag]: cli.md#cli_no_addons | 1164 | 1176 | [`ERR_PACKAGE_PATH_NOT_EXPORTED`]: errors.md#errors_err_package_path_not_exported | 1165 | 1177 | [`esm`]: https://github.com/standard-things/esm#readme | 1166 | 1178 | [`package.json`]: #packages_node_js_package_json_field_definitions | |
Collapse file Copy file name to clipboardExpand all lines: doc/node.1 +5Lines changed: 5 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -282,6 +282,11 @@ Silence deprecation warnings. | 282 | 282 | Disable runtime checks for `async_hooks`. | 283 | 283 | These will still be enabled dynamically when `async_hooks` is enabled. | 284 | 284 | . | | 285 | +.It Fl -no-addons | | 286 | +Disable the `node-addons` exports condition as well as disable loading native | | 287 | +addons. When `--no-addons` is specified, calling `process.dlopen` or requiring | | 288 | +a native C++ addon will fail and throw an exception. | | 289 | +. | 285 | 290 | .It Fl -no-warnings | 286 | 291 | Silence all process warnings (including deprecations). | 287 | 292 | . | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/modules/cjs/helpers.js +9-1Lines changed: 9 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -29,8 +29,16 @@ let debug = require('internal/util/debuglog').debuglog('module', (fn) => { | 29 | 29 | debug = fn; | 30 | 30 | }); | 31 | 31 |
| | 32 | +const noAddons = getOptionValue('--no-addons'); | | 33 | +const addonConditions = noAddons ? [] : ['node-addons']; | | 34 | + | 32 | 35 | // TODO: Use this set when resolving pkg#exports conditions in loader.js. | 33 | | -const cjsConditions = new SafeSet(['require', 'node', ...userConditions]); | | 36 | +const cjsConditions = new SafeSet([ | | 37 | + 'require', | | 38 | + 'node', | | 39 | + ...addonConditions, | | 40 | + ...userConditions, | | 41 | +]); | 34 | 42 |
| 35 | 43 | function loadNativeModule(filename, request) { | 36 | 44 | const mod = NativeModule.map.get(filename); | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/modules/esm/resolve.js +10-1Lines changed: 10 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -57,7 +57,16 @@ const { Module: CJSModule } = require('internal/modules/cjs/loader'); | 57 | 57 |
| 58 | 58 | const packageJsonReader = require('internal/modules/package_json_reader'); | 59 | 59 | const userConditions = getOptionValue('--conditions'); | 60 | | -const DEFAULT_CONDITIONS = ObjectFreeze(['node', 'import', ...userConditions]); | | 60 | +const noAddons = getOptionValue('--no-addons'); | | 61 | +const addonConditions = noAddons ? [] : ['node-addons']; | | 62 | + | | 63 | +const DEFAULT_CONDITIONS = ObjectFreeze([ | | 64 | + 'node', | | 65 | + 'import', | | 66 | + ...addonConditions, | | 67 | + ...userConditions, | | 68 | +]); | | 69 | + | 61 | 70 | const DEFAULT_CONDITIONS_SET = new SafeSet(DEFAULT_CONDITIONS); | 62 | 71 |
| 63 | 72 | const pendingDeprecation = getOptionValue('--pending-deprecation'); | |
Collapse file Copy file name to clipboardExpand all lines: src/env-inl.h +5Lines changed: 5 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -890,6 +890,11 @@ inline bool Environment::is_main_thread() const { | 890 | 890 | return worker_context() == nullptr; | 891 | 891 | } | 892 | 892 |
| | 893 | +inline bool Environment::no_native_addons() const { | | 894 | + return (flags_ & EnvironmentFlags::kNoNativeAddons) || | | 895 | + !options_->allow_native_addons; | | 896 | +} | | 897 | + | 893 | 898 | inline bool Environment::should_not_register_esm_loader() const { | 894 | 899 | return flags_ & EnvironmentFlags::kNoRegisterESMLoader; | 895 | 900 | } | |
Collapse file Copy file name to clipboardExpand all lines: src/env.h +1Lines changed: 1 addition & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -1054,6 +1054,7 @@ class Environment : public MemoryRetainer { | 1054 | 1054 | inline void set_has_serialized_options(bool has_serialized_options); | 1055 | 1055 |
| 1056 | 1056 | inline bool is_main_thread() const; | | 1057 | + inline bool no_native_addons() const; | 1057 | 1058 | inline bool should_not_register_esm_loader() const; | 1058 | 1059 | inline bool owns_process_state() const; | 1059 | 1060 | inline bool owns_inspector() const; | |
Collapse file Copy file name to clipboardExpand all lines: src/node.h +7-1Lines changed: 7 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -428,7 +428,13 @@ enum Flags : uint64_t { | 428 | 428 | // Set this flag to force hiding console windows when spawning child | 429 | 429 | // processes. This is usually used when embedding Node.js in GUI programs on | 430 | 430 | // Windows. | 431 | | - kHideConsoleWindows = 1 << 5 | | 431 | + kHideConsoleWindows = 1 << 5, | | 432 | + // Set this flag to disable loading native addons via `process.dlopen`. | | 433 | + // This environment flag is especially important for worker threads | | 434 | + // so that a worker thread can't load a native addon even if `execArgv` | | 435 | + // is overwritten and `--no-addons` is not specified but was specified | | 436 | + // for this Environment instance. | | 437 | + kNoNativeAddons = 1 << 6 | 432 | 438 | }; | 433 | 439 | } // namespace EnvironmentFlags | 434 | 440 |
| |
Collapse file Copy file name to clipboardExpand all lines: src/node_binding.cc +6Lines changed: 6 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -413,6 +413,12 @@ inline napi_addon_register_func GetNapiInitializerCallback(DLib* dlib) { | 413 | 413 | // cache that's a plain C list or hash table that's shared across contexts? | 414 | 414 | void DLOpen(const FunctionCallbackInfo<Value>& args) { | 415 | 415 | Environment* env = Environment::GetCurrent(args); | | 416 | + | | 417 | + if (env->no_native_addons()) { | | 418 | + return THROW_ERR_DLOPEN_DISABLED( | | 419 | + env, "Cannot load native addon because loading addons is disabled."); | | 420 | + } | | 421 | + | 416 | 422 | auto context = env->context(); | 417 | 423 |
| 418 | 424 | CHECK_NULL(thread_local_modpending); | |
|