Any foreign binaries provided externally rather than compiled locally do not have the PT_PAX_FLAGS header, so cannot be controlled via paxctl - only the legacy chpax flags currently work. The patch that follows allows paxctl to set flags on most alien binaries (e.g. java). The patch modifies paxctl so that it can "hijack" the PT_GNU_STACK or PT_NOTE headers (PT_GNU_STACK is a no-op on PaX systems; PT_NOTE is no-op on all systems by definition) and reuse them as a PT_PAX_FLAGS header. It turns out that almost all alien binaries have a PT_NOTE field. A new option, "-f", is implemented to enable the new functionality, which is off by default.
Created attachment 57800 [details, diff] Add -f option to force paxctl to hijack PT_NOTE, PT_GNU_STACK
We have concerns about hijacking the NOTE and not removing the elf segment headers (.note .note.ABI.tag) For the NOTE I'm also pretty sure that if it has a section header note and it's marked with the A (alloc) flag marking you should not hijack it. PT_GNU_STACK (great idea)
What would be really ideal is to inject a new program header.
My reading of the TIS ELF spec v1.2 is that the PT_NOTE and SHT_NOTE sections are not permitted to affect execution behaviour (book 1, 2-5 second note). A corollary of this is that the executable cannot therefore alter its execution behaviour as a result of the existence or contents of NOTEs. So as far as actually running an executable is concerned, hijacking PT_NOTE should be harmless. I figure that anyone on Gentoo implementing, for example, a signature verifier using the PT_NOTE header to hold the signature, will have modified the toolchain to do that and therefore will be building from source anyway. It's fun hijacking PT_GNU_STACK :-> but of limited real use as it tends not to exist on vendor-supplied binaries. If it exists on an ELF file, more often than not it's a shared library not the launch executable, which isn't much use with PaX. I did consider injecting a new header, but pageexec suggested that it may be problematic. I'm still working through the ELF spec to find all the gotchas; in particular the implications of the PT_PHDR header (2-3 last paragraph) may not be trivial.
first of all, i'm very sorry that i hadn't gotten back to you for such a long time... now i finally kicked my own butt and offer the following for testing: grsecurity.net/~paxguy1/test/paxctl-0.3.tar.gz . it is different from your approach in that it deals explicitly with PT_GNU_STACK only. as for PT_NOTE, it does affect execution behaviour, but only at startup, e.g., the .note.ABI-tag section tells ld.so which is the minimum required version of the kernel for the given binary (normally it matters for glibc only i think, this is what prevents you from booting a too old kernel under a glibc that expects a certain minimum kernel ABI, i.e., syscalls), on other archs it can tell which kind of emulation ABI is needed for the given binary (iirc, the BSDs mark their own executables in PT_NOTE).
Sorry pageexec; didn't think to cc you. Unfortunately in practice hijacking PT_GNU_STACK doesn't get us very far; none of the foreign binaries I have contain it. Seems like the only way to deal with that is to rewrite the ELF file. Maybe libelf can help; I'll have a go.
'execstack -[cs] binary; paxctl -c binary' ;-). if that fails, we can hardly do any better without some major ELF hacking (reducing the first PT_LOAD's base and adding space there). i didn't want to lift the code from execstack because IMHO it's just not worth the effort, prelink is installed everywhere these days, so is execstack.
In the case of java and probably most other programs provided by a 3rd party vendor we wont really be able to inject a PT_GNU_STACK header for later conversion into PT_PAX_FLAGS using execstack. tigger pointed out to me that execstack only works with ET_DYN. I tested this and found it to be true. cp /opt/blackdown*/bin/java . ; execstack.dyn -s ./java execstack.dyn: ./java: Reshuffling of objects to make room for program header entry only supported for shared libraries
before trying reshuffling, execstack tries a few trivial injection methods, i meant to rely on those. reshuffling ET_EXEC files is not possible in general that's why execstack doesn't do it. one method that could work is the extension of the first PT_LOAD segment downwards to make room for the expanded program header, but that's not a 5-minute hack (this is not meant to discourage anyone, just trying to explain why i'm trying to keep changes minimal/simple).
How about adding a PT_LOAD segment to be loaded at the end of the executable; i.e. at VirtAddr+MemSiz of the highest existing PT_LOAD segment, and place the expanded PHDR there (adjusting the Elf header appropriatey). If I read right, the PHDR entry in the PHDR itself has to be before that of any PT_LOAD segment, but it shouldn't be a problem locating the actual header segment itself anywhere. The elf spec explicitly states that only the location of the ELF header can be assumed, so presumably anthing that wants to access the PHDR segment has to find it through the Elf header.
adding another PT_LOAD on the top has a potential issue with the .bss and the brk() based heap since in normal files they're closely related, however sticking a PT_LOAD between the two will change this (it's a somewhat similar issue to what arises with brk() randomization, i think emacs during build breaks because of that). so really the safest approach is to put the program headers below the image, not above it (which then raises the nice implementation problems ;-).
i released paxctl 0.3 that converts PT_GNU_STACK into PT_PAX_FLAGS, further development (if any) will go into 0.4.
Created attachment 58078 [details] Attempt 1 at extending the first PT_LOAD downwards Well, here goes nothing. For simplicity, I've restricted myself to ELF files that conform to a few rules, at least for proof (or otherwise) of concept. Unfortunately, although it looks like it does what I intended it to do (comparing readelf output before and after indicates as much), the resulting ELFs are killed immediately by the kernel. Perhaps because the lowest address is below 08004800 - in which case the whole game is a no-go. On the other hand, maybe I've done something stupid...
In your output binary the PT_PHDR segment is starting in the middle of the ELF header, which is why your binary is killed. You need to extend down of 1 page the first PT_LOAD segment and adapt the PT_PHDR in order to have the room for additional PHT entries. The function : elfsh_inject_code_section() in section.c shows an example of this manipulation (not used for the same thing however since here a complete section is added in the additional pages) http://elfsh.devhell.org/files/elfsh-0.51b3/libelfsh/section.c - The ELF shell crew
Created attachment 58186 [details] Working proof-of concept PHDR insertion widget Got it - problem was that when I moved the first PT_LOAD segment, I didn't take account of its alignment. This updated widget hard-codes the alignment to 0x1000, just to demonstrate the trick works (obviously it should really get the alignment from the PT_PHDR of the PT_LOAD segment). I've only tested that relevant executables load ok and run as far as dumping out usage text, but so far it seems to work! It remains to be seen whether it breaks execution at all, but it looks promising. I've rigged my blackdown-jdk binaries with it, so we'll see.
a little update. I've run various things through this, and providing I set flag 'x' (the utility leaves them all '-') I don't get any kills. In particular bdc seems to work (so far this only seems happy with 'mxe', if the flags are set via PT header rather than chpax). I do get a segfault when running it on chpax'ed binaries - I'll have to track that down. I'll get around to writing a tidier version soonish. Originally I rigged it to generate a PT_NULL header; the idea being to have paxctl hijack it as a separate operation - thoughts?
After you hacked out the initial support to work for ET_EXEC ET_DYN bins I wanted to import this tool or a variation there of into http://www.gentoo.org/cgi-bin/viewcvs.cgi/pax-utils/?root=gentoo-projects&hideattic=1 (assuming you GPL it)
(In reply to comment #16) > a little update. I've run various things through this, and providing I set flag > 'x' (the utility leaves them all '-') I don't get any kills. FYI, the default value from ld is equivalent to paxctl -zex. > I'll get around to writing a tidier version soonish. Originally I rigged it to > generate a PT_NULL header; the idea being to have paxctl hijack it as a separate operation - thoughts? i don't mind directly including it into paxctl as well but it has to go through lots of testing before that. my main worry is that injecting something at the beginning of the image changes all file offsets afterwards, so any such info in structure fields must be all updated, this including not only mapped sections but stuff like debug symbols, etc as well. did you systematically check all this out already and make sure all file offset fields continue to refer to their original places?
I was thinking of a separate widget for a while, to be applied on an "if you dare" basis, to get confidence and maturity- pax-utils is an ideal repository for the moment (it'll certainly be GPL). On a related note we're putting together a "wrapper" for the various pax widgets so that we can abstract what ebuilds do into a simple call; this allows us to muck around with the set of widgets as time goes on without disrupting ebuild maintainers - hopefully. With regards file offset fields, I tried to cover everything, but I'll certainly go through that again more thoroughly. There are a few other things to tidy up (e.g. making it 64bit & 32bit compliant, deciding more carefully what assumptions need to be made and hence validated). Also there's ET_DYN to think about. I've concentrated on ET_EXEC to keep things simple, and because that's what most (if not all) vendor-built binaries are. I was also keeping an eye on the elfsh thing; there's some talk about adding PT entry injection on their website. It's bit quiet there at the moment, but I haven't made any noise yet.
(In reply to comment #19) > With regards file offset fields, I tried to cover everything, but I'll certainly > go through that again more thoroughly. There are a few other things to tidy up > (e.g. making it 64bit & 32bit compliant, deciding more carefully what > assumptions need to be made and hence validated). one thing that may matter for gentoo is cross-compilation where you have to take into account byte-endianess (something i blissfully ignore for paxctl ;-). > Also there's ET_DYN to think about. I've concentrated on ET_EXEC to keep things simple, and because that's what most (if not all) vendor-built binaries are. i don't see a problem with ET_DYN. only executables matter for PaX so that means you'd have care about PIEs only, not .so libraries. and any toolchain version that can produce a PIE will already produce PT_GNU_STACK so we can always reuse that. > I was also keeping an eye on the elfsh thing; there's some talk about adding PT > entry injection on their website. It's bit quiet there at the moment, but I > haven't made any noise yet. elfsh should already be able to do it (etrel_inject if i'm not mistaken).
This can be closed now paxctl has the magic :)