From 0b01dccfbbadaf7780358cc4efed7fdc6ab7e466 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Thu, 12 Jun 2025 13:52:17 -0700 Subject: [PATCH] runc update: handle duplicated devs properly In case there's a duplicate in the device list, the latter entry overrides the former one. So, we need to modify the last entry, not the first one. To do that, use slices.Backward. Amend the test case to test the fix. Reported-by: lifubang Signed-off-by: Kir Kolyshkin --- tests/integration/update.bats | 8 ++++++++ update.go | 9 +++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/tests/integration/update.bats b/tests/integration/update.bats index 9e0c64bdf..9651ff93c 100644 --- a/tests/integration/update.bats +++ b/tests/integration/update.bats @@ -905,6 +905,14 @@ EOF echo "===" skip "can't get device major number from /proc/partitions (got $major)" fi + # Add an entry to check that + # - existing devices can be updated; + # - duplicates are handled properly; + # (see func upsert* in update.go). + update_config ' .linux.resources.blockIO.throttleReadBpsDevice |= [ + { major: '"$major"', minor: 0, rate: 485760 }, + { major: '"$major"', minor: 0, rate: 485760 } + ]' runc run -d --console-socket "$CONSOLE_SOCKET" test_update [ "$status" -eq 0 ] diff --git a/update.go b/update.go index 0a352b7b9..bc8ed1318 100644 --- a/update.go +++ b/update.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "os" + "slices" "strconv" "github.com/opencontainers/cgroups" @@ -402,7 +403,9 @@ other options are ignored. } func upsertWeightDevice(devices []*cgroups.WeightDevice, wd specs.LinuxWeightDevice) []*cgroups.WeightDevice { - for i, dev := range devices { + // Iterate backwards because in case of a duplicate + // the last one will be used. + for i, dev := range slices.Backward(devices) { if dev.Major != wd.Major || dev.Minor != wd.Minor { continue } @@ -429,7 +432,9 @@ func upsertWeightDevice(devices []*cgroups.WeightDevice, wd specs.LinuxWeightDev } func upsertThrottleDevice(devices []*cgroups.ThrottleDevice, td specs.LinuxThrottleDevice) []*cgroups.ThrottleDevice { - for i, dev := range devices { + // Iterate backwards because in case of a duplicate + // the last one will be used. + for i, dev := range slices.Backward(devices) { if dev.Major == td.Major && dev.Minor == td.Minor { devices[i].Rate = td.Rate return devices