Source code
Revision control
Copy as Markdown
Other Tools
# 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;
}