Coverage Report

Created: 2025-12-10 07:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/node/src/permission/permission.h
Line
Count
Source
1
#ifndef SRC_PERMISSION_PERMISSION_H_
2
#define SRC_PERMISSION_PERMISSION_H_
3
4
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5
6
#include "debug_utils.h"
7
#include "node_options.h"
8
#include "permission/addon_permission.h"
9
#include "permission/child_process_permission.h"
10
#include "permission/fs_permission.h"
11
#include "permission/inspector_permission.h"
12
#include "permission/net_permission.h"
13
#include "permission/permission_base.h"
14
#include "permission/wasi_permission.h"
15
#include "permission/worker_permission.h"
16
#include "v8.h"
17
18
#include <string_view>
19
#include <unordered_map>
20
21
namespace node {
22
23
class Environment;
24
25
namespace fs {
26
class FSReqBase;
27
}
28
29
namespace permission {
30
31
#define THROW_IF_INSUFFICIENT_PERMISSIONS(env, perm, resource, ...)            \
32
0
  do {                                                                         \
33
0
    node::Environment* env__ = (env);                                          \
34
0
    const node::permission::PermissionScope perm__ = (perm);                   \
35
0
    const auto resource__ = (resource);                                        \
36
0
    if (!env__->permission()->is_granted(env__, perm__, resource__))           \
37
0
        [[unlikely]] {                                                         \
38
0
      node::permission::Permission::ThrowAccessDenied(                         \
39
0
          env__, perm__, resource__);                                          \
40
0
      return __VA_ARGS__;                                                      \
41
0
    }                                                                          \
42
0
  } while (0)
43
44
#define ASYNC_THROW_IF_INSUFFICIENT_PERMISSIONS(                               \
45
    env, wrap, perm, resource, ...)                                            \
46
0
  do {                                                                         \
47
0
    node::Environment* env__ = (env);                                          \
48
0
    const node::permission::PermissionScope perm__ = (perm);                   \
49
0
    const auto resource__ = (resource);                                        \
50
0
    if (!env__->permission()->is_granted(env__, perm__, resource__))           \
51
0
        [[unlikely]] {                                                         \
52
0
      node::permission::Permission::AsyncThrowAccessDenied(                    \
53
0
          env__, (wrap), perm__, resource__);                                  \
54
0
      return __VA_ARGS__;                                                      \
55
0
    }                                                                          \
56
0
  } while (0)
57
58
#define ERR_ACCESS_DENIED_IF_INSUFFICIENT_PERMISSIONS(                         \
59
    env, perm, resource, args, ...)                                            \
60
0
  do {                                                                         \
61
0
    node::Environment* env__ = (env);                                          \
62
0
    const node::permission::PermissionScope perm__ = (perm);                   \
63
0
    const auto resource__ = (resource);                                        \
64
0
    if (!env__->permission()->is_granted(env__, perm__, resource__))           \
65
0
        [[unlikely]] {                                                         \
66
0
      Local<Value> err_access;                                                 \
67
0
      if (node::permission::CreateAccessDeniedError(env__, perm__, resource__) \
68
0
              .ToLocal(&err_access)) {                                         \
69
0
        args.GetReturnValue().Set(err_access);                                 \
70
0
      } else {                                                                 \
71
0
        args.GetReturnValue().Set(UV_EACCES);                                  \
72
0
      }                                                                        \
73
0
      return __VA_ARGS__;                                                      \
74
0
    }                                                                          \
75
0
  } while (0)
76
77
#define SET_INSUFFICIENT_PERMISSION_ERROR_CALLBACK(scope)                      \
78
0
  void InsufficientPermissionError(std::string_view resource) {                \
79
0
    v8::HandleScope handle_scope(env()->isolate());                            \
80
0
    v8::Context::Scope context_scope(env()->context());                        \
81
0
    v8::Local<v8::Value> arg;                                                  \
82
0
    if (!permission::CreateAccessDeniedError(env(), (scope), resource)         \
83
0
             .ToLocal(&arg)) {                                                 \
84
0
    }                                                                          \
85
0
    MakeCallback(env()->oncomplete_string(), 1, &arg);                         \
86
0
  }
Unexecuted instantiation: node::cares_wrap::GetNameInfoReqWrap::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: node::cares_wrap::QueryWrap<node::cares_wrap::AnyTraits>::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: node::cares_wrap::QueryWrap<node::cares_wrap::ATraits>::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: node::cares_wrap::QueryWrap<node::cares_wrap::AaaaTraits>::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: node::cares_wrap::QueryWrap<node::cares_wrap::CaaTraits>::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: node::cares_wrap::QueryWrap<node::cares_wrap::CnameTraits>::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: node::cares_wrap::QueryWrap<node::cares_wrap::MxTraits>::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: node::cares_wrap::QueryWrap<node::cares_wrap::NsTraits>::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: node::cares_wrap::QueryWrap<node::cares_wrap::TlsaTraits>::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: node::cares_wrap::QueryWrap<node::cares_wrap::TxtTraits>::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: node::cares_wrap::QueryWrap<node::cares_wrap::SrvTraits>::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: node::cares_wrap::QueryWrap<node::cares_wrap::PtrTraits>::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: node::cares_wrap::QueryWrap<node::cares_wrap::NaptrTraits>::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: node::cares_wrap::QueryWrap<node::cares_wrap::SoaTraits>::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: node::cares_wrap::QueryWrap<node::cares_wrap::ReverseTraits>::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
87
88
class Permission {
89
 public:
90
  Permission();
91
92
  FORCE_INLINE bool is_granted(Environment* env,
93
                               const PermissionScope permission,
94
0
                               const std::string_view& res = "") const {
95
0
    if (!enabled_) [[likely]] {
96
0
      return true;
97
0
    }
98
0
    return is_scope_granted(env, permission, res);
99
0
  }
100
101
0
  FORCE_INLINE bool enabled() const { return enabled_; }
102
103
  static PermissionScope StringToPermission(const std::string& perm);
104
  static const char* PermissionToString(PermissionScope perm);
105
  static void ThrowAccessDenied(Environment* env,
106
                                PermissionScope perm,
107
                                const std::string_view& res);
108
  static void AsyncThrowAccessDenied(Environment* env,
109
                                     fs::FSReqBase* req_wrap,
110
                                     PermissionScope perm,
111
                                     const std::string_view& res);
112
113
  // CLI Call
114
  void Apply(Environment* env,
115
             const std::vector<std::string>& allow,
116
             PermissionScope scope);
117
  void EnablePermissions();
118
119
 private:
120
  COLD_NOINLINE bool is_scope_granted(Environment* env,
121
                                      const PermissionScope permission,
122
0
                                      const std::string_view& res = "") const {
123
0
    auto perm_node = nodes_.find(permission);
124
0
    if (perm_node != nodes_.end()) {
125
0
      return perm_node->second->is_granted(env, permission, res);
126
0
    }
127
0
    return false;
128
0
  }
129
130
  std::unordered_map<PermissionScope, std::shared_ptr<PermissionBase>> nodes_;
131
  bool enabled_;
132
};
133
134
v8::MaybeLocal<v8::Value> CreateAccessDeniedError(Environment* env,
135
                                                  PermissionScope perm,
136
                                                  const std::string_view& res);
137
138
}  // namespace permission
139
140
}  // namespace node
141
142
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
143
#endif  // SRC_PERMISSION_PERMISSION_H_