Skip to content

Commit 391bde2

Browse files
committed
src: prepare for v8 sandboxing
nodejs/node#58376
1 parent b9654ca commit 391bde2

File tree

1 file changed

+30
-161
lines changed

1 file changed

+30
-161
lines changed

patches/node/support_v8_sandboxed_pointers.patch

Lines changed: 30 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ This refactors several allocators to allocate within the V8 memory cage,
77
allowing them to be compatible with the V8_SANDBOXED_POINTERS feature.
88

99
diff --git a/src/api/environment.cc b/src/api/environment.cc
10-
index fd71ceac65ccef1d2832b45b0b5612877cee22c1..cb37fa080fc8e8d524cfa2758c4a8c2c5652324d 100644
10+
index d10f861c969..4fad275c865 100644
1111
--- a/src/api/environment.cc
1212
+++ b/src/api/environment.cc
13-
@@ -106,6 +106,14 @@ MaybeLocal<Value> PrepareStackTraceCallback(Local<Context> context,
13+
@@ -109,6 +109,14 @@ MaybeLocal<Value> PrepareStackTraceCallback(Local<Context> context,
1414
return result;
1515
}
1616

@@ -25,99 +25,19 @@ index fd71ceac65ccef1d2832b45b0b5612877cee22c1..cb37fa080fc8e8d524cfa2758c4a8c2c
2525
void* NodeArrayBufferAllocator::Allocate(size_t size) {
2626
void* ret;
2727
if (zero_fill_field_ || per_process::cli_options->zero_fill_all_buffers)
28-
diff --git a/src/crypto/crypto_dh.cc b/src/crypto/crypto_dh.cc
29-
index f23cedf4f2449d8edc9a8de1b70332e75d693cdd..976653dd1e9363e046788fc3419a9b649ceb2ea4 100644
30-
--- a/src/crypto/crypto_dh.cc
31-
+++ b/src/crypto/crypto_dh.cc
32-
@@ -55,13 +55,32 @@ void DiffieHellman::MemoryInfo(MemoryTracker* tracker) const {
33-
34-
namespace {
35-
MaybeLocal<Value> DataPointerToBuffer(Environment* env, DataPointer&& data) {
36-
+#if defined(V8_ENABLE_SANDBOX)
37-
+ std::unique_ptr<v8::BackingStore> backing;
38-
+ if (data.size() > 0) {
39-
+ std::unique_ptr<ArrayBuffer::Allocator> allocator(ArrayBuffer::Allocator::NewDefaultAllocator());
40-
+ void* v8_data = allocator->Allocate(data.size());
41-
+ CHECK(v8_data);
42-
+ memcpy(v8_data, data.get(), data.size());
43-
+ backing = ArrayBuffer::NewBackingStore(
44-
+ v8_data,
45-
+ data.size(),
46-
+ [](void* data, size_t length, void*) {
47-
+ std::unique_ptr<ArrayBuffer::Allocator> allocator(ArrayBuffer::Allocator::NewDefaultAllocator());
48-
+ allocator->Free(data, length);
49-
+ }, nullptr);
50-
+ } else {
51-
+ NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
52-
+ backing = v8::ArrayBuffer::NewBackingStore(env->isolate(), data.size());
53-
+ }
54-
+#else
55-
auto backing = ArrayBuffer::NewBackingStore(
56-
data.get(),
57-
data.size(),
58-
[](void* data, size_t len, void* ptr) { DataPointer free_me(data, len); },
59-
nullptr);
60-
data.release();
61-
-
62-
+#endif
63-
auto ab = ArrayBuffer::New(env->isolate(), std::move(backing));
64-
return Buffer::New(env, ab, 0, ab->ByteLength()).FromMaybe(Local<Value>());
65-
}
6628
diff --git a/src/crypto/crypto_util.cc b/src/crypto/crypto_util.cc
67-
index 6346f8f7199cf7b7d3736c59571606fff102fbb6..7eea2eaefcad5780663a6b87985925ae5d70a5f9 100644
29+
index 12b0d804c6f..768208f2802 100644
6830
--- a/src/crypto/crypto_util.cc
6931
+++ b/src/crypto/crypto_util.cc
70-
@@ -359,10 +359,35 @@ ByteSource& ByteSource::operator=(ByteSource&& other) noexcept {
71-
return *this;
72-
}
73-
74-
-std::unique_ptr<BackingStore> ByteSource::ReleaseToBackingStore() {
75-
+std::unique_ptr<BackingStore> ByteSource::ReleaseToBackingStore(Environment* env) {
76-
// It's ok for allocated_data_ to be nullptr but
77-
// only if size_ is zero.
78-
CHECK_IMPLIES(size_ > 0, allocated_data_ != nullptr);
79-
+#if defined(V8_ENABLE_SANDBOX)
80-
+ // When V8 sandboxed pointers are enabled, we have to copy into the memory
81-
+ // cage. We still want to ensure we erase the data on free though, so
82-
+ // provide a custom deleter that calls OPENSSL_cleanse.
83-
+ if (!size())
84-
+ return ArrayBuffer::NewBackingStore(env->isolate(), 0);
85-
+ std::unique_ptr<ArrayBuffer::Allocator> allocator(ArrayBuffer::Allocator::NewDefaultAllocator());
86-
+ void* v8_data = allocator->Allocate(size());
87-
+ CHECK(v8_data);
88-
+ memcpy(v8_data, allocated_data_, size());
89-
+ OPENSSL_clear_free(allocated_data_, size());
90-
+ std::unique_ptr<BackingStore> ptr = ArrayBuffer::NewBackingStore(
91-
+ v8_data,
92-
+ size(),
93-
+ [](void* data, size_t length, void*) {
94-
+ OPENSSL_cleanse(data, length);
95-
+ std::unique_ptr<ArrayBuffer::Allocator> allocator(ArrayBuffer::Allocator::NewDefaultAllocator());
96-
+ allocator->Free(data, length);
97-
+ }, nullptr);
98-
+ CHECK(ptr);
99-
+ allocated_data_ = nullptr;
100-
+ data_ = nullptr;
101-
+ size_ = 0;
102-
+ return ptr;
103-
+#else
104-
std::unique_ptr<BackingStore> ptr = ArrayBuffer::NewBackingStore(
105-
allocated_data_,
106-
size(),
107-
@@ -374,10 +399,11 @@ std::unique_ptr<BackingStore> ByteSource::ReleaseToBackingStore() {
32+
@@ -377,6 +377,7 @@ std::unique_ptr<BackingStore> ByteSource::ReleaseToBackingStore(
10833
data_ = nullptr;
10934
size_ = 0;
11035
return ptr;
11136
+#endif // defined(V8_ENABLE_SANDBOX)
11237
}
11338

11439
Local<ArrayBuffer> ByteSource::ToArrayBuffer(Environment* env) {
115-
- std::unique_ptr<BackingStore> store = ReleaseToBackingStore();
116-
+ std::unique_ptr<BackingStore> store = ReleaseToBackingStore(env);
117-
return ArrayBuffer::New(env->isolate(), std::move(store));
118-
}
119-
120-
@@ -674,6 +700,16 @@ namespace {
40+
@@ -661,6 +662,16 @@ namespace {
12141
// in which case this has the same semantics as
12242
// using OPENSSL_malloc. However, if the secure heap is
12343
// initialized, SecureBuffer will automatically use it.
@@ -132,76 +52,21 @@ index 6346f8f7199cf7b7d3736c59571606fff102fbb6..7eea2eaefcad5780663a6b87985925ae
13252
+}
13353
+#else
13454
void SecureBuffer(const FunctionCallbackInfo<Value>& args) {
135-
CHECK(args[0]->IsUint32());
13655
Environment* env = Environment::GetCurrent(args);
137-
@@ -695,6 +731,7 @@ void SecureBuffer(const FunctionCallbackInfo<Value>& args) {
138-
Local<ArrayBuffer> buffer = ArrayBuffer::New(env->isolate(), store);
56+
#ifdef V8_ENABLE_SANDBOX
57+
@@ -703,6 +714,7 @@ void SecureBuffer(const FunctionCallbackInfo<Value>& args) {
13958
args.GetReturnValue().Set(Uint8Array::New(buffer, 0, len));
59+
#endif // V8_ENABLE_SANDBOX
14060
}
14161
+#endif // defined(V8_ENABLE_SANDBOX)
14262

14363
void SecureHeapUsed(const FunctionCallbackInfo<Value>& args) {
144-
#ifndef OPENSSL_IS_BORINGSSL
145-
diff --git a/src/crypto/crypto_util.h b/src/crypto/crypto_util.h
146-
index ebc7fddeccf04a92c610849b626b33f900d63493..ed7d202d1b041f8a6cd43ae767d696fb29ab9cd9 100644
147-
--- a/src/crypto/crypto_util.h
148-
+++ b/src/crypto/crypto_util.h
149-
@@ -243,7 +243,7 @@ class ByteSource {
150-
// Creates a v8::BackingStore that takes over responsibility for
151-
// any allocated data. The ByteSource will be reset with size = 0
152-
// after being called.
153-
- std::unique_ptr<v8::BackingStore> ReleaseToBackingStore();
154-
+ std::unique_ptr<v8::BackingStore> ReleaseToBackingStore(Environment* env);
155-
156-
v8::Local<v8::ArrayBuffer> ToArrayBuffer(Environment* env);
157-
158-
diff --git a/src/crypto/crypto_x509.cc b/src/crypto/crypto_x509.cc
159-
index f616223cfb0f6e10f7cf57ada9704316bde2797e..eb6dad44a49d997097c8fb5009eeb60a7305da27 100644
160-
--- a/src/crypto/crypto_x509.cc
161-
+++ b/src/crypto/crypto_x509.cc
162-
@@ -167,6 +167,19 @@ MaybeLocal<Value> ToV8Value(Local<Context> context, const BIOPointer& bio) {
163-
MaybeLocal<Value> ToBuffer(Environment* env, BIOPointer* bio) {
164-
if (bio == nullptr || !*bio) return {};
165-
BUF_MEM* mem = *bio;
166-
+#if defined(V8_ENABLE_SANDBOX)
167-
+ std::unique_ptr<ArrayBuffer::Allocator> allocator(ArrayBuffer::Allocator::NewDefaultAllocator());
168-
+ void* v8_data = allocator->Allocate(mem->length);
169-
+ CHECK(v8_data);
170-
+ memcpy(v8_data, mem->data, mem->length);
171-
+ std::unique_ptr<v8::BackingStore> backing = ArrayBuffer::NewBackingStore(
172-
+ v8_data,
173-
+ mem->length,
174-
+ [](void* data, size_t length, void*) {
175-
+ std::unique_ptr<ArrayBuffer::Allocator> allocator(ArrayBuffer::Allocator::NewDefaultAllocator());
176-
+ allocator->Free(data, length);
177-
+ }, nullptr);
178-
+#else
179-
auto backing = ArrayBuffer::NewBackingStore(
180-
mem->data,
181-
mem->length,
182-
@@ -174,6 +187,8 @@ MaybeLocal<Value> ToBuffer(Environment* env, BIOPointer* bio) {
183-
BIOPointer free_me(static_cast<BIO*>(data));
184-
},
185-
bio->release());
186-
+#endif
187-
+
188-
auto ab = ArrayBuffer::New(env->isolate(), std::move(backing));
189-
Local<Value> ret;
190-
if (!Buffer::New(env, ab, 0, ab->ByteLength()).ToLocal(&ret)) return {};
64+
args.GetReturnValue().Set(
19165
diff --git a/src/node_i18n.cc b/src/node_i18n.cc
192-
index 61b6ecd240c9500f21f683065a2f920af3afb502..ad2b1c76325cb5c8f18a618c5a85ae87b6a7bbe7 100644
66+
index 3c4f419aa29..584d0f62743 100644
19367
--- a/src/node_i18n.cc
19468
+++ b/src/node_i18n.cc
195-
@@ -104,7 +104,7 @@ namespace {
196-
197-
template <typename T>
198-
MaybeLocal<Object> ToBufferEndian(Environment* env, MaybeStackBuffer<T>* buf) {
199-
- MaybeLocal<Object> ret = Buffer::New(env, buf);
200-
+ MaybeLocal<Object> ret = Buffer::Copy(env, reinterpret_cast<char*>(buf->out()), buf->length() * sizeof(T));
201-
if (ret.IsEmpty())
202-
return ret;
203-
204-
@@ -181,7 +181,7 @@ MaybeLocal<Object> TranscodeLatin1ToUcs2(Environment* env,
69+
@@ -182,7 +182,7 @@ MaybeLocal<Object> TranscodeLatin1ToUcs2(Environment* env,
20570
return {};
20671
}
20772

@@ -210,7 +75,7 @@ index 61b6ecd240c9500f21f683065a2f920af3afb502..ad2b1c76325cb5c8f18a618c5a85ae87
21075
}
21176

21277
MaybeLocal<Object> TranscodeFromUcs2(Environment* env,
213-
@@ -226,7 +226,7 @@ MaybeLocal<Object> TranscodeUcs2FromUtf8(Environment* env,
78+
@@ -227,7 +227,7 @@ MaybeLocal<Object> TranscodeUcs2FromUtf8(Environment* env,
21479
return {};
21580
}
21681

@@ -219,7 +84,7 @@ index 61b6ecd240c9500f21f683065a2f920af3afb502..ad2b1c76325cb5c8f18a618c5a85ae87
21984
}
22085

22186
MaybeLocal<Object> TranscodeUtf8FromUcs2(Environment* env,
222-
@@ -250,7 +250,7 @@ MaybeLocal<Object> TranscodeUtf8FromUcs2(Environment* env,
87+
@@ -251,7 +251,7 @@ MaybeLocal<Object> TranscodeUtf8FromUcs2(Environment* env,
22388
return {};
22489
}
22590

@@ -229,7 +94,7 @@ index 61b6ecd240c9500f21f683065a2f920af3afb502..ad2b1c76325cb5c8f18a618c5a85ae87
22994

23095
constexpr const char* EncodingName(const enum encoding encoding) {
23196
diff --git a/src/node_internals.h b/src/node_internals.h
232-
index 12ea72b61b0a5e194207bb369dfed4b8667107cb..64442215714a98f648971e517ddd9c77e38fe3f2 100644
97+
index 12ea72b61b0..64442215714 100644
23398
--- a/src/node_internals.h
23499
+++ b/src/node_internals.h
235100
@@ -121,7 +121,9 @@ v8::MaybeLocal<v8::Object> InitializePrivateSymbols(
@@ -253,7 +118,7 @@ index 12ea72b61b0a5e194207bb369dfed4b8667107cb..64442215714a98f648971e517ddd9c77
253118

254119
// Delegate to V8's allocator for compatibility with the V8 memory cage.
255120
diff --git a/src/node_serdes.cc b/src/node_serdes.cc
256-
index c55a2e28066147ae5ca5def10ec76ccc03c634b4..c54183c72944989219b6437c9e571a3f7f3f8dd5 100644
121+
index 00fcd4b6afc..5f96ee2051e 100644
257122
--- a/src/node_serdes.cc
258123
+++ b/src/node_serdes.cc
259124
@@ -29,6 +29,26 @@ using v8::ValueSerializer;
@@ -307,8 +172,8 @@ index c55a2e28066147ae5ca5def10ec76ccc03c634b4..c54183c72944989219b6437c9e571a3f
307172
};
308173

309174
class DeserializerContext : public BaseObject,
310-
@@ -144,6 +170,24 @@ Maybe<uint32_t> SerializerContext::GetSharedArrayBufferId(
311-
return id.ToLocalChecked()->Uint32Value(env()->context());
175+
@@ -145,6 +171,24 @@ Maybe<uint32_t> SerializerContext::GetSharedArrayBufferId(
176+
return id->Uint32Value(env()->context());
312177
}
313178

314179
+void* SerializerContext::ReallocateBufferMemory(void* old_buffer,
@@ -331,14 +196,15 @@ index c55a2e28066147ae5ca5def10ec76ccc03c634b4..c54183c72944989219b6437c9e571a3f
331196
+
332197
Maybe<bool> SerializerContext::WriteHostObject(Isolate* isolate,
333198
Local<Object> input) {
334-
MaybeLocal<Value> ret;
335-
@@ -209,9 +253,14 @@ void SerializerContext::ReleaseBuffer(const FunctionCallbackInfo<Value>& args) {
199+
Local<Value> args[1] = { input };
200+
@@ -211,10 +255,17 @@ void SerializerContext::ReleaseBuffer(const FunctionCallbackInfo<Value>& args) {
336201
// Note: Both ValueSerializer and this Buffer::New() variant use malloc()
337202
// as the underlying allocator.
338203
std::pair<uint8_t*, size_t> ret = ctx->serializer_.Release();
339-
- auto buf = Buffer::New(ctx->env(),
340-
- reinterpret_cast<char*>(ret.first),
341-
- ret.second);
204+
- Local<Object> buf;
205+
- if (Buffer::New(ctx->env(), reinterpret_cast<char*>(ret.first), ret.second)
206+
- .ToLocal(&buf)) {
207+
- args.GetReturnValue().Set(buf);
342208
+ std::unique_ptr<v8::BackingStore> bs =
343209
+ v8::ArrayBuffer::NewBackingStore(reinterpret_cast<char*>(ret.first), ret.second,
344210
+ [](void* data, size_t length, void* deleter_data) {
@@ -347,14 +213,17 @@ index c55a2e28066147ae5ca5def10ec76ccc03c634b4..c54183c72944989219b6437c9e571a3f
347213
+ Local<ArrayBuffer> ab = v8::ArrayBuffer::New(ctx->env()->isolate(), std::move(bs));
348214
+
349215
+ auto buf = Buffer::New(ctx->env(), ab, 0, ret.second);
216+
+
217+
+ if (!buf.IsEmpty()) {
218+
+ args.GetReturnValue().Set(buf.ToLocalChecked());
219+
}
220+
}
350221

351-
if (!buf.IsEmpty()) {
352-
args.GetReturnValue().Set(buf.ToLocalChecked());
353222
diff --git a/src/node_trace_events.cc b/src/node_trace_events.cc
354-
index 9787b14352753c5e0f8dc2b90093680e7cd10f1a..31af9e62396368af1b81f8841a705fd313df2b9f 100644
223+
index ef659f1c39f..225b1465b7c 100644
355224
--- a/src/node_trace_events.cc
356225
+++ b/src/node_trace_events.cc
357-
@@ -132,12 +132,28 @@ static void GetCategoryEnabledBuffer(const FunctionCallbackInfo<Value>& args) {
226+
@@ -129,12 +129,28 @@ static void GetCategoryEnabledBuffer(const FunctionCallbackInfo<Value>& args) {
358227
const uint8_t* enabled_pointer =
359228
TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_name.out());
360229
uint8_t* enabled_pointer_cast = const_cast<uint8_t*>(enabled_pointer);

0 commit comments

Comments
 (0)