OS-6323: want stack-clash mitigation

Details

Issue Type:Bug
Priority:4 - Normal
Status:Resolved
Created at:2017-09-01T18:39:19.000Z
Updated at:2017-09-29T00:45:00.000Z

People

Created by:Former user
Reported by:Former user
Assigned to:Former user

Resolution

Fixed: A fix for this issue is checked into the tree and tested.
(Resolution Date: 2017-09-29T00:45:00.000Z)

Fix Versions

2017-10-12 Cactaur Island (Release Date: 2017-10-12)

Description

The stack-clash advisory for Qualys cited Solaris as a potential target for the exploit. In a 64-bit address space, we do indeed map in ld.so almost immediately after the stack segment. A much larger guard segment of some time would be nice to serve as a mitigation.

Comments

Comment by Former user
Created at 2017-09-22T21:53:24.000Z

One of my primary test programs was this stack boundary explorer:

#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
#include <strings.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/resource.h>

#define MIN(a,b) ((a) > (b)) ? (b) : (a);

jmp_buf env;

void
segv_handler(int sig, siginfo_t *info, void *p)
{
        longjmp(env, 1);
}

uintptr_t
stack_walk(uintptr_t start, uintptr_t len)
{
        volatile uintptr_t pos = 0;
        const uintptr_t walksize = 0x200;

        printf("start:\t%p\t%p\n", start, len);
        if (setjmp(env)) {
                printf("pass:\t%p - %p\n", start, pos);
                return (start - (pos - walksize));
        }

        for (pos = 0; pos < len; pos += walksize) {
                volatile int *data = (int *)(start - pos);

                *data = 0;
        }
        return (start - (pos - walksize));
}

void
setup_sig()
{
        struct sigaction sa;

        bzero(&sa, sizeof (sa));
        sa.sa_sigaction = segv_handler;
        sa.sa_flags = SA_NODEFER;


        if (sigaction(SIGSEGV, &sa, NULL)) {
                perror("sigaction");
                exit(1);
        }
}

int
main()
{
        uintptr_t start, end, prev;
        struct rlimit rl;
        char b;

        setup_sig();
        getrlimit(RLIMIT_STACK, &rl);

        /* pause for any inspection before stack walk */
        read(0, &b, 1);

        /* round up to the next page so we don't crush our own frame */
        start = ((uintptr_t)&start  - 0x1fff) & ~0xfff;
        end = stack_walk(start, rl.rlim_cur);

        printf("start:\t%p\nend:\t%p\n", start, end);

        /* pause for any inspection before stack expansion */
        read(0, &b, 1);

        while (rl.rlim_cur < rl.rlim_max) {
                rl.rlim_cur += 0x1000;
                prev = end;

                if (setrlimit(RLIMIT_STACK, &rl) != 0) {
                        break;
                }
                end = stack_walk(start, rl.rlim_cur);
                printf("start:\t%p\nend:\t%p\n", start, end);
                if (prev == end) {
                        break;
                }
        }

        /* pause for any inspection before exiting */
        read(0, &b, 1);

        return 0;
}

It has a few blocking reads to make it easier to examine the state of the AS. It performs a number of walks over the stack, trying to find its end. After the initial search, it'll attempt to grow the stack limit until it's no longer allowed. This confirms that the stack guard is shrunk as expected, but only down to the minimum size.


Comment by Former user
Created at 2017-09-22T21:55:29.000Z

That program was also used to ensure that a low ulimit on virtual size did not prevent 64-bit programs from running due to the stack guard segment being in their AS. With the appropriate exception logic in place, seg_hole is completely ignored when it comes to AS size accounting.


Comment by Former user
Created at 2017-09-22T21:58:13.000Z

Processes with the stack guard emit expected results when core files are requested (via gcore or termination). Like live pmap inspection, seg_hole segments not included in the core.


Comment by Former user
Created at 2017-09-28T15:37:23.000Z

illumos-joyent commit dd35f9f (branch master, by Patrick Mooney)

OS-6323 want stack-clash mitigation
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Alex Wilson <alex.wilson@joyent.com>
Approved by: Alex Wilson <alex.wilson@joyent.com>


Comment by Former user
Created at 2017-09-28T19:30:01.000Z

illumos-joyent commit 5d95817 (branch master, by Patrick Mooney)

OS-6323 want stack-clash mitigation [fix missing parens]
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Alex Wilson <alex.wilson@joyent.com>
Approved by: Alex Wilson <alex.wilson@joyent.com>