This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Could we harden GCC's stack smashing? (Re: Adam Zabrocki's Adventure with stack smashing protection)


Hello,

Adam Zabrocki's Adventure with stack smashing protection at
(http://blog.pi3.com.pl/?p=485 ) is kind of interesting. It lists some possible
weaknesses in GCC's -fstack-protector. Given that the weaknesses happen when the
stack has already been smashed I do not think they are critical but they do bug
me. I think that the issues happen due to the fundamental problem with the
approach that GCC's reporting method is taking. Instead of dealing with the
messed up state of the process it could exec a whole new process or simply
abort. We could also actually raise our own SIGSEGV signal. I coded up a small
illustration of how the exec strategy would work.

Thank you,
Steven Stewart-Gallus

#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

/*
 * In a real implementation this would be a real crash reporting
 * program. It would use /proc to examine debugging information such
 * as the command line. It could also do ptrace debugger stuff. It
 * could also be set by a command line option.
 */
#define CRASH_REPORTER "/bin/echo"

void stack_overflow(void);

int main()
{
    stack_overflow();
}

void stack_overflow(void)
{
    /*
     * As soon as possible give control over to a fresh crash reporter
     * instance. If any bad things happen abort immmediately and don't
     * risk compromise due to an attack from an enemy.
     */

    /*
     * Fork a copy of the program to be debugged from the crash
     * reporter instance. The copy of the program must be the child
     * because certain systems are hardened to only allow parents of
     * the processes to do certain debugging tasks.
     */
    pid_t child = fork();
    if (-1 == child) {
        abort();
    }

    if (0 == child) {
        raise(SIGSTOP);
        abort();
    }

    /* Don't bother with sprintf to minimize the chance of attacks. */
    char child_string[sizeof child + 1];
    memcpy(child_string, &child, sizeof child);
    child_string[sizeof child] = '\0';

    /*
     * execve the crash reporter to use the thinnest possible wrapper
     * over the system call.
     */
    char * argv[] = {
        (char *) CRASH_REPORTER,
        child_string,
        NULL
    };
    char * envp[] = { NULL };
    execve(CRASH_REPORTER, argv, envp);
    abort();
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]