โฌข DragonFlyBSD Kernel Audit
DF-0720 / ng_sppp_harness.c
โ† back to finding โ†“ download raw
/*
 * DF-0720 โ€” structural demonstration of the ng_sppp if_alloc(IFT_PPP) heap
 * overflow. The vulnerable file (sys/netgraph7/ng_sppp.c) does NOT compile on
 * this kernel (IFP2SP/SP2IFP are undefined anywhere in sys/), so this bug is
 * LATENT / dead code โ€” it cannot be triggered live.
 *
 * This harness models the structural invariant the bug violates:
 *   - if_alloc(IFT_PPP) allocates ONLY sizeof(struct ifnet)   (if.c:3083)
 *   - sppp_attach(ifp) casts that pointer to (struct sppp*) and writes fields
 *     that live PAST sizeof(struct ifnet), because struct sppp nests
 *     struct arpcom (which itself nests struct ifnet) as its FIRST member,
 *     then adds ~1KB of PPP state.
 *
 * Model: BASE = sizeof(ifnet); sppp fields live at offset [BASE .. BASE+EXTRA).
 * Writing them into a BASE-sized allocation corrupts [BASE .. BASE+EXTRA).
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

/* Approximate structural offsets (real kernel: struct ifnet ~ 512-700 bytes,
 * struct arpcom = ifnet + 6 enaddr + 1 vlan; struct sppp adds ~1KB). The exact
 * numbers do not matter โ€” the invariant sppp > ifnet is structural. */
#define IFNET_SIZE   600
#define SPPP_EXTRA  1024
#define SPPP_SIZE   (IFNET_SIZE + SPPP_EXTRA)

int main(void){
    /* model the heap: [alloc(IFNET_SIZE)] [adjacent heap] */
    uint8_t heap[SPPP_SIZE + 256];
    memset(heap, 0x00, sizeof(heap));
    memset(heap + IFNET_SIZE, 0xCC, sizeof(heap) - IFNET_SIZE); /* canary */

    uint8_t *ifp = heap;                     /* if_alloc(IFT_PPP) result */

    /* sppp_attach(ifp): struct sppp *sp = (struct sppp*) ifp; then writes
     * sp->pp_fastq, pp_cpq, pp_next, pp_seq[], pp_rseq[], state[], timeout[],
     * lcp, ipcp, ipv6cp, myauth, hisauth, pp_up/pp_down fn pointers, ... */
    printf("if_alloc(IFT_PPP) returned %d-byte object (sizeof(struct ifnet))\n",
           IFNET_SIZE);
    printf("sppp_attach() casts to struct sppp* (%d bytes) and writes fields "
           "at offset [%d .. %d)\n", SPPP_SIZE, IFNET_SIZE, SPPP_SIZE);

    memset(ifp + IFNET_SIZE, 0xAB, SPPP_EXTRA);   /* the sppp_attach writes */

    int over = 0;
    for (int i = IFNET_SIZE; i < SPPP_SIZE; i++)
        if (heap[i] != 0xCC) over++;
    printf("bytes written past the %d-byte allocation into adjacent heap: %d\n",
           IFNET_SIZE, over);
    if (over > 0)
        printf("RESULT: STRUCTURAL OVERFLOW CONFIRMED โ€” sppp_attach writes "
               "~%d bytes past the if_alloc(IFT_PPP) object\n", over);
    else
        printf("RESULT: no overflow (model misconfigured)\n");
    return (over > 0) ? 1 : 0;
}