DF-3398 / kcheck.c
/* DF-3398 fix-check: dump qwords past the cpu's cfg_alias end. * usage: kcheck <cpu> <ip_fw3_nat_ctx_runtime_addr> */ #include <sys/types.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <stdint.h> #define ALIAS_RANGE 64511 #define ICMP_IN_OFF (24 + 2 * (ALIAS_RANGE * 8)) /* next(8)+prev(8)+ip(4)+pad(4)+tcp_in+udp_in */ #define CFG_ALIAS_SZ (24 + 3 * (ALIAS_RANGE * 8)) /* 1548288 = exactly 378 pages */ static int fd; static int rd(uint64_t a, void *b, size_t n) { return pread(fd, b, n, (off_t)a) == (ssize_t)n ? 0 : -1; } int main(int argc, char **argv) { int cpu = atoi(argv[1]); uint64_t sym = strtoull(argv[2], NULL, 16); uint64_t ctx, nat, alias, a; uint64_t v; fd = open("/dev/kmem", O_RDONLY); if (rd(sym + cpu * 8, &ctx, 8)) { perror("ctx"); return 1; } if (rd(ctx, &nat, 8)) { perror("nat"); return 1; } if (rd(nat + 8, &alias, 8)) { perror("alias"); return 1; } printf("cpu%d ctx=0x%llx nat=0x%llx alias=0x%llx alias_sz=%d\n", cpu, (unsigned long long)ctx, (unsigned long long)nat, (unsigned long long)alias, CFG_ALIAS_SZ); printf("qwords past allocation end:\n"); for (a = 0; a < 128; a += 8) { char tag[64] = ""; if (rd(alias + CFG_ALIAS_SZ + a, &v, 8)) { printf(" +%4lld: READ FAIL\n", (long long)a); continue; } if (a == 8) strcpy(tag, "<- idx 64512 (x=0xfc store, baseline wrote here)"); if (a == 16) strcpy(tag, "<- idx 64513 (x=0x1fc)"); if (a == 24) strcpy(tag, "<- idx 64514 (x=0x2fc)"); if (a == 32) strcpy(tag, "<- idx 64515 (x=0x3fc)"); printf(" +%4lld: 0x%016llx %s\n", (long long)a, (unsigned long long)v, tag); } /* also verify the in-bounds slots hold the states after the fix */ printf("in-bounds icmp_in slots (252/508/764/1020 after fix):\n"); { uint64_t base = alias + ICMP_IN_OFF; int slots[] = {252, 508, 764, 1020, 300}; int i; for (i = 0; i < 5; i++) { if (rd(base + 8ULL * slots[i], &v, 8)) v = 0xDEAD; printf(" icmp_in[%d] = 0x%016llx\n", slots[i], (unsigned long long)v); } } return 0; } |