|
COMMAND kernel SYSTEMS AFFECTED OpenBSD 2.9 OpenBSD 3.0 PROBLEM Marco Peereboom found following : while coding in userland, he crashes down the kernel... Here is the code : [root@corona src]# cat crashme.c #include #include #include #include #include #include #include /* globals */ int fd[8]; /* temp pipe file descriptors */ int fd_real[4]; /* real pipe\'s */ static int __DEBUG__ = 0; static int __SYSLOG__ = 0; void enable_debug(void) { __DEBUG__ = 1; } void disable_debug(void) { __DEBUG__ = 0; } void enable_syslog(void) { __SYSLOG__ = 1; } void disable_syslog(void) { __SYSLOG__ = 0; } void s_fprintf(FILE *file, const char *fmt, ...) { va_list ap; if (__DEBUG__) { fflush(file); va_start(ap, fmt); vfprintf(file, fmt, ap); va_end(ap); fflush(file); } if (__SYSLOG__) { va_start(ap, fmt); vsyslog(LOG_INFO, fmt, ap); va_end(ap); } } void *s_malloc(size_t size) { char serr[40]; /* can not allocate more mem so lets use this ugly beast */ void *p; if (__DEBUG__ || __SYSLOG__) { s_fprintf(stderr, \"PID=%-5i PPID=%-5i: malloc(%i)\\n\", getpid(), getppid(), size); } if ((p = malloc(size)) == NULL ) { sprintf(serr,\"PID=%i, Could not allocate memory\", getpid()); perror(serr); exit(6); } return p; } void s_perror(const char *str) { char *buf; if (__DEBUG__ || __SYSLOG__) { s_fprintf(stderr, \"PID=%-5i PPID=%-5i: perror(%s)\\n\", getpid(), getppid(), str); } buf = s_malloc(11 + strlen(str)); /* PID=%-5i = 11 chars */ sprintf(buf, \"PID=%-5i %s\", getpid(), str); perror(buf); free(buf); } void s_pipe(int *fd) { if (__DEBUG__ || __SYSLOG__) { s_fprintf(stderr, \"PID=%-5i PPID=%-5i: pipe(%x)\\n\", getpid(), getppid(), (unsigned int)fd); } if (pipe(fd) == -1) { s_perror(\"Could not create pipe\"); exit(3); } } int main(int argc, char **argv) { enable_debug(); enable_syslog(); fprintf(stderr, \"Before pipe\\n\"); s_pipe(NULL); /* test if s_pipe exits */ fprintf(stderr, \"Will never reach this\\n\"); return 0; } SOLUTION Marco Peereboom explains : I tried to debug the kernel and I was partially successful at that. I definitively need more practice at BSD kernel debugging ;) but I did find what was wrong. We were releasing the user mode retval instead of the *real* rval kernel mode values. And since retval was pointing at NULL bad things happened. Anyway here is the patch for 3.0: [root@corona kern]# diff -u uipc_syscalls.c.old uipc_syscalls.c --- uipc_syscalls.c.old Sun Dec 2 10:48:21 2001 +++ uipc_syscalls.c Sun Dec 2 10:48:48 2001 @@ -903,8 +903,8 @@ error = copyout((caddr_t)fds, (caddr_t)SCARG(uap, fdp), 2 * sizeof (int)); if (error) { - fdrelease(p, retval[0]); - fdrelease(p, retval[1]); + fdrelease(p, rval[0]); + fdrelease(p, rval[1]); } return (error); } Here is the patch for 2.9: [root@vuurmuur kern]# diff -u uipc_syscalls.c.old uipc_syscalls.c --- uipc_syscalls.c.old Sun Dec 2 11:00:51 2001 +++ uipc_syscalls.c Sun Dec 2 11:01:17 2001 @@ -886,8 +886,8 @@ error = copyout((caddr_t)fds, (caddr_t)SCARG(uap, fdp), 2 * sizeof (int)); if (error) { - fdrelease(p, retval[0]); - fdrelease(p, retval[1]); + fdrelease(p, rval[0]); + fdrelease(p, rval[1]); } return (error); }