Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Re: Tests requiring MD hooks

0 views
Skip to first unread message

Matt Thomas

unread,
Jul 11, 2011, 12:38:13 AM7/11/11
to

On Jul 10, 2011, at 7:58 PM, Valeriy E. Ushakov wrote:

>
>> 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

jean-Yves Migeon

unread,
Jul 11, 2011, 7:34:03 AM7/11/11
to
On Mon, 11 Jul 2011 14:34:38 +0400, Valeriy E. Ushakov wrote:
>> On Jul 10, 2011, at 7:58 PM, Valeriy E. Ushakov wrote:
>>
>> >> 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.
>
> You mean "fat" function pointers like e.g. ia64? It's easier to
> special case couple of arches where we introduce a bit of special
> case
> MI code to deconstruct the fat function pointer to get the code
> address, than to write asm code for all arches. Or?

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

Valeriy E. Ushakov

unread,
Jul 11, 2011, 11:46:33 AM7/11/11
to
On Mon, Jul 11, 2011 at 12:34:03 +0100, jean-Yves Migeon wrote:

> 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

jean-Yves Migeon

unread,
Jul 11, 2011, 1:39:38 PM7/11/11
to
On Mon, 11 Jul 2011 19:46:33 +0400, Valeriy E. Ushakov wrote:
> But you do cast your mapped address to a function pointer. Does that
> do the right thing for architectures with fat function pointers?

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

Jean-Yves Migeon

unread,
Jul 11, 2011, 8:36:35 PM7/11/11
to
On 11.07.2011 18:13, Matt Thomas wrote:
> Would the easiest method be something like:
>
> volatile int a1;
> extern const char mprotect_this[];
> void
> victim(void)
> {
> a1 = 1;
> __insn_barrier();
> __asm volatile(".globl mprotect_this" __ASM_DELIMITER
> "mprotect_this:");
> a1 = 0;
> }

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

Jean-Yves Migeon

unread,
Jul 11, 2011, 8:44:44 PM7/11/11
to
On 11.07.2011 20:13, David Holland wrote:
> How about something like this:
>
> void testme(void) {
> char buf[32768];
> uintptr_t addr = (uintptr_t)&buf;
> int fd;
>
> system("gcc -c victim.c");
> system("ld -mumble -static -Ttext %lu victim.o -o victim", addr);
>
> fd = open("victim");
> /* read elf headers, get offset and size of text and entrypoint */
> lseek(fd, text_offset, SEEK_SET);
> read(fd, buf, text_size);
> close(fd);
> mprotect(buf, sizeof(buf), whatever);
> entrypoint(argc, argv);
> }
>
> This requires some elf-specific code but not very much, and there
> might be issues with linker scripts, but it should all be fairly
> manageable.
>
> (victim.o could also be built in advance, it's only the link that matters)

That will work yes, but IMHO this is overkill; it does have the
advantage of avoiding function descriptors games, thanks to ld.

David Laight

unread,
Jul 12, 2011, 2:59:51 AM7/12/11
to
On Sun, Jul 10, 2011 at 09:38:13PM -0700, Matt Thomas wrote:
>
> On Jul 10, 2011, at 7:58 PM, Valeriy E. Ushakov wrote:
>
> >
> >> 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.

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

0 new messages