Re: 1023rd thread crashes 2.4.0-test8 from non-root user

From: Mark Hahn (hahn@coffee.psychology.mcmaster.ca)
Date: Sun Sep 24 2000 - 23:40:09 EST


> The problem is large numbers of threads in 2.4.0-test8 can result in a
> hard crash of the entire kernel. This can be done as a non-root user.

this appears to be reproducable (128M duron, haven't tried intel UP/SMP):

// code derived from a clone demo in lmbench.
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/user.h>
#include <sys/wait.h>
#include <sched.h>
#include <syscall.h>
#include <errno.h>
#include <sys/time.h>
#include <asm/atomic.h>

int
do_clone(void (*fn)(void *), void *data, char *stack) {
    long retval;

    *--(void**)stack = data;

    __asm__ __volatile__(
        "int $0x80\n\t" /* Linux/i386 system call */
        "testl %0,%0\n\t" /* check return value */
        "jne 1f\n\t" /* jump if parent */
        "call *%3\n\t" /* start subthread function */
        "movl %2,%0\n\t"
        "int $0x80\n" /* exit system call: exit subthread */
        "1:\t"
        :"=a" (retval)
        :"0" (__NR_clone),"i" (__NR_exit),
        "r" (fn),
        "b" (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD),
        "c" (stack));
    
    if (retval < 0) {
        errno = -retval;
        retval = -1;
    }
    return retval;
}

atomic_t counter = ATOMIC_INIT(0);
atomic_t die = ATOMIC_INIT(0);

void
kid(void *data) {
    atomic_inc(&counter);
    while (!atomic_read(&die))
        sleep(1);
    exit(0);
}

double
gtod() {
    struct timeval tv;
    gettimeofday(&tv,0);
    return tv.tv_sec + 1e-6 * tv.tv_usec;
}

int
main() {
    const unsigned n = 2000;
    const int stackPerThread = 4096;
    char stack[n * stackPerThread];
    char *stacktop = stack + sizeof(stack) - 1;

    double before = gtod();
    for (unsigned i=0; i<n; i++) {
        if (do_clone(kid, (void*) "hey", stacktop) < 0) {
            perror("clone");
            exit(1);
        }
        stacktop -= 4096;
    }
    double elapsed = gtod() - before;
    printf("OK, created %d threads in %f seconds (%f/second)\n",
           n, elapsed, n/elapsed);
    printf("hit any key to tell them all to die..."); fflush(stdout);
    getchar();
    atomic_set(&die,1);
    for (int c=0; c<atomic_read(&counter); c++)
        wait(0);
    printf("OK, all dead\n");
    return 0;
}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sat Sep 30 2000 - 21:00:13 EST