|
From: Dirk M. <dm...@gm...> - 2005-11-08 02:26:38
|
Hi,
it seems valgrind 3.1 cannot deal anymore with executable stack requirement.
testcase:
=== libtest.c ===
void foo()
{
__asm__("\n"
".section .note.GNU-stack,\"x\",@progbits\n"
".previous\n"
);
}
=== libtest.c ===
=== test.c ===
#include <stdio.h>
extern void foo();
int main()
{
foo();
printf("hello world\n");
return 0;
}
=== test.c ===
gcc -shared -o libtest.so libtest.c
gcc -o test test.c -L. -ltest
LD_LIBRARY_PATH=. valgrind --trace-syscalls=yes ./test
gives:
SYSCALL[671,1](125) sys_mprotect ( 0xBEE5C000, 4096, 16777223 )[sync] -->
Failure(0x16)
SYSCALL[671,1]( 6) sys_close ( 3 )[sync] --> Success(0x0)
SYSCALL[671,1](146) sys_writev ( 2, 0xBEE5C3B8, 10 ) --> [async] ...
./test: error while loading shared libraries: libtest.so: cannot enable
executable stack as shared object requires: Invalid argument
Any idea what could be wrong? looks like the actual mprotect fails with a very
weird way.
Dirk
|
|
From: Julian S. <js...@ac...> - 2005-11-08 02:43:02
|
> SYSCALL[671,1](125) sys_mprotect ( 0xBEE5C000, 4096, 16777223 )[sync] --> > Failure(0x16) > SYSCALL[671,1]( 6) sys_close ( 3 )[sync] --> Success(0x0) > SYSCALL[671,1](146) sys_writev ( 2, 0xBEE5C3B8, 10 ) --> [async] ... > ./test: error while loading shared libraries: libtest.so: cannot enable > executable stack as shared object requires: Invalid argument > > > Any idea what could be wrong? looks like the actual mprotect fails with a > very weird way. It could be that the mprotect was made to fail because the 16M area extended off the end of the stack into some place which V "owns". I'll look at it tomorrow. J |
|
From: Tom H. <to...@co...> - 2005-11-08 09:00:14
|
In message <200...@gm...>
Dirk Mueller <dm...@gm...> wrote:
> it seems valgrind 3.1 cannot deal anymore with executable stack requirement.
It seems to work find on my FC4 box with your test case.
> LD_LIBRARY_PATH=. valgrind --trace-syscalls=yes ./test
>
> gives:
>
> SYSCALL[671,1](125) sys_mprotect ( 0xBEE5C000, 4096, 16777223 )[sync] -->
> Failure(0x16)
> SYSCALL[671,1]( 6) sys_close ( 3 )[sync] --> Success(0x0)
> SYSCALL[671,1](146) sys_writev ( 2, 0xBEE5C3B8, 10 ) --> [async] ...
> ./test: error while loading shared libraries: libtest.so: cannot enable
> executable stack as shared object requires: Invalid argument
>
> Any idea what could be wrong? looks like the actual mprotect fails
> with a very weird way.
Well EINVAL just means there is no mapping at that address. As you
haven't posted the rest of the log we can't see if there was an early
map call that mapped that address.
Curiously I see the same failure on my box but then it carries on
instead of stopping:
SYSCALL[1462,1]( 10) sys_mprotect ( 0x7FEFFF000, 4096, 16777223 )[sync] --> Failure(0x16)
SYSCALL[1462,1]( 10) sys_mprotect ( 0x7FEFF8000, 32768, 7 )[sync] --> Failure(0xC)
SYSCALL[1462,1]( 10) sys_mprotect ( 0x7FEFFC000, 16384, 7 )[sync] --> Failure(0xC)
SYSCALL[1462,1]( 10) sys_mprotect ( 0x7FEFFE000, 8192, 7 )[sync] --> Success(0x0)
SYSCALL[1462,1]( 10) sys_mprotect ( 0x7FEFFC000, 8192, 7 )[sync] --> Failure(0xC)
SYSCALL[1462,1]( 10) sys_mprotect ( 0x7FEFFD000, 4096, 7 )[sync] --> Failure(0xC)
Actually those ENOMEM errors I am getting are far weirder... at least
they would be if you believed the mprotect manual page. Looking at the
kernel source it seems you sometimes get that if the mapping doesn't
exist though.
Actually it looks like you always get ENOMEM for that so the manual
page is complete nonsense.
The problem is that the first mprotect has PROT_GROWSDOWN set and that
causes mprotect to fail with EINVAL if the underlying VMA in the kernel
doesn't have VM_GROWSDOWN set. The normal system provided stack does
have that set, but our one doesn't and there is no way to set it from
user space as far as I know.
This isn't new in version 3 as far as I know - there are complaints
about it with older versions I think.
What PROT_GROWSDOWN does is to cause the kernel to round down the
start address given to that of the underlying VMA and apply the
protection specified to the whole area. In other words the stack
extension area also gets those permissions.
I believe that the valgrind address space manager copies the
permissions of the area being extended when extending into a
reservation so we can probably just clear PROT_GROWSUP/PROT_GROWSDOWN
when we are processing an extendable area.
Tom
--
Tom Hughes (to...@co...)
http://www.compton.nu/
|
|
From: Tom H. <to...@co...> - 2005-11-08 09:41:50
Attachments:
valgrind-grows.patch
|
In message <yek...@de...>
Tom Hughes <to...@co...> wrote:
> The problem is that the first mprotect has PROT_GROWSDOWN set and that
> causes mprotect to fail with EINVAL if the underlying VMA in the kernel
> doesn't have VM_GROWSDOWN set. The normal system provided stack does
> have that set, but our one doesn't and there is no way to set it from
> user space as far as I know.
>
> This isn't new in version 3 as far as I know - there are complaints
> about it with older versions I think.
>
> What PROT_GROWSDOWN does is to cause the kernel to round down the
> start address given to that of the underlying VMA and apply the
> protection specified to the whole area. In other words the stack
> extension area also gets those permissions.
The critical files to understand all this are mm/mprotect.c in the
kernel and sysdeps/unix/sysv/linux/dl-execstack.c in glibc.
The kernel provides PROT_GROWSDOWN and PROT_GROWSUP which round the
start/end address of mprotect to the start/end of the underlying vma
and glibc uses that as an easy way to change the protection of the
stack by calling mprotect on the last page of the stack with
PROT_GROWSDOWN set.
The sanity check provided by the kernel is that the vma must have
the VM_GROWSDOWN/VM_GROWSUP flag set as appropriate.
If that mprotect fails with EINVAL then glibc falls back to doing a
binary search to try and work out the size of the stack and change
it's protection. Obviously your glibc is not doing that for some
reason - I have glibc 2.3.5 if that helps.
> I believe that the valgrind address space manager copies the
> permissions of the area being extended when extending into a
> reservation so we can probably just clear PROT_GROWSUP/PROT_GROWSDOWN
> when we are processing an extendable area.
It's a bit more complicated than that - we need to check that we
are working on an area with an appropriate reservation next to
it - much like the kernel checks for VM_GROWSDOWN - and then move
the start address and length as appropriate and clear the flag.
The attached patch seems to work for me - if it works for you as
well then I guess we can go with it.
Tom
--
Tom Hughes (to...@co...)
http://www.compton.nu/
|
|
From: Dirk M. <dm...@gm...> - 2005-11-08 14:43:49
|
On Tuesday 08 November 2005 10:41, Tom Hughes wrote:
> The critical files to understand all this are mm/mprotect.c in the
> kernel and sysdeps/unix/sysv/linux/dl-execstack.c in glibc.
I'm looking at both for a while already :)
> If that mprotect fails with EINVAL then glibc falls back to doing a
> binary search
Thats what the Redhat glibc might do, yes. The plan FSF glibc 2.3.6 doesn't do
that:
/* Newer Linux kernels support a flag to make our job easy. */
#if defined PROT_GROWSDOWN || defined PROT_GROWSUP
# if __ASSUME_PROT_GROWSUPDOWN == 0
static bool no_growsupdown;
if (! no_growsupdown)
# endif
{
if (__builtin_expect (__mprotect ((void *) page, GLRO(dl_pagesize),
__stack_prot) == 0, 1))
goto return_success;
# if __ASSUME_PROT_GROWSUPDOWN == 0
if (errno == EINVAL)
no_growsupdown = true;
else
# endif
{
result = errno;
goto out;
}
}
#endif
where __ASSUME_PROT_GROWSUPDOWN is defined to 1 by default:
* The PROT_GROWSDOWN/PROT_GROWSUP flags were introduced in the 2.6.0-test
series. */
#if __LINUX_KERNEL_VERSION >= 132609
# define __ASSUME_PROT_GROWSUPDOWN 1
#endif
This means that by default an unpatched glibc doesn't do the binary search you
described.
> reason - I have glibc 2.3.5 if that helps.
using glibc 2.3.6 here.
> The attached patch seems to work for me - if it works for you as
> well then I guess we can go with it.
it crashes:
./test: error while loading shared libraries: libtest.so: cannot enable
executable stack as shared object requires: Invalid argument
==27757== Jump to the invalid address stated on the next line
==27757== at 0x46E: ???
==27757== by 0x400AD47: _dl_signal_error (in /lib/ld-2.3.5.so)
==27757== by 0x400A4AC: _dl_map_object_deps (in /lib/ld-2.3.5.so)
==27757== by 0x4001FAD: dl_main (in /lib/ld-2.3.5.so)
==27757== by 0x400E40E: _dl_sysdep_start (in /lib/ld-2.3.5.so)
==27757== by 0x4003731: _dl_start (in /lib/ld-2.3.5.so)
==27757== by 0x40007B6: (within /lib/ld-2.3.5.so)
==27757== Address 0x46E is not stack'd, malloc'd or (recently) free'd
==27757==
==27757== Process terminating with default action of signal 11 (SIGSEGV):
dumping core
==27757== Bad permissions for mapped region at address 0x46E
==27757== at 0x46E: ???
I'll try finding out what goes wrong.
Dirk
|
|
From: Tom H. <to...@co...> - 2005-11-08 15:35:58
|
In message <200...@gm...>
Dirk Mueller <dm...@gm...> wrote:
> On Tuesday 08 November 2005 10:41, Tom Hughes wrote:
>
>> The critical files to understand all this are mm/mprotect.c in the
>> kernel and sysdeps/unix/sysv/linux/dl-execstack.c in glibc.
>
> I'm looking at both for a while already :)
>
>> If that mprotect fails with EINVAL then glibc falls back to doing a
>> binary search
>
> Thats what the Redhat glibc might do, yes. The plan FSF glibc 2.3.6
> doesn't do that:
I was looking at the plain FSF one actually, but I had missed the
fact that you could configure it to assume PROT_GROWSDOWN support.
Obviously RedHat have no done so.
>> The attached patch seems to work for me - if it works for you as
>> well then I guess we can go with it.
>
> it crashes:
> ./test: error while loading shared libraries: libtest.so: cannot enable
> executable stack as shared object requires: Invalid argument
> ==27757== Jump to the invalid address stated on the next line
> ==27757== at 0x46E: ???
> ==27757== by 0x400AD47: _dl_signal_error (in /lib/ld-2.3.5.so)
> ==27757== by 0x400A4AC: _dl_map_object_deps (in /lib/ld-2.3.5.so)
> ==27757== by 0x4001FAD: dl_main (in /lib/ld-2.3.5.so)
> ==27757== by 0x400E40E: _dl_sysdep_start (in /lib/ld-2.3.5.so)
> ==27757== by 0x4003731: _dl_start (in /lib/ld-2.3.5.so)
> ==27757== by 0x40007B6: (within /lib/ld-2.3.5.so)
> ==27757== Address 0x46E is not stack'd, malloc'd or (recently) free'd
> ==27757==
> ==27757== Process terminating with default action of signal 11 (SIGSEGV):
> dumping core
> ==27757== Bad permissions for mapped region at address 0x46E
> ==27757== at 0x46E: ???
Hmm. It worked for me (and suppressed the binary search for the
stack judging by the syscall trace).
Tom
--
Tom Hughes (to...@co...)
http://www.compton.nu/
|
|
From: Dirk M. <dm...@gm...> - 2005-11-08 15:40:27
|
On Tuesday 08 November 2005 15:20, Dirk Mueller wrote: > I'll try finding out what goes wrong. forget my previous mail, your patch works great. please commit. Julian, permission to backport this to 3.0 branch? Thanks, Dirk |
|
From: Tom H. <to...@co...> - 2005-11-08 15:54:47
|
In message <200...@gm...>
Dirk Mueller <dm...@gm...> wrote:
> On Tuesday 08 November 2005 15:20, Dirk Mueller wrote:
>
>> I'll try finding out what goes wrong.
>
> forget my previous mail, your patch works great. please commit. Julian,
> permission to backport this to 3.0 branch?
I think a backport will be hard as it is intimately tied to the
address space manager.
Tom
--
Tom Hughes (to...@co...)
http://www.compton.nu/
|
|
From: Julian S. <js...@ac...> - 2005-11-08 16:02:06
|
> Julian, > permission to backport this to 3.0 branch? Sure, although 3.1 will be available in < 2 weeks hopefully. J |
|
From: Dirk M. <dm...@gm...> - 2005-11-08 16:59:00
|
On Tuesday 08 November 2005 17:06, Julian Seward wrote: > Sure, although 3.1 will be available in < 2 weeks hopefully. As long as there is no callgrind working for 3.1 I can't update. Dirk |
|
From: Julian S. <js...@ac...> - 2005-11-08 15:34:06
|
Dirk, I can't reproduce this on a standard SuSE 10 install on PIII. What setup are you using? Is it an NX-enabled cpu? J |
|
From: Dirk M. <dm...@gm...> - 2005-11-08 15:52:55
|
On Tuesday 08 November 2005 16:38, Julian Seward wrote: > Dirk, I can't reproduce this on a standard SuSE 10 install on PIII. > What setup are you using? Its kinda self-made ;) Basically a recent snapshot of upcoming 10.1 with NX patches. Dirk |
|
From: Julian S. <js...@ac...> - 2005-11-09 14:57:06
|
On Tuesday 08 November 2005 15:40, Dirk Mueller wrote:
> On Tuesday 08 November 2005 15:20, Dirk Mueller wrote:
> > I'll try finding out what goes wrong.
>
> forget my previous mail, your patch works great. please commit. Julian,
> permission to backport this to 3.0 branch?
One minor question: now that it handles VKI_PROT_GROWS{UP,DOWN}, does
that mean this wrapper moves from the generic category to Linux-specific?
J
|
|
From: Tom H. <to...@co...> - 2005-11-09 15:28:15
|
In message <200...@ac...>
Julian Seward <js...@ac...> wrote:
> On Tuesday 08 November 2005 15:40, Dirk Mueller wrote:
>> On Tuesday 08 November 2005 15:20, Dirk Mueller wrote:
>> > I'll try finding out what goes wrong.
>>
>> forget my previous mail, your patch works great. please commit. Julian,
>> permission to backport this to 3.0 branch?
>
> One minor question: now that it handles VKI_PROT_GROWS{UP,DOWN}, does
> that mean this wrapper moves from the generic category to Linux-specific?
I suspect so, yes.
Tom
--
Tom Hughes (to...@co...)
http://www.compton.nu/
|