diff --git a/kernel-open/common/inc/nvkms-kapi.h b/kernel-open/common/inc/nvkms-kapi.h index 8e838eafa9..9b292c183a 100644 --- a/kernel-open/common/inc/nvkms-kapi.h +++ b/kernel-open/common/inc/nvkms-kapi.h @@ -1357,6 +1357,9 @@ struct NvKmsKapiFunctionsTable { * \param [out] pMaxSubmittedMap Returns a CPU mapping of the semaphore * surface's semaphore memory to the client. * + * \param [out] pSurfaceSize Returns the size of the imported semaphore + * surface in bytes. May be NULL. + * * \return struct NvKmsKapiSemaphoreSurface* on success, NULL on failure. */ struct NvKmsKapiSemaphoreSurface* (*importSemaphoreSurface) @@ -1365,7 +1368,8 @@ struct NvKmsKapiFunctionsTable { NvU64 nvKmsParamsUser, NvU64 nvKmsParamsSize, void **pSemaphoreMap, - void **pMaxSubmittedMap + void **pMaxSubmittedMap, + NvU64 *pSurfaceSize ); /*! diff --git a/kernel-open/nvidia-drm/nvidia-drm-fence.c b/kernel-open/nvidia-drm/nvidia-drm-fence.c index 7af1ed7f13..7483de1ef7 100644 --- a/kernel-open/nvidia-drm/nvidia-drm-fence.c +++ b/kernel-open/nvidia-drm/nvidia-drm-fence.c @@ -1231,13 +1231,15 @@ __nv_drm_semsurf_fence_ctx_new( struct NvKmsKapiSemaphoreSurface *pSemSurface; uint8_t *semMapping; uint8_t *maxSubmittedMapping; + NvU64 surfaceSize = 0; char worker_name[20+16+1]; /* strlen(nvidia-drm/timeline-) + 16 for %llx + NUL */ pSemSurface = nvKms->importSemaphoreSurface(nv_dev->pDevice, p->nvkms_params_ptr, p->nvkms_params_size, (void **)&semMapping, - (void **)&maxSubmittedMapping); + (void **)&maxSubmittedMapping, + &surfaceSize); if (!pSemSurface) { NV_DRM_DEV_LOG_ERR( nv_dev, @@ -1246,6 +1248,27 @@ __nv_drm_semsurf_fence_ctx_new( goto failed; } + /* + * The index is provided by userspace as a 64-bit value. Reject values + * outside the imported surface before shifting the CPU mappings by them, + * and before truncating to the 32-bit RM semaphore index below. The + * max-submitted value must fit within one stride so that indexing the + * semaphore mapping also bounds the max-submitted mapping. + */ + if (nv_dev->semsurf_stride == 0 || + (nv_dev->semsurf_max_submitted_offset + sizeof(NvU64)) > + nv_dev->semsurf_stride || + p->index >= (surfaceSize / nv_dev->semsurf_stride) || + p->index > NV_U32_MAX) { + NV_DRM_DEV_LOG_ERR( + nv_dev, + "Invalid semaphore index %" NvU64_fmtu " for semaphore surface of %" + NvU64_fmtu " bytes", + p->index, surfaceSize); + + goto failed_alloc_fence_context; + } + /* * Allocate a fence context object and initialize it. */ diff --git a/src/nvidia-modeset/kapi/include/nvkms-kapi-internal.h b/src/nvidia-modeset/kapi/include/nvkms-kapi-internal.h index 1757f13953..0fcc89328f 100644 --- a/src/nvidia-modeset/kapi/include/nvkms-kapi-internal.h +++ b/src/nvidia-modeset/kapi/include/nvkms-kapi-internal.h @@ -237,7 +237,8 @@ nvKmsKapiImportSemaphoreSurface(struct NvKmsKapiDevice *device, NvU64 nvKmsParamsUser, NvU64 nvKmsParamsSize, void **pSemaphoreMap, - void **pMaxSubmittedMap); + void **pMaxSubmittedMap, + NvU64 *pSurfaceSize); void nvKmsKapiFreeSemaphoreSurface(struct NvKmsKapiDevice *device, diff --git a/src/nvidia-modeset/kapi/interface/nvkms-kapi.h b/src/nvidia-modeset/kapi/interface/nvkms-kapi.h index 8e838eafa9..9b292c183a 100644 --- a/src/nvidia-modeset/kapi/interface/nvkms-kapi.h +++ b/src/nvidia-modeset/kapi/interface/nvkms-kapi.h @@ -1357,6 +1357,9 @@ struct NvKmsKapiFunctionsTable { * \param [out] pMaxSubmittedMap Returns a CPU mapping of the semaphore * surface's semaphore memory to the client. * + * \param [out] pSurfaceSize Returns the size of the imported semaphore + * surface in bytes. May be NULL. + * * \return struct NvKmsKapiSemaphoreSurface* on success, NULL on failure. */ struct NvKmsKapiSemaphoreSurface* (*importSemaphoreSurface) @@ -1365,7 +1368,8 @@ struct NvKmsKapiFunctionsTable { NvU64 nvKmsParamsUser, NvU64 nvKmsParamsSize, void **pSemaphoreMap, - void **pMaxSubmittedMap + void **pMaxSubmittedMap, + NvU64 *pSurfaceSize ); /*! diff --git a/src/nvidia-modeset/kapi/src/nvkms-kapi-sync.c b/src/nvidia-modeset/kapi/src/nvkms-kapi-sync.c index 1b243d64e6..09fa698b10 100644 --- a/src/nvidia-modeset/kapi/src/nvkms-kapi-sync.c +++ b/src/nvidia-modeset/kapi/src/nvkms-kapi-sync.c @@ -185,7 +185,8 @@ nvKmsKapiImportSemaphoreSurface NvU64 nvKmsParamsUser, NvU64 nvKmsParamsSize, void **pSemaphoreMap, - void **pMaxSubmittedMap + void **pMaxSubmittedMap, + NvU64 *pSurfaceSize ) { struct NvKmsKapiSemaphoreSurface *ss = NULL; @@ -311,6 +312,10 @@ nvKmsKapiImportSemaphoreSurface *pMaxSubmittedMap = NULL; } + if (pSurfaceSize != NULL) { + *pSurfaceSize = p.semaphoreSurfaceSize; + } + return ss; fail: