Bug 997239 - p11-kit-trust.so tries to use mmap with write+exec
Summary: p11-kit-trust.so tries to use mmap with write+exec
Status: REOPENED
Alias: None
Product: openSUSE Tumbleweed
Classification: openSUSE
Component: Basesystem (show other bugs)
Version: Current
Hardware: Other Other
: P5 - None : Normal (vote)
Target Milestone: ---
Assignee: Michael Matz
QA Contact: E-mail List
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-09-05 10:32 UTC by Marcus Rückert
Modified: 2016-09-14 09:29 UTC (History)
4 users (show)

See Also:
Found By: ---
Services Priority:
Business Priority:
Blocker: ---
Marketing QA Status: ---
IT Deployment: ---
rguenther: needinfo? (mrueckert)


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Marcus Rückert 2016-09-05 10:32:32 UTC
when p11-kit tries to load the p11-kit-trust.so we run into the following code:

```
1623  mmap(NULL, 4096, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x3834e70b000
```

This gets killed by the grsec kernel with:

```
8097.931220] PAX: From 127.0.0.1: execution attempt in: <anonymous mapping>, 3532a352000-3532a354000 3532a352000
[ 8097.931223] PAX: terminating task: /usr/bin/pdnsutil(pdnsutil):23868, uid/euid: 0/0, PC: 000003532a352010, SP: 000003ab64903928
[ 8097.931224] PAX: bytes at PC: 4c 8d 15 f9 ff ff ff ff 25 03 00 00 00 0f 1f 00 68 b1 25 27 
[ 8097.931230] PAX: bytes at SP-8: 000000472c954320 0000035328ba3ef2 0000000000000000 0000000000000000 000000472c954320 000000472c954320 000003ab649039d0 000003ab649039e0 000003ab64903bf0 000003ab64903bd8 0000000000000002 
```

moving /usr/share/p11-kit/modules/p11-kit-trust.module away, "solves" the issue, as the module is no longer loaded. During the discussion with the maintainer of the pkcs#11 part in powerdns, he mentioned that in the future systemd will have a DenyWriteExec option to deny WRITE+EXEC pages there as well. so the grsec kernel will not be the only way to trigger this bug. 

complete strace is available if needed.

kernel-grsec-guest-kvm-4.7.2-2.1 obs://build.opensuse.org/home:dsterba:grsecurity/openSUSE_Tumbleweed/68ce05d9439e32ada1b1151bf6f9b7e8-kernel-grsec-guest-kvm
Comment 1 Ludwig Nussel 2016-09-06 08:20:49 UTC
the only mmap p11-kit implements itself (p11_mmap_open in common/compat.c) uses PROT_READ so the mmap you see is from dlopen, ie glibc.
Comment 2 Marcus Rückert 2016-09-06 09:34:24 UTC
I run other daemons on the same host that use dlopen just fine. it is only the 2 packages which use that fail to start. so in doubt this is libtasn or so that does something weird.
Comment 3 Marcus Rückert 2016-09-06 09:34:44 UTC
which use p11-kit....
Comment 4 Ludwig Nussel 2016-09-06 09:47:51 UTC
I see not reason why I should invest time here to debug issues you get with a custom kernel. Feel free to report upstream.
Comment 5 Marcus Rückert 2016-09-06 09:51:55 UTC
because we might want to set DenyWriteExec in service files with future systemd versions.
Comment 6 Marcus Rückert 2016-09-06 09:52:52 UTC
https://github.com/systemd/systemd/issues/3319
Comment 7 Marcus Rückert 2016-09-06 12:51:09 UTC
this could be caused by bind_ffi_closure

(gdb) bt
#0  __mmap (addr=addr@entry=0x0, len=len@entry=4096, prot=prot@entry=7, flags=flags@entry=34, fd=fd@entry=-1, offset=offset@entry=0) at ../sysdeps/unix/sysv/linux/wordsize-64/mmap.c:33
#1  0x00007ffff71a9a0d in dlmmap (length=length@entry=4096, offset=0, fd=-1, flags=34, prot=3, start=0x0) at ../../../libffi/src/closures.c:536
#2  0x00007ffff71aa4f3 in sys_alloc (m=0x7ffff73af220 <_gm_>, nb=56) at ../../../libffi/src/dlmalloc.c:3515
#3  dlmalloc (bytes=48) at ../../../libffi/src/dlmalloc.c:4245
#4  ffi_closure_alloc (size=size@entry=48, code=code@entry=0x60a158) at ../../../libffi/src/closures.c:616
#5  0x00007ffff7bae870 in bind_ffi_closure (wrapper=wrapper@entry=0x60a150, binding_data=binding_data@entry=0x609f10, binding_func=0x7ffff7bacd80 <binding_C_Initialize>, 
    args=args@entry=0x7ffff7dd3cb0 <function_info+48>, bound_func=0x60a158) at p11-kit/virtual.c:2660
#6  0x00007ffff7baeada in init_wrapper_funcs (wrapper=0x60a150) at p11-kit/virtual.c:2701
#7  p11_virtual_wrap (virt=virt@entry=0x609f10, destroyer=<optimized out>) at p11-kit/virtual.c:2755
#8  0x00007ffff7b92cd1 in prepare_module_inlock_reentrant (mod=0x609520, flags=<optimized out>, module=0x6108d0) at p11-kit/modules.c:1861
#9  0x00007ffff7b93c30 in p11_modules_load_inlock_reentrant (flags=0, results=0x7fffffffd750) at p11-kit/modules.c:1919
#10 0x00007ffff7b93d97 in p11_kit_modules_load (reserved=<optimized out>, flags=0) at p11-kit/modules.c:1991
#11 0x00007ffff7b941ba in p11_kit_modules_load_and_initialize (flags=flags@entry=0) at p11-kit/modules.c:2103
#12 0x0000000000401ebe in print_modules () at p11-kit/lists.c:210
#13 p11_kit_list_modules (argc=1, argv=0x7fffffffe328) at p11-kit/lists.c:289
#14 0x00007ffff73d0711 in __libc_start_main (main=0x401bf0 <main>, argc=2, argv=0x7fffffffe328, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, 
    stack_end=0x7fffffffe318) at ../csu/libc-start.c:289
#15 0x0000000000401c29 in _start () at ../sysdeps/x86_64/start.S:118



gdb --args p11-kit list-modules
catch syscall mmap
condition 1 $rdx==7
Comment 8 Marcus Rückert 2016-09-07 13:49:42 UTC
some more findings:

compile libffi-gcc5 with the following patch:
https://gist.github.com/darix/35996fe2be10d40680a359316c045256

makes the tools work even with 

paxctl -v /usr/bin/p11*
/usr/bin/p11-kit:
        XATTR_PAX : PEMRS

/usr/bin/p11tool:
        XATTR_PAX : PEMRS
Comment 9 Ludwig Nussel 2016-09-08 08:13:47 UTC
libffi -> gcc
Comment 10 Richard Biener 2016-09-14 09:13:59 UTC
I don't see how this is _not_ an issue with GRSEC.  If we are allowed to
mmap a PROT_WRITE|PROT_EXEC mapping (no error when doing that) but then
get killed when actually executing from it then something is broken.

Yes, libffi seems to have "dances" around similar issues in SElinux
but "misses" the GRsec case.  Hmm, in fact it _does_ have it!  See
the emutramp_enabled_check () in closures.c:

/* On PaX enable kernels that have MPROTECT enable we can't use PROT_EXEC. */
#ifdef FFI_MMAP_EXEC_EMUTRAMP_PAX
#include <stdlib.h>

static int emutramp_enabled = -1;

static int
emutramp_enabled_check (void)
{
  char *buf = NULL;
  size_t len = 0;
  FILE *f;
  int ret;
  f = fopen ("/proc/self/status", "r");
  if (f == NULL)
    return 0;
  ret = 0;

  while (getline (&buf, &len, f) != -1)
    if (!strncmp (buf, "PaX:", 4))
      {
        char emutramp;
        if (sscanf (buf, "%*s %*c%c", &emutramp) == 1)
          ret = (emutramp == 'E');
        break;
      }
  free (buf);
  fclose (f);
  return ret;
}

#define is_emutramp_enabled() (emutramp_enabled >= 0 ? emutramp_enabled \
                               : (emutramp_enabled = emutramp_enabled_check ()))


but that needs to be enabled at configure time it seems (--enable-pax_emutramp)

Can you check if using a libffi built with that flag works?
Comment 11 Marcus Rückert 2016-09-14 09:27:27 UTC
This is a fix that makes it work https://github.com/libffi/libffi/pull/282
Comment 12 Marcus Rückert 2016-09-14 09:29:33 UTC
osc rdiff {,home:darix:branches:}devel:gcc/gcc5