From 4b48c18b109be08409b6b282123078cc037b16bc Mon Sep 17 00:00:00 2001 From: Nakshatra Sharma Date: Wed, 5 Aug 2026 00:01:57 +0530 Subject: [PATCH] fix(monitor): clamp SetDeviceSmLimit and SetDeviceMemoryLimit to maxDevices Both v0 and v1 setter loops used sr.num as the upper bound without clamping to the backing array size. A corrupt or unexpectedly large num field from shared memory would cause an index out-of-bounds panic, bringing down the vGPU monitor and silencing all GPU metrics. Cap the loop to min(sr.num, maxDevices) in all four setters, matching the same guard already applied to sr.procnum in activeProcs. Signed-off-by: Nakshatra Sharma --- pkg/monitor/nvidia/v0/spec.go | 10 ++++------ pkg/monitor/nvidia/v0/spec_test.go | 24 ++++++++++++++++++++---- pkg/monitor/nvidia/v1/spec.go | 10 ++++------ pkg/monitor/nvidia/v1/spec_test.go | 14 ++++++++++++++ 4 files changed, 42 insertions(+), 16 deletions(-) diff --git a/pkg/monitor/nvidia/v0/spec.go b/pkg/monitor/nvidia/v0/spec.go index 444bddf827..fde2c9dcd8 100644 --- a/pkg/monitor/nvidia/v0/spec.go +++ b/pkg/monitor/nvidia/v0/spec.go @@ -138,10 +138,9 @@ func (s Spec) DeviceSmUtil(idx int) uint64 { } func (s Spec) SetDeviceSmLimit(l uint64) { - idx := uint64(0) - for idx < s.sr.num { + n := min(s.sr.num, maxDevices) + for idx := range n { s.sr.smLimit[idx] = l - idx += 1 } } @@ -158,10 +157,9 @@ func (s Spec) DeviceMemoryLimit(idx int) uint64 { } func (s Spec) SetDeviceMemoryLimit(l uint64) { - idx := uint64(0) - for idx < s.sr.num { + n := min(s.sr.num, maxDevices) + for idx := range n { s.sr.limit[idx] = l - idx += 1 } } diff --git a/pkg/monitor/nvidia/v0/spec_test.go b/pkg/monitor/nvidia/v0/spec_test.go index 0e68e78250..812e8d5c5c 100644 --- a/pkg/monitor/nvidia/v0/spec_test.go +++ b/pkg/monitor/nvidia/v0/spec_test.go @@ -469,6 +469,15 @@ func TestSpec_SetDeviceSmLimit(t *testing.T) { } }) } + + t.Run("num larger than maxDevices does not panic", func(t *testing.T) { + s := &Spec{sr: &sharedRegionT{num: 9999}} + s.SetDeviceSmLimit(500) + want := [16]uint64{500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500} + if s.sr.smLimit != want { + t.Errorf("SetDeviceSmLimit with oversized num: got %v, want %v", s.sr.smLimit, want) + } + }) } func TestSpec_IsValidUUID(t *testing.T) { @@ -649,10 +658,8 @@ func TestSpec_SetDeviceMemoryLimit(t *testing.T) { }, }, }, - input: 500, - expected: []uint64{ - 500, 500, 500, - }, + input: 500, + expected: []uint64{500, 500, 500}, }, } @@ -665,6 +672,15 @@ func TestSpec_SetDeviceMemoryLimit(t *testing.T) { } }) } + + t.Run("num larger than maxDevices does not panic", func(t *testing.T) { + s := &Spec{sr: &sharedRegionT{num: 9999}} + s.SetDeviceMemoryLimit(750) + want := [16]uint64{750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750} + if s.sr.limit != want { + t.Errorf("SetDeviceMemoryLimit with oversized num: got %v, want %v", s.sr.limit, want) + } + }) } func TestSpec_LastKernelTime(t *testing.T) { diff --git a/pkg/monitor/nvidia/v1/spec.go b/pkg/monitor/nvidia/v1/spec.go index 49a12aac11..a0e214bbdc 100644 --- a/pkg/monitor/nvidia/v1/spec.go +++ b/pkg/monitor/nvidia/v1/spec.go @@ -152,10 +152,9 @@ func (s Spec) DeviceSmUtil(idx int) uint64 { } func (s Spec) SetDeviceSmLimit(l uint64) { - idx := uint64(0) - for idx < s.sr.num { + n := min(s.sr.num, maxDevices) + for idx := range n { s.sr.smLimit[idx] = l - idx += 1 } } @@ -172,10 +171,9 @@ func (s Spec) DeviceMemoryLimit(idx int) uint64 { } func (s Spec) SetDeviceMemoryLimit(l uint64) { - idx := uint64(0) - for idx < s.sr.num { + n := min(s.sr.num, maxDevices) + for idx := range n { s.sr.limit[idx] = l - idx += 1 } } diff --git a/pkg/monitor/nvidia/v1/spec_test.go b/pkg/monitor/nvidia/v1/spec_test.go index 59f93c0362..9761a840c7 100644 --- a/pkg/monitor/nvidia/v1/spec_test.go +++ b/pkg/monitor/nvidia/v1/spec_test.go @@ -740,6 +740,13 @@ func Test_SetDeviceSmLimit(t *testing.T) { assert.DeepEqual(t, result, test.want) }) } + + t.Run("num larger than maxDevices does not panic", func(t *testing.T) { + s := &Spec{sr: &sharedRegionT{num: 9999, smLimit: [16]uint64{}}} + s.SetDeviceSmLimit(500) + want := [16]uint64{500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500} + assert.DeepEqual(t, s.sr.smLimit, want) + }) } func Test_IsValidUUID(t *testing.T) { @@ -970,6 +977,13 @@ func Test_SetDeviceMemoryLimit(t *testing.T) { assert.DeepEqual(t, result, test.want) }) } + + t.Run("num larger than maxDevices does not panic", func(t *testing.T) { + s := &Spec{sr: &sharedRegionT{num: 9999}} + s.SetDeviceMemoryLimit(750) + want := [16]uint64{750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750} + assert.DeepEqual(t, s.sr.limit, want) + }) } func Test_LastKernelTime(t *testing.T) {