diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-12-20 12:00:35 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-01-05 09:47:49 +0000 |
commit | 6e4dc7836378c1ed20df9b8b63ddf3c09435e3d3 (patch) | |
tree | f3fba45851563ccb078c42cc196d0b89c88628f5 | |
parent | 51bfe4452921803d0a7a145785b11832f321aa2a (diff) | |
download | qtwebengine-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.cc | 38 | ||||
-rw-r--r-- | chromium/content/zygote/zygote_main_linux.cc | 75 |
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(); } } |