[OpenBSD] staticperl dying unexpectedly with Coro/jit...

Marc Lehmann schmorp at schmorp.de
Sat Oct 29 21:16:52 CEST 2016


On Thu, Oct 27, 2016 at 03:59:41PM +0200, nomad at null.net wrote:
> > Yes, make sure everything is compiled with debug info (it might
> > already be), then create a coredump and make a backtrace.
> > Alternatively, run it under a debugger (e.g. gdb) and see till it
> > crashes and make a backtrace, or even set a breakpoint in the abort
> > function and see if it is reached. I assume you already know how to
> > do this, if not, I will happily explain in more detail :)
> 
> I took this opportunity to learn about debugging (part of the reason
> for taking this long to get back) and this is what I see:
> 
>     Program received signal SIGABRT, Aborted.

Wow, so apparently your kernel abort's on the mmap call.

>     #2  0x00001d7c0c86f0b5 in jit_init () at State.xs:3588

This mmap call is indeed used by the jit, disbaling it will make this
problem go away.

> If I build Coro using the system perl *with* the JIT option enabled the
> tests all pass, and I can't reproduce the abort. So that brings me back
> to some kind of Coro(JIT)/Staticperl interaction.

That's interesting, but might be down to compiler flags passed when building
Coro or perl, you might want to compare, and especially look for flags that
"fortify" or somehow make the enivronment more "secure".

The speed hit from disabling the JIT might not kill you, though, so it
might be a good idea to just do it, unless you really want to dig deeper.

> Relevant perhaps still is your suggestion about looking at the system
> package for Coro. A comment on a recent openbsd mailing list
> discussion[1] claims that the coro JIT "violates W^X" and they are
> disabling JIT because of that.

That is quite interetsing - there are two areas in Coro that do that, one is
the the jit setup phase, where the actual code is generated - that will go
away once the jit is disabled.

The other place is when allocating stacks - and Coro normally adjusts itself
when it fails to allocate an executable stack.

The problem here is that openbsd apparently crashes instead of simply failing
the allocation as other operating systems do. That means that programs can't
even check.

However, this is not the full picture, because:

a) if the jit works when built with the system perl, there is another trick.
b) if disabling the jit works, W^X violations can't be the sole issue, as
   the stack allocator also fails this (and falls bac to a non-executable
   stack otherwqise).

> I have no idea what W^X refers to. I also don't know what behaviour (if

It almost certainly refers to the fact that Coro tries to allocate a writable
and executable memory region. While this is not a security issue in itself,
it can make other security bugs easier to exploit.

Now, Coro, outside the JIT, normally works around this by retrying the
allocation without executable rights, but that can't work if the kernel
aborts the process instead of returning an error.

On Thu, Oct 27, 2016 at 05:27:28PM +0200, nomad at null.net wrote:
> > If I disable the JIT feature (also had to learn about the fact that
> > Coro has a bunch of features) I no longer see the abort under
> > staticperl.
> 
> So the above is true for the test case of "Coro::State->VERSION".
> However now that I can build my staticperl-based application (with
> CORO_JIT=n) I still see an abort at runtime:

This is now in the second place, where Coro tries to allocate a stack.

The expected behaviour for an unsatisfiable mmap call is to return an error
to the application (this is what sane systems do). There is little that Coro
can do if it is being aborted - it simply has no chance to react.

Since this doesn't always seem to happen for you, it still sounds like a
debugging or fortification option that bsomehow switches the kernel (or
maybe the libc) into this special mode.

You should compare the flags used in staticperl compilation with the flags
used to compile your system perl. Or rather, that's what I would look
into. Maybe reading any documentatoion for this feature, or finding the
place in the kernel or libc which causes these aborts, and see why they don't
fail with an error instead (or to see when they fail with an error).

-- 
                The choice of a       Deliantra, the free code+content MORPG
      -----==-     _GNU_              http://www.deliantra.net
      ----==-- _       generation
      ---==---(_)__  __ ____  __      Marc Lehmann
      --==---/ / _ \/ // /\ \/ /      schmorp at schmorp.de
      -=====/_/_//_/\_,_/ /_/\_\



More information about the anyevent mailing list