⬢ DragonFlyBSD Kernel Audit
DF-5700 / instr_driver.c
← back to finding ↓ download raw
/*
 * Driver for bcmp_instr.c: measures out-of-region loads of the bcmp.c
 * algorithm over the exhaustive alignment/length sweep, while verifying the
 * instrumented copy still agrees with memcmp (instrumentation did not
 * perturb semantics).  Region per buffer = [call_ptr, call_ptr + len).
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

int bcmp_instr(const void *, const void *, size_t);
extern unsigned long g_below_start[2], g_past_end[2], g_in[2],
                     g_max_below[2], g_max_past[2];
extern const unsigned char *g_lo[2], *g_hi[2];
extern long g_last_outside_case[4];
extern int g_case[3];

#define BUF 256
static unsigned char A[BUF], B[BUF];

static uint64_t s_state = 0xd1b54a32d192ed03ULL;
static uint64_t prng(void)
{
    s_state ^= s_state << 13; s_state ^= s_state >> 7; s_state ^= s_state << 17;
    return s_state;
}

int main(void)
{
    long mism = 0;
    for (size_t n = 1; n <= 96; n++)
        for (int off1 = 0; off1 < 8; off1++)
            for (int off2 = 0; off2 < 8; off2++) {
                for (int i = 0; i < BUF; i++) { A[i] = (unsigned char)(i * 7); B[i] = A[i]; }
                if (n % 3 == 0 && n > 2) B[off2 + n / 2] ^= 1;   /* some mismatches */
                g_case[0] = off1; g_case[1] = off2; g_case[2] = (int)n;
                const unsigned char *q1 = A + off1, *q2 = B + off2;
                g_lo[0] = q1; g_hi[0] = q1 + n; g_lo[1] = q2; g_hi[1] = q2 + n;
                int r = bcmp_instr(q1, q2, n);
                if ((r == 0) != (memcmp(q1, q2, n) == 0)) mism++;
            }
    /* randomized tail */
    for (long it = 0; it < 100000; it++) {
        int off1 = (int)(prng() % 32), off2 = (int)(prng() % 32);
        size_t n = (size_t)(prng() % 192) + 1;
        for (int i = 0; i < BUF; i++) { A[i] = (unsigned char)prng(); B[i] = A[i]; }
        if (prng() & 1) B[off2 + (prng() % n)] ^= (unsigned char)prng();
        g_case[0] = off1; g_case[1] = off2; g_case[2] = (int)n;
        const unsigned char *q1 = A + off1, *q2 = B + off2;
        g_lo[0] = q1; g_hi[0] = q1 + n; g_lo[1] = q2; g_hi[1] = q2 + n;
        int r = bcmp_instr(q1, q2, n);
        if ((r == 0) != (memcmp(q1, q2, n) == 0)) mism++;
    }
    printf("semantics check: %ld mismatches vs memcmp (must be 0)\n", mism);
    for (int i = 0; i < 2; i++) {
        printf("buf%d: in-region loads=%lu  below-start loads=%lu (max %lu B)  "
               "past-end loads=%lu (max %lu B, case off1=%ld off2=%ld n=%ld)\n",
               i, g_in[i], g_below_start[i], g_max_below[i],
               g_past_end[i], g_max_past[i],
               g_last_outside_case[0], g_last_outside_case[1],
               g_last_outside_case[2]);
    }
    int overread = (g_below_start[0]||g_below_start[1]||g_past_end[0]||g_past_end[1]);
    printf("RESULT: %s — longword loads DO%s read outside [ptr,ptr+len): "
           "max %lu B below start, %lu B past end\n",
           overread ? "OVERREAD-CONFIRMED" : "no out-of-region load",
           overread ? "" : " NOT",
           g_max_below[0] | g_max_below[1] ? (g_max_below[0] > g_max_below[1] ? g_max_below[0] : g_max_below[1]) : 0,
           g_max_past[0] > g_max_past[1] ? g_max_past[0] : g_max_past[1]);
    return mism ? 1 : 0;
}