www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 17561] New: safe code can write beyond Fiber's stack,

https://issues.dlang.org/show_bug.cgi?id=17561

          Issue ID: 17561
           Summary:  safe code can write beyond Fiber's stack, despite
                    guard page
           Product: D
           Version: D2
          Hardware: x86_64
                OS: Linux
            Status: NEW
          Keywords: safe
          Severity: normal
          Priority: P1
         Component: dmd
          Assignee: nobody puremagic.com
          Reporter: ag0aep6g gmail.com

Inspired by <https://www.qualys.com/2017/06/19/stack-clash/stack-clash.txt> and
<https://github.com/dlang/druntime/pull/1698>, here is some code that skips
over a Fiber's stack guard page to corrupt another Fiber's stack:

----
import core.thread: Fiber;
import std.conv: text;

enum pagesize = 4096; /* educated guess */
enum distance = 5 * pagesize; /* 4 pages of stack + 1 guard page */

void main()
{
    auto f1 = new Fiber(()  safe {
        ubyte[distance + 250] mess_up_f2 = void;
            /* skipping over the guard page */
        mess_up_f2[0] = 13;
    });

    auto f2 = new Fiber(() {
        ubyte[500] data = 0;
        foreach (d; data) assert(d == 0); /* passes */
        Fiber.yield();
        foreach (d; data) assert(d == 0, text(d)); /* fails; prints "13" */
    });

    assert(f1.tupleof[8] > f2.tupleof[8]);
    immutable actualDistance = f1.tupleof[8] - f2.tupleof[8];
    assert(distance == actualDistance, text(actualDistance));
        /* If this fails, change `distance` to printed value. */

    f2.call(); /* f2 sets up its data */
    f1.call(); /* f1 messes with it */
    f2.call(); /* f2 sees the corrupted data */
}
----

Tested in Ubuntu Linux with a git HEAD dmd. Might behave differently on other
platforms.

As far as I see, this is an  safe issue, which can't be detected/prevented in
the Fiber code. Fiber's operations are currently not  safe, but surely there is
an expectation that a running an  safe function in a Fiber is safe.

I guess one possible fix would be to outlaw void initialization in  safe code.
Maybe it can be allowed below a certain size, when it's also ensured that guard
pages have at least that size.

--
Jun 27 2017