fix: verify device identity before publishing volume - #1456
Conversation
waitDeviceReady only checked that the by-id path exists, so a symlink udev had not finished updating could resolve to another volume's device. Publish then mounted it, and formatted it when that device was empty. Compare the device serial against the volume ID and retry on mismatch. Refs hetznercloud#1455
|
Hey, before going any further, please have a quick look at our contributing guideline, in particular the AI/LLM policy: https://github.com/hetznercloud/csi-driver?tab=contributing-ov-file#ai--llm-policy I suspect this PR was created with the assistance of an AI tool, but this was not disclosed. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1456 +/- ##
===========================================
- Coverage 72.13% 41.25% -30.89%
===========================================
Files 17 17
Lines 1529 1549 +20
===========================================
- Hits 1103 639 -464
- Misses 337 883 +546
+ Partials 89 27 -62
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
|
Added it |
…ation Tighten test fixture file permissions, bounds-check the serial length before the byte cast, and document the two intentional nil returns that nilerr was flagging (identity is unverifiable, so the mount is allowed to proceed rather than blocked). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012fVGHF8JbyBUiyYdjwLe3W
Problem
NodePublishVolumetrusts the device path fromPublishContextverbatim.waitDeviceReadyonly checks that the/dev/disk/by-idpath exists, not that it points at the requested volume. The symlinks are maintained asynchronously by udev, so at boot with several volumes attaching, a path can resolve to another volume's block device.Publish then proceeds on the wrong device:
Both were reproduced against current
mainat thePublishlevel (mkfs ran and zeroed a data-carrying aliased device).Fix
After the existing stat check, resolve the symlink and compare the device's SCSI serial (
/sys/block/<dev>/device/vpd_pg80, which Hetzner sets to the volume ID) against the ID in the path. A mismatch is retried inside the existing backoff loop, treating a stale symlink like one that does not exist yet, and ends inErrDeviceMismatchinstead of a wrong mount.Verification fails open: non Hetzner paths, LUKS mappings, or an unreadable VPD page skip the check, so a mount that cannot be verified is never blocked. The VPD layout (4 byte header, then the volume ID) was confirmed against production nodes.
Tests
TestPublishRejectsAliasedDevice: aliased by-id path at thePublishentry point, assertsErrDeviceMismatchand that the aliased device's data is untouched. Needs a writable/dev, skips otherwise.TestVerifyDeviceSerial: match, mismatch, kernel padded serial, unverifiable device.TestVerifyDeviceIdentitySkipsForeignPaths: LUKS mappings and the sanity tests' fakedevpathare never rejected.Full suite passes;
go vetandgofmtclean.Refs #1455
This PR (and code) were written using Claude Opus 5 assistance