# DF-0007 — PoC

`leak_sigaction.c` — unprivileged leak of up to 4 bytes of kernel stack via
the trailing padding of `struct sigaction` returned by `sigaction()`.

## The issue

On amd64 `struct sigaction` (`sys/sys/signal.h:221`) is 32 bytes with **4
bytes of trailing padding** at offset 28-31:

```
offset  0: union __sigaction_u (8)   -- written
offset  8: int sa_flags       (4)    -- written
offset 12: sigset_t sa_mask   (16)   -- written (full assignment)
offset 28: <trailing padding> (4)    -- NOT written  <-- LEAK
sizeof = 32 (struct alignment 8)
```

`sys_sigaction()` (`sys/kern/kern_sig.c:384`) stack-allocates `oact`
uninitialized; `kern_sigaction()` (`:260-279`) writes `oact` field-by-field
but never the trailing padding; `copyout(oactp, uap->oact, sizeof(oact))`
(`:397`) copies all 32 bytes — leaking the 4 uninitialized kernel-stack
bytes. i386 is unaffected (`sizeof == 24`, no trailing pad).

## Build

```
cc -o leak_sigaction leak_sigaction.c
```

## Run

As an **unprivileged** user on amd64:

```
./leak_sigaction
```

## Expected output (bug present, e.g. unpatched `6.5-DEVELOPMENT #0`)

```
sizeof(struct sigaction) = 32
sample: 00 00 00 00 00 00 00 00  00 00 00 00 ff fe fe ff  ff ff ff ff ff ff ff ff  ff ff ff ff | 00 f8 ff ff  (pad word 0xfffff800)
... (8/8 samples) ...
samples with non-marker non-zero padding (leaked residue): 8/8
result: LEAK CONFIRMED
```

The padding word (`00 f8 ff ff` = `0xfffff800`) is a kernel-address-space
pointer fragment leaked from the kernel stack — it is neither the `0xAA`
marker the buffer was filled with nor a value the kernel wrote to a named
field. The exact value is deterministic for this syscall path but is
genuinely uninitialized kernel-stack residue at offset 28-31.

## Expected output (bug FIXED — single-fix kernel `6.5-DEVELOPMENT #1`)

```
sample: 00 00 00 00 00 00 00 00  00 00 00 00 ff fe fe ff  ff ff ff ff ff ff ff ff  ff ff ff ff | 00 00 00 00  (pad word 0x00000000)
...
samples with non-marker non-zero padding (leaked residue): 0/8
result: no residue observed (padding zero/defined)
```

The fix (`fix.diff`) zero-initializes the `act`/`oact` structs at the
`sys_sigaction` declaration, so the trailing padding is defined (zero) before
`copyout`. The named fields (offsets 0-27) are unchanged.

## Leak-detection logic

A sample is counted as **leaked residue** iff the trailing 4 bytes are
**neither** the `0xAAAAAAAA` marker (what the userland buffer was memset with)
**nor** `0x00000000` (zero = defined by the fix). On the buggy kernel the
padding holds non-zero kernel-stack residue; on the fixed kernel it is zero.
