Closed
Bug 867530
Opened 12 years ago
Closed 12 years ago
Move the nsPresArena poisoning code to MFBT
Categories
(Core :: MFBT, enhancement)
Core
MFBT
Tracking
()
RESOLVED
FIXED
mozilla23
People
(Reporter: MatsPalmgren_bugz, Assigned: MatsPalmgren_bugz)
References
Details
(Keywords: sec-want)
Attachments
(4 files, 1 obsolete file)
3.01 KB,
patch
|
benjamin
:
review+
|
Details | Diff | Splinter Review |
2.91 KB,
patch
|
roc
:
review+
|
Details | Diff | Splinter Review |
1.12 KB,
patch
|
roc
:
review+
|
Details | Diff | Splinter Review |
20.58 KB,
patch
|
roc
:
review+
|
Details | Diff | Splinter Review |
This is good stuff that should be generally available to all code.
MFBT seems like a good home.
Assignee | ||
Comment 1•12 years ago
|
||
Attachment #744060 -
Flags: review?(roc)
Assignee | ||
Comment 2•12 years ago
|
||
Attachment #744061 -
Flags: review?(benjamin)
Assignee | ||
Comment 3•12 years ago
|
||
Attachment #744062 -
Flags: review?(roc)
Attachment #744060 -
Flags: review?(roc) → review+
Comment 4•12 years ago
|
||
Comment on attachment 744060 [details] [diff] [review]
Move the code
Review of attachment 744060 [details] [diff] [review]:
-----------------------------------------------------------------
::: layout/base/nsPresArena.cpp
@@ +110,5 @@
>
> char* p = reinterpret_cast<char*>(aPtr);
> char* limit = p + list->mEntrySize;
> for (; p < limit; p += sizeof(uintptr_t)) {
> + *reinterpret_cast<uintptr_t*>(p) = mozPoisonValue();
Can you call into mfbt here?
::: mfbt/Poison.h
@@ +15,5 @@
> +#include "mozilla/Assertions.h"
> +#include "mozilla/StandardInteger.h"
> +#include "mozilla/Types.h"
> +
> +#ifdef __cplusplus
Do we use this from C?
@@ +32,5 @@
> +
> +/**
> + * Overwrite the memory block of aSize bytes at aPtr with the poison value.
> + * aPtr MUST be aligned at a sizeof(uintptr_t) boundary.
> + * Only an even number of sizeof(uintptr_t) bytes are overwritten, the last
I don't see the "event number" behaviour in the code.
@@ +37,5 @@
> + * few bytes (if any) is not overwritten.
> + */
> +inline void mozWritePoison(void* aPtr, size_t aSize)
> +{
> + MOZ_ASSERT((uintptr_t)aPtr % sizeof(uintptr_t) == 0, "bad alignment");
reinterpret_cast (three times)
Attachment #744060 -
Flags: review+ → review?(roc)
Attachment #744062 -
Flags: review?(roc) → review+
Assignee | ||
Comment 5•12 years ago
|
||
(In reply to :Ms2ger from comment #4)
> > for (; p < limit; p += sizeof(uintptr_t)) {
> > + *reinterpret_cast<uintptr_t*>(p) = mozPoisonValue();
>
> Can you call into mfbt here?
Sure, I will replace that loop with a mozWritePoison call, thanks!
> Do we use this from C?
I intentionally made the API C compatible since I think poisoning can be
useful in C code too.
> > + * Overwrite the memory block of aSize bytes at aPtr with the poison value.
> > + * aPtr MUST be aligned at a sizeof(uintptr_t) boundary.
> > + * Only an even number of sizeof(uintptr_t) bytes are overwritten, the last
>
> I don't see the "event number" behaviour in the code.
char* p = (char*)aPtr;
char* limit = p + aSize;
for (; p < limit; p += sizeof(uintptr_t)) {
*((uintptr_t*)p) = POISON;
}
p+=sizeof(uintptr_t) will stop the iteration *before* limit is reached
in case it's not an even number of words, i.e. the last few bytes of the
last word is not poisoned. This is how the original code did it, I guess
for efficiency and since poisoning the last uneven bytes doesn't improve
security much.
> > + MOZ_ASSERT((uintptr_t)aPtr % sizeof(uintptr_t) == 0, "bad alignment");
>
> reinterpret_cast (three times)
Does C have reinterpret_cast?
Assignee | ||
Comment 6•12 years ago
|
||
(I'll fold this with the last patch above before landing.)
Attachment #744071 -
Flags: review?(roc)
Attachment #744071 -
Flags: review?(roc) → review+
Comment 7•12 years ago
|
||
Can we make this self-initializing? In particular we will want to use this from the allocator (see bug 860254). I don't expect that a branch in mozPoisonValue would be noticeable.
Flags: needinfo?(matspal)
Updated•12 years ago
|
Whiteboard: [call-jenny-for-a-good-time][great-bug-numbers]
Assignee | ||
Comment 8•12 years ago
|
||
(In reply to Benjamin Smedberg [:bsmedberg] from comment #7)
> Can we make this self-initializing?
Wouldn't that require some kind of lock to be thread-safe?
Flags: needinfo?(matspal)
Comment 9•12 years ago
|
||
It should require a lock only in the slow case, but you'd need to statically allocate the lock (jemalloc does this).
Updated•12 years ago
|
Whiteboard: [call-jenny-for-a-good-time][great-bug-numbers]
Comment 10•12 years ago
|
||
Comment on attachment 744061 [details] [diff] [review]
Initialize it from xpcom
This is ok given the current usage, but if we can lazy-init I'd really prefer that.
Attachment #744061 -
Flags: review?(benjamin) → review+
Comment 11•12 years ago
|
||
(In reply to Mats Palmgren [:mats] from comment #5)
> char* p = (char*)aPtr;
> char* limit = p + aSize;
> for (; p < limit; p += sizeof(uintptr_t)) {
> *((uintptr_t*)p) = POISON;
> }
>
> p+=sizeof(uintptr_t) will stop the iteration *before* limit is reached
> in case it's not an even number of words, i.e. the last few bytes of the
> last word is not poisoned. This is how the original code did it, I guess
> for efficiency and since poisoning the last uneven bytes doesn't improve
> security much.
This looks funny. Suppose p is 0x100, aSize is 5. Then limit is 0x105, so the first time around the condition passes, and sizeof(uintpt_t) bytes starting at |p| get overwritten. On 64-bit doesn't that overwrite 0x105, 0x106, and 0x107, beyond the specified size? Or am I missing something totally obvious beyond the limited context/documentation here?
mfbt generally prefers things be C++. Here, using C++ gives various good behaviors like being able to take advantage of type-parametric methods, to eliminate sizeof multiplications that can easily be gotten wrong. If no user requires C here, I'd rather see this as C++ from get-go. If someone wants to use this from C, and we can't get them converted to C++, we can add a C API at that point to wrap the C++ API.
Comment 12•12 years ago
|
||
Comment on attachment 744060 [details] [diff] [review]
Move the code
Review of attachment 744060 [details] [diff] [review]:
-----------------------------------------------------------------
::: mfbt/Poison.h
@@ +17,5 @@
> +#include "mozilla/Types.h"
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
MOZ_BEGIN_EXTERN_C
@@ +59,5 @@
> +extern MFBT_DATA uintptr_t gMozillaPoisonSize;
> +
> +#ifdef __cplusplus
> +} /*extern "C" */
> +#endif
MOZ_END_EXTERN_C
Assignee | ||
Comment 13•12 years ago
|
||
(In reply to Jeff Walden [:Waldo] (remove +bmo to email) from comment #11)
> This looks funny. Suppose p is 0x100, aSize is 5. Then limit is 0x105, so
> the first time around the condition passes, and sizeof(uintpt_t) bytes
> starting at |p| get overwritten. On 64-bit doesn't that overwrite 0x105,
> 0x106, and 0x107, beyond the specified size?
There's no point in poisoning an object that is smaller than a pointer.
There's an assertion that covers it:
MOZ_ASSERT(aSize >= sizeof(uintptr_t), "poisoning this object has no effect");
> If no user requires C here
It appears there is, bug 860254, and of course various arena allocators like
nsPresArena which has a void* and a length rather than some typed object.
Assignee | ||
Comment 14•12 years ago
|
||
(In reply to Mike Hommey [:glandium] from comment #12)
> MOZ_BEGIN_EXTERN_C
> MOZ_END_EXTERN_C
Fixed.
Attachment #744060 -
Attachment is obsolete: true
Attachment #744060 -
Flags: review?(roc)
Attachment #746120 -
Flags: review?(roc)
Attachment #746120 -
Flags: review?(roc) → review+
Assignee | ||
Comment 15•12 years ago
|
||
https://hg.mozilla.org/integration/mozilla-inbound/rev/35deab019135
https://hg.mozilla.org/integration/mozilla-inbound/rev/69c5ebd945de
https://hg.mozilla.org/integration/mozilla-inbound/rev/b8e1d4abf560
Flags: in-testsuite-
Comment 16•12 years ago
|
||
https://hg.mozilla.org/mozilla-central/rev/35deab019135
https://hg.mozilla.org/mozilla-central/rev/69c5ebd945de
https://hg.mozilla.org/mozilla-central/rev/b8e1d4abf560
Status: NEW → RESOLVED
Closed: 12 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla23
You need to log in
before you can comment on or make changes to this bug.
Description
•