# DF-2166: pagecache_write_begin() stores shmem ERR_PTR in *pagep, causes kmap panic

## Verdict: NOT REPRODUCED (HW-gated) — source-confirmed real bug

## Reachability
**NOT reachable on this QEMU guest.** `pagecache_write_begin()` is in
`sys/dev/drm/linux_shmem.c`, part of `drm.ko`. Called from DRM GEM write paths.
Without GPU hardware, unreachable.

## Mechanism (source-confirmed)
`pagecache_write_begin()` at `linux_shmem.c:98-105`:
```c
int
pagecache_write_begin(struct vm_object *obj, struct address_space *mapping,
    loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata)
{
    *pagep = shmem_read_mapping_page(obj, OFF_TO_IDX(pos));
    return 0;
}
```

`shmem_read_mapping_page()` returns `ERR_PTR(-ENOMEM)` on failure (lines 57, 60, 70, 73).
The result is stored directly into `*pagep` **without** checking `IS_ERR()`, and the
function returns 0 (success).

The caller (typically i915 GEM write path) then dereferences `*pagep` via `kmap(*pagep)`
or `page_address(*pagep)`. Since `*pagep` contains the error value (e.g. `(void*)-ENOMEM`
= `0xFFFFFFFFFFFFFFEA`), this causes a **kernel panic** (invalid page address) or
arbitrary memory access.

This compounds with DF-2165: the same error paths also leak the VM object lock.

## Primitive
- Class: unchecked error → invalid pointer dereference → panic/arbitrary access
- The error pointer `0xFFFFFFFFFFFFFFEA` is used as a `struct page *` → page fault
- On non-INVARIANTS kernels: may access arbitrary kernel memory at high addresses

## Fix
`fix.diff`: Check `IS_ERR()` on the return of `shmem_read_mapping_page()` and propagate
the error instead of returning 0:
```c
struct page *page = shmem_read_mapping_page(obj, OFF_TO_IDX(pos));
if (IS_ERR(page))
    return PTR_ERR(page);
*pagep = page;
return 0;
```
