Skip to content

fix: verify device identity before publishing volume - #1456

Open
victorlane wants to merge 2 commits into
hetznercloud:mainfrom
victorlane:fix/verify-device-identity
Open

fix: verify device identity before publishing volume#1456
victorlane wants to merge 2 commits into
hetznercloud:mainfrom
victorlane:fix/verify-device-identity

Conversation

@victorlane

@victorlane victorlane commented Aug 10, 2026

Copy link
Copy Markdown

Problem

NodePublishVolume trusts the device path from PublishContext verbatim. waitDeviceReady only checks that the /dev/disk/by-id path 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 main at the Publish level (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 in ErrDeviceMismatch instead 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 the Publish entry point, asserts ErrDeviceMismatch and 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' fake devpath are never rejected.

Full suite passes; go vet and gofmt clean.

Refs #1455

This PR (and code) were written using Claude Opus 5 assistance

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
@victorlane
victorlane requested a review from a team as a code owner August 10, 2026 15:30
@lukasmetzner

Copy link
Copy Markdown
Contributor

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

codecov Bot commented Aug 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 52.00000% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 41.25%. Comparing base (e8812c3) to head (aa2f815).

Files with missing lines Patch % Lines
internal/volumes/mount.go 52.00% 12 Missing ⚠️
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     
Flag Coverage Δ
e2e-controller ?
e2e-node ?
integration ?
unit 41.25% <52.00%> (+0.31%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@lukasmetzner

Copy link
Copy Markdown
Contributor

Test / kubernetes * (pull_request) Test / nomad * (pull_request) failing is expected.

@victorlane

Copy link
Copy Markdown
Author

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.

Added it

@victorlane victorlane closed this Aug 11, 2026
@victorlane victorlane reopened this Aug 11, 2026
…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
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