Hi, I have a program that consistently crashes my vps. I believe it has to do with a bug that I reported to misc@ about a month ago:
http://marc.info/?l=openbsd-misc&m=138622955012214&w=2 While I did not see the last 2 days crash console I suspect it's the same bug. So here is the dmesg of the box, notice the little RAM: OpenBSD 5.4-stable (GENERIC.MP) #0: Sat Nov 23 04:37:53 EST 2013 [email protected]:/home/src/sys/arch/amd64/compile/GENERIC.MP real mem = 788463616 (751MB) avail mem = 759803904 (724MB) mainbus0 at root bios0 at mainbus0: SMBIOS rev. 2.5 @ 0xe1000 (9 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 APIC SSDT acpi0: wakeup devices acpitimer0 at acpi0: 3579545 Hz, 32 bits acpimadt0 at acpi0 addr 0xfee00000: PC-AT compat cpu0 at mainbus0: apid 0 (boot processor) cpu0: Intel(R) Xeon(R) CPU L5410 @ 2.33GHz, 2448.32 MHz cpu0: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,MMX,FXSR,SSE,SSE2,HTT,SSE3,SSSE3,NXE,LONG,LAHF,PERF cpu0: 6MB 64b/line 16-way L2 cache cpu0: smt 0, core 0, package 0 cpu0: apic clock running at 999MHz cpu1 at mainbus0: apid 1 (application processor) cpu1: Intel(R) Xeon(R) CPU L5410 @ 2.33GHz, 2446.21 MHz cpu1: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,MMX,FXSR,SSE,SSE2,HTT,SSE3,SSSE3,NXE,LONG,LAHF,PERF cpu1: 6MB 64b/line 16-way L2 cache cpu1: smt 0, core 1, package 0 ioapic0 at mainbus0: apid 2 pa 0xfec00000, version 11, 24 pins acpiprt0 at acpi0: bus 0 (PCI0) acpicpu0 at acpi0 acpicpu1 at acpi0 acpibat0 at acpi0: BAT0 not present acpiac0 at acpi0: AC unit online 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 atapiscsi0 at pciide0 channel 0 drive 1 scsibus0 at atapiscsi0: 2 targets cd0 at scsibus0 targ 0 lun 0: <VBOX, CD-ROM, 1.0> ATAPI 5/cdrom removable cd0(pciide0:0:1): 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 82540EM" rev 0x02: apic 2 int 19, address 08:00:27:af:35:d3 "InnoTek VirtualBox Guest Service" rev 0x00 at pci0 dev 4 function 0 not configured piixpm0 at pci0 dev 7 function 0 "Intel 82371AB Power" rev 0x08: SMBus disabled ahci0 at pci0 dev 13 function 0 "Intel 82801HBM AHCI" rev 0x02: apic 2 int 21, AHCI 1.1 ahci0: device on port 0 didn't come ready, TFD: 0x171<ERR> scsibus1 at ahci0: 32 targets sd0 at scsibus1 targ 0 lun 0: <ATA, VBOX HARDDISK, 1.0> SCSI3 0/direct fixed t10.ATA_VBOX_HARDDISK_VBc2bb66cd-51092c1b_ sd0: 10240MB, 512 bytes/sector, 20971520 sectors 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 spkr0 at pcppi0 mtrr: CPU supports MTRRs but not enabled vscsi0 at root scsibus2 at vscsi0: 256 targets softraid0 at root scsibus3 at softraid0: 256 targets root on sd0a (2dcea048a32f887d.a) swap on sd0b dump on sd0b WARNING: R/W mount of /usr/X11R6 denied. Filesystem is not clean - run fsck And here is the program that I suspect puts it into this state, please don't redistribute it, it's a little personal and stems from closed source, I will attach it after my signature. So this program usually runs at 4AM and when it does my box locks up (it has in the last 2 days). I will rewrite this program to use less RAM (by taking out 1 anonymous mmaping) and that hopefully gets rid of the trigger event that causes the infinite loop but the base problem still exists probably somewhere in swap. I hope you'll be able to figure out from here what's causing this. Perhaps recreate a box such as this inside vmware, or virtualbox OSE which is what it is running. Thanks! -peter /* * Copyright (C) 2014 Peter J. Philipp * * This program is restricted and shall only be allowed for debug purposes * by people working with and improving the OpenBSD Operating System. * * Merkle Puzzle Server v.2 * */ #include <sys/types.h> #include <sys/mman.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <openssl/evp.h> #include <openssl/sha.h> void getmessagenum(void *mn); int mycmp(const void *, const void *); u_int64_t * findsavedmsg(char *save, u_int64_t num); #define BLOCKSIZE 32 /* for AES */ #define SALTSIZE 8 #define MESSAGES (4 * 1024 * 1024) #define CIPHERFILE "cipherfile" #define PLAINFILE "plainfile" #define GIGABYTE (BLOCKSIZE + SALTSIZE) * MESSAGES #define PLAINGIGABYTE (BLOCKSIZE * MESSAGES) struct message { u_int64_t salt; char crypt[32]; }; int main(int argc, char *argv[]) { EVP_CIPHER_CTX *evpctx; EVP_CIPHER *ec; SHA256_CTX ctx; int fd, plainfd; char *gigabytefile = CIPHERFILE; char *plainfile = PLAINFILE; char *mgig, *mplain; char *rand; char *save; char *offset, *p; char block[BLOCKSIZE]; unsigned char outbuf[1024]; char mykey[16]; char hexstr[32]; u_int64_t messagenum, key; u_int64_t *num, *num2; u_int32_t i, j, k; int buflen, tmplen; int bit = 1; int collision; int set = 0; int blocksize; int ch; struct message *mp; while ((ch = getopt(argc, argv, "c:p:")) != -1) { switch (ch) { case 'c': gigabytefile = optarg; break; case 'p': plainfile = optarg; break; case '?': default: fprintf(stderr, "usage: %s [-c cipherfile] [-p plainfile]\n"); break; } } /* open our gigabyte file */ fprintf(stderr, "opening cipherfile %s\n", gigabytefile); fd = open(gigabytefile, O_RDWR | O_CREAT | O_TRUNC, 0644); if (fd < 0) { perror("open"); exit(1); } lseek(fd, GIGABYTE - 1, SEEK_SET); write(fd, "", 1); if ((mgig = mmap(NULL, GIGABYTE, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { perror("mmap"); exit(1); } fprintf(stderr, "opening plainfile %s\n", plainfile); plainfd = open(plainfile, O_RDWR | O_CREAT | O_TRUNC, 0600); if (plainfd < 0) { perror("open"); exit(1); } lseek(plainfd, PLAINGIGABYTE - 1, SEEK_SET); write(plainfd, "", 1); if ((mplain = mmap(NULL, PLAINGIGABYTE, PROT_WRITE|PROT_READ, MAP_SHARED, plainfd, 0)) == MAP_FAILED) { perror("mmap"); exit(1); } fprintf(stderr, "trying to allocate %d bytes of random keys\n", MESSAGES * 8); if ((rand = mmap(NULL, MESSAGES * 8, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) { perror("mmap 2"); exit(1); } if ((save = mmap(NULL, MESSAGES * 8, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) { perror("mmap 3"); exit(1); } fprintf(stderr, "memsetting both mmap'ed regions\n"); memset(mgig, 0, GIGABYTE); memset(rand, 0, MESSAGES * 8); fprintf(stderr, "here we go!\n"); for (i = 0; i < MESSAGES; i++) { getmessagenum(&messagenum); num = (u_int64_t *)rand; num[i] = messagenum; if (i == bit) { fprintf(stderr, "%d, ", bit); fflush(stderr); bit <<= 1; } } memcpy(save, rand, MESSAGES * 8); printf("\n"); fprintf(stderr, "searching random numbers for duplicates\n"); collision = 0; do { /* need to re-sort after every collision */ qsort(rand, i, sizeof(u_int64_t), mycmp); num = (u_int64_t *)rand; for (i = 1; i < MESSAGES; i++) { if (num[i] == num[i - 1]) { num2 = findsavedmsg(save, num[i]); getmessagenum(&messagenum); num[i - 1] = messagenum; *num2 = messagenum; collision = 1; fprintf(stderr, "."); fflush(stderr); break; } } if (i == MESSAGES) collision = 0; } while (collision); fprintf(stderr, "\n"); /* now we need to randomize the messages again */ fprintf(stderr, "randomizing order\n"); memcpy(rand, save, MESSAGES * 8); munmap(save, MESSAGES * 8); fprintf(stderr, "writing keys and nums to disk\n"); ec = (EVP_CIPHER *)EVP_aes_256_ecb(); if ((evpctx = (EVP_CIPHER_CTX *)malloc(sizeof(EVP_CIPHER_CTX))) == NULL){ perror("malloc"); exit(1); } num2 = (u_int64_t *)rand; for (i = 0; i < MESSAGES; i++) { mp = (struct message *)mgig; getmessagenum(&key); // offset = mgig + (i * BLOCKSIZE); memset(&block, 0, sizeof(block)); offset = &block[0]; num = (u_int64_t *)offset; *num = num2[i]; offset += 8; num = (u_int64_t *)offset; *num = key; /* this is for the crib taking yet another chunk from key */ /* the reason this is alright is that 2^32 worth key is still */ /* very good */ memcpy(offset, (char *)&i, sizeof(u_int32_t)); offset += 8; getmessagenum(offset); offset += 8; getmessagenum(offset); EVP_CIPHER_CTX_init(evpctx); getmessagenum(&(mp + i)->salt); memset(&mykey, 0, sizeof(mykey)); memcpy(&mykey[8], (char *)&key, sizeof(key)); memcpy(&mykey[8], (char *)&i, sizeof(u_int32_t)); memcpy(&mykey, (char *)&(mp + i)->salt, sizeof(u_int64_t)); SHA256_Init(&ctx); SHA256_Update(&ctx, mykey, sizeof(mykey)); SHA256_Final(hexstr, &ctx); if (!EVP_EncryptInit_ex(evpctx, ec, NULL, NULL, NULL)) { /* error */ fprintf(stderr, "encryption error 0!\n"); } blocksize = EVP_CIPHER_block_size(ec); if (blocksize != BLOCKSIZE) { // fprintf(stderr, "blocksize != BLOCKSIZE\n"); } EVP_CIPHER_CTX_set_padding(evpctx, 0); // EVP_CIPHER_CTX_set_key_length(evpctx, 32); EVP_EncryptInit_ex(evpctx, NULL, NULL, (u_char *)hexstr, NULL); if (!EVP_EncryptUpdate(evpctx, outbuf, &buflen, block , BLOCKSIZE)) { fprintf(stderr, "encryption error!\n"); } if (buflen != BLOCKSIZE) { fprintf(stderr, "buflen != BLOCKSIZE\n"); } if (!EVP_EncryptFinal_ex(evpctx, outbuf + buflen, &tmplen)) { fprintf(stderr, "encryption error 2!\n"); } if (tmplen > 0) { fprintf(stderr, "tmplen > 0 == %d\n", tmplen); } EVP_CIPHER_CTX_cleanup(evpctx); memcpy((mp + i)->crypt, outbuf, BLOCKSIZE); memcpy(mplain + (i * BLOCKSIZE), block, BLOCKSIZE); } munmap(mgig, GIGABYTE); munmap(rand, MESSAGES); munmap(mplain, GIGABYTE); close(fd); close(plainfd); exit(0); } void getmessagenum(void *mn) { u_int32_t *a; int i; for (i = 0, a = (u_int32_t *)mn; i < 2; i++) { a[i] = arc4random(); } return; } int mycmp(const void *a, const void *b) { u_int64_t *pa = (u_int64_t *)a; u_int64_t *pb = (u_int64_t *)b; if (*pa < *pb) return -1; else if (*pa > *pb) return 1; else return (0); } u_int64_t * findsavedmsg(char *save, u_int64_t num) { int i; for (i = 0; i < MESSAGES; i++) { if (save[i] == num) return((u_int64_t *)save + i); } }
