Re: [osol-discuss] 32-bit noexec_user_stack on per-process basis?
>ppgsz(1) or mpss.so.1(1) can set preferred page size for >existing (ppgsz) or new (both) processes. > >Is there anything that can similarly remove execute permission >from the stack of 32-bit processes, without do so on a system-wide >basis (i.e. without putting set noexec_user_stack=1 in /etc/system)? Without relinking, you mean? If you can relink the program, there's -M /usr/lib/ld/map.noexstk >It strikes me that something like that might be good with high risk >programs like browsers, that are often still 32-bit, and usually >have a shell wrapper anyway. We use this in many consolidations: % pmap `pgrep firefox`|grep stack E60FA000 8K rw--R[ stack tid=2846 ] F727A000 8K rw--R[ stack tid=14 ] F74F8000 16K rw--R[ stack tid=13 ] F7AF8000 16K rw--R[ stack tid=7 ] F83FA000 8K rw--R[ stack tid=2858 ] FA5FA000 8K rw--R[ stack tid=5 ] FA6FA000 8K rw--R[ stack tid=4 ] FABFA000 8K rw--R[ stack tid=3 ] FACFA000 8K rw--R[ stack tid=2 ] FFB9C000 400K rw---[ stack ] FFBFC000 16K rw---[ stack ] You can detect such programs using "elfdump"; you'll find a Program header similar to this: Program Header[5]: p_vaddr: 0 p_flags:[ PF_W PF_R ] <- RW, no N! p_paddr: 0 p_type: [ PT_SUNWSTACK ] p_filesz: 0 p_memsz:0 p_offset: 0 p_align:0 Casper ___ opensolaris-discuss mailing list opensolaris-discuss@opensolaris.org
Re: [osol-discuss] 32-bit noexec_user_stack on per-process basis?
> > >ppgsz(1) or mpss.so.1(1) can set preferred page size > for > >existing (ppgsz) or new (both) processes. > > > >Is there anything that can similarly remove execute > permission > >from the stack of 32-bit processes, without do so on > a system-wide > >basis (i.e. without putting set noexec_user_stack=1 > in /etc/system)? > Without relinking, you mean? > > If you can relink the program, there's > > -M /usr/lib/ld/map.noexstk > > >It strikes me that something like that might be good > with high risk > >programs like browsers, that are often still 32-bit, > and usually > >have a shell wrapper anyway. > > > We use this in many consolidations: > > % pmap `pgrep firefox`|grep stack > E60FA000 8K rw--R[ stack tid=2846 ] > F727A000 8K rw--R[ stack tid=14 ] > F74F8000 16K rw--R[ stack tid=13 ] > F7AF8000 16K rw--R[ stack tid=7 ] > F83FA000 8K rw--R[ stack tid=2858 ] > FA5FA000 8K rw--R[ stack tid=5 ] > FA6FA000 8K rw--R[ stack tid=4 ] > FABFA000 8K rw--R[ stack tid=3 ] > FACFA000 8K rw--R[ stack tid=2 ] > FFB9C000 400K rw---[ stack ] > FFBFC000 16K rw---[ stack ] > > You can detect such programs using "elfdump"; you'll > find a Program header > similar to this: > > Program Header[5]: > p_vaddr: 0 p_flags:[ PF_W PF_R > ] <- RW, no N! > p_paddr: 0 p_type: [ > PT_SUNWSTACK ] > p_filesz: 0 p_memsz:0 > p_offset: 0 p_align:0 > > Casper > Thanks for the info. Doesn't help with existing binaries, but it's good to know for when one can re-link. If there's a way to construct an LD_PRELOAD'able shared object to do the trick for existing binaries, I don't see how given the description of mprotect(2), to specify the entire present (and future) stack or heap of a process. >From some of the stuff I've looked at, it seems that executables were first widely built to disable an executable stack (using something as boring as /usr/bin/who as the test case) in Solaris 9; on Solaris 8, I didn't see a program header for the stack for the "who" executable, but when I recompiled with the -M option you gave, and checked the new binary with elfdump, I saw the additional program header. There are a few oddball programs that legitimately want a segment that's both writable and executable (because they compile on-the-fly); some LISP interpreters used to do that, I think; and I can imagine that some Forth implementations might want to do strange things. (I wonder if the JVM does anything like that?) But I suppose they ought to create an explicit anonymous mapping with the permissions they desire for that use. Now...if there only weren't still 32-bit executables that aren't large-file aware. :-) -- This message posted from opensolaris.org ___ opensolaris-discuss mailing list opensolaris-discuss@opensolaris.org
Re: [osol-discuss] 32-bit noexec_user_stack on per-process basis?
>Thanks for the info. > >Doesn't help with existing binaries, but it's good to know for >when one can re-link. If there's a way to construct an >LD_PRELOAD'able shared object to do the trick for existing >binaries, I don't see how given the description of mprotect(2), >to specify the entire present (and future) stack or heap of a process. True. That's why we have the /etc/system tunable. Before we created the tunable, I created a "poke the kernel" script. Because of the limitations in where I could poke the kernel, I modified the routine which created all the "zero-fill-on-demand" pages; this includes the stack but everything allocated in on the heap, including the BSS segment. >From some of the stuff I've looked at, it seems that executables were >first widely built to disable an executable stack >(using something as boring as /usr/bin/who as the test case) >in Solaris 9; on Solaris 8, I didn't see a program header for the stack for >the "who" executable, but when I recompiled with the -M option you >gave, and checked the new binary with elfdump, I saw the additional >program header. I'm not sure when we added support for that header in the kernel. >There are a few oddball programs that legitimately want a segment >that's both writable and executable (because they compile on-the-fly); >some LISP interpreters used to do that, I think; and I can imagine that >some Forth implementations might want to do strange things. (I wonder >if the JVM does anything like that?) But I suppose they ought >to create an explicit anonymous mapping with the permissions they >desire for that use. With the patch script above, we did find that java and some other runtime create code run into the problem. But we limit it to the stack as the kernel does, there is no issue apart from some of the cases where gcc creates code on the stack. >Now...if there only weren't still 32-bit executables that aren't large-file >aware. :-) The only issue we were able to fix was the inability to open more than 256 FILE*s and we have a pre-loaded script. I don't think we have a routine to change the stack protection on the fly. Casper ___ opensolaris-discuss mailing list opensolaris-discuss@opensolaris.org
Re: [osol-discuss] 32-bit noexec_user_stack on per-process basis?
On 10/16/10 08:54 AM, Richard L. Hamilton wrote: Doesn't help with existing binaries, but it's good to know for when one can re-link. If there's a way to construct an LD_PRELOAD'able shared object to do the trick for existing binaries, I don't see how given the description of mprotect(2), to specify the entire present (and future) stack or heap of a process. From some of the stuff I've looked at, it seems that executables were first widely built to disable an executable stack (using something as boring as /usr/bin/who as the test case) in Solaris 9; on Solaris 8, I didn't see a program header for the stack for the "who" executable, but when I recompiled with the -M option you gave, and checked the new binary with elfdump, I saw the additional program header. There are a few oddball programs that legitimately want a segment that's both writable and executable (because they compile on-the-fly); some LISP interpreters used to do that, I think; and I can imagine that some Forth implementations might want to do strange things. (I wonder if the JVM does anything like that?) But I suppose they ought to create an explicit anonymous mapping with the permissions they desire for that use. I believe you've already covered the essential facts, so allow me to toss out some related supplemental trivia... The stack permissions are set up within exec, based on the executable's PT_SUNWSTACK program header, 'set noexec_user_stack' in /etc/system, and failing those, the ABI mandated default. The stack headers that come in later with other objects don't have a vote in this, and their PT_SUNWSTACK headers are ignored, including PRELOAD objects. Another point of trivia is that if you have an executable with a PT_SUNWSTACK, you can use elfedit to make its stack executable: % elfedit -e 'phdr:p_flags -or sunwstack x' /bin/ls my.ls % elfdump -p my.ls Program Header[6]: p_vaddr: 0 p_flags:[ PF_X PF_W PF_R ] p_paddr: 0 p_type: [ PT_SUNWSTACK ] p_filesz: 0 p_memsz:0 p_offset: 0 p_align:0 Unfortunately, the reverse is generally not possible: ld doesn't issue a PT_SUNWSTACK when the permissions match the ABI defaults, so there's nothing there for you to edit. When I introduced the new mapfile syntax for ld earlier this year, the question of whether we could change the default to make stacks non-executable came up. I asked around, and the general consensus seemed to be that while no one wants an executable stack, that going against the ABI seemed to be a step too far. All of which seems to say that linking with -M /usr/lib/ld/map.noexstk is about the best you can currently do. - Ali ___ opensolaris-discuss mailing list opensolaris-discuss@opensolaris.org
Re: [osol-discuss] 32-bit noexec_user_stack on per-process basis?
While it doesn't help existing binaries, would it be possible to for new 32-bit binaries persuade the linker to issue a redundant (same as ABI) PT_SUNWSTACK header? That I suppose elfedit _would_ be able to change after-the-fact. I gather one could do it indirectly, by linking with -M /usr/lib/ld/map.noexstk and then restoring stack execute permission with elfedit (so that someone could take it away again later if they wanted to), but that's clearly silly. [Update] I just tried back on SXCE snv_97 (still haven't updated) with a map file containing stack = STACK ?RWX; and that appeared to work - the header was generated with the requested permissions. So it ought to be rather easy to change the linker to just generate the header explicitly by default. The point would be if inserting the seemingly redundant header could happen by default, which would allow someone to correct the developer's omission of turning off stack execute permission when linking. OTOH, I suppose elfedit would mess with signed executables (not that they're that big a deal until enforcement is generally available). And of course, whenever reasonably expected calculations involving future times would pass the Jan 19 03:14:07 2038 mark, the existing 32-bit ABI would be broken anyway. (to figure out something involving a 30 year mortgage, that would already have been a problem for a couple of years now...) Too bad larger time_t wasn't part of largefile support. -- This message posted from opensolaris.org ___ opensolaris-discuss mailing list opensolaris-discuss@opensolaris.org
Re: [osol-discuss] 32-bit noexec_user_stack on per-process basis?
On 10/17/10 4:58 AM, Richard L. Hamilton wrote: While it doesn't help existing binaries, would it be possible to for new 32-bit binaries persuade the linker to issue a redundant (same as ABI) PT_SUNWSTACK header? That I suppose elfedit _would_ be able to change after-the-fact. I gather one could do it indirectly, by linking with -M /usr/lib/ld/map.noexstk and then restoring stack execute permission with elfedit (so that someone could take it away again later if they wanted to), but that's clearly silly. [Update] I just tried back on SXCE snv_97 (still haven't updated) with a map file containing stack = STACK ?RWX; and that appeared to work - the header was generated with the requested permissions. So it ought to be rather easy to change the linker to just generate the header explicitly by default. The point would be if inserting the seemingly redundant header could happen by default, which would allow someone to correct the developer's omission of turning off stack execute permission when linking. OTOH, I suppose elfedit would mess with signed executables (not that they're that big a deal until enforcement is generally available). And of course, whenever reasonably expected calculations involving future times would pass the Jan 19 03:14:07 2038 mark, the existing 32-bit ABI would be broken anyway. (to figure out something involving a 30 year mortgage, that would already have been a problem for a couple of years now...) Too bad larger time_t wasn't part of largefile support. 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 don't view the fact that elfedit breaks the signature of an object as a problem. If we deliver an object with an executable stack, and it's modified in the field, that's the sort of thing you'd want to detect. You can certainly cause ld to inject a redundant header yourself, using a mapfile. However, as you pointed out earlier in this thread, it's a rare application that really needs an executable stack. So if you're aware enough of the issue to be able to arrange for a PT_SUNWSTACK to be added to the object with a mapfile, you might as well and make it non-executable, rather than the redundant one. The redundant header is only really helpful if it's always put there by ld as a default action. - Ali ___ opensolaris-discuss mailing list opensolaris-discuss@opensolaris.org
Re: [osol-discuss] 32-bit noexec_user_stack on per-process basis?
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 #include /* 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
Re: [osol-discuss] 32-bit noexec_user_stack on per-process basis?
> On 10/17/10 10:01, Ali Bahrami wrote: [...] > 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. In that case, perhaps if a /usr/lib/ld/map.exstk containing stack = STACK ?RWX; were supplied (and mentioned in whatever documentation that other pre-supplied mapfiles are mentioned), it might be likelier to encourage developers to do as you suggest, explicitly disabling (or in the rare case needed, enabling) executable stack support for each executable. -- This message posted from opensolaris.org ___ opensolaris-discuss mailing list opensolaris-discuss@opensolaris.org
Re: [osol-discuss] 32-bit noexec_user_stack on per-process basis?
>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. > Thanks for this investigation. There is another issue we haven't explored is the use a system call; there's a sysconf(_SC_STACK_PROT) but there's no way to set in on the fly. If we create a function to change it on the fly, we could make a LD_PRELOAD object which enforce it. The current mapped pages would not be protected but threadstacks and additional pages would be rw-. Casper ___ opensolaris-discuss mailing list opensolaris-discuss@opensolaris.org
Re: [osol-discuss] 32-bit noexec_user_stack on per-process basis?
> > > >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. > > > > Thanks for this investigation. > > There is another issue we haven't explored is the use > a system call; > there's a sysconf(_SC_STACK_PROT) but there's no way > to set in on the > fly. If we create a function to change it on the > fly, we could make a > LD_PRELOAD object which enforce it. The current > mapped pages would not be > protected but threadstacks and additional pages would > be rw-. > > Casper I picture this somehow as being just a bit more functionality added to mprotect(2): /* following magic to identify operating on that segment, rather than * a particular address */ #define ADDR_STACK (void *) (-1) #define ADDR_HEAP (void *) (-2) mprotect(ADDR_STACK, 0, (PROT_READ|PROT_WRITE|PROT_EXEC)); where a length of 0 implies something similar to what (MCL_CURRENT|MCL_FUTURE) implies with memcntl(2), namely to apply that behavior to both the present and future pages of the segment; that would combine applying mprotect() to the existing pages as well as setting p_stkprot or p_datprot in the proc structure. Such an interface would be ideal for runtime control either by the developer or after-the-fact with an LD_PRELOAD'ed shared object. Adding this functionality to mprotect() would be more understandable than a new function, and would avoid adding an additional system call. I don't imagine that any existing software (except _maybe_ an emulator?) would call mprotect() so often that the addition of a couple of if's or a switch() applied to the addr arg would present a performance problem. I haven't thought of a good way to search for what (if any) precedent there is for how other OSs handle this. -- This message posted from opensolaris.org ___ opensolaris-discuss mailing list opensolaris-discuss@opensolaris.org
Re: [osol-discuss] 32-bit noexec_user_stack on per-process basis?
>I picture this somehow as being just a bit more functionality added to >mprotect(2): > >/* following magic to identify operating on that segment, rather than > * a particular address > */ >#define ADDR_STACK (void *) (-1) >#define ADDR_HEAP (void *) (-2) > >mprotect(ADDR_STACK, 0, (PROT_READ|PROT_WRITE|PROT_EXEC)); It's a bit harder to bolt on the current implementation of the stack protection. And what is the "ADDR_STACK" *all* current thread stacks, the stack of main or the current stack? >where a length of 0 implies something similar to what (MCL_CURRENT|MCL_FUTURE) >implies with memcntl(2), namely to apply that behavior to both the present and >future pages of the segment; that would combine applying mprotect() to the >existing pages as well as setting p_stkprot or p_datprot in the proc structure. > >Such an interface would be ideal for runtime control either by >the developer or after-the-fact with an LD_PRELOAD'ed shared object. > >Adding this functionality to mprotect() would be more understandable than >a new function, and would avoid adding an additional system call. I don't >imagine that any existing software (except _maybe_ an emulator?) would >call mprotect() so often that the addition of a couple of if's or a switch() >applied to the addr arg would present a performance problem. There is one particular issue where gcc uses a trampoline created on the stack when you are passing a nested function as a function argument. (A nested function requires an additional argument) Casper ___ opensolaris-discuss mailing list opensolaris-discuss@opensolaris.org
Re: [osol-discuss] 32-bit noexec_user_stack on per-process basis?
How does the trampoline work on architectures which have noexec bit for stack by default, like sparcv9? Olga On Wed, Oct 20, 2010 at 2:26 PM, wrote: > > >>I picture this somehow as being just a bit more functionality added to >>mprotect(2): >> >>/* following magic to identify operating on that segment, rather than >> * a particular address >> */ >>#define ADDR_STACK (void *) (-1) >>#define ADDR_HEAP (void *) (-2) >> >>mprotect(ADDR_STACK, 0, (PROT_READ|PROT_WRITE|PROT_EXEC)); > > It's a bit harder to bolt on the current implementation of the > stack protection. And what is the "ADDR_STACK" *all* current > thread stacks, the stack of main or the current stack? > >>where a length of 0 implies something similar to what (MCL_CURRENT|MCL_FUTURE) >>implies with memcntl(2), namely to apply that behavior to both the present and >>future pages of the segment; that would combine applying mprotect() to the >>existing pages as well as setting p_stkprot or p_datprot in the proc >>structure. >> >>Such an interface would be ideal for runtime control either by >>the developer or after-the-fact with an LD_PRELOAD'ed shared object. >> >>Adding this functionality to mprotect() would be more understandable than >>a new function, and would avoid adding an additional system call. I don't >>imagine that any existing software (except _maybe_ an emulator?) would >>call mprotect() so often that the addition of a couple of if's or a switch() >>applied to the addr arg would present a performance problem. > > There is one particular issue where gcc uses a trampoline created on the > stack when you are passing a nested function as a function argument. > > (A nested function requires an additional argument) > > Casper > > ___ > opensolaris-discuss mailing list > opensolaris-discuss@opensolaris.org > -- , __ , { \/`o;-Olga Kryzhanovska -;o`\/ } .'-/`-/ olga.kryzhanov...@gmail.com \-`\-'. `'-..-| / http://twitter.com/fleyta \ |-..-'` /\/\ Solaris/BSD//C/C++ programmer /\/\ `--` `--` ___ opensolaris-discuss mailing list opensolaris-discuss@opensolaris.org
Re: [osol-discuss] 32-bit noexec_user_stack on per-process basis?
>How does the trampoline work on architectures which have noexec bit >for stack by default, like sparcv9? A long time ago, I made some changes to gcc; I'm not sure if the changes are still in current gcc, but what happens is that we run mprotect() on the parts of the stack where we need to execute code. Casper ___ opensolaris-discuss mailing list opensolaris-discuss@opensolaris.org
Re: [osol-discuss] 32-bit noexec_user_stack on per-process basis?
> > > >I picture this somehow as being just a bit more > functionality added to mprotect(2): > > > >/* following magic to identify operating on that > segment, rather than > > * a particular address > > */ > >#define ADDR_STACK (void *) (-1) > >#define ADDR_HEAP (void *) (-2) > > > >mprotect(ADDR_STACK, 0, > (PROT_READ|PROT_WRITE|PROT_EXEC)); > > It's a bit harder to bolt on the current > implementation of the > stack protection. And what is the "ADDR_STACK" *all* > current > thread stacks, the stack of main or the current > stack? Which does the PT_SUNWSTACK header apply to? I'm not sure what point there would be in per-thread control; if any one thread in an address space is exploitable, the whole address space is potentially corruptible. -- This message posted from opensolaris.org ___ opensolaris-discuss mailing list opensolaris-discuss@opensolaris.org
Re: [osol-discuss] 32-bit noexec_user_stack on per-process basis?
>Which does the PT_SUNWSTACK header apply to? It sets the fields in the proc structure which defines the stack protection. >I'm not sure what point there would be in per-thread >control; if any one thread in an address space is exploitable, >the whole address space is potentially corruptible. It's different because mprotect() works on the process. Using mprotect requires you to run mprotect on all process stacks (as long as they are created by the library). I'm not sure that the kernel has sufficient information to figure that out. Casper ___ opensolaris-discuss mailing list opensolaris-discuss@opensolaris.org
Re: [osol-discuss] 32-bit noexec_user_stack on per-process basis?
> > > >Which does the PT_SUNWSTACK header apply to? > > It sets the fields in the proc structure which > defines the stack > protection. > > >I'm not sure what point there would be in per-thread > >control; if any one thread in an address space is > exploitable, > >the whole address space is potentially corruptible. > > > It's different because mprotect() works on the > process. Using mprotect > requires you to run mprotect on all process stacks > (as long as they are > created by the library). I'm not sure that the > kernel has sufficient > information to figure that out. Looks to me like http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libc/port/threads/thr.c checks sysconf(_SC_STACK_PROT) and honors it. The only problem is that it caches the return value (static variable stackprot), which would have to be invalidated by the mprotect() wrapper when the magic ADDR_STACK was used (so that it would pick up the new process-wide value that was also set in the proc structure). That would make that setting apply to all future thread stacks. In other words, that source file would have to add a _-prefixed library internal function that zeros stackprot. Maybe the best one can do is the main stack (current+future) and the thread stacks (future), if one can't readily figure out from either user space (syscall wrapper check) or kernel space the location and size of all the current thread stacks. I haven't looked at how sigaltstack() handling might get involved... -- This message posted from opensolaris.org ___ opensolaris-discuss mailing list opensolaris-discuss@opensolaris.org
Re: [osol-discuss] 32-bit noexec_user_stack on per-process basis?
>Looks to me like >http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libc/port/threads/thr.c > >checks sysconf(_SC_STACK_PROT) and honors it. The only problem is >that it caches the return value (static variable stackprot), which >would have to be invalidated by the mprotect() wrapper when the magic >ADDR_STACK was used (so that it would pick up the new process-wide >value that was also set in the proc structure). That would make that >setting apply to all future thread stacks. > >In other words, that source file would have to add a _-prefixed library >internal function that zeros stackprot. > >Maybe the best one can do is the main stack (current+future) and >the thread stacks (future), if one can't readily figure out from >either user space (syscall wrapper check) or kernel space the location >and size of all the current thread stacks. > >I haven't looked at how sigaltstack() handling might get involved... It's created by the application and so it's either rwx (32 bit or sparc) or rw- on amd64 unless they created it differently. (The differences are part of history and part of the implementation [PLT tables are instructions on SPARC but are data on x86]) Casper ___ opensolaris-discuss mailing list opensolaris-discuss@opensolaris.org
Re: [osol-discuss] 32-bit noexec_user_stack on per-process basis?
In that case, let me revise my earlier proposal: ADDR_HEAP would apply to the entire heap, current and future. ADDR_STACK would alter future behavior (both for main stack and by invalidating stackprot as previously mentioned, for thread stacks), but for the sake of gcc trampolines and the complexity of determining the bounds of all existing thread stacks, need not alter behavior with respect to current stack pages. (Hypothetically, if it could on some future platform, that's great, but it probably can't now.) That seems like a reasonable, non-disruptive best effort, which, since there are apparently some exceptions that make attempting to make the stack non-executable on 32-bit (x86 or spark) somewhat less than bulletproof anyway, should probably be good enough, and better than nothing (enough to complicate the work involved in an overflow attack, anyway). And quite possibly also good enough given that an LD_PRELOADed shared object that was designed to run very early (using a #pragma init(func) perhaps) should be able to know that it didn't have to worry about stepping on existing trampolines (or about multiple threads), and could take separate action (regular mprotect() usage with a bit of knowledge of the main stack layout) to protect the existing main stack. Any later use of ADDR_STACK, by _not_ altering the protection of existing stack pages, but only future ones, would avoid breaking anything unexpectedly. -- This message posted from opensolaris.org ___ opensolaris-discuss mailing list opensolaris-discuss@opensolaris.org
Re: [osol-discuss] 32-bit noexec_user_stack on per-process basis?
On 10/20/10 3:39 AM, casper@sun.com wrote: 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. Thanks for this investigation. There is another issue we haven't explored is the use a system call; there's a sysconf(_SC_STACK_PROT) but there's no way to set in on the fly. If we create a function to change it on the fly, we could make a LD_PRELOAD object which enforce it. The current mapped pages would not be protected but threadstacks and additional pages would be rw-. Casper Yet another possibility would be for ld to issue an extra PT_NULL program header, rather than a PT_SUNWSTACK. PT_NULL is a no-op, and would not alter behavior, but elfedit can be later be used to turn it into something else, such as PT_SUNWSTACK. - Ali ___ opensolaris-discuss mailing list opensolaris-discuss@opensolaris.org
Re: [osol-discuss] 32-bit noexec_user_stack on per-process basis?
> On 10/20/10 3:39 AM, casper@sun.com wrote: > > > > > >> 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. > >> > > > > Thanks for this investigation. > > > > There is another issue we haven't explored is the > use a system call; > > there's a sysconf(_SC_STACK_PROT) but there's no > way to set in on the > > fly. If we create a function to change it on the > fly, we could make a > > LD_PRELOAD object which enforce it. The current > mapped pages would not be > > protected but threadstacks and additional pages > would be rw-. > > > > Casper > > > > Yet another possibility would be for ld to issue an > extra PT_NULL > program header, rather than a PT_SUNWSTACK. PT_NULL > is a no-op, and > would not alter behavior, but elfedit can be later be > used to turn it > into something else, such as PT_SUNWSTACK. While I still like the idea of a runtime function (new syscall or extension to mprotect()) to control default stack or heap permissions (mainly for use with a preloadable shared object to apply to existing binaries that don't have a spare program header, although some other runtime uses might be imaginable), leaving oneself the leeway to patch a binary statically also seems desirable. I gather that something had been done to leave some room so that for newer binaries, one could patch in runpath changes longer than the original runpath (whereas for older ones, one might well have been limited to a new runpath that fit in the same space as the old one). Are there any _current_ uses you can see for a spare unused (PT_NULL) program header other than changing it into a PT_SUNWSTACK header? (I imagine that there's always a good chance that future uses as yet unsupported might turn up, i.e. some future feature that could be retrofitted into existing binaries given a spare header to put it into; but I'm thinking now in terms of current possibilities.) -- This message posted from opensolaris.org ___ opensolaris-discuss mailing list opensolaris-discuss@opensolaris.org
Re: [osol-discuss] 32-bit noexec_user_stack on per-process basis?
On 10/20/10 21:42, Richard L. Hamilton wrote: While I still like the idea of a runtime function (new syscall or extension to mprotect()) to control default stack or heap permissions (mainly for use with a preloadable shared object to apply to existing binaries that don't have a spare program header, although some other runtime uses might be imaginable), leaving oneself the leeway to patch a binary statically also seems desirable. I gather that something had been done to leave some room so that for newer binaries, one could patch in runpath changes longer than the original runpath (whereas for older ones, one might well have been limited to a new runpath that fit in the same space as the old one). Are there any _current_ uses you can see for a spare unused (PT_NULL) program header other than changing it into a PT_SUNWSTACK header? (I imagine that there's always a good chance that future uses as yet unsupported might turn up, i.e. some future feature that could be retrofitted into existing binaries given a spare header to put it into; but I'm thinking now in terms of current possibilities.) The something was 6516118 Reserved space needed in ELF dynamic section and string table PSARC 2007/127 Reserved space for editing ELF dynamic sections This is definitely a similar idea, elfedit being the common thread. I don't see another use for a spare program header, other than for this SUNWSTACK purpose, at this time. However, the cost of an extra program header is nil, so that doesn't worry me. We'll see... - Ali ___ opensolaris-discuss mailing list opensolaris-discuss@opensolaris.org