|
From: Julian S. <js...@ac...> - 2005-11-16 12:50:28
|
I've been looking into problems with LinuxThreads on a ppc system running 2.4.20 and glibc-2.3.2. A strange thing happens. Everything works fine until V tries to deliver a signal -- #32 or #33, one of the ones used internally by LinuxThreads -- to a thread whose SP (r1) points into the bss segment. That I found strange enough -- normally LinuxThreads allocates thread stacks via mmap of 8M chunks. However, I suspect perhaps the signalled thread was the manager thread and perhaps it has a small fixed size stack in bss. (Doesn't sound completely implausible). So all this works fine, the signal handler runs, but when the handler returns there's a problem: it returns to a 2-insn trampoline in the stack (created by stack_mcontext in sigframe-ppc32-linux.c). And that stack is in the bss and so is marked non-executable, and V notices that, and refuses to run that code, declaring a segfault instead. Then it all goes to hell. If I remove that no-translate-if-non-executable check, then it works fine. So I am mystified: - can anyone familiar with LinuxThreads internals comment on whether my inferences about the manager thread stack are correct? - should we be creating a bss segment which is executable as well as r/w-able? J |
|
From: Julian S. <js...@ac...> - 2005-11-16 15:31:59
|
To follow up: > - should we be creating a bss segment which is executable as well as > r/w-able? In fact it's the data segment, which with the new aspacemgr was being given permissions rw-, whereas natively it's rwx. So that's an (easily fixable) bug. But it shows a nastier problem. We're trying to execute code in a segment marked without x permission (until said bug is fixed, at least). However, the code being run was is in a place which memcheck (correctly) regards as addressible and defined, so it doesn't complain; instead the program just appears to die with a (synthesised) segfault. What ought to happen, but doesn't, is that an error message should be emitted if either the tool or aspacem believes the (code) address in question is invalid. Problem is there's no way (core/tool iface fn) to tell the tool to notify the user of such an event. J |
|
From: Tom H. <to...@co...> - 2005-11-16 16:06:08
|
In message <200...@ac...>
Julian Seward <js...@ac...> wrote:
> To follow up:
>
>> - should we be creating a bss segment which is executable as well as
>> r/w-able?
>
> In fact it's the data segment, which with the new aspacemgr was being
> given permissions rw-, whereas natively it's rwx. So that's an
> (easily fixable) bug.
How is that happening then? mapelf in m_ume.c looks like it respects
the permissions given by the PT_LOAD entries in the PHdr.
Tom
--
Tom Hughes (to...@co...)
http://www.compton.nu/
|
|
From: Julian S. <js...@ac...> - 2005-11-16 16:16:03
|
> > In fact it's the data segment, which with the new aspacemgr was being > > given permissions rw-, whereas natively it's rwx. So that's an > > (easily fixable) bug. > > How is that happening then? mapelf in m_ume.c looks like it respects > the permissions given by the PT_LOAD entries in the PHdr. Um, perhaps I'm confusing myself. It's the segment that is set up by "setup_client_dataseg" in m_main.c. Which is the same segment that cat /proc/self/maps labels "[heap]" on recent kernels. Now I'm not sure I have the names right. J |
|
From: Tom H. <to...@co...> - 2005-11-16 16:25:51
|
In message <200...@ac...>
Julian Seward <js...@ac...> wrote:
>> > In fact it's the data segment, which with the new aspacemgr was being
>> > given permissions rw-, whereas natively it's rwx. So that's an
>> > (easily fixable) bug.
>>
>> How is that happening then? mapelf in m_ume.c looks like it respects
>> the permissions given by the PT_LOAD entries in the PHdr.
>
> Um, perhaps I'm confusing myself. It's the segment that is set up
> by "setup_client_dataseg" in m_main.c. Which is the same segment
> that cat /proc/self/maps labels "[heap]" on recent kernels. Now
> I'm not sure I have the names right.
Ah. I thought you meant the .data segment of an ELF image. You
meant the heap which is also sometimes called the data segment
in as much as RLIMIT_DATA applies to it ;-)
That would be my fault - you were originally mapping that with
execute permission and I changed it because x86 and amd64 don't
do so. Obviously ppc32 does...
Tom
--
Tom Hughes (to...@co...)
http://www.compton.nu/
|
|
From: Paul M. <pa...@sa...> - 2005-11-16 22:53:29
|
Julian Seward writes: > So all this works fine, the signal handler runs, but when the handler > returns there's a problem: it returns to a 2-insn trampoline in the > stack (created by stack_mcontext in sigframe-ppc32-linux.c). And that > stack is in the bss and so is marked non-executable, and V notices that, > and refuses to run that code, declaring a segfault instead. Then it > all goes to hell. I'm surprised you get that far, considering that the PLT is in the BSS and the PLT contains executable code trampolines. :) > - can anyone familiar with LinuxThreads internals comment on whether > my inferences about the manager thread stack are correct? Sounds reasonable. > - should we be creating a bss segment which is executable as well as > r/w-able? For ppc32, yes. Paul. |
|
From: Nicholas N. <nj...@cs...> - 2005-11-16 23:03:18
|
On Thu, 17 Nov 2005, Paul Mackerras wrote:
>> - should we be creating a bss segment which is executable as well as
>> r/w-able?
>
> For ppc32, yes.
In that case should we make this code:
/* We make the data segment (heap) executable because LinuxThreads on
ppc32 creates trampolines in this area. */
sres = VG_(am_mmap_anon_fixed_client)(
anon_start,
anon_size,
VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC
);
only set EXEC for ppc32, using a "#if defined(ppc32)"?
|
|
From: Tom H. <to...@co...> - 2005-11-17 12:25:33
|
In message <200...@ac...>
Julian Seward <js...@ac...> wrote:
>> In that case should we make this code:
>>
>> /* We make the data segment (heap) executable because LinuxThreads on
>> ppc32 creates trampolines in this area. */
>> sres = VG_(am_mmap_anon_fixed_client)(
>> anon_start,
>> anon_size,
>> VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC
>> );
>>
>> only set EXEC for ppc32, using a "#if defined(ppc32)"?
>
> Well, the thing is, I'm not sure why it didn't screw up LinuxThreads
> on x86 (I tried that too). It's kind-of hard to argue that ppc32 and
> x86 LinuxThreads have the stack of their manager thread in totally
> different places. I did notice that the order in which signals were
> delivered was different running the same ultra-trivial threaded test
> on both x86 and ppc32 running SuSE10 with LD_ASSUME_KERNEL=2.2.19.
Maybe LinuxThreads on x86 doesn't have the manager thread stack in
the heap or maybe nobody has tried it since I took away the exec
permission a few weeks ago.
Most x86 processors won't be policing exec properly anyway so you
still might get away with it.
> However .. the clinchers are that (1) even on x86, the data seg is
> rwx natively, at least according to cat /proc/self/maps, and (2)
> having a non-executable data seg would kill any program which tried
> to create code in the data seg and then run it. So I'd say it should
> be rwx on all platforms.
Like I said my x86 boxes don't have it executable, although that
can be open to variation due to x86 exec flag wierdness. My amd64
boxes certainly don't have it executable.
Killing programs that put executable code in the heap/stack is of
course exactly what operating systems are trying to do these days
in the name of security.
Tom
--
Tom Hughes (to...@co...)
http://www.compton.nu/
|
|
From: Nicholas N. <nj...@cs...> - 2005-11-17 19:21:31
|
On Thu, 17 Nov 2005, Tom Hughes wrote: >>> /* We make the data segment (heap) executable because LinuxThreads on >>> ppc32 creates trampolines in this area. */ >>> sres = VG_(am_mmap_anon_fixed_client)( >>> anon_start, >>> anon_size, >>> VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC >>> ); >>> >>> only set EXEC for ppc32, using a "#if defined(ppc32)"? > > Like I said my x86 boxes don't have it executable, although that > can be open to variation due to x86 exec flag wierdness. My amd64 > boxes certainly don't have it executable. > > Killing programs that put executable code in the heap/stack is of > course exactly what operating systems are trying to do these days > in the name of security. So should the code or the comment be changed? I don't have strong opinions because I'm no expert on this kind of stuff, but I want to get it right because this kind of minor detail can be crucial. Nick |
|
From: Julian S. <js...@ac...> - 2005-11-16 23:18:12
|
> In that case should we make this code: > > /* We make the data segment (heap) executable because LinuxThreads on > ppc32 creates trampolines in this area. */ > sres = VG_(am_mmap_anon_fixed_client)( > anon_start, > anon_size, > VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC > ); > > only set EXEC for ppc32, using a "#if defined(ppc32)"? Well, the thing is, I'm not sure why it didn't screw up LinuxThreads on x86 (I tried that too). It's kind-of hard to argue that ppc32 and x86 LinuxThreads have the stack of their manager thread in totally different places. I did notice that the order in which signals were delivered was different running the same ultra-trivial threaded test on both x86 and ppc32 running SuSE10 with LD_ASSUME_KERNEL=2.2.19. However .. the clinchers are that (1) even on x86, the data seg is rwx natively, at least according to cat /proc/self/maps, and (2) having a non-executable data seg would kill any program which tried to create code in the data seg and then run it. So I'd say it should be rwx on all platforms. J |
|
From: Paul M. <pa...@sa...> - 2005-11-17 02:51:00
|
Julian Seward writes: > However .. the clinchers are that (1) even on x86, the data seg is > rwx natively, at least according to cat /proc/self/maps, and (2) > having a non-executable data seg would kill any program which tried > to create code in the data seg and then run it. So I'd say it should > be rwx on all platforms. Forgive me if I missed something at the beginning of this discussion, but why can't Valgrind just use the permissions as set by the kernel and listed in /proc/self/maps? Paul. |
|
From: Tom H. <to...@co...> - 2005-11-17 12:22:21
|
In message <172...@ca...>
Paul Mackerras <pa...@sa...> wrote:
> Julian Seward writes:
>
>> However .. the clinchers are that (1) even on x86, the data seg is
>> rwx natively, at least according to cat /proc/self/maps, and (2)
>> having a non-executable data seg would kill any program which tried
>> to create code in the data seg and then run it. So I'd say it should
>> be rwx on all platforms.
>
> Forgive me if I missed something at the beginning of this discussion,
> but why can't Valgrind just use the permissions as set by the kernel
> and listed in /proc/self/maps?
Well it would be a bit of a pain to have to go wading through that
just to find out what permissions the original brk segment had. I'm
not even sure it will be there if you haven't called brk to allocate
some memory from it which valgrind probably won't have done.
Tom
--
Tom Hughes (to...@co...)
http://www.compton.nu/
|