From f14cad5a432298aa1533d2b2f8126606449639f7 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 (cherry picked from commit 0b01dccfbbadaf7780358cc4efed7fdc6ab7e466) 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 2a360333a..7ed1d8d20 100644 --- a/tests/integration/update.bats +++ b/tests/integration/update.bats @@ -904,6 +904,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 a9acf27a3..d1697a6a7 100644 --- a/update.go +++ b/update.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "os" + "slices" "strconv" "github.com/opencontainers/cgroups" @@ -406,7 +407,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 } @@ -433,7 +436,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