>
>> That seems to be a bit tricky to write in a portable way: testing --x
>> right in memory pages requires to put/copy some payload in a page and
>> call it.
>
> dlopen something, find a function with dlsym, disable exec on that
> page and call the function. Catch SIGSEGV, check siginfo. mprotect
> it back and call the function again.
doesn't work when the target uses function descriptors.
--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-...@muc.de
Exactly; use of function pointers is dictated by the ABI, so I can't
really use them as I'd like to, like i386/amd64 (these need some care
too, you could end up pointing to the GOT entry rather than the first
byte of the function).
On a side note, as stated in my initial mail, I'd like to provide MD
hooks so I can write tests for any part of memory, like testing
non-executable stack(s) (especially when grown), or check that correct
protections are applied to different part of memory regions.
I can't do that simply through rtld, as I need to memcpy(2) the payload
and therefore have access to the beginning (which is not necessarily
trivial given certain architectures), and the end (never found a way to
properly label those without using assembly routines).
--
Jean-Yves Migeon
j...@NetBSD.org
> Exactly; use of function pointers is dictated by the ABI, so I can't
> really use them as I'd like to
But you do cast your mapped address to a function pointer. Does that
do the right thing for architectures with fat function pointers?
You also don't seem to mention instruction/data-cache issues. I don't
remember if mprotecting something +x makes any guarantees about caches
(cf. arm_sync_icache(2) for example).
> I can't do that simply through rtld, as I need to memcpy(2) the payload
> and therefore have access to the beginning (which is not necessarily
> trivial given certain architectures), and the end (never found a way to
> properly label those without using assembly routines).
You can always parse ELF yourself (unfortunately libelf is still not
imported, it seems).
-uwe
Untested; will see this evening what the resulting code does.
> You also don't seem to mention instruction/data-cache issues. I
> don't
> remember if mprotecting something +x makes any guarantees about
> caches
> (cf. arm_sync_icache(2) for example).
OG does say a thing about this. I assume that mprotect(2) should flush
them (especially icache upon removal of --x right), and count this as a
bug if it does not.
Best way to see is through testing, although I see a couple of
icache_sync in ARM pmap each time execute mappings are modified.
>> I can't do that simply through rtld, as I need to memcpy(2) the
>> payload
>> and therefore have access to the beginning (which is not necessarily
>> trivial given certain architectures), and the end (never found a way
>> to
>> properly label those without using assembly routines).
>
> You can always parse ELF yourself (unfortunately libelf is still not
> imported, it seems).
That's a possibility, yes. Although this would restrict me to ELF, and
rule out all other binary formats.
--
Jean-Yves Migeon
j...@NetBSD.org
Yeah, I gave the "volatile" approach a try, but reusability is almost
nil. Sooner or later I'll have to copy a payload somewhere for testing
(easiest example: in a stack array), so I am back to my original issue:
generate trivial MD code in pure-C, and have a way to copy it
arbitrarily at any place in memory.
--
Jean-Yves Migeon
jeanyve...@free.fr
That will work yes, but IMHO this is overkill; it does have the
advantage of avoiding function descriptors games, thanks to ld.
I'm confused (not difficult these days!).
dlsym() returns 'void *', there is no separate dlsym_function_ptr() that
can return a 'fat' function pointer, or is the symbol attached to
something more akin to an x86 'call gate descriptor' - which is used
as the target of the call instruction?
This gives the inverse problem - if (as suggested in another path of
this thread) you try to allocate the function code on an array,
you'll need to generate the function descriptor as well as the code
itself - this could be somewhat tricky!
Of course, the compiler could be doing horrid things when casting
function pointers to/from void *.
David
--
David Laight: da...@l8s.co.uk