From 26c00501651314deebc5516c9bda238be66d16d8 Mon Sep 17 00:00:00 2001 From: Philipp Dunkel Date: Mon, 31 Aug 2026 14:28:12 +0200 Subject: [PATCH 1/4] vfs: load native addons from a mounted file system A native addon inside a virtual file system could not be require()d: dlopen() and LoadLibrary() open a shared object by path, and a VFS path has no inode for them to open. Read the addon's bytes from the VFS and load them from a private, self-cleaning image instead, using the smallest on-disk footprint each platform allows: on Linux an anonymous memfd loaded through /proc/self/fd, so the bytes never reach the file system; on other POSIX platforms a file in a 0700 mkdtemp() directory, unlinked right after loading, with the mapping keeping it alive; on Windows a temp file opened FILE_FLAG_DELETE_ON_CLOSE whose handle is held until exit. This is internal. process.dlopen() keeps its documented (module, filename[, flags]) signature and ignores anything further; the bytes are passed to a dlopenBinary() reachable only through the process_methods binding, which the VFS hook calls for VFS paths. Addons on the real file system are untouched and load directly. Signed-off-by: Philipp Dunkel --- doc/api/vfs.md | 6 + lib/internal/vfs/setup.js | 22 ++ src/node_binding.cc | 325 +++++++++++++++++++++++++++- src/node_binding.h | 1 + src/node_process_methods.cc | 2 + test/parallel/test-dlopen-binary.js | 51 +++++ test/parallel/test-vfs-addon.js | 37 ++++ 7 files changed, 438 insertions(+), 6 deletions(-) create mode 100644 test/parallel/test-dlopen-binary.js create mode 100644 test/parallel/test-vfs-addon.js diff --git a/doc/api/vfs.md b/doc/api/vfs.md index 2070efdac238..ea1d392787f8 100644 --- a/doc/api/vfs.md +++ b/doc/api/vfs.md @@ -417,6 +417,12 @@ system, the callers are responsible for avoiding removal or invalidation of modules in the virtual file system while they are being loaded. +Native addons (`.node` files) stored in a mounted VFS can be `require()`d as +well. The operating system's dynamic loader cannot open a virtual path, so the +addon's bytes are read from the VFS and loaded from a private, self-cleaning +temporary image instead. Addons on the real file system are unaffected and +load directly. + ## Class: `VirtualProvider` + +> Stability: 1.1 - Active development + +When using the [Permission Model][], a [virtual file system][] cannot be +mounted by default: [`vfs.mount()`][] throws `ERR_INVALID_STATE` unless the +user explicitly passes the `--allow-fs-vfs` flag when starting Node.js. + +A mounted VFS serves paths that the file system permissions do not describe, +so mounting one is gated on its own flag rather than on `--allow-fs-read` or +`--allow-fs-write`. + +```console +$ node --experimental-vfs --permission --allow-fs-vfs app.js +``` + ### `--allow-fs-write`