Uploaded image for project: 'RHEL'
  1. RHEL
  2. RHEL-143905

[RHEL10.2] Job.Cancel() Does Not Terminate Child Process

Linking RHIVOS CVEs to...Migration: Automation ...SWIFT: POC ConversionSync from "Extern...XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: Undefined Undefined
    • None
    • rhel-10.2
    • udisks2
    • None
    • None
    • None
    • rhel-storage-management
    • None
    • False
    • False
    • Hide

      None

      Show
      None
    • None
    • None
    • None
    • None
    • Unspecified
    • Unspecified
    • Unspecified
    • None

      What were you trying to do that didn't work?

      What is the impact of this issue to you?

      Please provide the package NVR for which the bug is seen:

      How reproducible is this bug?:

      Steps to reproduce

      1.  
      2.  
      3.  

      Expected results

       

      After `Job.Cancel()` returns:

      • ✅ Child process (dd/wipefs) should be terminated with SIGTERM
      • ✅ Device should become available within a few seconds
      • ✅ Inhibitor locks should be released
      • ✅ Job status should show as cancelled

       

      Actual results

      After `Job.Cancel()` returns:

      • ✅ Job is marked as cancelled (D-Bus property updates correctly)
      • ❌ Child process {}continues running{} until completion or daemon restart
      • ❌ Device remains busy (locked by the orphaned process)
      • ❌ Inhibitor lock leaks
      • ❌ Subsequent operations fail with EBUSY

       

       

      ## Summary
      When `Job.Cancel()` is called on a running `UDisksSpawnedJob` (e.g., disk erase operation), the D-Bus method returns successfully and the job is marked as cancelled, but **the underlying child process continues running**. This causes:
      1. Device remains busy indefinitely
      2. Inhibitor locks are not released
      3. Subsequent operations on the device fail with "Device or resource busy"
      4. System suspend/shutdown may be blocked
       

       

      All operations using `UDisksSpawnedJob`:
      - **Disk erase** (`Format 'empty'` with `'erase': 'zero'` or `'erase': 'ata-secure-erase'`) - **Critical**
      - **Filesystem formatting** (mkfs.ext4, mkfs.xfs, etc.) - Moderate
      - **Filesystem check** (fsck) - Moderate
      - Any other spawned external commands 
      ## Additional Evidence### Test Logs```
      [07:45:38] Starting wipe operation (cancelable job)...
      [07:46:39] Found cancelable job: /org/freedesktop/UDisks2/jobs/1066
      [07:46:39] Cancelling job...
      [07:46:39] Job cancel request sent
      [07:46:39] SUCCESS: Job cancellation tested# But the erase process continues!
      [07:46:40] Found job: /org/freedesktop/UDisks2/jobs/1813
      [07:46:40]   Operation: format-erase
      [07:46:40]   Progress: 1.5%  ← Still running
      [07:46:41]   Progress: 1.5%
      [07:46:42]   Progress: 1.6%  ← Progressing
      [07:46:43]   Progress: 1.6%
      
      # Device cleanup fails
      wipefs: error: /dev/sde: Device or resource busy
      
      # Inhibitor leaked
      Disk Manager   0   root 6768 udisksd   shutdown:sleep:idle Erasing Device   block
       

       

      ```python
      import dbus
      import time
      import subprocess# Setup
      bus = dbus.SystemBus()
      manager = bus.get_object('org.freedesktop.UDisks2', '/org/freedesktop/UDisks2/Manager')
      
      # Start long operation
      block_obj = bus.get_object('org.freedesktop.UDisks2', '/org/freedesktop/UDisks2/block_devices/sde')
      block_iface = dbus.Interface(block_obj, 'org.freedesktop.UDisks2.Block')
      
      # Format with erase (long operation)
      block_iface.Format('empty', {'erase': 'zero'})# Wait for job to start
      time.sleep(2)# Find and cancel the job
      jobs = ... 
      
      # Get job list
      job_iface.Cancel({})
      
      # ✅ PASS: No dd process should be running
      result = subprocess.run(['pgrep', '-f', 'dd.*sde'], capture_output=True)
      assert result.returncode != 0, "FAIL: dd process still running after cancel"
      
      
      # ✅ PASS: Device should be accessible
      result = subprocess.run(['wipefs', '-a', '/dev/sde'], capture_output=True)
      assert result.returncode == 0, "FAIL: Device still busy after cancel"
      ```
       
      
      
      Disk Manager 0 root 6768 udisksd shutdown:sleep:idle Erasing Device block 

       

       

       

      This is a {}confirmed implementation bug{} where the cancel callback fails to terminate the child process. The fix is straightforward: call `kill()` in `on_cancelled()` or invoke `udisks_spawned_job_release_resources()`.

       

       

       

       

      udisks2-2.11.0-1.el10.x86_64

      6.12.0-184.el10.x86_64

              tbzatek Tomáš Bžatek
              guazhang@redhat.com Guangwu Zhang
              Tomáš Bžatek Tomáš Bžatek
              Guangwu Zhang Guangwu Zhang
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

                Created:
                Updated: