DF-4385 / trigger.c
/* * DF-4385 trigger replica: oce_img_flashing_required() CRC read. * * oce_sysctl.c:458 crc_offset = hdrs_size + img_offset + img_size - 4; * oce_sysctl.c:460 p += crc_offset; // p = fw->data * oce_sysctl.c:468 bcmp(flashed_crc, p, 4); // NO fw->datasize check * * Called from oce_be3_flashdata() case IMG_REDBOOT (:334) with * img_offset=262144, img_size=1048576, BEFORE the image-size gate at :389. * A tiny "firmware" whose cookie scan succeeds makes the kernel read at * fw->data + ~1.31 MB regardless of fw->datasize. * * Build: cc -O2 -o trigger trigger.c * Run: ./trigger -> prints offset, then dies on the guard page. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <sys/mman.h> /* file header(128) + num_imgs(1)*image_hdr(48) โ bin_offset in the driver */ static uint32_t sizeof_hdrs(void) { return 128 + 1 * 48; } int main(void) { /* smallest viable hostile image: valid file header + one image * header with imageid==1 + a sec-info block with the right cookie โ * a couple of KB is plenty for the parse to succeed */ size_t datasize = 4096; uint8_t *fw = mmap(NULL, 16384, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0); if (fw == MAP_FAILED) { perror("mmap"); return 1; } /* readable region of exactly datasize, then an UNMAPPED-mood guard */ if (mprotect(fw, datasize, PROT_READ) != 0) { perror("mprotect"); return 1; } uint32_t hdrs_size = sizeof_hdrs(); uint32_t img_offset = 262144; /* IMG_REDBOOT start */ uint32_t img_size = 1048576; /* IMG_REDBOOT size */ uint32_t crc_offset = hdrs_size + img_offset + img_size - 4; printf("fw->datasize = %zu\n", datasize); printf("bcmp read at fw->data + %u (%.2f MB past a %zu-byte image)\n", crc_offset, crc_offset / 1048576.0, datasize); fflush(stdout); const char *p = (const char *)fw + crc_offset; /* :460 */ uint8_t flashed_crc[4] = {0}; int differs = bcmp(flashed_crc, p, 4) != 0; /* :468 โ OOB READ */ printf("unreachable: bcmp returned %d\n", differs); return 0; } |