Re: libc malloc poison

2013-07-05 Thread Henri Kemppainen
> On Thu, Jul 04, 2013 at 05:24:20PM +0200, Mark Kettenis wrote:
> > > From: Theo de Raadt 
> > > Date: Thu, 04 Jul 2013 09:04:54 -0600
> > > 
> > > I suspect the best approach would be a hybrid value.  The upper half
> > > of the address should try to land in an unmapped zone, or into the zero
> > > page, or into some address space hole, ir into super high memory above
> > > the stack which is gauranteed unmapped.
> > 
> > Don't forget strict alignment architectures, where it is beneficial
> > to have the lowest bit set to trigger alignment traps.
>
> You also want the highest bit set. This makes sure signed indexes get
> interpreted as negative, which should more often detect problems than
> positive ones. There are not only pointers in the heap. 

A while ago someone hit a bug in my code that I hadn't (and wouldn't ever
have) triggered with MALLOC_OPTIONS=S because the Duh pattern always sets
the high bit, giving a negative integer which just so happened to be
harmless.  Back then I wished malloc would've used all random bits instead.

If you test run your code more than a couple times (as one obviously should,
before going into release), then I'd say randomness (which will likely
soon produce a bug-trigger value) is better than a fixed pattern that attempts
to be useful in some (common?) scenarios but will reliably fail to make a
difference in other cases.

I do see the value in having the option to use fixed patterns though, so
perhaps the hybrid value with a configurable mask as Theo proposed is a
good idea.



Re: libc malloc poison

2013-07-04 Thread Otto Moerbeek
On Thu, Jul 04, 2013 at 05:24:20PM +0200, Mark Kettenis wrote:

> > From: Theo de Raadt 
> > Date: Thu, 04 Jul 2013 09:04:54 -0600
> > 
> > I suspect the best approach would be a hybrid value.  The upper half
> > of the address should try to land in an unmapped zone, or into the zero
> > page, or into some address space hole, ir into super high memory above
> > the stack which is gauranteed unmapped.
> 
> Don't forget strict alignment architectures, where it is beneficial
> to have the lowest bit set to trigger alignment traps.

You also want the highest bit set. This makes sure signed indexes get
interpreted as negative, which should more often detect problems than
positive ones. There are not only pointers in the heap. 

I very much prefer the values te be easily recognizable in a debugger
and to keep a clear distinction between "uninitialized" and "freed"
chunks.  Too much random is not good thing in this case. I picked 0xdf
a few years ago to mark free'd memory. The f is supposed to help you
remember that when you see it in a debugger. 

Maybe put a fixed pattern in the low nibbles and a random in the high
nibble. Together with the lowest and highest bit set this would go
like:

0x8e0d0e0f || 0xr0r0r0r0

(pick another lhs for free'ed mem)

Wondering if that would produce easily recognizable patterns that
still trigger enough faults.

-Otto




Re: libc malloc poison

2013-07-04 Thread Theo de Raadt
> > From: Theo de Raadt 
> > Date: Thu, 04 Jul 2013 09:04:54 -0600
> > 
> > I suspect the best approach would be a hybrid value.  The upper half
> > of the address should try to land in an unmapped zone, or into the zero
> > page, or into some address space hole, ir into super high memory above
> > the stack which is gauranteed unmapped.
> 
> Don't forget strict alignment architectures, where it is beneficial
> to have the lowest bit set to trigger alignment traps.

That's why I vaguely mentioned the idea of a sysctl or MD defines, which
would declare a fixed component, plus a mask on top of random.

That fixed component need not just be high bits, it can also cover the
lowest bit (or two) for instance.



Re: libc malloc poison

2013-07-04 Thread Mark Kettenis
> From: Theo de Raadt 
> Date: Thu, 04 Jul 2013 09:04:54 -0600
> 
> I suspect the best approach would be a hybrid value.  The upper half
> of the address should try to land in an unmapped zone, or into the zero
> page, or into some address space hole, ir into super high memory above
> the stack which is gauranteed unmapped.

Don't forget strict alignment architectures, where it is beneficial
to have the lowest bit set to trigger alignment traps.



Re: libc malloc poison

2013-07-04 Thread Theo de Raadt
> On Wed, Jul 03, 2013 at 17:21, Theo de Raadt wrote:
> >> +   int pval = 0xd0d0caca;
> > 
> > Can you explain the choice of this?
>> 
> I thought it sounded clever.

Ok, because there's more to the picture.

Inside the kernel, we tend to use 0xdeadbeef, or the DEADBEEF0/DEADBEEF1 values.

Reason for the latter is that we can try to put this value into memory
which the kernel does not manage.  Basically on half of our kernel
architectures if that is loaded into a pointer, it will hit unmanaged
kernel memory, exposing the bug.

Furthermore, the idea is that the 0xdeadbeef value should have a high
mix of set bits versus clear bits, for when it lands in a flag
variable.  A lot of bits are set; some paper I read years ago
discussed that on average "flag bits set" tends to traverse.

Furthermore, each of the sub-fields tend to be odd, which in other
use after cases regarding offsets/indexes can lead to more unaligned
access, once again triggering and exposing a bug.

Those are all theoretical ideas to try to expose the bugs as early
as possible.

I think the use of 0xd0d0caca in userland might not be the most
suitable choice, especially in a MI fashion.

> > There are arguments to make this MI; other arguments to make it MD;
> > and other arguments to introduce a bit of randomness.
> > 
> > I'd like to know which arguments you have
> 
> Since libc doesn't do free list integrity checking, I'm currently
> leaning towards a random value. (even with random, we could still
> check that all words of a free chunk are the same.)
> 
> Somebody also noticed that we don't have separate values for allocated
> and freed memory. I suppose this makes debugging harder since you
> can't obviously identify freed memory? I lean towards prioritizing
> finding more bugs, which implies we need more variability, since any
> one value may allow a program to work where a different value would
> not.

I agree with this last sentence.

I suspect the best approach would be a hybrid value.  The upper half
of the address should try to land in an unmapped zone, or into the zero
page, or into some address space hole, ir into super high memory above
the stack which is gauranteed unmapped.

The 64-bit machines require a bit more consideration as well; we want
two 32-bit values to combine into a nice trashy address.

Should we use a kernel sysctl to "recommend" the high word?, and a mask
against random?  Of course, that could also be done using MD includes.

 



Re: libc malloc poison

2013-07-03 Thread Ted Unangst
On Wed, Jul 03, 2013 at 17:21, Theo de Raadt wrote:
>> +   int pval = 0xd0d0caca;
> 
> Can you explain the choice of this?

I thought it sounded clever.

> There are arguments to make this MI; other arguments to make it MD;
> and other arguments to introduce a bit of randomness.
> 
> I'd like to know which arguments you have

Since libc doesn't do free list integrity checking, I'm currently
leaning towards a random value. (even with random, we could still
check that all words of a free chunk are the same.)

Somebody also noticed that we don't have separate values for allocated
and freed memory. I suppose this makes debugging harder since you
can't obviously identify freed memory? I lean towards prioritizing
finding more bugs, which implies we need more variability, since any
one value may allow a program to work where a different value would
not.



Re: libc malloc poison

2013-07-03 Thread Theo de Raadt
> +   int pval = 0xd0d0caca;

Can you explain the choice of this?

There are arguments to make this MI; other arguments to make it MD;
and other arguments to introduce a bit of randomness.

I'd like to know which arguments you have