Skip to content

nvidia-drm: propagate errno from semaphore surface fence wait ioctl - #1318

Open
VaggelisGian wants to merge 1 commit into
NVIDIA:mainfrom
VaggelisGian:fix-semsurf-fence-wait-errno
Open

nvidia-drm: propagate errno from semaphore surface fence wait ioctl#1318
VaggelisGian wants to merge 1 commit into
NVIDIA:mainfrom
VaggelisGian:fix-semsurf-fence-wait-errno

Conversation

@VaggelisGian

Copy link
Copy Markdown

Found while investigating #1297.

Problem

nv_drm_semsurf_fence_wait_ioctl() initializes ret = -EINVAL, sets it to 0 on success paths, but then ends in a bare return 0. Every validation failure logs an error and reports success to userspace even though no wait was registered with RM:

  • non-monotonic pre_wait_value >= post_wait_value
  • unknown fence context handle
  • wrong fence context type
  • callback data allocation failure
  • invalid sync FD (nv_drm_sync_file_get_fence() returned NULL)

A caller that trusts the return value believes its wait is armed. The semaphore it waits on is never signaled, and the caller hangs. This is exactly the sequence in #1297's log: Attempt to wait on invalid sync FD: 1511 followed by a hung render thread.

Every sibling ioctl in the file (SEMSURF_FENCE_CREATE, SEMSURF_FENCE_ATTACH, the prime fence ioctls) propagates its errno the same way this one already computes but discards it, and the first check in this very function (pDevice == NULL) already returns -EOPNOTSUPP.

Change

One line: done: now does return ret;.

  • Success paths still return 0, including the deliberate proceed-as-signaled path where dma_fence_add_callback() fails after the wait was registered with RM (there the wait IS registered, so reporting success is correct).
  • Error paths return -EINVAL; no path changes from nonzero to zero.
  • Ownership is unchanged: on error paths wait_data is NULL or freshly allocated and unshared when it is freed; the inline work-callback path resets ret = 0 before the label.
  • The ioctl number and params struct are untouched.

Test Plan

Prepared on Windows without Linux kernel toolchain or NVIDIA GPU, so no build and no runtime test were possible; verification was static:

git diff --stat
 kernel-open/nvidia-drm/nvidia-drm-fence.c | 2 +-

git diff --check        # clean

Traced all eight paths through the function for ret/wait_data state at the label, confirmed the sole caller is the DRM ioctl dispatch table, and searched open-source userspace (Mesa, libdrm, Proton ecosystem) for callers of DRM_IOCTL_NVIDIA_SEMSURF_FENCE_WAIT: none found outside header vendoring, so the only caller affected is NVIDIA's own userspace, which already handles nonzero returns from this same function. A repro of #1297 with the patched module should show the game receiving an error at wait time instead of hanging.

nv_drm_semsurf_fence_wait_ioctl() initializes ret to -EINVAL and sets
it to 0 on the success paths, but ends in a bare return 0. Every
validation failure (non-monotonic wait values, unknown fence context
handle, wrong context type, allocation failure, invalid sync FD) logs
an error and then reports success to userspace even though no wait was
registered with RM. A caller that trusts the return value believes its
wait is armed; the semaphore it waits on is never signaled and the
caller hangs (NVIDIA#1297).

Return ret instead. The success paths still return 0, including the
deliberate proceed-as-signaled path where dma_fence_add_callback()
failed after the wait was registered with RM, and the early
-EOPNOTSUPP check is unchanged. Sibling ioctls in this file already
propagate their errno the same way.

Test Plan:
  No build or runtime test possible in the preparation environment
  (no Linux kernel toolchain, no NVIDIA GPU). Verified statically:
  git diff --stat : 1 file changed, 1 insertion(+), 1 deletion(-)
  Traced all eight paths through the function: error paths reach
  done: with ret == -EINVAL while wait_data is NULL or unshared,
  success paths set ret = 0 before the label, and the callback-
  registration-failure path resets ret to 0 after running the work
  callback inline, so no double free and no success-path change.
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants