Skip to content

fix(yurthub): use uint64 parsing for resourceVersion in completeListObjWithObjs to prevent 32-bit overflow - #2733

Open
nishantbkl3345-ship-it wants to merge 3 commits into
openyurtio:masterfrom
nishantbkl3345-ship-it:fix/resource-version-uint64-parse
Open

fix(yurthub): use uint64 parsing for resourceVersion in completeListObjWithObjs to prevent 32-bit overflow#2733
nishantbkl3345-ship-it wants to merge 3 commits into
openyurtio:masterfrom
nishantbkl3345-ship-it:fix/resource-version-uint64-parse

Conversation

@nishantbkl3345-ship-it

Copy link
Copy Markdown

What this PR does / why we need it

Fixes an integer overflow vulnerability and data corruption bug in completeListObjWithObjs when calculating the synthesized resourceVersion for cached list responses.

Previously, strconv.Atoi was used to parse object resourceVersion strings into a signed Go int, ignoring parsing errors.

  • In production Kubernetes clusters (etcd counter), resourceVersion values frequently exceed ,147,483,647$ (^{31}-1$).
  • On 32-bit platforms (such as ARM32 / linux/arm/v7 edge devices, an officially published release target for OpenYurt), signed int is 32-bit.
  • Any resourceVersion above ^{31}-1$ caused strconv.Atoi to return strconv.ErrRange and clamp to MaxInt32 ($).
  • Furthermore, Kubernetes resourceVersion is standardly defined as an unsigned 64-bit integer (uint64).

This caused synthesized list responses to output corrupted resourceVersion values on edge nodes, resulting in 410 Gone errors and relist storms across WAN links.

This PR switches completeListObjWithObjs to use strconv.ParseUint(rvStr, 10, 64) with uint64 for listRv, safely skips invalid strings, and formats the output back with strconv.FormatUint.

Which issue(s) this PR fixes

N/A

Special notes for your reviewer

  • Added unit test Test_completeListObjWithObjs in pkg/yurthub/cachemanager/cache_manager_test.go covering 64-bit uint64 resourceVersions exceeding 32-bit max integer limits, empty, and invalid resourceVersions.
  • All unit tests and go test -race pass cleanly.

APPLE added 3 commits August 3, 2026 00:26
…key mismatch in enhancement mode

In gcPodsWhenRestart, KeyBuildInfo for pods fetched from the apiserver
was missing the Version field. In enhancement mode, this produced keys
like 'pods..core' instead of 'pods.v1.core', causing them to never
match the cached keys from ListResourceKeysOfComponent. As a result,
all cached pods appeared deleted, triggering the safety guard that
skips GC entirely — making pod GC silently non-functional on restart.

Added Version: 'v1' to the KeyBuildInfo and created gc_test.go with
unit tests that prove the mismatch and verify the fix.
…bjWithObjs to prevent overflow

In completeListObjWithObjs, resourceVersion was parsed using strconv.Atoi into a signed Go int, ignoring parsing errors. On 32-bit platforms (such as ARM32 linux/arm/v7 edge devices), signed int is 32-bit (max 2147483647). Any resourceVersion above 2^31-1 caused strconv.Atoi to return ErrRange and clamp to 2147483647.

This produced corrupted resourceVersion strings on synthesized list responses, causing relist storms and 410 Gone errors on edge devices.

Switched to strconv.ParseUint(rvStr, 10, 64) with uint64 listRv and added unit tests covering 64-bit uint64 resourceVersions and edge cases.
@nishantbkl3345-ship-it
nishantbkl3345-ship-it requested a review from a team as a code owner August 4, 2026 20:52
Copilot AI lite review requested due to automatic review settings August 4, 2026 20:52
@sonarqubecloud

sonarqubecloud Bot commented Aug 4, 2026

Copy link
Copy Markdown

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens yurthub cached list resourceVersion synthesis by switching parsing from int to uint64, preventing 32-bit overflow/corruption on edge devices. It also includes two additional behavioral fixes in hubleader reconciliation and yurthub GC key construction.

Changes:

  • Update completeListObjWithObjs to parse resourceVersion via strconv.ParseUint(..., 64) and emit via FormatUint, with a new unit test covering large/invalid values.
  • Prevent a potential nil-map overwrite/panic in hubleader reconciliation when LeaderNodeLabelSelector is nil by copying selector labels into a fresh map.
  • Fix yurthub pod-GC key construction to include Version: "v1" and add a regression test for disk-storage key consistency.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
pkg/yurtmanager/controller/hubleader/hubleader_controller.go Avoids overwriting matchLabels with a potentially nil selector map; copies labels safely.
pkg/yurtmanager/controller/hubleader/hubleader_controller_test.go Adds coverage for mark strategy when LeaderNodeLabelSelector is nil.
pkg/yurthub/gc/gc.go Ensures pod GC key-building includes API version to match stored keys in enhancement mode.
pkg/yurthub/gc/gc_test.go Adds regression tests for disk-storage key consistency / map lookup behavior.
pkg/yurthub/cachemanager/cache_manager.go Switches list RV synthesis to uint64 parsing/formatting to prevent 32-bit overflow corruption.
pkg/yurthub/cachemanager/cache_manager_test.go Adds unit test coverage for large/invalid resourceVersion handling.
Suppressed comments (2)

pkg/yurthub/gc/gc_test.go:72

  • This comment claims the fixed code includes "Version and Group", but the fixed KeyBuildInfo only sets Version (Group is defaulted internally). Adjust the wording to avoid confusion.
	// Simulate the FIXED code (with Version and Group)
	fixedKey, err := store.KeyFunc(storage.KeyBuildInfo{

pkg/yurthub/gc/gc_test.go:143

  • This test ignores the error return from KeyFunc when building fixedKey. Failing fast on error keeps the test from passing with an unintended nil/zero-value key if KeyFunc behavior changes.
	fixedKey, _ := store.KeyFunc(storage.KeyBuildInfo{
		Component: "kubelet",
		Namespace: "kube-system",
		Name:      "coredns-abc123",
		Resources: "pods",

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +335 to +339
rvUint, err := strconv.ParseUint(rvStr, 10, 64)
if err != nil {
klog.Warningf("failed to parse resourceVersion %q: %v", rvStr, err)
continue
}
Comment on lines 176 to +181
// Set match labels
matchLabels := make(map[string]string)
if nodepool.Spec.LeaderElectionStrategy == string(appsv1beta2.ElectionStrategyMark) {
// Add mark strategy match labels
matchLabels = nodepool.Spec.LeaderNodeLabelSelector
// Add mark strategy match labels safely without overwriting matchLabels with a potential nil map
for k, v := range nodepool.Spec.LeaderNodeLabelSelector {
matchLabels[k] = v
Comment thread pkg/yurthub/gc/gc_test.go
Comment on lines +29 to +35
// TestGcPodKeyConsistency proves that the keys built in gcPodsWhenRestart
// (when constructing currentPodKeys from apiserver response) must include
// Version and Group to match the keys returned by ListResourceKeysOfComponent.
//
// Before the fix, gcPodsWhenRestart called KeyFunc without Version/Group,
// producing "pods..core" in enhancement mode instead of "pods.v1.core",
// causing all cached pod keys to appear deleted.
Comment thread pkg/yurthub/gc/gc_test.go
Comment on lines +129 to +135
buggyKey, _ := store.KeyFunc(storage.KeyBuildInfo{
Component: "kubelet",
Namespace: "kube-system",
Name: "coredns-abc123",
Resources: "pods",
})
currentPodKeysBuggy[buggyKey] = struct{}{}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants