Monday, 18 March 2019

Does anyone get strncpy right?

I decided to have a quick look at OpenBIOS. 5 seconds in, it's clear that strncpy is used incorrectly in a number of places. OpenBSD realised many years ago how prone to bugs strncpy was and replaced it with the non standard strlcpy.
static void
create_free_part( char *ptr, int size )
{
        nvpart_t *nvp = (nvpart_t*)ptr;
        memset( nvp, 0, size );

        strncpy( nvp->name, "777777777777", sizeof(nvp->name) );
        nvp->signature = NV_SIG_FREE;
        nvp->len_hi = (size /16) >> 8;
        nvp->len_lo = size /16;
        nvp->checksum = nvpart_checksum(nvp);
}
And more..

static int
create_nv_part( int signature, const char *name, int size )
{
        nvpart_t *p = NULL;
        int fs;

        while( next_nvpart(&p) > 0 ) {
                if( p->signature != NV_SIG_FREE )
                        continue;

                fs = nvpart_size( p );
                if( fs < size )
                        size = fs;
                p->signature = signature;
                memset( p->name, 0, sizeof(p->name) );
                strncpy( p->name, name, sizeof(p->name) );
                p->len_hi = (size>>8)/16;
                p->len_lo = size/16;
                p->checksum = nvpart_checksum(p);
                if( fs > size ) {
                        char *fp = (char*)p + size;
                        create_free_part( fp, fs-size );
                }
                return size;
        }
        printk("create-failed\n");
        return -1;
}
And more..
        intprop = get_int_property(chosen, "stdout", &proplen);
        PUSH(intprop);
        fword("get-instance-path");
        ((struct linux_romvec *)romvec)->pv_stdout = pop_fstr_copy();

        /* Get the name of the selected boot device, along with the device and u
nit number */
        prop = get_property(chosen, "bootpath", &proplen);
        strncpy(bootpathbuf, prop, proplen);
        prop = get_property(chosen, "bootargs", &proplen);
        strncpy(bootargsbuf, prop, proplen);    

        /* Set bootpath pointer used in romvec table to the bootpath */
        push_str(bootpathbuf);
        fword("pathres-resolve-aliases");
        bootpath = pop_fstr_copy();
        printk("bootpath: %s\n", bootpath);

There are a number of more cases of this simple bug, but I think the readers get the point..

Exploiting the Lorex 2K Indoor Wifi at Pwn2Own Ireland

Introduction In October InfoSect participated in Pwn2Own Ireland 2024 and successfully exploited the Sonos Era 300 smart speaker and Lor...