qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH] Permit zero-sized qemu_malloc() & friends


From: Markus Armbruster
Subject: Re: [Qemu-devel] [PATCH] Permit zero-sized qemu_malloc() & friends
Date: Mon, 07 Dec 2009 10:42:55 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux)

malc <address@hidden> writes:

> On Sun, 6 Dec 2009, Markus Armbruster wrote:
>
>> malc <address@hidden> writes:
>> 
>> > On Sun, 6 Dec 2009, Markus Armbruster wrote:
>> >
>> >> malc <address@hidden> writes:
>> >> 
>> >
>> > [..snip..]
>> >
>> >> 
>> >> read(fd, malloc(0), 0) is just fine, because read() doesn't touch the
>> >> buffer when the size is zero.
>> >> 
>> >
>> > [..snip..]
>> >
>> > Yet under linux the address is checked even for zero case.
>> 
>> Any value you can obtain from malloc() passes that check.
>> 
>> Why does the fact that you can construct pointers that don't pass this
>> check matter for our discussion of malloc()?
>> 
>> >> > I don't know what a "valid pointer" in this context represents.
>> >> 
>> >> I can talk standardese, if you prefer :)
>> >> 
>> >> malloc() either returns either a null pointer or a pointer to the
>> >> allocated space.  In either case, you must not dereference the pointer.
>> >> 
>> >> OpenBSD chooses to return a pointer to the allocated space.  It chooses
>> >> to catch common ways to dereference the pointer.
>> >> 
>> >> Your "p = (void *)-1" is neither a null pointer nor can it point to
>> >> allocated space on your particular system.  Hence, it cannot be a value
>> >> of malloc() for any argument, and therefore what read() does with it on
>> >> that particular system doesn't matter.
>> >> 
>> >
>> > Here, i believe, you are inventing artificial restrictions on how
>> > malloc behaves, i don't see anything that prevents the implementor
>> > from setting aside a range of addresses with 31st bit set as an
>> > indicator of "zero" allocations, and then happily giving it to the
>> > user of malloc and consumming it in free.
>> 
>> Misunderstanding?  Such behavior is indeed permissible, and I can't see
>> where I restricted it away.  An implementation that behaves as you
>> describe returns "pointer to allocated space".  That the pointer has
>> some funny bit set doesn't matter.  That it can't be dereferenced is
>> just fine.
>> 
>> I'm not sure what your point is.  If it is that malloc(0) can return a
>> value that cannot be passed to a zero-sized read(), then I fear you have
>> not made your point.
>
> One more attempt to make it clearer. If you agree that this behaviour
> is permissible then the game is lost as things stand now under Linux,
> since replacing [1]:
>
> void *p = (void *) -1 
> with:
> void *p = (void *) 0x80000000
>
> or anything else with said bit set will yield EFAULT. Consequently the
> code you cited as a well behaving malloc(0) call site will bomb.
>
> [1] Under 32bit Linux that is, with the usual split.

You can't just pull pointers out of your ear and expect stuff to work.

malloc() is free to return a pointer to allocated space that is set up
in a way that catches access beyond the allocated size.  OpenBSD does
that for size zero; it allocates one byte then, from pages that are used
only for zero-sized allocations, and takes care to disable access to
these pages with mprotect(..., PROT_NONE)[*].  Since read(..., 0) does
not access beyond the allocated size, it still works just fine.

If you replace glibc's malloc() to get OpenBSD-like behavior, you can't
just make up some pointer to a memory area you believe to be unused, you
have to do it right, like OpenBSD does.


[*] Check out omalloc_make_chunks() at
http://www.openbsd.org/cgi-bin/cvsweb/src/lib/libc/stdlib/malloc.c?rev=1.121;content-type=text%2Fplain




reply via email to

[Prev in Thread] Current Thread [Next in Thread]