From d788c40b192d1713b0350a3f09268844790391e4 Mon Sep 17 00:00:00 2001 From: Ayush Ranjan Date: Wed, 24 Jan 2024 15:07:24 -0800 Subject: [PATCH] Fix NV0080_CTRL_CMD_GPU_GET_CLASSLIST to use RMAPI_PARAM_COPY_MAX_PARAMS_SIZE. Earlier we were using a smaller limit (NV0080_CTRL_GPU_CLASSLIST_MAX_SIZE=160) for the class list size. But Nvidia driver uses a 1 MB limit defined by RMAPI_PARAM_COPY_MAX_PARAMS_SIZE. Fixes 293905243015 ("Add unimplemented commands used by DeviceGetComputeRunningProcesses") PiperOrigin-RevId: 601246811 --- pkg/abi/nvgpu/ctrl.go | 12 +++++++--- pkg/sentry/devices/nvproxy/frontend.go | 23 ++++++++++++++----- pkg/sentry/devices/nvproxy/frontend_unsafe.go | 2 +- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/pkg/abi/nvgpu/ctrl.go b/pkg/abi/nvgpu/ctrl.go index 22530cbf7..26eb6d9a2 100644 --- a/pkg/abi/nvgpu/ctrl.go +++ b/pkg/abi/nvgpu/ctrl.go @@ -19,6 +19,14 @@ const ( RM_GSS_LEGACY_MASK = 0x00008000 ) +// From src/nvidia/inc/kernel/rmapi/param_copy.h: +const ( + // RMAPI_PARAM_COPY_MAX_PARAMS_SIZE is the size limit imposed while copying + // "embedded pointers" in rmapi parameter structs. + // See src/nvidia/src/kernel/rmapi/param_copy.c:rmapiParamsAcquire(). + RMAPI_PARAM_COPY_MAX_PARAMS_SIZE = 1 * 1024 * 1024 +) + // From src/common/sdk/nvidia/inc/ctrl/ctrlxxxx.h: // +marshal @@ -95,12 +103,10 @@ const ( NV0080_CTRL_CMD_GPU_QUERY_SW_STATE_PERSISTENCE = 0x800288 NV0080_CTRL_CMD_GPU_GET_VIRTUALIZATION_MODE = 0x800289 NV0080_CTRL_CMD_GPU_GET_CLASSLIST_V2 = 0x800292 - - NV0080_CTRL_GPU_CLASSLIST_MAX_SIZE = 160 ) // +marshal -type NV0080_CTRL_CMD_GPU_GET_CLASSLIST_PARAMS struct { +type NV0080_CTRL_GPU_GET_CLASSLIST_PARAMS struct { NumClasses uint32 Pad [4]byte ClassList P64 diff --git a/pkg/sentry/devices/nvproxy/frontend.go b/pkg/sentry/devices/nvproxy/frontend.go index bd8583698..c1a9093d2 100644 --- a/pkg/sentry/devices/nvproxy/frontend.go +++ b/pkg/sentry/devices/nvproxy/frontend.go @@ -549,6 +549,13 @@ func rmControlSimple(fi *frontendIoctlState, ioctlParams *nvgpu.NVOS54Parameters return n, nil } +func ctrlCmdFailWithStatus(fi *frontendIoctlState, ioctlParams *nvgpu.NVOS54Parameters, status uint32) error { + outIoctlParams := *ioctlParams + outIoctlParams.Status = status + _, err := outIoctlParams.CopyOut(fi.t, fi.ioctlParamsAddr) + return err +} + func ctrlClientSystemGetBuildVersion(fi *frontendIoctlState, ioctlParams *nvgpu.NVOS54Parameters) (uintptr, error) { var ctrlParams nvgpu.NV0000_CTRL_SYSTEM_GET_BUILD_VERSION_PARAMS if ctrlParams.SizeBytes() != int(ioctlParams.ParamsSize) { @@ -588,8 +595,10 @@ func ctrlClientSystemGetBuildVersion(fi *frontendIoctlState, ioctlParams *nvgpu. } func ctrlDevGpuGetClasslist(fi *frontendIoctlState, ioctlParams *nvgpu.NVOS54Parameters) (uintptr, error) { - var ctrlParams nvgpu.NV0080_CTRL_CMD_GPU_GET_CLASSLIST_PARAMS - + var ctrlParams nvgpu.NV0080_CTRL_GPU_GET_CLASSLIST_PARAMS + if ctrlParams.SizeBytes() != int(ioctlParams.ParamsSize) { + return 0, linuxerr.EINVAL + } if _, err := ctrlParams.CopyIn(fi.t, addrFromP64(ioctlParams.Params)); err != nil { return 0, err } @@ -600,10 +609,12 @@ func ctrlDevGpuGetClasslist(fi *frontendIoctlState, ioctlParams *nvgpu.NVOS54Par return rmControlSimple(fi, ioctlParams) } - // classList pointer is not NULL. Do classList buffer management. - if ctrlParams.NumClasses > nvgpu.NV0080_CTRL_GPU_CLASSLIST_MAX_SIZE { - fi.ctx.Warningf("nvproxy: requested classlist size exceeds max (%d > %d)", ctrlParams.NumClasses, nvgpu.NV0080_CTRL_GPU_CLASSLIST_MAX_SIZE) - return 0, linuxerr.EINVAL + // classList pointer is not NULL. Check classList size against limit. See + // src/nvidia/src/kernel/rmapi/embedded_param_copy.c:embeddedParamCopyIn() => + // case NV0080_CTRL_CMD_GPU_GET_CLASSLIST => RMAPI_PARAM_COPY_INIT(). + // paramCopy.paramsSize is initialized as numClasses * sizeof(NvU32). + if ctrlParams.NumClasses*4 > nvgpu.RMAPI_PARAM_COPY_MAX_PARAMS_SIZE { + return 0, ctrlCmdFailWithStatus(fi, ioctlParams, nvgpu.NV_ERR_INVALID_ARGUMENT) } classList := make([]uint32, ctrlParams.NumClasses) diff --git a/pkg/sentry/devices/nvproxy/frontend_unsafe.go b/pkg/sentry/devices/nvproxy/frontend_unsafe.go index f23141c05..f13900745 100644 --- a/pkg/sentry/devices/nvproxy/frontend_unsafe.go +++ b/pkg/sentry/devices/nvproxy/frontend_unsafe.go @@ -75,7 +75,7 @@ func ctrlClientSystemGetBuildVersionInvoke(fi *frontendIoctlState, ioctlParams * return n, nil } -func ctrlDevGpuGetClasslistInvoke(fi *frontendIoctlState, ioctlParams *nvgpu.NVOS54Parameters, ctrlParams *nvgpu.NV0080_CTRL_CMD_GPU_GET_CLASSLIST_PARAMS, classList []uint32) (uintptr, error) { +func ctrlDevGpuGetClasslistInvoke(fi *frontendIoctlState, ioctlParams *nvgpu.NVOS54Parameters, ctrlParams *nvgpu.NV0080_CTRL_GPU_GET_CLASSLIST_PARAMS, classList []uint32) (uintptr, error) { sentryCtrlParams := *ctrlParams sentryCtrlParams.ClassList = p64FromPtr(unsafe.Pointer(&classList[0])) n, err := rmControlInvoke(fi, ioctlParams, &sentryCtrlParams)