libffi / libffi

A portable foreign-function interface library.
http://sourceware.org/libffi
Other
3.22k stars 705 forks source link

Add static trampoline support for s390 #862

Closed fneddy closed 6 days ago

fneddy commented 1 month ago

added static trampoline support for ibm s390x. This implementation does not use an intermediate ffi_closure_SYSV_alt function but directly loads the address of ffi_closure_SYSV from the parameter code block and jumps there.

the complete testsuite is pass. I tested it within docker qemu static emulation: podman run --platform=linux/s390x ....

i verified manually that there is no W&X mmap during execution time with a simple test program:

# without static trampolins:
[root@77755a78e43a libffi]# QEMU_STRACE=1 ./a.out  2>&1 | grep PROT_EXEC
92 mmap(0x00000200007fee80,1396736,PROT_EXEC|PROT_READ,MAP_PRIVATE|MAP_DENYWRITE|MAP_FIXED,3,0x7fefc8) = 0x000002000086b000
92 mmap(0x00000200007ffff0,4096,PROT_EXEC|PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0x100ba63) = 0x0000020000a26000

# with static trampolins:
[root@77755a78e43a libffi]# QEMU_STRACE=1 ./a.out  2>&1 | grep PROT_EXEC
2171 mmap(0x00000200007fee80,1396736,PROT_EXEC|PROT_READ,MAP_PRIVATE|MAP_DENYWRITE|MAP_FIXED,3,0x7fefc8) = 0x000002000086b000
2171 mmap(0x00000200007fdd50,4096,PROT_EXEC|PROT_READ,MAP_PRIVATE|MAP_FIXED,3,0) = 0x0000020000a26000

i am planing to do more tests and will come back with the results:

atgreen commented 1 month ago

Very nice! Thanks!

fneddy commented 2 weeks ago

So this is what i testes:

here is the bpftrace script. it filters on:

#!/usr/bin/bpftrace

#define PROT_WRITE 0x2
#define PROT_EXEC  0x4
#define FFI390_TRAMP_MAP_SIZE 0x1000

BEGIN {
        printf("name                ,pid       ,addr        ,len         ,prot        ,flags       ,fd          ,offset      ,return \n");
}

tracepoint:syscalls:sys_enter_old_mmap
/       (args->arg->addr == 0x0) &&
        (args->arg->prot & PROT_EXEC) &&
        (strcontains(str(curtask->mm->exe_file->f_path.dentry->d_name.name),".exe")) /
{
        @filter[pid] = args->arg;
}

tracepoint:syscalls:sys_exit_old_mmap
/ @filter[pid] /
{
        printf("%-20s,%-10d,0x%-10x,0x%-10x,0x%-10x,0x%-10x,0x%-10x,0x%-10x,0x%-10x\n",
                str(curtask->mm->exe_file->f_path.dentry->d_name.name),
                pid,
                @filter[pid]->addr,
                @filter[pid]->len,
                @filter[pid]->prot,
                @filter[pid]->flags,
                @filter[pid]->fd,
                @filter[pid]->offset,
                args->ret
                );

        delete(@filter[pid]);
}

i ran the script output before applying my patch while running make check. All the exec mapping are being logged:

sudo bpftrace mmap.bt > old.log

old.log

after the patch applied there are no more of this mapping visible:

sudo bpftrace mmap.bt > new.log

new.log

from my side this looks good. is there more that i should test?

fneddy commented 1 week ago

I changed the patch to only apply to s390x and not s390 as i doubt its ever needed there. I think its ready for review.

atgreen commented 6 days ago

Thank you!