>Synopsis:      semop with nsops > 10 and SEM_UNDO flag causes kernel panic
>Category:      kernel
>Environment:
        System      : OpenBSD 5.1
        Details     : OpenBSD 5.1 (GENERIC) #181: Sun Feb 12 09:35:53 MST 2012

[email protected]:/usr/src/sys/arch/amd64/compile/GENERIC

        Architecture: OpenBSD.amd64
        Machine     : amd64
>Description:
    A semop() with an array of > kern.seminfo.semume semaphore operations, each
    operating on a different semaphore in a set of >
kern.seminfo.semume semaphores,
    and each with the SEM_UNDO flag, causes a kernel panic.

>How-To-Repeat:

    The following program creates a set of NSEMS semaphores; initializes them
    to 0; and performs an array of NSEMS operations, one per semaphore, each
    with the SEM_UNDO flag:

    ########################################
    /* semop.c */
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/sem.h>
    #include <sys/stat.h>

    int main(void) {
        unsigned short array[NSEMS];
        struct sembuf sops[NSEMS];
        int i, semid;
        union semun {
            int val;
            struct semid_ds *buf;
            unsigned short  *array;
        } arg;

        if ((semid = semget(IPC_PRIVATE, NSEMS,
                            IPC_CREAT | S_IRUSR | S_IWUSR)) == -1) {
            perror("semget");
            exit(EXIT_FAILURE);
        }

        for (i = 0; i < NSEMS; i++)
            array[i] = 1;

        arg.array = array;

        if (semctl(semid, 0, SETALL, arg) == -1) {
            perror("semctl SETALL");
            exit(EXIT_FAILURE);
        }

        for (i = 0; i < NSEMS; i++) {
            sops[i].sem_num = i;
            sops[i].sem_op = 1;
            sops[i].sem_flg = SEM_UNDO;
        }

        if (semop(semid, sops, NSEMS) == -1) {
            perror("semop");
            exit(EXIT_FAILURE);
        }

        /* clean up */
        if (semctl(semid, 0, IPC_RMID) == -1) {
            perror("semctl IPC_RMID");
            exit(EXIT_FAILURE);
        }

        return 0;
    }
    ########################################

    This program works when NSEMS <= 10 (the value of kern.seminfo.semume)

    ########################################
    $ sysctl kern.seminfo.semume
    kern.seminfo.semume=10
    $ cc -DNSEMS=10 semop.c
    $ ./a.out
    ########################################

    However, a kernel panic results when semume < NSEMS
    (and NSEMS is <= min(semopm, semmns))

    ########################################
    $ cc -DNSEMS=11 semop.c
    uvm_fault(0xffffffff80cf9c00, 0xffff80000000f000, 0, 1) -> e
    kernel: page fault trap, code=0
    Stopped at      sys_semop+0x474:        testb $0x10,0xffffffffffffffff(%rbx)
    ddb> trace
    sys_semop() at sys_semop+0x474
    syscall() at syscall+0x165
    --- syscall (number 290) ---
    end of kernel
    end trace frame: 0x7f7ffffcdb40, count: -2
    0x20899f4ba:
    ddb>
    ########################################

    Alternatively, this bug can be succintly replicated using ipcmd, a
    command-line interface to SysV semaphores and message queues
    (available at https://ipcmd.googlecode.com/):

    1. Download & build (for the version 0.1.0 makefile, the "bin/ipcmd"
       target must be explicitly specified, as OpenBSD 'make' seems to
       consider the ".POSIX:" line as the default target instead of a special
       target):

           $ cd ipcmd-0.1.0
           $ make bin/ipcmd CC=gcc CFLAGS=-std=c99

    2. Execute; e.g., demonstrating that with set of 11 semaphores, an array
       of 10 semaphore operations (each with the SEM_UNDO flag) succeeds,
       while an array of 11 such semaphore operations causes a kernel panic:

           $ export IPCMD_SEMID=$(bin/ipcmd semget -N 11)
           $ bin/ipcmd semctl setall 0
           $ bin/ipcmd semop -u 0:9=1
           $ bin/ipcmd semop -u 0:10=1
           ...kernel panic...

>Fix:
        None. kern.seminfo.semume is not a changeable value.

dmesg:
OpenBSD 5.1 (GENERIC) #181: Sun Feb 12 09:35:53 MST 2012
    [email protected]:/usr/src/sys/arch/amd64/compile/GENERIC
real mem = 535756800 (510MB)
avail mem = 507420672 (483MB)
mainbus0 at root
bios0 at mainbus0: SMBIOS rev. 2.5 @ 0xe1000 (5 entries)
bios0: vendor innotek GmbH version "VirtualBox" date 12/01/2006
bios0: innotek GmbH VirtualBox
acpi0 at bios0: rev 2
acpi0: sleep states S0 S5
acpi0: tables DSDT FACP SSDT
acpi0: wakeup devices
acpitimer0 at acpi0: 3579545 Hz, 32 bits
acpiprt0 at acpi0: bus 0 (PCI0)
acpibat0 at acpi0: BAT0 not present
acpiac0 at acpi0: AC unit online
cpu0 at mainbus0: (uniprocessor)
cpu0: Intel(R) Core(TM)2 Duo CPU T7300 @ 2.00GHz, 1980.05 MHz
cpu0: 
FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,MMX,FXSR,SSE,SSE2,SSE3,MWAIT,SSSE3,NXE,LONG,LAHF
cpu0: 4MB 64b/line 16-way L2 cache
pci0 at mainbus0 bus 0
pchb0 at pci0 dev 0 function 0 "Intel 82441FX" rev 0x02
pcib0 at pci0 dev 1 function 0 "Intel 82371SB ISA" rev 0x00
pciide0 at pci0 dev 1 function 1 "Intel 82371AB IDE" rev 0x01: DMA,
channel 0 configured to compatibility, channel 1 configured to
compatibility
wd0 at pciide0 channel 0 drive 0: <VBOX HARDDISK>
wd0: 128-sector PIO, LBA, 8192MB, 16777216 sectors
wd0(pciide0:0:0): using PIO mode 4, Ultra-DMA mode 2
pciide0: channel 1 disabled (no drives)
vga1 at pci0 dev 2 function 0 "InnoTek VirtualBox Graphics Adapter" rev 0x00
wsdisplay0 at vga1 mux 1: console (80x25, vt100 emulation)
wsdisplay0: screen 1-5 added (80x25, vt100 emulation)
em0 at pci0 dev 3 function 0 "Intel PRO/1000MT (82540EM)" rev 0x02:
irq 10, address 08:00:27:d6:dc:16
"InnoTek VirtualBox Guest Service" rev 0x00 at pci0 dev 4 function 0
not configured
auich0 at pci0 dev 5 function 0 "Intel 82801AA AC97" rev 0x01: irq 5, ICH AC97
ac97: codec id 0x83847600 (SigmaTel STAC9700)
audio0 at auich0
ohci0 at pci0 dev 6 function 0 "Apple Intrepid USB" rev 0x00: irq 11,
version 1.0
piixpm0 at pci0 dev 7 function 0 "Intel 82371AB Power" rev 0x08: SMBus disabled
isa0 at pcib0
isadma0 at isa0
com0 at isa0 port 0x3f8/8 irq 4: ns16550a, 16 byte fifo
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
spkr0 at pcppi0
usb0 at ohci0: USB revision 1.0
uhub0 at usb0 "Apple OHCI root hub" rev 1.00/1.00 addr 1
nvram: invalid checksum
mtrr: CPU supports MTRRs but not enabled
vscsi0 at root
scsibus0 at vscsi0: 256 targets
softraid0 at root
scsibus1 at softraid0: 256 targets
root on wd0a (ecc8c01561c4bf77.a) swap on wd0b dump on wd0b

usbdevs:
Controller /dev/usb0:
addr 1: full speed, self powered, config 1, OHCI root hub(0x0000),
Apple(0x106b), rev 1.00
 port 1 powered
 port 2 powered
 port 3 powered
 port 4 powered
 port 5 powered
 port 6 powered
 port 7 powered
 port 8 powered


--
Nathan Weeks
Systems Analyst
Iowa State University - IT Services (HPC Group)
http://weeks.public.iastate.edu/

Reply via email to