DF-1661 / harness.c
/* DF-1661: IPMI IPMICTL_RECEIVE_MSG_TRUNC size_t underflow harness. * len = kreq->ir_replylen + 1; (e.g., 64) * // EMSGSIZE guard SKIPPED for TRUNC * len = min(recv->msg.data_len, len); (data_len=0 -> len=0) * copyout(ir_reply, data+1, len-1); (len-1 underflows -> SIZE_MAX) */ #include <stdio.h> #include <stdint.h> #include <string.h> #include <stdlib.h> static int fixed = 0; static size_t copyout_len; static int copyout_mock(const void *k, void *u, size_t n) { copyout_len = n; if (n > 1024*1024) { printf("COPYOUT: %zu bytes (would leak kernel heap until page fault)\n", n); return 14; /* EFAULT */ } return 0; } int main(int argc, char **argv) { if (argc > 1 && !strcmp(argv[1], "--fixed")) fixed = 1; /* simulate TRUNC path with data_len=0 */ int ir_replylen = 64; int data_len = 0; char ir_reply[64] = {0}; int len = ir_replylen + 1; /* TRUNC skips EMSGSIZE guard */ len = (data_len < len) ? data_len : len; char data_buf[16]; int error; if (fixed) { /* patched: guard each copyout */ error = copyout_mock("addr", data_buf, sizeof(int)); if (error == 0 && len >= 1) error = copyout_mock("\0", data_buf, 1); if (error == 0 && len > 1) error = copyout_mock(ir_reply, data_buf, len - 1); } else { /* buggy: unconditional compcode copyout + len-1 underflow */ error = copyout_mock("addr", data_buf, sizeof(int)); if (error == 0) error = copyout_mock("\0", data_buf, 1); if (error == 0) error = copyout_mock(ir_reply, data_buf, len - 1); } if (fixed) printf("RESULT: PATCHED - no copyout underflow (len=%d)\n", len); else printf("RESULT: BUGGY - copyout size=%zu (underflowed len-1)\n", copyout_len); return 0; } |