DragonFlyBSD Kernel Audit
DF-0795 / df0795_harness_fixed.c
← back to finding ↓ download raw
/* Patched variant: includes the new bounds check from fix.diff. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

#define WIN_CHARS  13
#define WIN_MAXLEN 255
#define ENAMETOOLONG 63

struct mbnambuf { size_t nb_len; int nb_last_id; char nb_buf[WIN_MAXLEN+1]; };

static int
mbnambuf_write_FIXED(struct mbnambuf *nbp, char *name, int id)
{
    char *slot;
    size_t count, newlen;
    if (nbp->nb_len != 0 && id != nbp->nb_last_id - 1) return -1;
    slot = &nbp->nb_buf[id * WIN_CHARS];
    count = strlen(name);
    newlen = nbp->nb_len + count;
    if (newlen > WIN_MAXLEN || newlen > 127) return -1;
    if (count > WIN_CHARS && nbp->nb_len != 0) {
        if ((id * WIN_CHARS + count + nbp->nb_len) > sizeof(nbp->nb_buf))
            return -1;
        memmove(slot + count, slot + WIN_CHARS, nbp->nb_len);
    }
    /* *** THE FIX *** */
    if (id * WIN_CHARS + count > sizeof(nbp->nb_buf))
        return -ENAMETOOLONG;
    memcpy(slot, name, count);
    nbp->nb_len = newlen;
    nbp->nb_last_id = id;
    return 0;
}

static int
mbnambuf_write_ORIG(struct mbnambuf *nbp, char *name, int id)
{
    char *slot;
    size_t count, newlen;
    if (nbp->nb_len != 0 && id != nbp->nb_last_id - 1) return -1;
    slot = &nbp->nb_buf[id * WIN_CHARS];
    count = strlen(name);
    newlen = nbp->nb_len + count;
    if (newlen > WIN_MAXLEN || newlen > 127) return -1;
    if (count > WIN_CHARS && nbp->nb_len != 0) {
        if ((id * WIN_CHARS + count + nbp->nb_len) > sizeof(nbp->nb_buf))
            return -1;
        memmove(slot + count, slot + WIN_CHARS, nbp->nb_len);
    }
    memcpy(slot, name, count);  /* unchecked */
    nbp->nb_len = newlen;
    nbp->nb_last_id = id;
    return 0;
}

int main(void){
    struct mbnambuf nb_orig, nb_fix;
    /* poison the bytes past nb_buf to detect overflow */
    char name13[14]; memset(name13,0,sizeof(name13));
    for(int i=0;i<13;i++) name13[i]='A'+i;

    memset(&nb_orig, 0xCC, sizeof(nb_orig)); nb_orig.nb_len=0; nb_orig.nb_last_id=-1;
    int rc_orig = mbnambuf_write_ORIG(&nb_orig, name13, 19);
    int overflow_orig = 0;
    unsigned char *p = (unsigned char *)&nb_orig.nb_buf[256];
    for(int i=0;i<4;i++) if(p[i]!=0xCC) overflow_orig++;
    printf("ORIG mbnambuf_write(id=19, count=13) rc=%d ; bytes-past-end corrupted=%d (expected 4)\n",
           rc_orig, overflow_orig);

    memset(&nb_fix, 0xCC, sizeof(nb_fix)); nb_fix.nb_len=0; nb_fix.nb_last_id=-1;
    int rc_fix = mbnambuf_write_FIXED(&nb_fix, name13, 19);
    int overflow_fix = 0;
    p = (unsigned char *)&nb_fix.nb_buf[256];
    for(int i=0;i<4;i++) if(p[i]!=0xCC) overflow_fix++;
    printf("FIXED mbnambuf_write(id=19, count=13) rc=%d (-63=ENAMETOOLONG) ; bytes-past-end corrupted=%d (expected 0)\n",
           rc_fix, overflow_fix);

    return (rc_orig==0 && overflow_orig==4 && rc_fix==(-ENAMETOOLONG) && overflow_fix==0) ? 0 : 1;
}