>Synopsis: RLIMIT_CPU doesn't work reliably on mostly idle systems
>Category: system
>Environment:
        System      : OpenBSD 7.3
        Details     : OpenBSD 7.3 (GENERIC.MP) #1242: Sat Mar 25 18:04:31 MDT 
2023
                         
dera...@octeon.openbsd.org:/usr/src/sys/arch/octeon/compile/GENERIC.MP

        Architecture: OpenBSD.octeon
        Machine     : octeon
>Description:

RLIMIT_CPU doesn't work reliably when few/no syscalls are made on an
otherwise idle system (aside from the test process using up CPU).
It can take 20-50s to fire SIGKILL with rlim_max=9 (and the SIGXCPU
from rlim_cur=1 won't even fire).

I can reproduce this on a private amd64 VM and also on gcc231
on GCC compiler farm <https://cfarm.tetaneutral.net/>.
I can't reproduce this on a busy system like gcc220 on cfarm,
however.

>How-To-Repeat:

Following is a standalone C program which demonstrates the problem on
a mostly idle system:
/*
 * Most reliably reproduced with compiler optimizations disabled:
 *
 *   cc -o rlimit_cpu -ggdb3 -Wall rlimit_cpu.c
 *
 * Neither SIGXCPU (from rlim_cur) nor SIGKILL (from rlim_max)
 * with RLIMIT_CPU set seem to fire reliably with few syscalls being made.
 * On an otherwise idle system, it can take many more seconds (20-50s)
 * than expected when rlim_max=9 (SIGXCPU doesn't even happen).
 * Best case is 2 seconds for SIGXCPU when rlim_cur=1 on a busy system
 * which is understandable due to kernel accounting delays.
 *
 * I rely on RLIMIT_CPU to protect systems from pathological userspace
 * code (diff generation, regexps, etc)
 *
 * Testing on cfarm <https://cfarm.tetaneutral.net/> machines,
 * the issue is visible on a mostly-idle 4-core gcc231 mips64
 * but doesn't seem to happen on the busy 12-core gcc220 machine
 * (only 2 seconds for XCPU w/ rlim_cur=1)
 */
#include <sys/resource.h>
#include <assert.h>
#include <signal.h>
#include <unistd.h>

static void sigxcpu(int sig)
{
        write(1, "SIGXCPU\n", 8);
        _exit(1);
}

static volatile size_t nr; // volatile to disable optimizations
int main(void)
{
        struct rlimit rlim = { .rlim_cur = 1, .rlim_max = 9 };
        int rc;

        signal(SIGXCPU, sigxcpu);
        rc = setrlimit(RLIMIT_CPU, &rlim);
        assert(rc == 0);

        /*
         * adding some time, times, and write syscalls improve likelyhood of
         * of rlimit signals firing in a timely manner.  writes to /dev/null
         * seems less-likely to trigger than writes to the terminal or
         * regular file.
         */
        for (;; nr++) {
        }

        return 0;
}

>Fix:
        Making more syscalls can workaround the problem, but that's not
an option when dealing with userspace-heavy code like pathological regexps.


dmesg:
OpenBSD 7.3 (GENERIC.MP) #1242: Sat Mar 25 18:04:31 MDT 2023
    dera...@octeon.openbsd.org:/usr/src/sys/arch/octeon/compile/GENERIC.MP
real mem = 1073741824 (1024MB)
avail mem = 1035304960 (987MB)
random: good seed from bootblocks
mainbus0 at root: board 20300 rev 0.15, model cavium,ubnt_e300
cpu0 at mainbus0: CN70xx/CN71xx CPU rev 0.2 1000 MHz, CN70xx/CN71xx FPU rev 0.0
cpu0: cache L1-I 78KB 39 way D 32KB 32 way, L2 1024KB 8 way
cpu1 at mainbus0: CN70xx/CN71xx CPU rev 0.2 1000 MHz, CN70xx/CN71xx FPU rev 0.0
cpu1: cache L1-I 78KB 39 way D 32KB 32 way, L2 1024KB 8 way
cpu2 at mainbus0: CN70xx/CN71xx CPU rev 0.2 1000 MHz, CN70xx/CN71xx FPU rev 0.0
cpu2: cache L1-I 78KB 39 way D 32KB 32 way, L2 1024KB 8 way
cpu3 at mainbus0: CN70xx/CN71xx CPU rev 0.2 1000 MHz, CN70xx/CN71xx FPU rev 0.0
cpu3: cache L1-I 78KB 39 way D 32KB 32 way, L2 1024KB 8 way
clock0 at mainbus0: int 5
octcrypto0 at mainbus0
iobus0 at mainbus0
simplebus0 at iobus0: "soc"
"bootbus" at simplebus0 not configured
octciu0 at simplebus0
octcib0 at simplebus0: max-bits 23
octcib1 at simplebus0: max-bits 12
octcib2 at simplebus0: max-bits 6
octcib3 at simplebus0: max-bits 15
octcib4 at simplebus0: max-bits 4
octcib5 at simplebus0: max-bits 11
octcib6 at simplebus0: max-bits 11
octgpio0 at simplebus0: 20 pins, xbit 16
octsmi0 at simplebus0
octsmi1 at simplebus0
octpip0 at simplebus0
octgmx0 at octpip0 interface 0
cnmac0 at octgmx0: port 0 SGMII, address e0:63:da:c0:62:27
ukphy0 at cnmac0 phy 4: Generic IEEE 802.3u media interface, rev. 2: OUI 
0x0001c1, model 0x000c
cnmac1 at octgmx0: port 1 SGMII, address e0:63:da:c0:62:28
ukphy1 at cnmac1 phy 5: Generic IEEE 802.3u media interface, rev. 2: OUI 
0x0001c1, model 0x000c
cnmac2 at octgmx0: port 2 SGMII, address e0:63:da:c0:62:29
ukphy2 at cnmac2 phy 6: Generic IEEE 802.3u media interface, rev. 2: OUI 
0x0001c1, model 0x000c
cnmac3 at octgmx0: port 3 SGMII, address e0:63:da:c0:62:2a
ukphy3 at cnmac3 phy 7: Generic IEEE 802.3u media interface, rev. 2: OUI 
0x0001c1, model 0x000c
octsctl0 at simplebus0: disabled
octxctl0 at simplebus0: DWC3 rev 0x250a
xhci0 at octxctl0, xHCI 1.0
usb0 at xhci0: USB revision 3.0
uhub0 at usb0 configuration 1 interface 0 "Generic xHCI root hub" rev 3.00/1.00 
addr 1
octxctl1 at simplebus0: DWC3 rev 0x250a
xhci1 at octxctl1, xHCI 1.0
usb1 at xhci1: USB revision 3.0
uhub1 at usb1 configuration 1 interface 0 "Generic xHCI root hub" rev 3.00/1.00 
addr 1
"i2c" at simplebus0 not configured
"i2c" at simplebus0 not configured
com0 at simplebus0: ns16550a, 64 byte fifo
com0: console
com1 at simplebus0: ns16550a, 64 byte fifo
com1: probed fifo depth: 0 bytes
octmmc0 at simplebus0
sdmmc0 at octmmc0: 8-bit, mmc high-speed
"spi" at simplebus0 not configured
"ocla0" at simplebus0 not configured
"dma-engine" at simplebus0 not configured
"dma-engine" at simplebus0 not configured
octrng0 at iobus0 base 0x1400000000000 irq 0
octpcie0 at iobus0: 3 ports
octpcie0 port 0: link timeout
octpcie0 port 1: reset timeout
octpcie0 port 2: reset timeout
umass0 at uhub0 port 2 configuration 1 interface 0 "asmedia ASMT1153E" rev 
3.00/1.00 addr 2
umass0: using SCSI over Bulk-Only
scsibus0 at umass0: 2 targets, initiator 0
sd0 at scsibus0 targ 1 lun 0: <asmedia, ASMT1153E, 0> 
serial.174c55aa123456789010
sd0: 953869MB, 512 bytes/sector, 1953525168 sectors
scsibus1 at sdmmc0: 2 targets, initiator 0
sd1 at scsibus1 targ 1 lun 0: <Kingston, MMC4GB, 0000> removable
sd1: 3728MB, 512 bytes/sector, 7634944 sectors
vscsi0 at root
scsibus2 at vscsi0: 256 targets
softraid0 at root
scsibus3 at softraid0: 256 targets
root on sd0a (12d0a02327a609ac.a) swap on sd0b dump on sd0b
WARNING: /mnt was not properly unmounted
WARNING: CHECK AND RESET THE DATE!

usbdevs:
usbdevs: no USB controllers found

Reply via email to