Skip to content

Commit 4dbc8ac

Browse files
committed
src: use policy per environment
1 parent c99d946 commit 4dbc8ac

File tree

12 files changed

+106
-92
lines changed

12 files changed

+106
-92
lines changed

src/env-inl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,10 @@ inline TickInfo* Environment::tick_info() {
335335
return &tick_info_;
336336
}
337337

338+
inline policy::Policy* Environment::policy() {
339+
return &policy_;
340+
}
341+
338342
inline uint64_t Environment::timer_base() const {
339343
return timer_base_;
340344
}

src/env.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,10 @@ Environment::Environment(IsolateData* isolate_data,
884884
"args",
885885
std::move(traced_value));
886886
}
887+
888+
policy()->Apply(
889+
options_->policy_deny_fs,
890+
policy::Permission::kFileSystem);
887891
}
888892

889893
Environment::Environment(IsolateData* isolate_data,

src/env.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include "util.h"
4444
#include "uv.h"
4545
#include "v8.h"
46+
#include "policy/policy.h"
4647

4748
#include <array>
4849
#include <atomic>
@@ -1160,6 +1161,7 @@ class Environment : public MemoryRetainer {
11601161
inline ImmediateInfo* immediate_info();
11611162
inline TickInfo* tick_info();
11621163
inline uint64_t timer_base() const;
1164+
inline policy::Policy* policy();
11631165
inline std::shared_ptr<KVStore> env_vars();
11641166
inline void set_env_vars(std::shared_ptr<KVStore> env_vars);
11651167

@@ -1526,6 +1528,7 @@ class Environment : public MemoryRetainer {
15261528
AsyncHooks async_hooks_;
15271529
ImmediateInfo immediate_info_;
15281530
TickInfo tick_info_;
1531+
policy::Policy policy_;
15291532
const uint64_t timer_base_;
15301533
std::shared_ptr<KVStore> env_vars_;
15311534
bool printed_error_ = false;

src/node.cc

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -858,14 +858,6 @@ int ProcessGlobalArgs(std::vector<std::string>* args,
858858

859859
if (v8_args_as_char_ptr.size() > 1) return 9;
860860

861-
if (policy::root_policy.Apply(
862-
per_process::cli_options->policy_deny_fs,
863-
policy::Permission::kFileSystem).IsNothing()) {
864-
errors->emplace_back(
865-
"invalid permissions passed to --policy-deny-fs");
866-
return 12;
867-
}
868-
869861
return 0;
870862
}
871863

src/node_file.cc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1622,8 +1622,6 @@ static void RealPath(const FunctionCallbackInfo<Value>& args) {
16221622

16231623
BufferValue path(isolate, args[0]);
16241624
CHECK_NOT_NULL(*path);
1625-
THROW_IF_INSUFFICIENT_PERMISSIONS(
1626-
env, policy::Permission::kFileSystemIn, *path);
16271625

16281626
const enum encoding encoding = ParseEncoding(isolate, args[1], UTF8);
16291627

src/node_options.cc

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,11 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
380380
&EnvironmentOptions::experimental_policy_integrity,
381381
kAllowedInEnvironment);
382382
Implies("--policy-integrity", "[has_policy_integrity_string]");
383+
384+
AddOption("--policy-deny-fs",
385+
"denied permissions to the filesystem",
386+
&EnvironmentOptions::policy_deny_fs,
387+
kAllowedInEnvironment);
383388
AddOption("--experimental-repl-await",
384389
"experimental await keyword support in REPL",
385390
&EnvironmentOptions::experimental_repl_await,
@@ -859,10 +864,6 @@ PerProcessOptionsParser::PerProcessOptionsParser(
859864
"force FIPS crypto (cannot be disabled)",
860865
&PerProcessOptions::force_fips_crypto,
861866
kAllowedInEnvironment);
862-
AddOption("--policy-deny-fs",
863-
"denied permissions to the filesystem",
864-
&PerProcessOptions::policy_deny_fs,
865-
kAllowedInEnvironment);
866867
AddOption("--secure-heap",
867868
"total size of the OpenSSL secure heap",
868869
&PerProcessOptions::secure_heap,

src/node_options.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ class EnvironmentOptions : public Options {
118118
std::string experimental_policy;
119119
std::string experimental_policy_integrity;
120120
bool has_policy_integrity_string = false;
121+
std::string policy_deny_fs;
121122
bool experimental_repl_await = true;
122123
bool experimental_vm_modules = false;
123124
bool expose_internals = false;
@@ -244,8 +245,6 @@ class PerProcessOptions : public Options {
244245
bool print_v8_help = false;
245246
bool print_version = false;
246247

247-
std::string policy_deny_fs;
248-
249248
#ifdef NODE_HAVE_I18N_SUPPORT
250249
std::string icu_data_dir;
251250
#endif

src/policy/policy.cc

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,30 +8,25 @@
88

99
#include "v8.h"
1010

11+
#include <iostream>
12+
#include <memory>
1113
#include <string>
1214
#include <vector>
13-
#include <iostream>
1415

1516
namespace node {
1617

1718
using v8::Array;
1819
using v8::Context;
1920
using v8::FunctionCallbackInfo;
2021
using v8::Integer;
21-
using v8::Just;
2222
using v8::Local;
23-
using v8::Maybe;
2423
using v8::Nothing;
2524
using v8::Object;
2625
using v8::String;
2726
using v8::Value;
2827

2928
namespace policy {
3029

31-
// The root policy is establish at process start using
32-
// the --policy-deny-* command line arguments.
33-
Policy root_policy;
34-
3530
namespace {
3631

3732
// policy.deny('fs.in', ['/tmp/'])
@@ -43,26 +38,30 @@ static void Deny(const FunctionCallbackInfo<Value>& args) {
4338
CHECK(args[0]->IsString());
4439
CHECK(args.Length() >= 2 || args[1]->IsArray());
4540

46-
std::string denyScope = *String::Utf8Value(isolate, args[0]);
47-
Permission scope = Policy::StringToPermission(denyScope);
41+
std::string deny_scope = *String::Utf8Value(isolate, args[0]);
42+
Permission scope = Policy::StringToPermission(deny_scope);
4843
if (scope == Permission::kPermissionsRoot) {
4944
return args.GetReturnValue().Set(false);
5045
}
5146

52-
Local<Array> jsParams = Local<Array>::Cast(args[1]);
53-
std::vector<std::string> params;
54-
for (uint32_t i = 0; i < jsParams->Length(); ++i) {
55-
Local<Value> arg(
56-
jsParams
57-
->Get(isolate->GetCurrentContext(), Integer::New(isolate, i))
58-
.ToLocalChecked());
47+
Local<Array> js_params = Local<Array>::Cast(args[1]);
48+
Local<Context> context = isolate->GetCurrentContext();
5949

50+
std::vector<std::string> params;
51+
for (uint32_t i = 0; i < js_params->Length(); ++i) {
52+
Local<Value> arg;
53+
if (!js_params->Get(context, Integer::New(isolate, i)).ToLocal(&arg)) {
54+
return;
55+
}
6056
String::Utf8Value utf8_arg(isolate, arg);
57+
if (*utf8_arg == nullptr) {
58+
return;
59+
}
6160
params.push_back(*utf8_arg);
6261
}
6362

6463
return args.GetReturnValue()
65-
.Set(root_policy.Deny(scope, params));
64+
.Set(env->policy()->Deny(scope, params));
6665
}
6766

6867
// policy.check('fs.in', '/tmp/')
@@ -73,15 +72,23 @@ static void Check(const FunctionCallbackInfo<Value>& args) {
7372
CHECK(args[0]->IsString());
7473
CHECK(args.Length() >= 2 || args[1]->IsString());
7574

76-
std::string denyScope = *String::Utf8Value(isolate, args[0]);
77-
Permission scope = Policy::StringToPermission(denyScope);
75+
String::Utf8Value utf8_deny_scope(isolate, args[0]);
76+
if (*utf8_deny_scope == nullptr) {
77+
return;
78+
}
79+
80+
const std::string deny_scope = *utf8_deny_scope;
81+
Permission scope = Policy::StringToPermission(deny_scope);
7882
if (scope == Permission::kPermissionsRoot) {
79-
// TODO(rafaelgss): throw?
8083
return args.GetReturnValue().Set(false);
8184
}
8285

83-
return args.GetReturnValue()
84-
.Set(root_policy.is_granted(scope, *String::Utf8Value(isolate, args[1])));
86+
String::Utf8Value utf8_arg(isolate, args[1]);
87+
if (*utf8_arg == nullptr) {
88+
return;
89+
}
90+
91+
return args.GetReturnValue().Set(env->policy()->is_granted(scope, *utf8_arg));
8592
}
8693

8794
} // namespace
@@ -96,7 +103,7 @@ const char* Policy::PermissionToString(const Permission perm) {
96103

97104
#define V(Name, label, _) \
98105
if (perm == label) return Permission::k##Name;
99-
Permission Policy::StringToPermission(std::string perm) {
106+
Permission Policy::StringToPermission(const std::string& perm) {
100107
PERMISSIONS(V)
101108
return Permission::kPermissionsRoot;
102109
}
@@ -115,15 +122,14 @@ void Policy::ThrowAccessDenied(Environment* env, Permission perm) {
115122
env->isolate()->ThrowException(err);
116123
}
117124

118-
Maybe<bool> Policy::Apply(const std::string& deny, Permission scope) {
125+
void Policy::Apply(const std::string& deny, Permission scope) {
119126
auto policy = deny_policies.find(scope);
120127
if (policy != deny_policies.end()) {
121-
return policy->second->Apply(deny);
128+
policy->second->Apply(deny);
122129
}
123-
return Just(false);
124130
}
125131

126-
bool Policy::Deny(Permission scope, std::vector<std::string> params) {
132+
bool Policy::Deny(Permission scope, const std::vector<std::string>& params) {
127133
auto policy = deny_policies.find(scope);
128134
if (policy != deny_policies.end()) {
129135
return policy->second->Deny(scope, params);

src/policy/policy.h

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,20 @@ class Environment;
1818
namespace policy {
1919

2020
#define THROW_IF_INSUFFICIENT_PERMISSIONS(env, perm_, resource_, ...) \
21-
if (!node::policy::root_policy.is_granted(perm_, resource_)) { \
22-
return node::policy::Policy::ThrowAccessDenied((env), perm_); \
23-
}
21+
do { \
22+
if (UNLIKELY(!(env)->policy()->is_granted(perm_, resource_))) { \
23+
node::policy::Policy::ThrowAccessDenied((env), perm_); \
24+
return __VA_ARGS__; \
25+
} \
26+
} while (0)
2427

2528
class Policy {
2629
public:
27-
// TODO(rafaelgss): release pointers
2830
Policy() {
29-
auto denyFs = new PolicyDenyFs();
30-
#define V(Name, _, __) \
31-
deny_policies.insert(std::make_pair(Permission::k##Name, denyFs));
32-
FILESYSTEM_PERMISSIONS(V)
31+
std::shared_ptr<PolicyDeny> deny_fs = std::make_shared<PolicyDenyFs>();
32+
#define V(Name, _, __) \
33+
deny_policies.insert(std::make_pair(Permission::k##Name, deny_fs));
34+
FILESYSTEM_PERMISSIONS(V)
3335
#undef V
3436
}
3537

@@ -45,20 +47,19 @@ class Policy {
4547
return is_granted(permission, res.c_str());
4648
}
4749

48-
static Permission StringToPermission(std::string perm);
50+
static Permission StringToPermission(const std::string& perm);
4951
static const char* PermissionToString(Permission perm);
5052
static void ThrowAccessDenied(Environment* env, Permission perm);
5153

5254
// CLI Call
53-
v8::Maybe<bool> Apply(const std::string& deny, Permission scope);
55+
void Apply(const std::string& deny, Permission scope);
5456
// Policy.Deny API
55-
bool Deny(Permission scope, std::vector<std::string> params);
57+
bool Deny(Permission scope, const std::vector<std::string>& params);
5658

5759
private:
58-
std::map<Permission, PolicyDeny*> deny_policies;
60+
std::map<Permission, std::shared_ptr<PolicyDeny>> deny_policies;
5961
};
6062

61-
extern policy::Policy root_policy;
6263
} // namespace policy
6364

6465
} // namespace node

src/policy/policy_deny.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ enum class Permission {
2929

3030
class PolicyDeny {
3131
public:
32-
virtual v8::Maybe<bool> Apply(const std::string& deny) = 0;
33-
virtual bool Deny(Permission scope, std::vector<std::string> params) = 0;
32+
virtual void Apply(const std::string& deny) = 0;
33+
virtual bool Deny(Permission scope,
34+
const std::vector<std::string>& params) = 0;
3435
virtual bool is_granted(Permission perm, const std::string& param = "") = 0;
3536
};
3637

0 commit comments

Comments
 (0)