Skip to content

fix: eliminate TOCTOU bug in static IP preservation check - #494

Merged
myakove merged 3 commits into
RedHatQE:mainfrom
krcmarik:static_ip
May 19, 2026
Merged

myakove merged 3 commits into
RedHatQE:mainfrom
krcmarik:static_ip

Conversation

@krcmarik

@krcmarik krcmarik commented May 18, 2026 •

Copy link
Copy Markdown
Collaborator

Refactor check_static_ip_preservation() to verify all static IPs simultaneously instead of sequentially to ensure that all Static IPs are present on the migrated guest at the moment (to catch a possible bug when firstboot script on the guest wrongly overwrites already configured primary Static IP.

  • Single TimeoutSampler verifies all static IPs on each iteration
  • One SSH call per retry instead of one per IP
  • Use dict(matched) shallow copy to prevent mutation
  • Use zip(..., strict=True) for length safety

Summary by CodeRabbit

  • Bug Fixes

    • More reliable static IP verification after migration: waits until all expected static IPs appear simultaneously, and validates subnet masks and gateways to reduce false negatives.
  • Chores

    • Improved retry and timeout behavior with a longer default wait (660s) and clearer diagnostics on missing addresses, command/connection failures, and partial matches.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 18, 2026 •

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5391989d-301f-4464-a7c3-69967d42c74b

📥 Commits

Reviewing files that changed from the base of the PR and between 5ddd049 and 52544ba.

📒 Files selected for processing (1)
  • utilities/post_migration.py

Walkthrough

Single-file refactor in utilities/post_migration.py: default timeout raised to 660s; static-IP verification reworked to load all interfaces once per retry, match every expected static IP via MAC/name heuristics, then validate subnet masks and gateways; improved exception handling for command/SSH/timeouts.

Changes

Static IP Preservation Verification Refactoring

Layer / File(s) Summary
Load & match helpers
utilities/post_migration.py
Adds _load_current_interfaces to run the guest network command and parse interface state (returns None to trigger retry), and _match_expected_static_ips which matches expected static-IP entries to parsed interfaces using MAC → exact name → unique substring priority; returns matched configs annotated with expected subnet masks and a missing list.
Verification flow and timeout update
utilities/post_migration.py
Updates check_static_ip_preservation default timeout to 660s and refactors it to open a single SSH connection and use verify_all_static_ips inside a TimeoutSampler-style retry: runs one load+parse per attempt, succeeds only when all expected IPs are matched, raises TimeoutError with last_missing on timeout, raises ValueError on command failures, returns None to retry on SSH errors, and then validates subnet masks and gateways pairing expected entries with matched interface configs (zip(..., strict=True)).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and specifically addresses the main objective of the PR: eliminating a TOCTOU (time-of-check/time-of-use) bug in the static IP preservation check function.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@redhat-qe-bot1

Copy link
Copy Markdown

Report bugs in Issues

Welcome! 🎉

This pull request will be automatically processed with the following features:

🔄 Automatic Actions

  • Reviewer Assignment: Reviewers are automatically assigned based on the OWNERS file in the repository root
  • Size Labeling: PR size labels (XS, S, M, L, XL, XXL) are automatically applied based on changes
  • Issue Creation: Disabled for this repository
  • Branch Labeling: Branch-specific labels are applied to track the target branch
  • Auto-verification: Auto-verified users have their PRs automatically marked as verified
  • Labels: All label categories are enabled (default configuration)

📋 Available Commands

PR Status Management

  • /wip - Mark PR as work in progress (adds WIP: prefix to title)
  • /wip cancel - Remove work in progress status
  • /hold - Block PR merging (approvers only)
  • /hold cancel - Unblock PR merging
  • /verified - Mark PR as verified
  • /verified cancel - Remove verification status
  • /reprocess - Trigger complete PR workflow reprocessing (useful if webhook failed or configuration changed)
  • /regenerate-welcome - Regenerate this welcome message

Review & Approval

  • /lgtm - Approve changes (looks good to me)
  • /approve - Approve PR (approvers only)
  • /automerge - Enable automatic merging when all requirements are met (maintainers and approvers only)
  • /assign-reviewers - Assign reviewers based on OWNERS file
  • /assign-reviewer @username - Assign specific reviewer
  • /check-can-merge - Check if PR meets merge requirements

Testing & Validation

  • /retest tox - Run Python test suite with tox
  • /retest build-container - Rebuild and test container image
  • /retest conventional-title - Validate commit message format
  • /retest all - Run all available tests

Container Operations

  • /build-and-push-container - Build and push container image (tagged with PR number)
    • Supports additional build arguments: /build-and-push-container --build-arg KEY=value

Cherry-pick Operations

  • /cherry-pick <branch> - Schedule cherry-pick to target branch when PR is merged
    • Multiple branches: /cherry-pick branch1 branch2 branch3

Label Management

  • /<label-name> - Add a label to the PR
  • /<label-name> cancel - Remove a label from the PR

✅ Merge Requirements

This PR will be automatically approved when the following conditions are met:

  1. Approval: /approve from at least one approver
  2. Status Checks: All required status checks must pass
  3. No Blockers: No wip, hold, has-conflicts labels and PR must be mergeable (no conflicts)
  4. Verified: PR must be marked as verified

📊 Review Process

Approvers and Reviewers

Approvers:

  • myakove
  • solenoci

Reviewers:

  • krcmarik
  • myakove
  • solenoci
Available Labels
  • hold
  • verified
  • wip
  • lgtm
  • approve
  • automerge
AI Features
  • Conventional Title: Mode: fix (claude/claude-opus-4-6[1m])
  • Cherry-Pick Conflict Resolution: Enabled (claude/claude-opus-4-6[1m])
  • Test Oracle: Triggers: approved (cursor/gpt-5.4-xhigh-fast); /test-oracle can be used anytime

💡 Tips

  • WIP Status: Use /wip when your PR is not ready for review
  • Verification: The verified label is removed on new commits unless the push is detected as a clean rebase
  • Cherry-picking: Cherry-pick labels are processed when the PR is merged
  • Container Builds: Container images are automatically tagged with the PR number
  • Permission Levels: Some commands require approver permissions
  • Auto-verified Users: Certain users have automatic verification and merge privileges

For more information, please refer to the project documentation or contact the maintainers.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
utilities/post_migration.py (1)

407-425: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

LOW: Fix the stale docstring contract.

The signature now defaults to 660, but the docstring still says 600, and Raises: still advertises a generic Exception even though this path now surfaces concrete failures (TimeoutError, ValueError, assertions). Stale contract docs make triage harder for callers and for future test updates. As per coding guidelines, "All new functions must have docstrings with standard sections: Args (when function has parameters), Returns (only when returning meaningful non-None value), Raises (only when exceptions are actually raised)".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@utilities/post_migration.py` around lines 407 - 425, Update the docstring for
the function that verifies static IPs (parameters: vm_name, vm_ssh_connections,
source_vm_data, source_provider_data, timeout, retry_delay) so the timeout
default reads 660 (not 600), ensure Args reflect those parameters, add a Raises
section that lists the concrete exceptions the function may surface (e.g.,
TimeoutError, ValueError, AssertionError) instead of a generic Exception, and
include a Returns section only if the function returns a meaningful non-None
value (otherwise omit Returns).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@utilities/post_migration.py`:
- Around line 456-465: Split verify_all_static_ips into testable helpers:
extract transport setup and command execution into a new
_load_current_interfaces() that returns parsed interface data, and extract the
matching/matching-bookkeeping logic into
_match_expected_static_ips(current_interfaces, expected_static_ips) that returns
the list of matched interface configs or indicates missing entries; keep the
retry closure in verify_all_static_ips only coordinating retries, calling
_load_current_interfaces and _match_expected_static_ips, and mapping any
CommandExecFailed/timeout into the same exceptions; ensure each new helper has a
leading underscore, stays under ~50 lines, and that names referenced here
(verify_all_static_ips, _load_current_interfaces, _match_expected_static_ips)
are used to locate and replace the corresponding blocks in the original
function.
- Around line 493-500: The current loop in the interface matching logic uses a
permissive substring test (interface_name.lower() in iface_name.lower()) and
breaks on first match, which allows fuzzy name matches to beat later exact MAC
matches; refactor the matching in post_migration.py so you first normalize MACs
(source_mac/dest_mac) and scan all current_interfaces for an exact MAC match and
pick that if found, otherwise scan for an exact normalized name match (compare
normalized iface_name == interface_name), and only if neither yields a hit
perform a substring search that must return a single unambiguous candidate;
update the loop around current_interfaces so it collects candidates for each
phase instead of breaking on first hit and then selects the best match in order
(exact MAC -> exact name -> unique substring).

---

Outside diff comments:
In `@utilities/post_migration.py`:
- Around line 407-425: Update the docstring for the function that verifies
static IPs (parameters: vm_name, vm_ssh_connections, source_vm_data,
source_provider_data, timeout, retry_delay) so the timeout default reads 660
(not 600), ensure Args reflect those parameters, add a Raises section that lists
the concrete exceptions the function may surface (e.g., TimeoutError,
ValueError, AssertionError) instead of a generic Exception, and include a
Returns section only if the function returns a meaningful non-None value
(otherwise omit Returns).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 085be161-8b12-4963-9ae0-70197d827f21

📥 Commits

Reviewing files that changed from the base of the PR and between 4bcd4fb and d0b4891.

📒 Files selected for processing (1)
  • utilities/post_migration.py

Comment thread utilities/post_migration.py Resolved
Comment thread utilities/post_migration.py Resolved
@myakove

myakove commented May 18, 2026

Copy link
Copy Markdown
Collaborator

/lgtm
/approve

krcmarik added a commit to krcmarik/mtv-api-tests that referenced this pull request May 18, 2026
Address CodeRabbit review feedback on PR RedHatQE#494:
- Extract _load_current_interfaces() and _match_expected_static_ips()
  as module-level helpers for independent testability
- Implement phased interface matching priority: exact MAC match first,
  then exact name match, then unique substring name match (prevents
  false positives from ambiguous substring matches)
- Update docstring with correct timeout default (660s) and specific
  exception types
@rh-bot-1

Copy link
Copy Markdown

Clean rebase detected — no code changes compared to previous head (c45fc0f).
The following labels were preserved: approved-myakove, lgtm-myakove, commented-krcmarik, commented-coderabbitai[bot], changes-requested-coderabbitai[bot].

@krcmarik

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 18, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@utilities/post_migration.py`:
- Around line 432-436: The code currently calls _parse_windows_network_config or
_parse_linux_network_config and can propagate exceptions from malformed/partial
output; change this polling-path return to wrap the parser call in a try/except
that catches parsing errors (Exception) and logs a warning (using
LOGGER.warning) including the exception and the raw stdout, then return None so
the caller treats it like empty output and retries; apply the same defensive
try/except pattern to the other polling site that currently hard-fails (the code
around the _parse_* invocation referenced at lines 603-605) so parse failures do
not abort the wait window.
- Around line 402-407: The parameter annotation for _load_current_interfaces
currently uses ssh_conn: Any which disables static checks; update the signature
to use ssh_conn: VMSSHConnection and import VMSSHConnection from
utilities.ssh_utils (remove or keep Any only if still used elsewhere), ensuring
the function and its docstring references (rrmngmnt_host, rrmngmnt_user,
local_port) match the concrete VMSSHConnection attributes so type checkers can
validate attribute access; update any other occurrences in this file that
reference the old Any annotation for the same conceptual SSH connection to use
VMSSHConnection as well.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: c627df4c-7ddf-4d7c-94c9-fd8be80b28ab

📥 Commits

Reviewing files that changed from the base of the PR and between d0b4891 and 5ddd049.

📒 Files selected for processing (1)
  • utilities/post_migration.py

Comment thread utilities/post_migration.py Resolved
Comment thread utilities/post_migration.py Resolved
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 18, 2026
@krcmarik

Copy link
Copy Markdown
Collaborator Author

/verifed
/cherry-pick v2.10 v2.11

@redhat-qe-bot

Copy link
Copy Markdown

Cherry-pick requested for PR: fix: eliminate TOCTOU bug in static IP preservation check by user krcmarik
Adding label/s cherry-pick-v2.10 cherry-pick-v2.11 for automatic cherry-pick once the PR is merged

@krcmarik

Copy link
Copy Markdown
Collaborator Author

/verified

@myakove

myakove commented May 19, 2026

Copy link
Copy Markdown
Collaborator

/lgtm
/approve

@myakove
myakove enabled auto-merge (squash) May 19, 2026 06:41
@myakove
myakove merged commit 2dfc662 into RedHatQE:main May 19, 2026
7 checks passed
@redhat-qe-bot1

Copy link
Copy Markdown

Cherry-picked PR fix: eliminate TOCTOU bug in static IP preservation check into v2.11: #504

@redhat-qe-bot1

Copy link
Copy Markdown

Cherry-picked PR fix: eliminate TOCTOU bug in static IP preservation check into v2.10: #505

redhat-qe-bot pushed a commit that referenced this pull request May 19, 2026
* fix: eliminate TOCTOU bug in static IP preservation check

Refactor check_static_ip_preservation() to verify all static IPs
simultaneously instead of sequentially to ensure that all Static
IPs are present on the migrated guest at the moment (to catch
a possible bug when firstboot script on the guest wrongly overwrites
already configured primary Static IP.

- Single TimeoutSampler verifies all static IPs on each iteration
- One SSH call per retry instead of one per IP
- Use dict(matched) shallow copy to prevent mutation
- Use zip(..., strict=True) for length safety

* refactor: extract helper functions from static IP verification closure

Address CodeRabbit review feedback on PR #494:
- Extract _load_current_interfaces() and _match_expected_static_ips()
  as module-level helpers for independent testability
- Implement phased interface matching priority: exact MAC match first,
  then exact name match, then unique substring name match (prevents
  false positives from ambiguous substring matches)
- Update docstring with correct timeout default (660s) and specific
  exception types

* refactor: use VMSSHConnection type instead of Any in _load_current_interfaces

Addresses CodeRabbit review comment on PR #494. Replaces the
generic Any annotation with the concrete VMSSHConnection type for
static type safety and updates the docstring accordingly.

Co-authored-by: Marián Krčmárik <mkrcmari@redhat.com>
redhat-qe-bot2 pushed a commit that referenced this pull request May 19, 2026
* fix: eliminate TOCTOU bug in static IP preservation check

Refactor check_static_ip_preservation() to verify all static IPs
simultaneously instead of sequentially to ensure that all Static
IPs are present on the migrated guest at the moment (to catch
a possible bug when firstboot script on the guest wrongly overwrites
already configured primary Static IP.

- Single TimeoutSampler verifies all static IPs on each iteration
- One SSH call per retry instead of one per IP
- Use dict(matched) shallow copy to prevent mutation
- Use zip(..., strict=True) for length safety

* refactor: extract helper functions from static IP verification closure

Address CodeRabbit review feedback on PR #494:
- Extract _load_current_interfaces() and _match_expected_static_ips()
  as module-level helpers for independent testability
- Implement phased interface matching priority: exact MAC match first,
  then exact name match, then unique substring name match (prevents
  false positives from ambiguous substring matches)
- Update docstring with correct timeout default (660s) and specific
  exception types

* refactor: use VMSSHConnection type instead of Any in _load_current_interfaces

Addresses CodeRabbit review comment on PR #494. Replaces the
generic Any annotation with the concrete VMSSHConnection type for
static type safety and updates the docstring accordingly.

Co-authored-by: Marián Krčmárik <mkrcmari@redhat.com>
@redhat-qe-bot1

Copy link
Copy Markdown

New container for ghcr.io/redhatqe/mtv-api-tests:latest published

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants