summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-12-20 12:00:35 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-01-05 09:47:49 +0000
commit6e4dc7836378c1ed20df9b8b63ddf3c09435e3d3 (patch)
treef3fba45851563ccb078c42cc196d0b89c88628f5
parent51bfe4452921803d0a7a145785b11832f321aa2a (diff)
downloadqtwebengine-chromium-6e4dc7836378c1ed20df9b8b63ddf3c09435e3d3.tar.gz
[Backport] Serialize struct tm in a safe way.
BUG=765512 Reviewed-on: https://chromium-review.googlesource.com/679441 (CVE-2017-15415) Change-Id: I1c73afb2030d088243788b9c1819d19c75e55bfb Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
-rw-r--r--chromium/content/browser/renderer_host/sandbox_ipc_linux.cc38
-rw-r--r--chromium/content/zygote/zygote_main_linux.cc75
2 files changed, 83 insertions, 30 deletions
diff --git a/chromium/content/browser/renderer_host/sandbox_ipc_linux.cc b/chromium/content/browser/renderer_host/sandbox_ipc_linux.cc
index f2afba83732..6df6a20e4bb 100644
--- a/chromium/content/browser/renderer_host/sandbox_ipc_linux.cc
+++ b/chromium/content/browser/renderer_host/sandbox_ipc_linux.cc
@@ -31,6 +31,24 @@
#include "ui/gfx/font_fallback_linux.h"
#include "ui/gfx/font_render_params.h"
+namespace {
+
+void WriteTimeStruct(base::Pickle* pickle, const struct tm* time) {
+ pickle->WriteInt(time->tm_sec);
+ pickle->WriteInt(time->tm_min);
+ pickle->WriteInt(time->tm_hour);
+ pickle->WriteInt(time->tm_mday);
+ pickle->WriteInt(time->tm_mon);
+ pickle->WriteInt(time->tm_year);
+ pickle->WriteInt(time->tm_wday);
+ pickle->WriteInt(time->tm_yday);
+ pickle->WriteInt(time->tm_isdst);
+ pickle->WriteInt(time->tm_gmtoff);
+ pickle->WriteString(time->tm_zone);
+}
+
+} // namespace
+
namespace content {
namespace {
@@ -317,7 +335,8 @@ void SandboxIPCHandler::HandleLocaltime(
int fd,
base::PickleIterator iter,
const std::vector<base::ScopedFD>& fds) {
- // The other side of this call is in zygote_main_linux.cc
+ // The other side of this call is in |ProxyLocaltimeCallToBrowser|, in
+ // zygote_main_linux.cc.
std::string time_string;
if (!iter.ReadString(&time_string) || time_string.size() != sizeof(time_t))
@@ -325,21 +344,18 @@ void SandboxIPCHandler::HandleLocaltime(
time_t time;
memcpy(&time, time_string.data(), sizeof(time));
- // We use localtime here because we need the tm_zone field to be filled
+ // We use |localtime| here because we need the |tm_zone| field to be filled
// out. Since we are a single-threaded process, this is safe.
const struct tm* expanded_time = localtime(&time);
- std::string result_string;
- const char* time_zone_string = "";
+ base::Pickle reply;
if (expanded_time) {
- result_string = std::string(reinterpret_cast<const char*>(expanded_time),
- sizeof(struct tm));
- time_zone_string = expanded_time->tm_zone;
+ WriteTimeStruct(&reply, expanded_time);
+ } else {
+ // The {} constructor ensures the struct is 0-initialized.
+ struct tm zeroed_time = {};
+ WriteTimeStruct(&reply, &zeroed_time);
}
-
- base::Pickle reply;
- reply.WriteString(result_string);
- reply.WriteString(time_zone_string);
SendRendererReply(fds, reply, -1);
}
diff --git a/chromium/content/zygote/zygote_main_linux.cc b/chromium/content/zygote/zygote_main_linux.cc
index 28115e4dab7..1569d42cddc 100644
--- a/chromium/content/zygote/zygote_main_linux.cc
+++ b/chromium/content/zygote/zygote_main_linux.cc
@@ -91,6 +91,59 @@ void RunTwoClosures(const base::Closure* first, const base::Closure* second) {
second->Run();
}
+bool ReadTimeStruct(base::PickleIterator* iter,
+ struct tm* output,
+ char* timezone_out,
+ size_t timezone_out_len) {
+ int result;
+ if (!iter->ReadInt(&result))
+ return false;
+ output->tm_sec = result;
+ if (!iter->ReadInt(&result))
+ return false;
+ output->tm_min = result;
+ if (!iter->ReadInt(&result))
+ return false;
+ output->tm_hour = result;
+ if (!iter->ReadInt(&result))
+ return false;
+ output->tm_mday = result;
+ if (!iter->ReadInt(&result))
+ return false;
+ output->tm_mon = result;
+ if (!iter->ReadInt(&result))
+ return false;
+ output->tm_year = result;
+ if (!iter->ReadInt(&result))
+ return false;
+ output->tm_wday = result;
+ if (!iter->ReadInt(&result))
+ return false;
+ output->tm_yday = result;
+ if (!iter->ReadInt(&result))
+ return false;
+ output->tm_isdst = result;
+ if (!iter->ReadInt(&result))
+ return false;
+ output->tm_gmtoff = result;
+
+ std::string timezone;
+ if (!iter->ReadString(&timezone))
+ return false;
+ if (timezone_out_len) {
+ const size_t copy_len = std::min(timezone_out_len - 1, timezone.size());
+ memcpy(timezone_out, timezone.data(), copy_len);
+ timezone_out[copy_len] = 0;
+ output->tm_zone = timezone_out;
+ } else {
+ base::AutoLock lock(g_timezones_lock.Get());
+ auto ret_pair = g_timezones.Get().insert(timezone);
+ output->tm_zone = ret_pair.first->c_str();
+ }
+
+ return true;
+}
+
} // namespace
// See https://chromium.googlesource.com/chromium/src/+/master/docs/linux_zygote.md
@@ -103,35 +156,19 @@ static void ProxyLocaltimeCallToBrowser(time_t input, struct tm* output,
request.WriteString(
std::string(reinterpret_cast<char*>(&input), sizeof(input)));
+ memset(output, 0, sizeof(struct tm));
+
uint8_t reply_buf[512];
const ssize_t r = base::UnixDomainSocket::SendRecvMsg(
GetSandboxFD(), reply_buf, sizeof(reply_buf), NULL, request);
if (r == -1) {
- memset(output, 0, sizeof(struct tm));
return;
}
base::Pickle reply(reinterpret_cast<char*>(reply_buf), r);
base::PickleIterator iter(reply);
- std::string result;
- std::string timezone;
- if (!iter.ReadString(&result) ||
- !iter.ReadString(&timezone) ||
- result.size() != sizeof(struct tm)) {
+ if (!ReadTimeStruct(&iter, output, timezone_out, timezone_out_len)) {
memset(output, 0, sizeof(struct tm));
- return;
- }
-
- memcpy(output, result.data(), sizeof(struct tm));
- if (timezone_out_len) {
- const size_t copy_len = std::min(timezone_out_len - 1, timezone.size());
- memcpy(timezone_out, timezone.data(), copy_len);
- timezone_out[copy_len] = 0;
- output->tm_zone = timezone_out;
- } else {
- base::AutoLock lock(g_timezones_lock.Get());
- auto ret_pair = g_timezones.Get().insert(timezone);
- output->tm_zone = ret_pair.first->c_str();
}
}