|
From: Nicholas N. <nj...@cs...> - 2005-03-09 02:50:55
|
On Tue, 8 Mar 2005, Jeremy Fitzhardinge wrote:
>> ! at 0x........: creat (in /...libc...)
>> ! by 0x........: __libc_start_main (in /...libc...)
>> ! by 0x........: ...
>> --- 6,7 ----
>> ! at 0x........: open (in /...libc...)
>> ! by 0x........: main (fdleak_creat.c:18)
>>
>> ie. it looks like something has changed on my system so that libc's
>> creat() no calls open(). So probably not a problem.
>
> What's the context? I presume it ends up calling the same syscall? It
> doesn't look like anything more framepointer backtrace confusion.
strace tells me the program (run natively) calls the syscall open() rather
than creat(). Weird.
>> I'm not sure if this was a good thing to do -- IIRC I original put
>> that restriction in because some of the memory allocation functions
>> use 0 to represent failure, and so if a program did mmap(0x0, FIXED)
>> various problems could occur.
>
> Valgrind does a mmap(0, FIXED) as part of its address space padding; in
> general this is a legitimate but unusual operation. We could make it a
> clo which is off by default, but I'm not terribly keen on adding another
> special case clo. I guess a client request is another option (please
> let me mmap 0).
Neither of those are very appealing.
> What problems are you thinking of? Other problems occurring within
> Valgrind, or just that a program can get itself into a mess which we
> would detect too late?
The former. I think the issue was that it gets very confusing if you pass
0x0 as the 'addr' parameter to VG_(find_map_space)() -- because it
interprets that to mean "I don't care where you put it". Usually
VG_(find_map_space)() isn't called if you specify FIXED, but If you look
at the wrapper for mremap(), I think it will be an issue if you mremap()
some memory to address 0x0 with MREMAP_FIXED.
It's a type issue -- the problem comes from designating one particular
integer value as special, and then problems arise when you want to use
that value as a normal integer rather than the exceptional value.
VG_(find_map_space)() has inherited this problem from mmap() -- you can't
suggest to mmap(), without using MAP_FIXED, that you want the mapped
segment to go at 0x0.
The way to fix this is to add another Bool arg --
"use_address_as_suggestion" or something -- to VG_(find_map_space)(). If
it's true, we use the passed address as a suggestion (even if it's zero).
If it's false, we put the block anywhere.
Aside: malloc() suffers from a similar problem -- it can never put a heap
block at 0x0 because 0x0 means "no block allocated". Another consequence
of this idiom is that it's really easy to forget to check for the presence
of the exceptional value. That's why posix_memalign() returns a Bool, and
puts the address of the allocated block (if one was allocated) in the 2nd
argument pass-by-reference -- it doesn't steal the value, and it's much
harder to forget to check for failure. Unfortunately, NULL-as-failure is
so engrained in general C programmming that this problem will never go
away. In contrast, in languages like Haskell you have a "Maybe" type that
looks like this:
Maybe a = Just a | Nothing
where 'a' can be any type. The nice thing here is that you don't have to
steal one of your normal values to represent failure, and also it's
impossible to forget to check for the "Nothing" failure case.
>> Another problem... this program:
>>
>> int main(void)
>> {
>> read(0,0,1);
>> }
>>
>> behaves differently under Valgrind compared to native -- it doesn't
>> wait for user input.
>
> [...]
>
> Is this read(fd, 0, 1) example from a real program?
No, but it's my standard trick for forcing a program to pause at a
particular point -- usually to look at what /proc/self/maps looks like.
> Do you think this will cause a real problem? This case isn't
> particularly well defined, and I think older kernels would have failed
> it immediately. I don't like having variences from native behaviour,
> but I don't think this is too serious.
I'm not sure. I'm very uneasy about changing native behaviour. I'm
worried that in all the 250-odd syscalls there might be some cases that
are like this but occur in less contrived code.
N
|