# DF-5073 — Uninitialized kernel-stack value exported to unprivileged users via `hw.acpi.acline` when the AC-adapter `_PSR` returns no object

## What

`acpi_acad.c` reads the AC-line status with `acpi_GetInteger(h, "_PSR", &newstatus)`
(`sys/dev/acpica/acpi_acad.c:111`). When the firmware's `_PSR` method evaluates
successfully but **returns no object** (malformed/quirky AML), ACPICA returns
`AE_OK` and leaves the caller's return buffer **untouched**
(`sys/contrib/dev/acpica/source/components/namespace/nsxfeval.c:541-545`,
`!Info->ReturnObject → ReturnBuffer->Length = 0`, Pointer never written).
`acpi_GetInteger()` (`sys/dev/acpica/acpi.c:2162-2183`) then inspects its
**uninitialized** stack local `ACPI_OBJECT param`; if the residue byte at
offset 0 happens to equal `ACPI_TYPE_INTEGER` (4), it copies
`param.Integer.Value` — 32 bits of kernel-stack residue — into `*number`.

`acpi_acad.c:110-116` uses that garbage as the authoritative line status:

```c
newstatus = -1;
acpi_GetInteger(h, "_PSR", &newstatus);     /* may write stack residue */
if (newstatus != -1 && sc->status != newstatus) {
        sc->status = newstatus;             /* garbage persisted */
        ...
```

and the world-readable sysctl `hw.acpi.acline` returns it to **any
unprivileged user** on every read (`acpi_acad.c:289` → `acpi_acad.c:233-234`).
Every sysctl read re-evaluates `_PSR`, i.e. re-samples the stack residue.

Root cause is DF-3793 (filed pass 1 against `acpi.c`); this finding is the
**call-site export primitive** in `acpi_acad.c` (previously unaudited file).

## Reproduce (guest, no privilege needed for the read side)

1. Build the two SSDTs with the guest `iasl` (see `build.sh`):
   * `ssdt_acad_sane.asl` — control: `_PSR` returns `One`.
   * `ssdt_acad_leak.asl` — trigger: `_PSR` falls off the end (no Return).
2. Control boot: `cd dfbsd-qemu && QEMU_EXTRA="-acpitable file=ssdt_acad_sane.aml" ./vm.sh up 300`
   * `sysctl hw.acpi.acline` → **1** (root and uid 1001), `acpi_acad0` attaches.
3. Trigger boot: `QEMU_EXTRA="-acpitable file=ssdt_acad_leak.aml" ./vm.sh up 300`
   * Expected on a correct kernel: `hw.acpi.acline` = -1 (evaluation has no
     return value).
   * Observed: `hw.acpi.acline` = **0** — reachable only via the uninitialized
     `param` (`Type`=4 residue, `Value` low dword 0). See `run.log`, `run.2.log`.
4. Grooming (`groom.c`): same-thread deep syscalls (socket/connect,
   `kern.proc.all` sysctl, file reads) followed by immediate `acline` reads by
   uid 1001 — 21 reads, value stayed 0 on this build.

## Files

* `ssdt_acad_sane.asl` / `ssdt_acad_sane.aml` — control firmware
* `ssdt_acad_leak.asl` / `ssdt_acad_leak.aml` — trigger firmware
* `groom.c` — same-thread kstack groom + unprivileged acline reader
* `build.sh` / `run.sh` — exact commands
* `build.log` — iasl + cc output (full)
* `run.log` — decisive groom run (uid 1001, 21 reads)
* `run.2.log` — leak boot transcript incl. sanity control
* `run.sane.log` — boot A control transcript
* `env.txt` — guest environment
* `fix.diff` — root-cause one-liner in `acpi_GetInteger` (acpi.c; DF-3793's
  root cause), authored after verification, never applied to `sys/`
* `VERDICT.md`, `manifest.json`, `verdict.json`

## Expected output (trigger boot, unprivileged)

```
$ sysctl hw.acpi.acline
hw.acpi.acline: 0          <- should be -1; 0 proves uninitialized export
```
