Discussion:
canaries can cause malloc with a size of 0 to hang
Carlin Bingham
2017-07-07 00:31:27 UTC
Permalink
Synopsis: when canaries are enabled `malloc(0)' sometimes hangs
Category: system
System : OpenBSD 6.1
Details : OpenBSD 6.1-current (GENERIC.MP) #88: Wed Jul 5 23:16:11 MDT 2017
***@amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/GENERIC.MP

Architecture: OpenBSD.amd64
Machine : amd64
If malloc canaries are enabled in malloc.conf or MALLOC_OPTIONS
a call to malloc(3) with a size of 0 sometimes never returns.
Call `malloc(0)' enough and it should eventually happen.

In the wild, VLC seems to hang consistently at startup from
this.

Synthetic example:

$ cat stall.c && cc -o stall stall.c
#include <stdio.h>
#include <stdlib.h>

int
main()
{
int i;

printf("start\n");
for (i = 0; i < 5000000; i++) {
malloc(0);
}
printf("done\n");
}

$ time ./stall
start
done
0m00.36s real 0m00.30s user 0m00.05s system

$ MALLOC_OPTIONS="C" time ./stall
start
^CCommand terminated abnormally.
91.27 real 91.27 user 0.00 sys
MALLOC_OPTIONS="Sc" works as a work-around.


dmesg:
OpenBSD 6.1-current (GENERIC.MP) #88: Wed Jul 5 23:16:11 MDT 2017
***@amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/GENERIC.MP
real mem = 16835846144 (16055MB)
avail mem = 16319807488 (15563MB)
mpath0 at root
scsibus0 at mpath0: 256 targets
mainbus0 at root
bios0 at mainbus0: SMBIOS rev. 2.7 @ 0xacd3d000 (66 entries)
bios0: vendor LENOVO version "GLET70WW (2.24 )" date 05/21/2014
bios0: LENOVO 20ANCTO1WW
acpi0 at bios0: rev 2
acpi0: sleep states S0 S3 S4 S5
acpi0: tables DSDT FACP DBGP ECDT HPET APIC MCFG SSDT SSDT SSDT SSDT SSDT SSDT SSDT PCCT SSDT UEFI MSDM ASF! BATB FPDT UEFI
acpi0: wakeup devices LID_(S4) SLPB(S3) IGBE(S4) EXP2(S4) EXP3(S4) XHCI(S3) EHC1(S3) EHC2(S3)
acpitimer0 at acpi0: 3579545 Hz, 24 bits
acpiec0 at acpi0
acpihpet0 at acpi0: 14318179 Hz
acpimadt0 at acpi0 addr 0xfee00000: PC-AT compat
cpu0 at mainbus0: apid 0 (boot processor)
cpu0: Intel(R) Core(TM) i7-4710MQ CPU @ 2.50GHz, 2494.55 MHz
cpu0: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,SDBG,FMA3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,MOVBE,POPCNT,DEADLINE,AES,XSAVE,AVX,F16C,RDRAND,NXE,PAGE1GB,RDTSCP,LONG,LAHF,ABM,PERF,ITSC,FSGSBASE,BMI1,AVX2,SMEP,BMI2,ERMS,INVPCID,SENSOR,ARAT
cpu0: 256KB 64b/line 8-way L2 cache
cpu0: TSC frequency 2494554840 Hz
cpu0: smt 0, core 0, package 0
mtrr: Pentium Pro MTRR support, 10 var ranges, 88 fixed ranges
cpu0: apic clock running at 99MHz
cpu0: mwait min=64, max=64, C-substates=0.2.1.2.4, IBE
cpu1 at mainbus0: apid 1 (application processor)
cpu1: Intel(R) Core(TM) i7-4710MQ CPU @ 2.50GHz, 2494.22 MHz
cpu1: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,SDBG,FMA3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,MOVBE,POPCNT,DEADLINE,AES,XSAVE,AVX,F16C,RDRAND,NXE,PAGE1GB,RDTSCP,LONG,LAHF,ABM,PERF,ITSC,FSGSBASE,BMI1,AVX2,SMEP,BMI2,ERMS,INVPCID,SENSOR,ARAT
cpu1: 256KB 64b/line 8-way L2 cache
cpu1: smt 1, core 0, package 0
cpu2 at mainbus0: apid 2 (application processor)
cpu2: Intel(R) Core(TM) i7-4710MQ CPU @ 2.50GHz, 2494.22 MHz
cpu2: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,SDBG,FMA3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,MOVBE,POPCNT,DEADLINE,AES,XSAVE,AVX,F16C,RDRAND,NXE,PAGE1GB,RDTSCP,LONG,LAHF,ABM,PERF,ITSC,FSGSBASE,BMI1,AVX2,SMEP,BMI2,ERMS,INVPCID,SENSOR,ARAT
cpu2: 256KB 64b/line 8-way L2 cache
cpu2: smt 0, core 1, package 0
cpu3 at mainbus0: apid 3 (application processor)
cpu3: Intel(R) Core(TM) i7-4710MQ CPU @ 2.50GHz, 2494.22 MHz
cpu3: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,SDBG,FMA3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,MOVBE,POPCNT,DEADLINE,AES,XSAVE,AVX,F16C,RDRAND,NXE,PAGE1GB,RDTSCP,LONG,LAHF,ABM,PERF,ITSC,FSGSBASE,BMI1,AVX2,SMEP,BMI2,ERMS,INVPCID,SENSOR,ARAT
cpu3: 256KB 64b/line 8-way L2 cache
cpu3: smt 1, core 1, package 0
cpu4 at mainbus0: apid 4 (application processor)
cpu4: Intel(R) Core(TM) i7-4710MQ CPU @ 2.50GHz, 2494.22 MHz
cpu4: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,SDBG,FMA3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,MOVBE,POPCNT,DEADLINE,AES,XSAVE,AVX,F16C,RDRAND,NXE,PAGE1GB,RDTSCP,LONG,LAHF,ABM,PERF,ITSC,FSGSBASE,BMI1,AVX2,SMEP,BMI2,ERMS,INVPCID,SENSOR,ARAT
cpu4: 256KB 64b/line 8-way L2 cache
cpu4: smt 0, core 2, package 0
cpu5 at mainbus0: apid 5 (application processor)
cpu5: Intel(R) Core(TM) i7-4710MQ CPU @ 2.50GHz, 2494.23 MHz
cpu5: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,SDBG,FMA3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,MOVBE,POPCNT,DEADLINE,AES,XSAVE,AVX,F16C,RDRAND,NXE,PAGE1GB,RDTSCP,LONG,LAHF,ABM,PERF,ITSC,FSGSBASE,BMI1,AVX2,SMEP,BMI2,ERMS,INVPCID,SENSOR,ARAT
cpu5: 256KB 64b/line 8-way L2 cache
cpu5: smt 1, core 2, package 0
cpu6 at mainbus0: apid 6 (application processor)
cpu6: Intel(R) Core(TM) i7-4710MQ CPU @ 2.50GHz, 2494.22 MHz
cpu6: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,SDBG,FMA3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,MOVBE,POPCNT,DEADLINE,AES,XSAVE,AVX,F16C,RDRAND,NXE,PAGE1GB,RDTSCP,LONG,LAHF,ABM,PERF,ITSC,FSGSBASE,BMI1,AVX2,SMEP,BMI2,ERMS,INVPCID,SENSOR,ARAT
cpu6: 256KB 64b/line 8-way L2 cache
cpu6: smt 0, core 3, package 0
cpu7 at mainbus0: apid 7 (application processor)
cpu7: Intel(R) Core(TM) i7-4710MQ CPU @ 2.50GHz, 2494.23 MHz
cpu7: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,SDBG,FMA3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,MOVBE,POPCNT,DEADLINE,AES,XSAVE,AVX,F16C,RDRAND,NXE,PAGE1GB,RDTSCP,LONG,LAHF,ABM,PERF,ITSC,FSGSBASE,BMI1,AVX2,SMEP,BMI2,ERMS,INVPCID,SENSOR,ARAT
cpu7: 256KB 64b/line 8-way L2 cache
cpu7: smt 1, core 3, package 0
ioapic0 at mainbus0: apid 2 pa 0xfec00000, version 20, 24 pins
acpimcfg0 at acpi0 addr 0xf8000000, bus 0-63
acpiprt0 at acpi0: bus 0 (PCI0)
acpiprt1 at acpi0: bus -1 (PEG0)
acpiprt2 at acpi0: bus -1 (PEG_)
acpiprt3 at acpi0: bus 2 (EXP1)
acpiprt4 at acpi0: bus 3 (EXP2)
acpiprt5 at acpi0: bus -1 (EXP3)
acpiprt6 at acpi0: bus -1 (EXP6)
acpicpu0 at acpi0: C2(***@148 ***@0x33), C1(***@1 mwait.1), PSS
acpicpu1 at acpi0: C2(***@148 ***@0x33), C1(***@1 mwait.1), PSS
acpicpu2 at acpi0: C2(***@148 ***@0x33), C1(***@1 mwait.1), PSS
acpicpu3 at acpi0: C2(***@148 ***@0x33), C1(***@1 mwait.1), PSS
acpicpu4 at acpi0: C2(***@148 ***@0x33), C1(***@1 mwait.1), PSS
acpicpu5 at acpi0: C2(***@148 ***@0x33), C1(***@1 mwait.1), PSS
acpicpu6 at acpi0: C2(***@148 ***@0x33), C1(***@1 mwait.1), PSS
acpicpu7 at acpi0: C2(***@148 ***@0x33), C1(***@1 mwait.1), PSS
acpipwrres0 at acpi0: PUBS, resource for XHCI, EHC1, EHC2
acpipwrres1 at acpi0: NVP3, resource for PEG_
acpipwrres2 at acpi0: NVP2, resource for PEG_
acpitz0 at acpi0: critical temperature is 200 degC
acpibtn0 at acpi0: LID_
acpibtn1 at acpi0: SLPB
"LEN0071" at acpi0 not configured
"LEN0036" at acpi0 not configured
acpibat0 at acpi0: BAT0 model "45N1769" serial 224 type LION oem "SANYO"
acpiac0 at acpi0: AC unit online
acpithinkpad0 at acpi0
"PNP0C14" at acpi0 not configured
"PNP0C14" at acpi0 not configured
"PNP0C14" at acpi0 not configured
"INT340F" at acpi0 not configured
acpivideo0 at acpi0: VID_
acpivout at acpivideo0 not configured
acpivideo1 at acpi0: VID_
cpu0: Enhanced SpeedStep 2494 MHz: speeds: 2501, 2500, 2400, 2300, 2100, 2000, 1900, 1800, 1600, 1500, 1400, 1300, 1200, 1000, 900, 800 MHz
pci0 at mainbus0 bus 0
pchb0 at pci0 dev 0 function 0 "Intel Core 4G Host" rev 0x06
inteldrm0 at pci0 dev 2 function 0 "Intel HD Graphics 4600" rev 0x06
drm0 at inteldrm0
inteldrm0: msi
inteldrm0: 1920x1080, 32bpp
wsdisplay0 at inteldrm0 mux 1: console (std, vt100 emulation)
wsdisplay0: screen 1-5 added (std, vt100 emulation)
azalia0 at pci0 dev 3 function 0 "Intel Core 4G HD Audio" rev 0x06: msi
"Intel 8 Series MEI" rev 0x04 at pci0 dev 22 function 0 not configured
em0 at pci0 dev 25 function 0 "Intel I217-LM" rev 0x04: msi, address 28:d2:44:90:04:6c
ehci0 at pci0 dev 26 function 0 "Intel 8 Series USB" rev 0x04: apic 2 int 16
usb0 at ehci0: USB revision 2.0
uhub0 at usb0 configuration 1 interface 0 "Intel EHCI root hub" rev 2.00/1.00 addr 1
azalia1 at pci0 dev 27 function 0 "Intel 8 Series HD Audio" rev 0x04: msi
azalia1: codecs: Realtek ALC292
audio0 at azalia1
ppb0 at pci0 dev 28 function 0 "Intel 8 Series PCIE" rev 0xd4: msi
pci1 at ppb0 bus 2
rtsx0 at pci1 dev 0 function 0 "Realtek RTS5227 Card Reader" rev 0x01: msi
sdmmc0 at rtsx0: 4-bit
ppb1 at pci0 dev 28 function 1 "Intel 8 Series PCIE" rev 0xd4: msi
pci2 at ppb1 bus 3
iwm0 at pci2 dev 0 function 0 "Intel Dual Band Wireless AC 7260" rev 0x83, msi
ehci1 at pci0 dev 29 function 0 "Intel 8 Series USB" rev 0x04: apic 2 int 23
usb1 at ehci1: USB revision 2.0
uhub1 at usb1 configuration 1 interface 0 "Intel EHCI root hub" rev 2.00/1.00 addr 1
pcib0 at pci0 dev 31 function 0 "Intel QM87 LPC" rev 0x04
ahci0 at pci0 dev 31 function 2 "Intel 8 Series AHCI" rev 0x04: msi, AHCI 1.3
ahci0: port 0: 6.0Gb/s
ahci0: port 5: 1.5Gb/s
scsibus1 at ahci0: 32 targets
sd0 at scsibus1 targ 0 lun 0: <ATA, Samsung SSD 840, EXT0> SCSI3 0/direct fixed naa.50025388a05d9efb
sd0: 238475MB, 512 bytes/sector, 488397168 sectors, thin
cd0 at scsibus1 targ 5 lun 0: <HL-DT-ST, DVDRAM GU90N, LU20> ATAPI 5/cdrom removable
ichiic0 at pci0 dev 31 function 3 "Intel 8 Series SMBus" rev 0x04: apic 2 int 18
iic0 at ichiic0
spdmem0 at iic0 addr 0x50: 8GB DDR3 SDRAM PC3-12800 SO-DIMM
spdmem1 at iic0 addr 0x51: 8GB DDR3 SDRAM PC3-12800 SO-DIMM
isa0 at pcib0
isadma0 at isa0
pckbc0 at isa0 port 0x60/5 irq 1 irq 12
pckbd0 at pckbc0 (kbd slot)
wskbd0 at pckbd0: console keyboard, using wsdisplay0
pms0 at pckbc0 (aux slot)
wsmouse0 at pms0 mux 0
wsmouse1 at pms0 mux 0
pms0: Synaptics clickpad, firmware 8.1
pcppi0 at isa0 port 0x61
spkr0 at pcppi0
vmm0 at mainbus0: VMX/EPT
error: [drm:pid0:intel_uncore_check_errors] *ERROR* Unclaimed register before interrupt
uhub2 at uhub0 port 1 configuration 1 interface 0 "Intel Rate Matching Hub" rev 2.00/0.04 addr 2
ugen0 at uhub2 port 5 "Intel product 0x07dc" rev 2.00/0.01 addr 3
uvideo0 at uhub2 port 6 configuration 1 interface 0 "SunplusIT INC. Integrated Camera" rev 2.00/26.03 addr 4
video0 at uvideo0
uhub3 at uhub1 port 1 configuration 1 interface 0 "Intel Rate Matching Hub" rev 2.00/0.04 addr 2
sdmmc0: can't enable card
uhub4 at uhub3 port 1 configuration 1 interface 0 "Genesys Logic USB2.0 Hub" rev 2.00/32.98 addr 3
uhub5 at uhub4 port 1 configuration 1 interface 0 "Genesys Logic USB2.0 Hub" rev 2.00/32.98 addr 4
uhidev0 at uhub5 port 2 configuration 1 interface 0 "Logitech USB Receiver" rev 2.00/12.03 addr 5
uhidev0: iclass 3/1
ukbd0 at uhidev0: 8 variable keys, 6 key codes
wskbd1 at ukbd0 mux 1
wskbd1: connecting to wsdisplay0
uhidev1 at uhub5 port 2 configuration 1 interface 1 "Logitech USB Receiver" rev 2.00/12.03 addr 5
uhidev1: iclass 3/1, 8 report ids
ums0 at uhidev1 reportid 2: 16 buttons, Z and W dir
wsmouse2 at ums0 mux 0
uhid0 at uhidev1 reportid 3: input=4, output=0, feature=0
uhid1 at uhidev1 reportid 4: input=1, output=0, feature=0
uhid2 at uhidev1 reportid 8: input=1, output=0, feature=0
uhidev2 at uhub5 port 2 configuration 1 interface 2 "Logitech USB Receiver" rev 2.00/12.03 addr 5
uhidev2: iclass 3/0, 33 report ids
uhid3 at uhidev2 reportid 16: input=6, output=6, feature=0
uhid4 at uhidev2 reportid 17: input=19, output=19, feature=0
uhid5 at uhidev2 reportid 32: input=14, output=14, feature=0
uhid6 at uhidev2 reportid 33: input=31, output=31, feature=0
uhidev3 at uhub4 port 4 configuration 1 interface 0 "Holtek USB Keyboard" rev 1.10/1.10 addr 6
uhidev3: iclass 3/1
ukbd1 at uhidev3: 8 variable keys, 6 key codes
wskbd2 at ukbd1 mux 1
wskbd2: connecting to wsdisplay0
uhidev4 at uhub4 port 4 configuration 1 interface 1 "Holtek USB Keyboard" rev 1.10/1.10 addr 6
uhidev4: iclass 3/1, 2 report ids
uhid7 at uhidev4 reportid 1: input=6, output=0, feature=0
uhid8 at uhidev4 reportid 2: input=1, output=0, feature=0
vscsi0 at root
scsibus2 at vscsi0: 256 targets
softraid0 at root
scsibus3 at softraid0: 256 targets
sd1 at scsibus3 targ 1 lun 0: <OPENBSD, SR CRYPTO, 006> SCSI2 0/direct fixed
sd1: 236417MB, 512 bytes/sector, 484182507 sectors
root on sd1a (1082220374abdcb3.a) swap on sd1b dump on sd1b
iwm0: hw rev 0x140, fw ver 16.242414.0, address e8:2a:ea:60:e4:6f

usbdevs:
Controller /dev/usb0:
addr 1: high speed, self powered, config 1, EHCI root hub(0x0000), Intel(0x8086), rev 1.00
port 1 addr 2: high speed, self powered, config 1, Rate Matching Hub(0x8008), Intel(0x8087), rev 0.04
port 1 powered
port 2 powered
port 3 powered
port 4 powered
port 5 addr 3: full speed, self powered, config 1, product 0x07dc(0x07dc), Intel(0x8087), rev 0.01
port 6 addr 4: high speed, power 500 mA, config 1, Integrated Camera(0xb39a), SunplusIT INC.(0x04f2), rev 26.03
port 2 powered
port 3 powered
Controller /dev/usb1:
addr 1: high speed, self powered, config 1, EHCI root hub(0x0000), Intel(0x8086), rev 1.00
port 1 addr 2: high speed, self powered, config 1, Rate Matching Hub(0x8000), Intel(0x8087), rev 0.04
port 1 addr 3: high speed, self powered, config 1, USB2.0 Hub(0x0608), Genesys Logic(0x05e3), rev 32.98
port 1 addr 4: high speed, self powered, config 1, USB2.0 Hub(0x0608), Genesys Logic(0x05e3), rev 32.98
port 1 powered
port 2 addr 5: full speed, power 98 mA, config 1, USB Receiver(0xc52b), Logitech(0x046d), rev 12.03
port 3 powered
port 4 powered
port 2 powered
port 3 powered
port 4 addr 6: low speed, power 100 mA, config 1, USB Keyboard(0x0169), Holtek(0x04d9), rev 1.10
port 2 powered
port 3 addr 7: high speed, power 100 mA, config 1, Elements 10A2(0x10a2), Western Digital(0x1058), rev 10.33, iSerialNumber 575833314531334C58373832
port 4 powered
port 5 powered
port 6 powered
port 7 powered
port 8 powered
port 2 powered
port 3 powered
Ingo Schwarze
2017-07-07 02:27:30 UTC
Permalink
The end of the problem is that in malloc_bytes(), malloc.c line 981,
the code enters the double for loop with a bp having the inconvenient
property that in bp->bits, all sixteen entries are 0, causing the
inner for loop to spin indefinitely.

I must admit, though, that i have no idea what that means, and where
the problem starts leading to that ugly end: i clearly underestimated
the difficulty of reading malloc.c ... :-o

But maybe that rings a bell for somebody else.
Post by Carlin Bingham
Synopsis: when canaries are enabled `malloc(0)' sometimes hangs
Category: system
System : OpenBSD 6.1
Details : OpenBSD 6.1-current (GENERIC.MP) #88: Wed Jul 5 23:16:11 MDT 2017
Architecture: OpenBSD.amd64
Machine : amd64
If malloc canaries are enabled in malloc.conf or MALLOC_OPTIONS
a call to malloc(3) with a size of 0 sometimes never returns.
Call `malloc(0)' enough and it should eventually happen.
In the wild, VLC seems to hang consistently at startup from
this.
$ cat stall.c && cc -o stall stall.c
#include <stdio.h>
#include <stdlib.h>
int
main()
{
int i;
printf("start\n");
for (i = 0; i < 5000000; i++) {
malloc(0);
}
printf("done\n");
}
$ time ./stall
start
done
0m00.36s real 0m00.30s user 0m00.05s system
$ MALLOC_OPTIONS="C" time ./stall
start
^CCommand terminated abnormally.
91.27 real 91.27 user 0.00 sys
Otto Moerbeek
2017-07-07 06:35:39 UTC
Permalink
Post by Ingo Schwarze
The end of the problem is that in malloc_bytes(), malloc.c line 981,
the code enters the double for loop with a bp having the inconvenient
property that in bp->bits, all sixteen entries are 0, causing the
inner for loop to spin indefinitely.
I must admit, though, that i have no idea what that means, and where
the problem starts leading to that ugly end: i clearly underestimated
the difficulty of reading malloc.c ... :-o
But maybe that rings a bell for somebody else.
I guess that would be me ;)

WHat happens is the struct chunk_info says: there are chunks free, but
the bitmap itself says: no more.

I can reproduce, but I do not understand it yet. Will do some more
investigation,

-Otto
Post by Ingo Schwarze
Post by Carlin Bingham
Synopsis: when canaries are enabled `malloc(0)' sometimes hangs
Category: system
System : OpenBSD 6.1
Details : OpenBSD 6.1-current (GENERIC.MP) #88: Wed Jul 5 23:16:11 MDT 2017
Architecture: OpenBSD.amd64
Machine : amd64
If malloc canaries are enabled in malloc.conf or MALLOC_OPTIONS
a call to malloc(3) with a size of 0 sometimes never returns.
Call `malloc(0)' enough and it should eventually happen.
In the wild, VLC seems to hang consistently at startup from
this.
$ cat stall.c && cc -o stall stall.c
#include <stdio.h>
#include <stdlib.h>
int
main()
{
int i;
printf("start\n");
for (i = 0; i < 5000000; i++) {
malloc(0);
}
printf("done\n");
}
$ time ./stall
start
done
0m00.36s real 0m00.30s user 0m00.05s system
$ MALLOC_OPTIONS="C" time ./stall
start
^CCommand terminated abnormally.
91.27 real 91.27 user 0.00 sys
Otto Moerbeek
2017-07-07 06:52:42 UTC
Permalink
Post by Otto Moerbeek
Post by Ingo Schwarze
The end of the problem is that in malloc_bytes(), malloc.c line 981,
the code enters the double for loop with a bp having the inconvenient
property that in bp->bits, all sixteen entries are 0, causing the
inner for loop to spin indefinitely.
I must admit, though, that i have no idea what that means, and where
the problem starts leading to that ugly end: i clearly underestimated
the difficulty of reading malloc.c ... :-o
But maybe that rings a bell for somebody else.
I guess that would be me ;)
WHat happens is the struct chunk_info says: there are chunks free, but
the bitmap itself says: no more.
I can reproduce, but I do not understand it yet. Will do some more
investigation,
I think I found it: requested size is not recorded for malloc(0),
bp->offset is not initialized in that case. Other code is carefull not to
use ->offset for size == 0.
OA
-Otto

Index: malloc.c
===================================================================
RCS file: /cvs/src/lib/libc/stdlib/malloc.c,v
retrieving revision 1.226
diff -u -p -r1.226 malloc.c
--- malloc.c 19 Jun 2017 03:06:26 -0000 1.226
+++ malloc.c 7 Jul 2017 06:51:30 -0000
@@ -1013,7 +1013,7 @@ malloc_bytes(struct dir_info *d, size_t
/* Adjust to the real offset of that chunk */
k += (lp - bp->bits) * MALLOC_BITS;

- if (mopts.chunk_canaries)
+ if (mopts.chunk_canaries && size > 0)
bp->bits[bp->offset + k] = size;

k <<= bp->shift;
Otto Moerbeek
2017-07-07 06:54:48 UTC
Permalink
Post by Otto Moerbeek
Post by Otto Moerbeek
Post by Ingo Schwarze
The end of the problem is that in malloc_bytes(), malloc.c line 981,
the code enters the double for loop with a bp having the inconvenient
property that in bp->bits, all sixteen entries are 0, causing the
inner for loop to spin indefinitely.
I must admit, though, that i have no idea what that means, and where
the problem starts leading to that ugly end: i clearly underestimated
the difficulty of reading malloc.c ... :-o
But maybe that rings a bell for somebody else.
I guess that would be me ;)
WHat happens is the struct chunk_info says: there are chunks free, but
the bitmap itself says: no more.
I can reproduce, but I do not understand it yet. Will do some more
investigation,
I think I found it: requested size is not recorded for malloc(0),
bp->offset is not initialized in that case. Other code is carefull not to
use ->offset for size == 0.
OA
I have no idea who inserted "OA" here ;-)
Post by Otto Moerbeek
-Otto
Index: malloc.c
===================================================================
RCS file: /cvs/src/lib/libc/stdlib/malloc.c,v
retrieving revision 1.226
diff -u -p -r1.226 malloc.c
--- malloc.c 19 Jun 2017 03:06:26 -0000 1.226
+++ malloc.c 7 Jul 2017 06:51:30 -0000
@@ -1013,7 +1013,7 @@ malloc_bytes(struct dir_info *d, size_t
/* Adjust to the real offset of that chunk */
k += (lp - bp->bits) * MALLOC_BITS;
- if (mopts.chunk_canaries)
+ if (mopts.chunk_canaries && size > 0)
bp->bits[bp->offset + k] = size;
k <<= bp->shift;
Peter Hessler
2017-07-07 07:48:31 UTC
Permalink
On 2017 Jul 07 (Fri) at 08:52:42 +0200 (+0200), Otto Moerbeek wrote:
:I think I found it: requested size is not recorded for malloc(0),
:bp->offset is not initialized in that case. Other code is carefull not to
:use ->offset for size == 0.
:OA
: -Otto
:
:Index: malloc.c
:===================================================================
:RCS file: /cvs/src/lib/libc/stdlib/malloc.c,v
:retrieving revision 1.226
:diff -u -p -r1.226 malloc.c
:--- malloc.c 19 Jun 2017 03:06:26 -0000 1.226
:+++ malloc.c 7 Jul 2017 06:51:30 -0000
:@@ -1013,7 +1013,7 @@ malloc_bytes(struct dir_info *d, size_t
: /* Adjust to the real offset of that chunk */
: k += (lp - bp->bits) * MALLOC_BITS;
:
:- if (mopts.chunk_canaries)
:+ if (mopts.chunk_canaries && size > 0)
: bp->bits[bp->offset + k] = size;
:
: k <<= bp->shift;
:

OK
--
The identical is equal to itself, since it is different.
-- Franco Spisani
Alexander Bluhm
2017-07-07 16:55:23 UTC
Permalink
Post by Otto Moerbeek
I think I found it: requested size is not recorded for malloc(0),
bp->offset is not initialized in that case. Other code is carefull not to
use ->offset for size == 0.
This also fixes /usr/src/regress/lib/libc/malloc/malloc0test:

.../malloc0test$ MALLOC_OPTIONS=C make
cc -O2 -pipe -MD -MP -c /usr/src/regress/lib/libc/malloc/malloc0test/malloc0test.c
cc -o malloc0test malloc0test.o
./malloc0test

Hangs forever.

Install new libc:

.../malloc0test$ MALLOC_OPTIONS=C make
cc -o malloc0test malloc0test.o
./malloc0test
count = 100000

Passes immediately.

bluhm
Post by Otto Moerbeek
Index: malloc.c
===================================================================
RCS file: /cvs/src/lib/libc/stdlib/malloc.c,v
retrieving revision 1.226
diff -u -p -r1.226 malloc.c
--- malloc.c 19 Jun 2017 03:06:26 -0000 1.226
+++ malloc.c 7 Jul 2017 06:51:30 -0000
@@ -1013,7 +1013,7 @@ malloc_bytes(struct dir_info *d, size_t
/* Adjust to the real offset of that chunk */
k += (lp - bp->bits) * MALLOC_BITS;
- if (mopts.chunk_canaries)
+ if (mopts.chunk_canaries && size > 0)
bp->bits[bp->offset + k] = size;
k <<= bp->shift;
Ted Unangst
2017-07-07 17:50:51 UTC
Permalink
Post by Otto Moerbeek
I think I found it: requested size is not recorded for malloc(0),
bp->offset is not initialized in that case. Other code is carefull not to
use ->offset for size == 0.
OA
-Otto
OA from me. :)
Post by Otto Moerbeek
Index: malloc.c
===================================================================
RCS file: /cvs/src/lib/libc/stdlib/malloc.c,v
retrieving revision 1.226
diff -u -p -r1.226 malloc.c
--- malloc.c 19 Jun 2017 03:06:26 -0000 1.226
+++ malloc.c 7 Jul 2017 06:51:30 -0000
@@ -1013,7 +1013,7 @@ malloc_bytes(struct dir_info *d, size_t
/* Adjust to the real offset of that chunk */
k += (lp - bp->bits) * MALLOC_BITS;
- if (mopts.chunk_canaries)
+ if (mopts.chunk_canaries && size > 0)
bp->bits[bp->offset + k] = size;
k <<= bp->shift;
Otto Moerbeek
2017-07-08 12:11:19 UTC
Permalink
Post by Ted Unangst
Post by Otto Moerbeek
I think I found it: requested size is not recorded for malloc(0),
bp->offset is not initialized in that case. Other code is carefull not to
use ->offset for size == 0.
OA
-Otto
OA from me. :)
I lied.... I checked more uses of ->offset and as it turns out,
there's one more access of offset for size == 0. Fix that and assign a
definite value to offset in the size == 0 case, so errors are catched
in more cases.

-Otto

Index: malloc.c
===================================================================
RCS file: /cvs/src/lib/libc/stdlib/malloc.c,v
retrieving revision 1.227
diff -u -p -r1.227 malloc.c
--- malloc.c 7 Jul 2017 19:14:46 -0000 1.227
+++ malloc.c 8 Jul 2017 12:08:42 -0000
@@ -886,6 +886,7 @@ omalloc_make_chunks(struct dir_info *d,
while (i >>= 1)
bp->shift++;
bp->total = bp->free = MALLOC_PAGESIZE >> bp->shift;
+ bp->offset = 0xdead;
bp->page = pp;

k = mprotect(pp, MALLOC_PAGESIZE, PROT_NONE);
@@ -1793,7 +1794,7 @@ orecallocarray(struct dir_info *argpool,

REALSIZE(sz, r);
if (sz <= MALLOC_MAXCHUNK) {
- if (mopts.chunk_canaries) {
+ if (mopts.chunk_canaries && sz > 0) {
struct chunk_info *info = (struct chunk_info *)r->size;
uint32_t chunknum = find_chunknum(pool, r, p, 0);

Loading...