182 lines
7.2 KiB
Diff
182 lines
7.2 KiB
Diff
# HG changeset patch
|
|
# User Tom Ritter <tom@mozilla.com>
|
|
# Date 1528394907 18000
|
|
# Thu Jun 07 13:08:27 2018 -0500
|
|
# Node ID ffb6c5c06905538fb887464e9553e7b47cdf7575
|
|
# Parent 1987e062f1e5bf2998bb8e9d96353c5ccb0cc281
|
|
Bug 1461421 Use OffsetOf to calculate the location of parameters_ rather than making assumptions about the parent class r?bobowen
|
|
|
|
MozReview-Commit-ID: D7REZiAIMpN
|
|
|
|
diff --git a/sandbox/win/src/crosscall_params.h b/sandbox/win/src/crosscall_params.h
|
|
--- a/sandbox/win/src/crosscall_params.h
|
|
+++ b/sandbox/win/src/crosscall_params.h
|
|
@@ -78,16 +78,17 @@ union MultiType {
|
|
ULONG_PTR ulong_ptr;
|
|
};
|
|
|
|
// Maximum number of IPC parameters currently supported.
|
|
// To increase this value, we have to:
|
|
// - Add another Callback typedef to Dispatcher.
|
|
// - Add another case to the switch on SharedMemIPCServer::InvokeCallback.
|
|
// - Add another case to the switch in GetActualAndMaxBufferSize
|
|
+// - Add another case to the switch in GetMinDeclaredActualCallParamsSize
|
|
const int kMaxIpcParams = 9;
|
|
|
|
// Contains the information about a parameter in the ipc buffer.
|
|
struct ParamInfo {
|
|
ArgType type_;
|
|
uint32_t offset_;
|
|
uint32_t size_;
|
|
};
|
|
@@ -287,16 +288,18 @@ class ActualCallParams : public CrossCal
|
|
protected:
|
|
ActualCallParams() : CrossCallParams(IpcTag::UNUSED, NUMBER_PARAMS) {}
|
|
|
|
private:
|
|
ParamInfo param_info_[NUMBER_PARAMS + 1];
|
|
char parameters_[BLOCK_SIZE - sizeof(CrossCallParams) -
|
|
sizeof(ParamInfo) * (NUMBER_PARAMS + 1)];
|
|
DISALLOW_COPY_AND_ASSIGN(ActualCallParams);
|
|
+
|
|
+ friend uint32_t GetMinDeclaredActualCallParamsSize(uint32_t param_count);
|
|
};
|
|
|
|
static_assert(sizeof(ActualCallParams<1, 1024>) == 1024, "bad size buffer");
|
|
static_assert(sizeof(ActualCallParams<2, 1024>) == 1024, "bad size buffer");
|
|
static_assert(sizeof(ActualCallParams<3, 1024>) == 1024, "bad size buffer");
|
|
|
|
} // namespace sandbox
|
|
|
|
diff --git a/sandbox/win/src/crosscall_server.cc b/sandbox/win/src/crosscall_server.cc
|
|
--- a/sandbox/win/src/crosscall_server.cc
|
|
+++ b/sandbox/win/src/crosscall_server.cc
|
|
@@ -28,30 +28,31 @@ namespace {
|
|
|
|
// The buffer for a message must match the max channel size.
|
|
const size_t kMaxBufferSize = sandbox::kIPCChannelSize;
|
|
|
|
} // namespace
|
|
|
|
namespace sandbox {
|
|
|
|
+// The template types are used to calculate the maximum expected size.
|
|
+typedef ActualCallParams<0, kMaxBufferSize> ActualCP0;
|
|
+typedef ActualCallParams<1, kMaxBufferSize> ActualCP1;
|
|
+typedef ActualCallParams<2, kMaxBufferSize> ActualCP2;
|
|
+typedef ActualCallParams<3, kMaxBufferSize> ActualCP3;
|
|
+typedef ActualCallParams<4, kMaxBufferSize> ActualCP4;
|
|
+typedef ActualCallParams<5, kMaxBufferSize> ActualCP5;
|
|
+typedef ActualCallParams<6, kMaxBufferSize> ActualCP6;
|
|
+typedef ActualCallParams<7, kMaxBufferSize> ActualCP7;
|
|
+typedef ActualCallParams<8, kMaxBufferSize> ActualCP8;
|
|
+typedef ActualCallParams<9, kMaxBufferSize> ActualCP9;
|
|
+
|
|
// Returns the actual size for the parameters in an IPC buffer. Returns
|
|
// zero if the |param_count| is zero or too big.
|
|
uint32_t GetActualBufferSize(uint32_t param_count, void* buffer_base) {
|
|
- // The template types are used to calculate the maximum expected size.
|
|
- typedef ActualCallParams<1, kMaxBufferSize> ActualCP1;
|
|
- typedef ActualCallParams<2, kMaxBufferSize> ActualCP2;
|
|
- typedef ActualCallParams<3, kMaxBufferSize> ActualCP3;
|
|
- typedef ActualCallParams<4, kMaxBufferSize> ActualCP4;
|
|
- typedef ActualCallParams<5, kMaxBufferSize> ActualCP5;
|
|
- typedef ActualCallParams<6, kMaxBufferSize> ActualCP6;
|
|
- typedef ActualCallParams<7, kMaxBufferSize> ActualCP7;
|
|
- typedef ActualCallParams<8, kMaxBufferSize> ActualCP8;
|
|
- typedef ActualCallParams<9, kMaxBufferSize> ActualCP9;
|
|
-
|
|
// Retrieve the actual size and the maximum size of the params buffer.
|
|
switch (param_count) {
|
|
case 0:
|
|
return 0;
|
|
case 1:
|
|
return reinterpret_cast<ActualCP1*>(buffer_base)->GetSize();
|
|
case 2:
|
|
return reinterpret_cast<ActualCP2*>(buffer_base)->GetSize();
|
|
@@ -69,16 +70,45 @@ uint32_t GetActualBufferSize(uint32_t pa
|
|
return reinterpret_cast<ActualCP8*>(buffer_base)->GetSize();
|
|
case 9:
|
|
return reinterpret_cast<ActualCP9*>(buffer_base)->GetSize();
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
+// Returns the minimum size for the parameters in an IPC buffer. Returns
|
|
+// zero if the |param_count| is less than zero or too big.
|
|
+uint32_t GetMinDeclaredActualCallParamsSize(uint32_t param_count) {
|
|
+ switch (param_count) {
|
|
+ case 0:
|
|
+ return offsetof(ActualCP0, parameters_);
|
|
+ case 1:
|
|
+ return offsetof(ActualCP1, parameters_);
|
|
+ case 2:
|
|
+ return offsetof(ActualCP2, parameters_);
|
|
+ case 3:
|
|
+ return offsetof(ActualCP3, parameters_);
|
|
+ case 4:
|
|
+ return offsetof(ActualCP4, parameters_);
|
|
+ case 5:
|
|
+ return offsetof(ActualCP5, parameters_);
|
|
+ case 6:
|
|
+ return offsetof(ActualCP6, parameters_);
|
|
+ case 7:
|
|
+ return offsetof(ActualCP7, parameters_);
|
|
+ case 8:
|
|
+ return offsetof(ActualCP8, parameters_);
|
|
+ case 9:
|
|
+ return offsetof(ActualCP9, parameters_);
|
|
+ default:
|
|
+ return 0;
|
|
+ }
|
|
+}
|
|
+
|
|
// Verifies that the declared sizes of an IPC buffer are within range.
|
|
bool IsSizeWithinRange(uint32_t buffer_size,
|
|
uint32_t min_declared_size,
|
|
uint32_t declared_size) {
|
|
if ((buffer_size < min_declared_size) ||
|
|
(sizeof(CrossCallParamsEx) > min_declared_size)) {
|
|
// Minimal computed size bigger than existing buffer or param_count
|
|
// integer overflow.
|
|
@@ -133,18 +163,17 @@ CrossCallParamsEx* CrossCallParamsEx::Cr
|
|
// will catch memory access violations so we don't crash.
|
|
__try {
|
|
CrossCallParams* call_params =
|
|
reinterpret_cast<CrossCallParams*>(buffer_base);
|
|
|
|
// Check against the minimum size given the number of stated params
|
|
// if too small we bail out.
|
|
param_count = call_params->GetParamsCount();
|
|
- min_declared_size =
|
|
- sizeof(CrossCallParams) + ((param_count + 1) * sizeof(ParamInfo));
|
|
+ min_declared_size = GetMinDeclaredActualCallParamsSize(param_count);
|
|
|
|
// Initial check for the buffer being big enough to determine the actual
|
|
// buffer size.
|
|
if (buffer_size < min_declared_size)
|
|
return nullptr;
|
|
|
|
// Retrieve the declared size which if it fails returns 0.
|
|
declared_size = GetActualBufferSize(param_count, buffer_base);
|
|
@@ -158,18 +187,17 @@ CrossCallParamsEx* CrossCallParamsEx::Cr
|
|
copied_params = reinterpret_cast<CrossCallParamsEx*>(backing_mem);
|
|
memcpy(backing_mem, call_params, declared_size);
|
|
|
|
// Avoid compiler optimizations across this point. Any value stored in
|
|
// memory should be stored for real, and values previously read from memory
|
|
// should be actually read.
|
|
std::atomic_thread_fence(std::memory_order_seq_cst);
|
|
|
|
- min_declared_size =
|
|
- sizeof(CrossCallParams) + ((param_count + 1) * sizeof(ParamInfo));
|
|
+ min_declared_size = GetMinDeclaredActualCallParamsSize(param_count);
|
|
|
|
// Check that the copied buffer is still valid.
|
|
if (copied_params->GetParamsCount() != param_count ||
|
|
GetActualBufferSize(param_count, backing_mem) != declared_size ||
|
|
!IsSizeWithinRange(buffer_size, min_declared_size, declared_size)) {
|
|
delete[] backing_mem;
|
|
return nullptr;
|
|
}
|