[builtins] Hash & verify the embedded blob
Embed a hash of the embedded blob at serialization-time, and verify it when loading the blob. Drive-by: Keep the size of the blob trimmed, and only page-align for dynamic page allocation and freeing during mksnapshot. Bug: v8:6666 Change-Id: I10b6064f4f2847d4cc400f6f1bd6961194985b8f Reviewed-on: https://chromium-review.googlesource.com/1019144 Commit-Queue: Jakob Gruber <jgruber@chromium.org> Reviewed-by: Peter Marshall <petermarshall@chromium.org> Cr-Commit-Position: refs/heads/master@{#52707}
This commit is contained in:
parent
10152d6f43
commit
49f0e6483f
@ -69,7 +69,7 @@ void InstructionStream::CreateOffHeapInstructionStream(Isolate* isolate,
|
||||
PageAllocator::kReadExecute));
|
||||
|
||||
*data = allocated_bytes;
|
||||
*size = allocated_size;
|
||||
*size = d.size();
|
||||
|
||||
d.Dispose();
|
||||
}
|
||||
@ -77,7 +77,8 @@ void InstructionStream::CreateOffHeapInstructionStream(Isolate* isolate,
|
||||
// static
|
||||
void InstructionStream::FreeOffHeapInstructionStream(uint8_t* data,
|
||||
uint32_t size) {
|
||||
CHECK(FreePages(data, size));
|
||||
const uint32_t page_size = static_cast<uint32_t>(AllocatePageSize());
|
||||
CHECK(FreePages(data, RoundUp(size, page_size)));
|
||||
}
|
||||
#endif // V8_EMBEDDED_BUILTINS
|
||||
|
||||
|
@ -94,6 +94,15 @@ void Isolate::SetEmbeddedBlob(const uint8_t* blob, uint32_t blob_size) {
|
||||
embedded_blob_size_ = blob_size;
|
||||
current_embedded_blob_.store(blob, std::memory_order_relaxed);
|
||||
current_embedded_blob_size_.store(blob_size, std::memory_order_relaxed);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (blob != nullptr) {
|
||||
// Verify that the contents of the embedded blob are unchanged from
|
||||
// serialization-time, just to ensure the compiler isn't messing with us.
|
||||
EmbeddedData d = EmbeddedData::FromBlob();
|
||||
CHECK_EQ(d.Hash(), d.CreateHash());
|
||||
}
|
||||
#endif // DEBUG
|
||||
}
|
||||
|
||||
const uint8_t* Isolate::embedded_blob() const { return embedded_blob_; }
|
||||
|
@ -393,7 +393,17 @@ EmbeddedData EmbeddedData::FromIsolate(Isolate* isolate) {
|
||||
code->raw_instruction_size());
|
||||
}
|
||||
|
||||
return {blob, blob_size};
|
||||
EmbeddedData d(blob, blob_size);
|
||||
|
||||
// Hash the blob and store the result.
|
||||
STATIC_ASSERT(HashSize() == kSizetSize);
|
||||
const size_t hash = d.CreateHash();
|
||||
std::memcpy(blob + HashOffset(), &hash, HashSize());
|
||||
|
||||
DCHECK_EQ(hash, d.CreateHash());
|
||||
DCHECK_EQ(hash, d.Hash());
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
EmbeddedData EmbeddedData::FromBlob() {
|
||||
@ -406,10 +416,10 @@ EmbeddedData EmbeddedData::FromBlob() {
|
||||
|
||||
Address EmbeddedData::InstructionStartOfBuiltin(int i) const {
|
||||
DCHECK(Builtins::IsBuiltinId(i));
|
||||
|
||||
const uint32_t* offsets = Offsets();
|
||||
const uint8_t* result = RawData() + offsets[i];
|
||||
DCHECK_LT(result, data_ + size_);
|
||||
DCHECK_LE(result, data_ + size_);
|
||||
DCHECK_IMPLIES(result == data_ + size_, InstructionSizeOfBuiltin(i) == 0);
|
||||
return reinterpret_cast<Address>(result);
|
||||
}
|
||||
|
||||
@ -418,6 +428,12 @@ uint32_t EmbeddedData::InstructionSizeOfBuiltin(int i) const {
|
||||
const uint32_t* lengths = Lengths();
|
||||
return lengths[i];
|
||||
}
|
||||
|
||||
size_t EmbeddedData::CreateHash() const {
|
||||
STATIC_ASSERT(HashOffset() == 0);
|
||||
STATIC_ASSERT(HashSize() == kSizetSize);
|
||||
return base::hash_range(data_ + HashSize(), data_ + size_);
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t Snapshot::ExtractNumContexts(const v8::StartupData* data) {
|
||||
|
@ -100,16 +100,26 @@ class EmbeddedData final {
|
||||
return RoundUp<kCodeAlignment>(InstructionSizeOfBuiltin(i));
|
||||
}
|
||||
|
||||
size_t CreateHash() const;
|
||||
size_t Hash() const {
|
||||
return *reinterpret_cast<const size_t*>(data_ + HashOffset());
|
||||
}
|
||||
|
||||
// The layout of the blob is as follows:
|
||||
//
|
||||
// [0] offset of instruction stream 0
|
||||
// ... offsets
|
||||
// [N] length of instruction stream 0
|
||||
// ... lengths
|
||||
// ... instruction streams
|
||||
// [0] hash of the remaining blob
|
||||
// [1] offset of instruction stream 0
|
||||
// ... offsets
|
||||
// [N + 1] length of instruction stream 0
|
||||
// ... lengths
|
||||
// ... instruction streams
|
||||
|
||||
static constexpr uint32_t kTableSize = Builtins::builtin_count;
|
||||
static constexpr uint32_t OffsetsOffset() { return 0; }
|
||||
static constexpr uint32_t HashOffset() { return 0; }
|
||||
static constexpr uint32_t HashSize() { return kSizetSize; }
|
||||
static constexpr uint32_t OffsetsOffset() {
|
||||
return HashOffset() + HashSize();
|
||||
}
|
||||
static constexpr uint32_t OffsetsSize() { return kUInt32Size * kTableSize; }
|
||||
static constexpr uint32_t LengthsOffset() {
|
||||
return OffsetsOffset() + OffsetsSize();
|
||||
|
Loading…
Reference in New Issue
Block a user