0

Cache HandlerCloser serialized map

The serialized handle closer map in practice does not change once
a given handler closer is initialized. This allows us to cache the
serialized map and re-use it across multiple target launches, rather
than regenerating it each time. We add a protection to prevent
calling AddHandle after the cached map is generated.

Bug: 549319
Change-Id: Ic0414e9fcd80e74ed5e485dbed33161c5f09f782
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3821609
Commit-Queue: Alex Gough <ajgo@chromium.org>
Reviewed-by: Will Harris <wfh@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1043724}
This commit is contained in:
Alex Gough
2022-09-07 00:02:33 +00:00
committed by Chromium LUCI CQ
parent a14cb3284f
commit 02203152be
2 changed files with 18 additions and 7 deletions

@ -43,6 +43,11 @@ ResultCode HandleCloser::AddHandle(const wchar_t* handle_type,
if (!handle_type)
return SBOX_ERROR_BAD_PARAMS;
// Cannot call AddHandle if the cache has been initialized.
DCHECK(serialized_map_.empty());
if (!serialized_map_.empty())
return SBOX_ERROR_UNEXPECTED_CALL;
std::wstring resolved_name;
if (handle_name) {
resolved_name = handle_name;
@ -93,17 +98,20 @@ bool HandleCloser::InitializeTargetHandles(TargetProcess& target) {
if (handles_to_close_.empty())
return true;
size_t bytes_needed = GetBufferSize();
std::unique_ptr<size_t[]> local_buffer(
new size_t[bytes_needed / sizeof(size_t)]);
// Cache the serialized form as we might be used by shared configs.
if (serialized_map_.empty()) {
size_t bytes_needed = GetBufferSize();
serialized_map_.resize(bytes_needed);
if (!SetupHandleList(local_buffer.get(), bytes_needed))
return false;
if (!SetupHandleList(serialized_map_.data(), bytes_needed))
return false;
}
void* remote_data;
if (!CopyToChildMemory(target.Process(), local_buffer.get(), bytes_needed,
&remote_data))
if (!CopyToChildMemory(target.Process(), serialized_map_.data(),
serialized_map_.size(), &remote_data)) {
return false;
}
g_handles_to_close = reinterpret_cast<HandleCloserInfo*>(remote_data);

@ -53,9 +53,11 @@ class HandleCloser {
// Adds a handle that will be closed in the target process after lockdown.
// A nullptr value for handle_name indicates all handles of the specified
// type. An empty string for handle_name indicates the handle is unnamed.
// Note: this cannot be called after InitializeTargetHandles().
ResultCode AddHandle(const wchar_t* handle_type, const wchar_t* handle_name);
// Serializes and copies the closer table into the target process.
// Note: this can be called multiple times for different targets.
bool InitializeTargetHandles(TargetProcess& target);
private:
@ -70,6 +72,7 @@ class HandleCloser {
bool SetupHandleList(void* buffer, size_t buffer_bytes);
HandleMap handles_to_close_;
std::vector<uint8_t> serialized_map_;
};
} // namespace sandbox