[openbeosnetteam] Re: Big game hunting...

"David Reid" <dreid@xxxxxxxxxxxx> wrote:

>In fact I've just rewritten some code and am hoping that'll fix it!

I found the error, it is a buffer overrun, located in ethernet.c
in function ether_dev_start()

the  "= 0xff" assignment will crash, as is 9 bytes behind the allocated memory.

        /* now do mask... */
        sdl = (struct sockaddr_dl *)((caddr_t)sdl + socklen);
        ifa->ifa_netmask = (struct sockaddr*)sdl;
        sdl->sdl_len = masklen;
        /* build the mask */
        while (socklen != 0)
                sdl->sdl_data[socklen--] = 0xff;

stack backtrace is
ether_dev_start+0215
start_devices
start_stack
[...]

if you add this line into the /boot/home/config/settings/kernel/drivers/kernel 
file,
load_symbols enabled                            # load kernel and kernel addon 
symbols

you will start seeing symbols in KDL.
typing "dis eip" will show a diassably of the faulty code.

If I comment out the broken code, the stack runs fine and replys to broadcast 
icmp (ping) packets.

I'm have been working on a improved malloc/free debugging code, since
the old one seems to be unrelyable after short while, since the kernel
starts to allocated areas in the address space we wanted to use.
It is attached.

It currently looks like when receving and transmitting pakets, the malloc() 
function in pools.c, around line 47, gets executed
continuously, I don't know if this is correct, as I would assume that a pool 
does not allocate memory very often.
stack backtrace for this is
dbg_malloc
get_mem_block
block_get
m_devget
if_thread

regards
Marcus
 
PS: 
I don't have any more time until sunday to help with this, good luck
 
#ifndef OBOS_DBG_MALLOC_H
#define OBOS_DBG_MALLOC_H

void *  dbg_malloc(char *file, int line,size_t size);
void    dbg_free(char *file, int line,void *);

#define malloc(s)       dbg_malloc(__FILE__,__LINE__,s)
#define free(p)         do { dbg_free(__FILE__,__LINE__,p); p = 0xC0DEBABE; } 
while (0)

#endif
/* dbg_malloc.c 
 * by Marcus Overhagen <marcus@xxxxxxxxxxxx>
 */

#include <KernelExport.h>
#include <string.h>
#include <stdio.h>
#include "dbg_malloc.h"

void *dbg_malloc(char *file, int line, size_t size)
{
        static char *startaddr = 0;
        char *adr;
        size_t realsize;
        area_id id;
        char name[64];
        char *p;
        int n = 0;
        
        // create a area name that indicates where it was allocated
        p = strrchr(file,'/');
        p = (p == 0) ? file : p + 1;
        sprintf(name,"%s, %d",p,line);
        
        //aquire lock sem here

dbg_malloc_init:
        
        if (startaddr == 0) {
                //find a start address that is unused
                area_id id1;
                area_id id2;
                void *adr1;
                size_t size1 = 4000 * B_PAGE_SIZE; // about 16 MB
                size_t size2 = 30000 * B_PAGE_SIZE; // about 120 MB
                id1 = create_area("",(void 
**)&adr1,B_ANY_KERNEL_ADDRESS,size1,B_NO_LOCK,B_READ_AREA | B_WRITE_AREA);
                id2 = create_area("",(void 
**)&startaddr,B_ANY_KERNEL_ADDRESS,size2,B_NO_LOCK,B_READ_AREA | B_WRITE_AREA);
                if (id1 < 0 || id2 < 0)
                        panic("out of memory in init code");
                delete_area(id1);               
                delete_area(id2);
        }
        
        size += 4;
        
        realsize = (size + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1);
        adr = startaddr;
        
        // next start address is one unmapped page away
        startaddr += realsize + B_PAGE_SIZE;
        
        id = create_area(name,(void 
**)&adr,B_EXACT_ADDRESS,realsize,B_NO_LOCK,B_READ_AREA | B_WRITE_AREA);
        if (id < 0) {
                dprintf("out of memory or address space, reinit!");
                if (n++ > 10)
                        panic("out of memory or address space");
                startaddr = 0;
                goto dbg_malloc_init;
        }
        
        // align it to make the first byte after (adr + size) to be in an 
unallocated page
        adr += realsize - size;
        
        *(uint32*)adr = 0xDEADC0DE;
        adr += 4;
        
        // release lock sem
        
        return adr;
}

void dbg_free(char *file, int line, void *ptr)
{
        char *p = (char *)ptr;
        area_id id;
        char text[64];
        char *t;
        
        p -= 4;
        if (*(uint32*)p != 0xDEADC0DE) {
                t = strrchr(file,'/');
                t = (t == 0) ? file : t + 1;
                sprintf(text,"%s, %d buffer underrun",t,line);
                panic(text);
        }

        id = area_for(p);
        if (id < 0) {
                t = strrchr(file,'/');
                t = (t == 0) ? file : t + 1;
                sprintf(text,"%s, %d no area for buffer",t,line);
                panic(text);
        }

        delete_area(id);
}

Other related posts: