diff options
author | Rafael Gonzaga <rafael.nunu@hotmail.com> | 2023-02-23 15:11:51 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-23 18:11:51 +0000 |
commit | 00c222593e49d817281bc88a322f41f8dca95885 (patch) | |
tree | 29e6fd71f93dd98d8bb3fcd535d49ed80bdeacd5 /src/node_file.cc | |
parent | 42be7f6a0335c396810be91c3f3724007029f83d (diff) | |
download | node-new-00c222593e49d817281bc88a322f41f8dca95885.tar.gz |
src,process: add permission model
Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com>
PR-URL: https://github.com/nodejs/node/pull/44004
Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Michaƫl Zasso <targos@protonmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Diffstat (limited to 'src/node_file.cc')
-rw-r--r-- | src/node_file.cc | 84 |
1 files changed, 82 insertions, 2 deletions
diff --git a/src/node_file.cc b/src/node_file.cc index 388d9bf32c..c6d22b51f2 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -19,13 +19,14 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. #include "node_file.h" // NOLINT(build/include_inline) -#include "node_file-inl.h" #include "aliased_buffer.h" #include "memory_tracker-inl.h" #include "node_buffer.h" #include "node_external_reference.h" +#include "node_file-inl.h" #include "node_process-inl.h" #include "node_stat_watcher.h" +#include "permission/permission.h" #include "util-inl.h" #include "tracing/trace_event.h" @@ -961,6 +962,7 @@ void AfterScanDir(uv_fs_t* req) { void Access(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); + Isolate* isolate = env->isolate(); HandleScope scope(isolate); @@ -972,6 +974,8 @@ void Access(const FunctionCallbackInfo<Value>& args) { BufferValue path(isolate, args[0]); CHECK_NOT_NULL(*path); + THROW_IF_INSUFFICIENT_PERMISSIONS( + env, permission::PermissionScope::kFileSystemRead, path.ToStringView()); FSReqBase* req_wrap_async = GetReqWrap(args, 2); if (req_wrap_async != nullptr) { // access(path, mode, req) @@ -1022,6 +1026,8 @@ static void InternalModuleReadJSON(const FunctionCallbackInfo<Value>& args) { CHECK(args[0]->IsString()); node::Utf8Value path(isolate, args[0]); + THROW_IF_INSUFFICIENT_PERMISSIONS( + env, permission::PermissionScope::kFileSystemRead, path.ToStringView()); if (strlen(*path) != path.length()) { args.GetReturnValue().Set(Array::New(isolate)); @@ -1118,6 +1124,8 @@ static void InternalModuleStat(const FunctionCallbackInfo<Value>& args) { CHECK(args[0]->IsString()); node::Utf8Value path(env->isolate(), args[0]); + THROW_IF_INSUFFICIENT_PERMISSIONS( + env, permission::PermissionScope::kFileSystemRead, path.ToStringView()); uv_fs_t req; int rc = uv_fs_stat(env->event_loop(), &req, *path, nullptr); @@ -1139,6 +1147,8 @@ static void Stat(const FunctionCallbackInfo<Value>& args) { BufferValue path(env->isolate(), args[0]); CHECK_NOT_NULL(*path); + THROW_IF_INSUFFICIENT_PERMISSIONS( + env, permission::PermissionScope::kFileSystemRead, path.ToStringView()); bool use_bigint = args[1]->IsTrue(); FSReqBase* req_wrap_async = GetReqWrap(args, 2, use_bigint); @@ -1280,8 +1290,17 @@ static void Symlink(const FunctionCallbackInfo<Value>& args) { BufferValue target(isolate, args[0]); CHECK_NOT_NULL(*target); + auto target_view = target.ToStringView(); + // To avoid bypass the symlink target should be allowed to read and write + THROW_IF_INSUFFICIENT_PERMISSIONS( + env, permission::PermissionScope::kFileSystemRead, target_view); + THROW_IF_INSUFFICIENT_PERMISSIONS( + env, permission::PermissionScope::kFileSystemWrite, target_view); + BufferValue path(isolate, args[1]); CHECK_NOT_NULL(*path); + THROW_IF_INSUFFICIENT_PERMISSIONS( + env, permission::PermissionScope::kFileSystemWrite, path.ToStringView()); CHECK(args[2]->IsInt32()); int flags = args[2].As<Int32>()->Value(); @@ -1348,6 +1367,8 @@ static void ReadLink(const FunctionCallbackInfo<Value>& args) { BufferValue path(isolate, args[0]); CHECK_NOT_NULL(*path); + THROW_IF_INSUFFICIENT_PERMISSIONS( + env, permission::PermissionScope::kFileSystemRead, path.ToStringView()); const enum encoding encoding = ParseEncoding(isolate, args[1], UTF8); @@ -1393,8 +1414,18 @@ static void Rename(const FunctionCallbackInfo<Value>& args) { BufferValue old_path(isolate, args[0]); CHECK_NOT_NULL(*old_path); + auto view_old_path = old_path.ToStringView(); + THROW_IF_INSUFFICIENT_PERMISSIONS( + env, permission::PermissionScope::kFileSystemRead, view_old_path); + THROW_IF_INSUFFICIENT_PERMISSIONS( + env, permission::PermissionScope::kFileSystemWrite, view_old_path); + BufferValue new_path(isolate, args[1]); CHECK_NOT_NULL(*new_path); + THROW_IF_INSUFFICIENT_PERMISSIONS( + env, + permission::PermissionScope::kFileSystemWrite, + new_path.ToStringView()); FSReqBase* req_wrap_async = GetReqWrap(args, 2); if (req_wrap_async != nullptr) { @@ -1498,6 +1529,8 @@ static void Unlink(const FunctionCallbackInfo<Value>& args) { BufferValue path(env->isolate(), args[0]); CHECK_NOT_NULL(*path); + THROW_IF_INSUFFICIENT_PERMISSIONS( + env, permission::PermissionScope::kFileSystemWrite, path.ToStringView()); FSReqBase* req_wrap_async = GetReqWrap(args, 1); if (req_wrap_async != nullptr) { @@ -1522,6 +1555,8 @@ static void RMDir(const FunctionCallbackInfo<Value>& args) { BufferValue path(env->isolate(), args[0]); CHECK_NOT_NULL(*path); + THROW_IF_INSUFFICIENT_PERMISSIONS( + env, permission::PermissionScope::kFileSystemWrite, path.ToStringView()); FSReqBase* req_wrap_async = GetReqWrap(args, 1); // rmdir(path, req) if (req_wrap_async != nullptr) { @@ -1729,6 +1764,8 @@ static void MKDir(const FunctionCallbackInfo<Value>& args) { BufferValue path(env->isolate(), args[0]); CHECK_NOT_NULL(*path); + THROW_IF_INSUFFICIENT_PERMISSIONS( + env, permission::PermissionScope::kFileSystemWrite, path.ToStringView()); CHECK(args[1]->IsInt32()); const int mode = args[1].As<Int32>()->Value(); @@ -1827,6 +1864,8 @@ static void ReadDir(const FunctionCallbackInfo<Value>& args) { BufferValue path(isolate, args[0]); CHECK_NOT_NULL(*path); + THROW_IF_INSUFFICIENT_PERMISSIONS( + env, permission::PermissionScope::kFileSystemRead, path.ToStringView()); const enum encoding encoding = ParseEncoding(isolate, args[1], UTF8); @@ -1925,6 +1964,23 @@ static void Open(const FunctionCallbackInfo<Value>& args) { CHECK(args[2]->IsInt32()); const int mode = args[2].As<Int32>()->Value(); + auto pathView = path.ToStringView(); + // Open can be called either in write or read + if (flags == O_RDWR) { + // TODO(rafaelgss): it can be optimized to avoid O(2*n) + THROW_IF_INSUFFICIENT_PERMISSIONS( + env, permission::PermissionScope::kFileSystemRead, pathView); + THROW_IF_INSUFFICIENT_PERMISSIONS( + env, permission::PermissionScope::kFileSystemWrite, pathView); + } else if ((flags & ~(UV_FS_O_RDONLY | UV_FS_O_SYNC)) == 0) { + THROW_IF_INSUFFICIENT_PERMISSIONS( + env, permission::PermissionScope::kFileSystemRead, pathView); + } else if ((flags & (UV_FS_O_APPEND | UV_FS_O_TRUNC | UV_FS_O_CREAT | + UV_FS_O_WRONLY)) != 0) { + THROW_IF_INSUFFICIENT_PERMISSIONS( + env, permission::PermissionScope::kFileSystemWrite, pathView); + } + FSReqBase* req_wrap_async = GetReqWrap(args, 3); if (req_wrap_async != nullptr) { // open(path, flags, mode, req) req_wrap_async->set_is_plain_open(true); @@ -1954,6 +2010,9 @@ static void OpenFileHandle(const FunctionCallbackInfo<Value>& args) { BufferValue path(isolate, args[0]); CHECK_NOT_NULL(*path); + auto pathView = path.ToStringView(); + THROW_IF_INSUFFICIENT_PERMISSIONS( + env, permission::PermissionScope::kFileSystemRead, pathView); CHECK(args[1]->IsInt32()); const int flags = args[1].As<Int32>()->Value(); @@ -1961,6 +2020,22 @@ static void OpenFileHandle(const FunctionCallbackInfo<Value>& args) { CHECK(args[2]->IsInt32()); const int mode = args[2].As<Int32>()->Value(); + // Open can be called either in write or read + if (flags == O_RDWR) { + // TODO(rafaelgss): it can be optimized to avoid O(2*n) + THROW_IF_INSUFFICIENT_PERMISSIONS( + env, permission::PermissionScope::kFileSystemRead, pathView); + THROW_IF_INSUFFICIENT_PERMISSIONS( + env, permission::PermissionScope::kFileSystemWrite, pathView); + } else if ((flags & ~(UV_FS_O_RDONLY | UV_FS_O_SYNC)) == 0) { + THROW_IF_INSUFFICIENT_PERMISSIONS( + env, permission::PermissionScope::kFileSystemRead, pathView); + } else if ((flags & (UV_FS_O_APPEND | UV_FS_O_TRUNC | UV_FS_O_CREAT | + UV_FS_O_WRONLY)) != 0) { + THROW_IF_INSUFFICIENT_PERMISSIONS( + env, permission::PermissionScope::kFileSystemWrite, pathView); + } + FSReqBase* req_wrap_async = GetReqWrap(args, 3); if (req_wrap_async != nullptr) { // openFileHandle(path, flags, mode, req) FS_ASYNC_TRACE_BEGIN1( @@ -1992,9 +2067,13 @@ static void CopyFile(const FunctionCallbackInfo<Value>& args) { BufferValue src(isolate, args[0]); CHECK_NOT_NULL(*src); + THROW_IF_INSUFFICIENT_PERMISSIONS( + env, permission::PermissionScope::kFileSystemRead, src.ToStringView()); BufferValue dest(isolate, args[1]); CHECK_NOT_NULL(*dest); + THROW_IF_INSUFFICIENT_PERMISSIONS( + env, permission::PermissionScope::kFileSystemWrite, dest.ToStringView()); CHECK(args[2]->IsInt32()); const int flags = args[2].As<Int32>()->Value(); @@ -2138,7 +2217,6 @@ static void WriteString(const FunctionCallbackInfo<Value>& args) { const int argc = args.Length(); CHECK_GE(argc, 4); - CHECK(args[0]->IsInt32()); const int fd = args[0].As<Int32>()->Value(); @@ -2503,6 +2581,8 @@ static void UTimes(const FunctionCallbackInfo<Value>& args) { BufferValue path(env->isolate(), args[0]); CHECK_NOT_NULL(*path); + THROW_IF_INSUFFICIENT_PERMISSIONS( + env, permission::PermissionScope::kFileSystemWrite, path.ToStringView()); CHECK(args[1]->IsNumber()); const double atime = args[1].As<Number>()->Value(); |