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);
        }
}

Reply via email to