|
|
Created:
7 years, 11 months ago by nickolai.zeldovich Modified:
6 years, 4 months ago Reviewers:
willchan no longer on Chromium, halyavin, Mark Mentovai, darin (slow to review), brettw, jar (doing other things) CC:
chromium-reviews, erikwright+watch_chromium.org, DO NOT USE (jschuh), jln (very slow on Chromium) Base URL:
http://src.chromium.org/svn/trunk/src/ Visibility:
Public. |
DescriptionAvoid undefined behavior when checking for pointer wraparound due to
oversized pickled payload. Since pointer wraparound is undefined
behavior in C, the current code in Pickle::FindNext():
const char* payload_base = start + header_size;
const char* payload_end = payload_base + hdr->payload_size;
if (payload_end < payload_base)
return NULL;
which is equivalent to:
if (start + header_size + hdr->payload_size < start + header_size)
return NULL;
can be simplified by some compilers (e.g., clang) to something like:
if (header_size + hdr->payload_size < header_size)
return NULL;
For example, here's a simplified code snippet and the generated code,
which doesn't access the pointer argument at all:
nickolai@sahara:/tmp$ cat x.c
#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
void bar();
void
foo(const char* start, size_t header_size, uint32_t payload_size)
{
const char* payload_base = start + header_size;
const char* payload_end = payload_base + payload_size;
if (payload_end < payload_base)
bar();
}
nickolai@sahara:/tmp$ clang x.c -S -o - -O3 -m32
...
foo: # @foo
# BB#0:
movl 8(%esp), %eax
movl 12(%esp), %ecx
addl %eax, %ecx
cmpl %eax, %ecx
jge .LBB0_1
# BB#2:
jmp bar # TAILCALL
.LBB0_1:
ret
...
nickolai@sahara:/tmp$
Thus, on a 32-bit machine, this can lead to oversized pickle headers
bypassing this check and causing undetected pointer wraparound; the caller
may then be tricked into accessing memory outside of the pickle payload.
The patch replaces the check with one that avoids undefined behavior,
and fixes a similar problem in PickleIterator::GetReadPointerAndAdvance
pointed out by jar@chromium.org.
BUG=none
Patch Set 1 #Patch Set 2 : #
Total comments: 2
Patch Set 3 : #
Total comments: 2
Patch Set 4 : #Patch Set 5 : #Patch Set 6 : #Patch Set 7 : #Patch Set 8 : #
Created: 7 years, 1 month ago
Messages
Total messages: 30 (0 generated)
https://codereview.chromium.org/12079010/diff/2001/base/pickle.cc File base/pickle.cc (right): https://codereview.chromium.org/12079010/diff/2001/base/pickle.cc#newcode38 base/pickle.cc:38: if (read_ptr_ + sizeof(Type) > read_end_ptr_) Should this to be re-phrased: if (read_end_ptr_ - read_ptr_ < sizeof(Type)) https://codereview.chromium.org/12079010/diff/2001/base/pickle.cc#newcode356 base/pickle.cc:356: if (hdr->payload_size > (uintptr_t) (end - payload_base)) nit: Please use static_cast<...>(...) instead of C-style cast. Also, wouldn't size_t be enough, as we can expect this region was returned by an allocation?
On 2013/02/06 02:47:49, jar wrote: > https://codereview.chromium.org/12079010/diff/2001/base/pickle.cc > File base/pickle.cc (right): > > https://codereview.chromium.org/12079010/diff/2001/base/pickle.cc#newcode38 > base/pickle.cc:38: if (read_ptr_ + sizeof(Type) > read_end_ptr_) > Should this to be re-phrased: > > if (read_end_ptr_ - read_ptr_ < sizeof(Type)) I believe you're right, this check could also invoke undefined behavior. (Although I don't think current compilers will do anything damaging to this particular check.) There's another bug in this check: it checks whether there's room for sizeof(Type), but then sometimes advances the pointer by more than sizeof(Type) depending on alignment. I will try to upload a patch for both of these nits. > https://codereview.chromium.org/12079010/diff/2001/base/pickle.cc#newcode356 > base/pickle.cc:356: if (hdr->payload_size > (uintptr_t) (end - payload_base)) > nit: Please use static_cast<...>(...) instead of C-style cast. > > Also, wouldn't size_t be enough, as we can expect this region was returned by an > allocation? Yes, size_t should be enough. I will try to upload a new version of the patch to address both of these nits too.
Do you have the patch update? This seems worth finishing and landing. Thanks!!
On 2013/02/26 19:54:31, jar wrote: > Do you have the patch update? This seems worth finishing and landing. > > Thanks!! I'm not very familiar with the codereview.chromium.org interface, but I believe patch set 3 contains the updated patch.
Hi, Is there anything else you might be waiting for from me on this patch? I think I've uploaded the patch update. Nickolai. On Tue, Feb 26, 2013 at 2:54 PM, <jar@chromium.org> wrote: > Do you have the patch update? This seems worth finishing and landing. > > Thanks!! > > https://codereview.chromium.org/12079010/
I apologize... I missed the patch 2 that you pushed. Comments below. The patch is looking nicer still! thanks. If there is a good reason to use the shared functionality of AlignInt(...), you could remind me. (Side note: I was bothered that we currently have two implementations of the same static method AlignInt(...) in this file... but that is not your problem. They both have *identical* code, which annoys me to see). https://codereview.chromium.org/12079010/diff/4002/base/pickle.cc File base/pickle.cc (right): https://codereview.chromium.org/12079010/diff/4002/base/pickle.cc#newcode38 base/pickle.cc:38: size_t s; nit: style guide suggests avoiding single character names. Suggest: size_t type_size; https://codereview.chromium.org/12079010/diff/4002/base/pickle.cc#newcode40 base/pickle.cc:40: s = AlignInt(sizeof(Type), sizeof(uint32)); Am I correct in reading AlignInt(smaller, larger) as being equal to larger? So this is just: s = sizeof(uint32); IF so, we may as well write line 38: size_t = std::max(sizeof(Type), sizeof(uint32)); and toss lines 39-42. It would be much clearer. Am I missing anything?
On 2013/03/04 19:25:51, jar wrote: > (Side note: I was bothered that we currently have two implementations of the > same static method AlignInt(...) in this file... but that is not your problem. > They both have *identical* code, which annoys me to see). I agree, this seems unfortunate, although I don't know what would be the preferred way of fixing this in line with Chromium's code standards, and it seems to be a separate issue, as you mention. Thanks for the rest of the comments -- I agree with all of them, and I've integrated them into patch set 4 (which is now uploaded).
lgtm
On 2013/03/11 04:22:56, jar wrote: > lgtm Any updates on this?
lgtm My appologies... I approved it... but did not commit. I verified that you signed the electronic agreement on 2/5/13. This should land the change.
CQ is trying da patch. Follow status at https://chromium-status.appspot.com/cq/nickolai.zeldovich@gmail.com/12079010/...
Failed to apply patch for AUTHORS: While running patch -p0 --forward --force --no-backup-if-mismatch; patching file AUTHORS Hunk #1 FAILED at 219. 1 out of 1 hunk FAILED -- saving rejects to file AUTHORS.rej Patch: AUTHORS Index: AUTHORS =================================================================== --- AUTHORS (revision 178847) +++ AUTHORS (working copy) @@ -219,3 +219,4 @@ Trevor Perrin <unsafe@trevp.net> Ion Rosca <rosca@adobe.com> Sylvain Zimmer <sylvinus@gmail.com> +Nickolai Zeldovich <nickolai@csail.mit.edu>
On 2013/07/11 23:09:31, I haz the power (commit-bot) wrote: > Failed to apply patch for AUTHORS: > While running patch -p0 --forward --force --no-backup-if-mismatch; > patching file AUTHORS > Hunk #1 FAILED at 219. > 1 out of 1 hunk FAILED -- saving rejects to file AUTHORS.rej > > Patch: AUTHORS > Index: AUTHORS > =================================================================== > --- AUTHORS (revision 178847) > +++ AUTHORS (working copy) > @@ -219,3 +219,4 @@ > Trevor Perrin <mailto:unsafe@trevp.net> > Ion Rosca <mailto:rosca@adobe.com> > Sylvain Zimmer <mailto:sylvinus@gmail.com> > +Nickolai Zeldovich <mailto:nickolai@csail.mit.edu> Please just update your local copy of AUTHORS, and upload again... and then I'll submit. Thanks!
On 2013/07/12 00:26:55, jar wrote: > On 2013/07/11 23:09:31, I haz the power (commit-bot) wrote: > > Failed to apply patch for AUTHORS: > > While running patch -p0 --forward --force --no-backup-if-mismatch; > > patching file AUTHORS > > Hunk #1 FAILED at 219. > > 1 out of 1 hunk FAILED -- saving rejects to file AUTHORS.rej > > > > Patch: AUTHORS > > Index: AUTHORS > > =================================================================== > > --- AUTHORS (revision 178847) > > +++ AUTHORS (working copy) > > @@ -219,3 +219,4 @@ > > Trevor Perrin <mailto:unsafe@trevp.net> > > Ion Rosca <mailto:rosca@adobe.com> > > Sylvain Zimmer <mailto:sylvinus@gmail.com> > > +Nickolai Zeldovich <mailto:nickolai@csail.mit.edu> > > Please just update your local copy of AUTHORS, and upload again... and then I'll > submit. > > Thanks! I believe I've uploaded a new version. Thanks!
CQ is trying da patch. Follow status at https://chromium-status.appspot.com/cq/nickolai.zeldovich@gmail.com/12079010/...
Retried try job too often on chromium_presubmit for step(s) presubmit http://build.chromium.org/p/tryserver.chromium/buildstatus?builder=chromium_p...
CQ is trying da patch. Follow status at https://chromium-status.appspot.com/cq/nickolai.zeldovich@gmail.com/12079010/...
Retried try job too often on chromium_presubmit for step(s) presubmit http://build.chromium.org/p/tryserver.chromium/buildstatus?builder=chromium_p...
CQ is trying da patch. Follow status at https://chromium-status.appspot.com/cq/nickolai.zeldovich@gmail.com/12079010/...
Retried try job too often on chromium_presubmit for step(s) presubmit http://build.chromium.org/p/tryserver.chromium/buildstatus?builder=chromium_p...
CQ is trying da patch. Follow status at https://chromium-status.appspot.com/cq/nickolai.zeldovich@gmail.com/12079010/...
Retried try job too often on linux_aura for step(s) content_unittests http://build.chromium.org/p/tryserver.chromium/buildstatus?builder=linux_aura...
CQ is trying da patch. Follow status at https://chromium-status.appspot.com/cq/nickolai.zeldovich@gmail.com/12079010/...
Retried try job too often on mac_rel for step(s) browser_tests, content_unittests, net_unittests, unit_tests http://build.chromium.org/p/tryserver.chromium/buildstatus?builder=mac_rel&nu...
CQ is trying da patch. Follow status at https://chromium-status.appspot.com/cq/nickolai.zeldovich@gmail.com/12079010/...
Retried try job too often on win_rel for step(s) browser_tests http://build.chromium.org/p/tryserver.chromium/buildstatus?builder=win_rel&nu...
CQ is trying da patch. Follow status at https://chromium-status.appspot.com/cq/nickolai.zeldovich@gmail.com/12079010/...
Failed to apply patch for base/pickle.cc: While running patch -p0 --forward --force --no-backup-if-mismatch; patching file base/pickle.cc Hunk #2 FAILED at 291. 1 out of 2 hunks FAILED -- saving rejects to file base/pickle.cc.rej Patch: base/pickle.cc Index: base/pickle.cc =================================================================== --- base/pickle.cc (revision 232266) +++ base/pickle.cc (working copy) @@ -35,7 +35,7 @@ template<typename Type> inline const char* PickleIterator::GetReadPointerAndAdvance() { const char* current_read_ptr = read_ptr_; - if (read_ptr_ + sizeof(Type) > read_end_ptr_) + if (sizeof(Type) > static_cast<size_t>(read_end_ptr_ - read_ptr_)) return NULL; if (sizeof(Type) < sizeof(uint32)) read_ptr_ += AlignInt(sizeof(Type), sizeof(uint32)); @@ -291,11 +291,10 @@ const Header* hdr = reinterpret_cast<const Header*>(start); const char* payload_base = start + header_size; - const char* payload_end = payload_base + hdr->payload_size; - if (payload_end < payload_base) + if (hdr->payload_size > static_cast<size_t>(end - payload_base)) return NULL; - return (payload_end > end) ? NULL : payload_end; + return payload_base + hdr->payload_size; } template <size_t length> void Pickle::WriteBytesStatic(const void* data) {
I found the second bug independently and already committed the fix. This CL needs to be rebased. |