On 10/17/10 10:01, Ali Bahrami wrote:
I've had the same thought about having ld always generate a PT_SUNWSTACK, and even sent some internal email yesterday proposing it to my fellow linker alien. It's actually simpler than what we do now, since we'd just remove the code that checks the header flags against the ABI defaults before issuing the header. It seems reasonable to me, and we'll see what others think.
I had a few minutes today to try an experiment, and I'm afraid the idea of having ld always generate a PT_SUNWSTACK is a non-starter. The problem is that it overrides the behavior of 'set noexec_user_stack=1' in /etc/system, and can therefore quietly allow programs that would not previously been able to execute on the stack do so. I used the following test program to play with this. ------------------------------------------------------------------ #include <stdio.h> #include <strings.h> /* Code bytes for static void f(void) { } obtained by compiling with 'cc -Kpic', and using dis to disassemble. f: 55 pushl %ebp f+0x1: 8b ec movl %esp,%ebp f+0x3: 83 ec 04 subl $0x4,%esp f+0x6: 89 5d fc movl %ebx,-0x4(%ebp) f+0x9: 8b 5d fc movl -0x4(%ebp),%ebx f+0xc: c9 leave f+0xd: c3 ret 0x80509ee: 90 nop 0x80509ef: 90 nop */ unsigned char fbuf[] = { 0x55, 0x8b, 0xec, 0x83, 0xec, 0x04, 0x89, 0x5d, 0xfc, 0x8b, 0x5d, 0xfc, 0xc9, 0xc3, 0x90, 0x90 }; int main(int argc, char **argv) { double buf[(sizeof(fbuf) + 7) / 8]; void (* fp)(void); bcopy((void *) fbuf, buf, sizeof(fbuf)); fp = (void *) buf; (*fp)(); printf("DONE\n"); return (0); } ------------------------------------------------------------------ I then put the following in /etc/system on my X86 system, and rebooted: set noexec_user_stack=1 set noexec_user_stack_log=1 On my system: % cc main.c "main.c", line 44: warning: assignment type mismatch: pointer to function(void) returning void "=" pointer to void % ./a.out Segmentation Fault (core dumped) This is what you'd expect: The a.out, and the IA32 ABI allow an executable stack, but the kernel denies it due to noexec_user_stack. Running the same executable on a system without the /etc/system setting, it works: % ./a.out DONE Back on my system, let's give it a PT_SUNWSTACK, and disable the executable stack: % cc -Kpic -M /usr/lib/ld/map.noexstk main.c "main.c", line 40: warning: assignment type mismatch: pointer to function(void) returning void "=" pointer to void % ./a.out Segmentation Fault (core dumped) And using elfedit to modify the stack header, we can make this program run to completion: % elfedit -e 'phdr:p_flags -or sunwstack x' a.out % ./a.out DONE Note that we've still got noexec_user_stack set. Putting this all together, it appears that exec() uses the following rules when setting up the stack for an executable: 1) Initialize stack protections to ABI default for platform 2) If noexec_user_stack is set, remove the execute bit from the stack permissions. 3) If the executable has a PT_SUNWSTACK header, replace the stack permissions with those given by the header. So I'm imagining a system out there, in production, with noexec_user_stack set. This system has a bunch of executables built with the ld defaults, and so, these objects have no PT_SUNWSTACK. Two things happen: 1) The system is upgraded, and has our new ld that always issues PT_SUNWSTACK. 2) The executables are rebuilt on this new system. The result is that programs on this production system that would previously not have been allowed to execute code on the stack will now be allowed to do so. And this will have happened happened without anyone thinking about the security implications, or even being aware that they should. That's bad. Until there's a consensus that Solaris should ignore the platform ABI, I think we're back to the original assertion that the best you can do is to always link with -M /usr/lib/ld/map.noexstk, and to set noexec_user_stack. Since executables that need an executable stack are rare, another answer is to always set noexec_user_stack, and to insist that programs that need an executable stack must have a PT_SUNWSTACK that makes it so. - Ali _______________________________________________ opensolaris-discuss mailing list opensolaris-discuss@opensolaris.org