From mboxrd@z Thu Jan 1 00:00:00 1970 From: Claude Code Review Bot To: dri-devel-reviews@example.com Subject: Claude review: accel/amdxdna: Fix user buffer VMA checking and page pinning locking Date: Sat, 16 May 2026 08:54:22 +1000 Message-ID: In-Reply-To: <20260515155423.743134-1-lizhi.hou@amd.com> References: <20260515155423.743134-1-lizhi.hou@amd.com> <20260515155423.743134-1-lizhi.hou@amd.com> X-Mailer: Claude Code Patch Reviewer Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Patch Review **Positive aspects:** 1. **TOCTOU fix is correct.** The original code in `readonly_va_entry()` ac= quired and released `mmap_read_lock` independently: ```c // OLD: lock/unlock scoped only to the VMA check mmap_read_lock(mm); vma =3D find_vma(mm, va_ent->vaddr); ... ret =3D vma->vm_flags & VM_WRITE ? 0 : 1; mmap_read_unlock(mm); ``` Then `pin_user_pages_fast()` was called later without the lock. The new = code correctly lifts the lock to the caller (`amdxdna_get_ubuf`) and holds = it across both the readonly determination loop and the page pinning loop: ```c mmap_read_lock(current->mm); =20 for (i =3D 0; i < num_entries; i++) { if (readonly && readonly_va_entry(&va_ent[i]) !=3D 1) readonly =3D false; } for (i =3D 0; i < num_entries; i++) { ... ret =3D pin_user_pages(va_ent[i].vaddr, npages, (readonly ? 0 : FOLL_WRITE) | FOLL_LONGTERM, &ubuf->pages[start]); ... } =20 mmap_read_unlock(current->mm); ``` 2. **`pin_user_pages_fast` =E2=86=92 `pin_user_pages` switch is correct.** = `pin_user_pages()` passes `NULL` for the `locked` parameter to `is_valid_gu= p_args()`, so `FOLL_UNLOCKABLE` is not set. This means the GUP internals as= sume mmap_read_lock is already held and won't try to manage it. The caller = holds the lock =E2=80=94 consistent. 3. **`VM_MAYWRITE` addition is important.** The old check: ```c ret =3D vma->vm_flags & VM_WRITE ? 0 : 1; ``` only checked current writability. The new check: ```c ret =3D vma->vm_flags & (VM_WRITE | VM_MAYWRITE) ? 0 : 1; ``` prevents the scenario where a user pins pages from a read-only VMA that = has `VM_MAYWRITE`, then calls `mprotect()` to gain write access to the DMA-= pinned pages. Without this, the read-only pinning could be bypassed after t= he fact. 4. **Error path restructuring is correct.** Changing `goto destroy_pages` t= o `break` inside the pinning loop, followed by `mmap_read_unlock()` and the= n the `if (ret < 0) goto destroy_pages` check, ensures the lock is always r= eleased before cleanup. The success case (all pages pinned) has `ret` set t= o the last `pin_user_pages()` return (positive), so the `ret < 0` check cor= rectly skips the error path. 5. **`ret =3D 0` initialization** is necessary since `ret` is now checked a= fter the loops, and in the edge case of `num_entries =3D=3D 0`, the pinning= loop body never executes. **Minor concern:** - **`readonly_va_entry()` error return silently treated as writable.** When= `readonly_va_entry()` returns `-ENOENT` (VMA not found or doesn't cover th= e range), the check `!=3D 1` evaluates to true, so `readonly` is set to `fa= lse`. This means pages will be pinned with `FOLL_WRITE`. The `pin_user_page= s()` call will ultimately fail because the VMA doesn't exist, so there's no= security issue =E2=80=94 but it would be cleaner to propagate the error ea= rly rather than relying on `pin_user_pages` to fail later. This also existe= d in the original code, so it's not a regression. Consider: ```c for (i =3D 0; i < num_entries; i++) { ret =3D readonly_va_entry(&va_ent[i]); if (ret < 0) break; if (readonly && ret !=3D 1) readonly =3D false; } if (ret < 0) { mmap_read_unlock(current->mm); goto destroy_pages; } ``` This is a suggestion for improvement, not a blocker. **No issues found with:** - Lock ordering (mmap_read_lock is a reader lock; no nesting conflicts with= GUP internals since FOLL_UNLOCKABLE is not set) - The `static` function `readonly_va_entry()` being called only from the lo= cked region (confirmed: single call site at line 214) - Consistency between `current->mm` and `ubuf->mm` (set to `current->mm` at= line 164) --- Generated by Claude Code Patch Reviewer