DF-4639 / flush_invert_harness.c
/* * DF-4639 PoC harness — inverted debug.ips.ignore_flush_cmd polarity in * sys/dev/raid/ips/ips_commands.c ips_send_flush_request (lines 195-220). * * The control flow below is a faithful extraction of the kernel function: * only the kernel-only calls (command-buffer fill, bus_dmamap_sync, * sc->ips_issue_cmd) are replaced by instrumented stubs. The *branch* is * verbatim: * * if (!ips_debug_ignore_flush_cmd) { // ips_commands.c:202 * ips_insert_free_cmd(sc, command); * ipsd_finish(bio); * return 0; // flush SKIPPED, bio completed OK * } * ... build IPS_CACHE_FLUSH_CMD, issue to adapter ... * * against the tunable's own description (ips_commands.c:40): * "Do not issue IPS_CACHE_FLUSH_CMD on BUF_CMD_FLUSH" * i.e. documented semantics: flag SET (1) -> skip the command. * Actual semantics: flag CLEAR (0, the default) -> skip the command. * * Build: cc -O2 -o flush_invert_harness flush_invert_harness.c * Run: ./flush_invert_harness * Success criterion (bug present): flag=0 -> 0 adapter commands issued, * bio finished with no error; flag=1 -> exactly 1 adapter command issued * with opcode 0x0A (IPS_CACHE_FLUSH_CMD). */ #include <stdio.h> /* ---- ips.h constants ---- */ #define IPS_CACHE_FLUSH_CMD 0x0A /* ips.h:141 */ /* ---- stubs for the kernel symbols used by ips_send_flush_request ---- */ static int ips_debug_ignore_flush_cmd; /* ips_commands.c:35 (TUNABLE_INT/SYSCTL_INT, default 0) */ typedef struct { int n; } ips_softc_t; typedef struct { int n; } ips_command_t; struct bio { int n; }; static int adapter_cmds_issued; static unsigned char last_cmd_opcode; static int bios_finished; static void ips_insert_free_cmd(ips_softc_t *sc, ips_command_t *c) { (void)sc; (void)c; } static void ipsd_finish(struct bio *b) { bios_finished = 1; (void)b; } static void adapter_issue(ips_command_t *c, unsigned char opcode) { (void)c; adapter_cmds_issued++; last_cmd_opcode = opcode; } /* ==== ips_commands.c:195-220, verbatim control flow ==== */ static int ips_send_flush_request(ips_command_t *command, struct bio *bio) { (void)command; ips_softc_t *sc = (ips_softc_t *)0; if (!ips_debug_ignore_flush_cmd) { ips_insert_free_cmd(sc, command); ipsd_finish(bio); return 0; } /* real path: flush_cmd->command = IPS_CACHE_FLUSH_CMD; ...; sc->ips_issue_cmd(command) */ adapter_issue(command, IPS_CACHE_FLUSH_CMD); return 0; } static int run_case(int flag, const char *label) { adapter_cmds_issued = 0; last_cmd_opcode = 0; bios_finished = 0; ips_debug_ignore_flush_cmd = flag; ips_send_flush_request((ips_command_t *)0, (struct bio *)0); printf("%-28s flag=%d -> adapter_cmds_issued=%d last_opcode=0x%02x bio_finished=%d(no error)\n", label, flag, adapter_cmds_issued, last_cmd_opcode, bios_finished); return adapter_cmds_issued; } int main(void) { int n0, n1; printf("sysctl description (ips_commands.c:40): \"Do not issue IPS_CACHE_FLUSH_CMD on BUF_CMD_FLUSH\"\n"); printf("kernel default (TUNABLE_INT): debug.ips.ignore_flush_cmd = 0\n\n"); n0 = run_case(0, "DEFAULT (flag=0):"); /* expected: 0 cmds => flush silently dropped */ n1 = run_case(1, "DEBUG SET (flag=1):"); /* expected: 1 cmd opcode 0x0A => real flush */ printf("\n"); if (n0 == 0 && n1 == 1) { printf("RESULT: INVERTED — with the DEFAULT value the real adapter cache-flush\n"); printf(" command is never issued; BUF_CMD_FLUSH bios complete as if flushed.\n"); return 42; /* distinctive marker: inversion reproduced */ } printf("RESULT: not inverted (unexpected)\n"); return 1; } |