From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pl1-f176.google.com (mail-pl1-f176.google.com [209.85.214.176]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3880A279DB1 for ; Mon, 17 Aug 2026 02:31:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.176 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786933879; cv=none; b=s8en18qNqU26+2g9aoZ50dYlTjHRfEXKtlK9DA8tzgyfis5ug7YV+THu2QHPfGrt/TUJxyxCQJSQvF0ATzhkgd96FEB0BVCzVIzKsOizNxJLnuaGYznKam3pXt3fTxE0rcl+VEv+u+rjtKIKAoa51zL+N3p1NexrU0BtQ1l3IEo= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786933879; c=relaxed/simple; bh=RIdT78GVIOU79dvwJtmny4FuRS/G6OQEjs1Q0z+8uD8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Vfx7PXloGpsXfXz4G1znZvEW6K/gr7de/u7AHiuMNzCAdGlVZyZVDjEdpnP/go4YVSgU4/ETarlEYK8xCPUgymBGJ7oWjtwFJ/NmtUIVqnhrVcm3HiKcns3Lz846U1yzvMfjeSUiqY48GIVkez+Iqc3FOY/weYViHzQ4B2xi4I0= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ajUo7GjO; arc=none smtp.client-ip=209.85.214.176 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ajUo7GjO" Received: by mail-pl1-f176.google.com with SMTP id d9443c01a7336-2cca0c5799eso25891755ad.0 for ; Sun, 16 Aug 2026 19:31:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1786933877; x=1787538677; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=r5/OtHgevkIAK5SI9bRivZoT+Oh1LU2NNLDc67pJhOs=; b=ajUo7GjOvOZ1qLkEoFucBCOlTSFPEndsQsry9GpVZW/QutTJmD9iCpeLvcVMSJEzED z3+h2RH+QpJCAppya786mVZD7PKJQaOhKNXtfPDUyjyg3BUJJkwK8kBmqv50FnBfiTVQ WTCkMEO/S0mRLmTagFPM5Vu2DhsIRQi9g7OlEPllJshpvhQntQ+po9o1s9zbRaSmeVI6 6zBFpHZwLVK9GZgaGVuZOrbT2bb9y1dUqvP3tLUSJ6xx65malB7gOFbNh30JzHvcyHe/ TLZb+b+tBqhbZJopAvqraRo1P8V+PTTwm/xwdgCm/FfRjGE0+SGLpeWso/0CBorUuO5h z2Ww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786933877; x=1787538677; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=r5/OtHgevkIAK5SI9bRivZoT+Oh1LU2NNLDc67pJhOs=; b=FQWNw7bHMjy59VtdQj+ZMBu5pwbzUzCG0mKtYRju8KbvVEcl1/i5NYcU/w70ofV9R9 pOMnGRSqe19Ikr0a0prVn8iWlCcbIK7hn+AhbgHyuinByYZKxExglWBd+qtiekXz10km W26m5xcFo3azy54dlcw+twMvUXwYnydrGkQo165qOIb8rcI+J8JOT8ym+KavFcFugL7q +ZIKICh9wzoaDc8lt6CFr32+t9xiwWjV+cwji+/ON3IpwQD8vEvNIM9c6uYE2ar/ToSA Cgb7biN9RHP7ZAVXK5+pNzIuV/AZC5us6KBkUeJEA64FcbjRFCYE8JZReLf/VlFXMrNt yBZg== X-Forwarded-Encrypted: i=1; AHgh+RpoiFU18N1mq1VOJzqvytjQS8GF+zGVE5qMu4z9iM/FrkF3XxdqlnWkMPsxQDDwGB3IMizfAd0G8Z/Ql3M=@vger.kernel.org X-Gm-Message-State: AOJu0YyFXQFPIcrLFLZe0ikTsoAcMKFeyyd9XJCpr4TMWxLShs34DSYY i3ffQL/wB/HKMDpCp67d5bkE7w5ykafoSChVfLTYyIwgMwCGJy8+W+0/ X-Gm-Gg: AR+sD10femNaLM1YrMpiOXQfNltIUL+7x0pK/WSURNXiBTTAXFgiqXAugA6UGh1WXnf 3dnkcjRSPUDUgSCUOUZvdElyV3w+dhUCeh+M/kNSsT9SOcMIbcOzgsJ608KVoIulIoYmNd2x7Yc RDAVGrUNKxjHsE9JGnACmTOB4rqaHqPq09OmslY0VLYiHZ8ItZwJ1xNy2gWCn5pW3hVpT5A654+ EeKJIM7nFTddeM05b08Qyf+i2Kh2Ziu9O2ZYKRB1ihVsecSgQAMH/eFMuLDKgDHc0rRsIJVLXFa 0PSoo9pIvNaihLyJk7W3Ce1RQfwbOPc10Kpu2RB+N2WbOZko4HXEy20utm900bEjxI/nFcGRae7 PXVYRjyDMympyj+cwwsRJO1GCN3VNj9dx+WdhPCgfu0CkHGX2NR6q0Jrb2x2smqxI+0xu2RJkeQ FkhUliti3PMbtbu87TC1E9/Cud8LAq4yVP9rprGTXmE63u1rtwv0JbhmYVZ5H9JesFaJt2qZS6 X-Received: by 2002:a17:90b:5606:b0:38e:c232:9d3f with SMTP id 98e67ed59e1d1-3933b81d0aemr21565647a91.5.1786933877299; Sun, 16 Aug 2026 19:31:17 -0700 (PDT) Received: from localhost.localdomain ([120.236.7.85]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-39531ff679fsm2916875a91.14.2026.08.16.19.31.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 16 Aug 2026 19:31:16 -0700 (PDT) From: Cheng Liu To: Marc Kleine-Budde , Wolfgang Grandegger Cc: linux-can@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Elaine Zhang , Cheng Liu Subject: Re: [PATCH can] can: rockchip: rk3576: fix rtnl_lock deadlock during interface down under bus traffic Date: Mon, 17 Aug 2026 10:31:08 +0800 Message-Id: <20260817023108.1854647-1-chengliu480@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260817013750.1836064-1-chengliu480@gmail.com> References: <20260817013750.1836064-1-chengliu480@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Hi Marc, Elaine, and linux-can community, To help anyone easily reproduce and verify this deadlock scenario on RV1126B / RK3576, below is the full standalone Python SocketCAN test script used to trigger the race condition: ```python #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ reproduce_can_deadlock.py Constructs a concurrent kernel-level deadlock scenario: 1. Blocking sender threads: deep sleep wait in can_send() waiting for TX FIFO. 2. Error frame receiver: setsockopt(CAN_RAW_ERR_FILTER) to receive all error frames. 3. Socket churn: rapid open/bind/send/close. 4. Down/up interrupt loop: calls `ip link set can0 down` during active traffic. """ import os import sys import time import socket import struct import threading import subprocess AF_CAN = getattr(socket, "AF_CAN", 29) PF_CAN = AF_CAN CAN_RAW = getattr(socket, "CAN_RAW", 1) SOL_CAN_BASE = 100 CAN_RAW_FILTER = 1 CAN_RAW_ERR_FILTER = 2 CAN_RAW_LOOPBACK = 3 CAN_RAW_RECV_OWN_MSGS = 4 CAN_RAW_FD_FRAMES = 5 CAN_ERR_MASK = 0x1FFFFFFF INTERFACE = "can0" STOP_EVENT = threading.Event() DEADLOCK_DETECTED = threading.Event() def build_can_frame(can_id, data): can_dlc = len(data) data = data.ljust(8, b'\x00') return struct.pack("=IB3x8s", can_id, can_dlc, data) def build_canfd_frame(can_id, data, flags=0): length = len(data) data = data.ljust(64, b'\x00') return struct.pack("=IBB2x64s", can_id, length, flags, data) def sender_thread(thread_id, is_fd=False): sock = socket.socket(PF_CAN, socket.SOCK_RAW, CAN_RAW) try: if is_fd: try: sock.setsockopt(SOL_CAN_BASE, CAN_RAW_FD_FRAMES, 1) except Exception: pass sock.bind((INTERFACE,)) sock.setblocking(True) except Exception: sock.close() return frame_data = b'\x11\x22\x33\x44\x55\x66\x77\x88' can_id = 0x100 + thread_id frame = build_can_frame(can_id, frame_data) while not STOP_EVENT.is_set(): try: sock.send(frame) except socket.error: time.sleep(0.001) except Exception: break sock.close() def receiver_thread(): try: sock = socket.socket(PF_CAN, socket.SOCK_RAW, CAN_RAW) sock.setsockopt(SOL_CAN_BASE, CAN_RAW_ERR_FILTER, CAN_ERR_MASK) sock.bind((INTERFACE,)) sock.settimeout(0.1) except Exception: return while not STOP_EVENT.is_set(): try: _ = sock.recv(72) except socket.timeout: continue except Exception: time.sleep(0.01) sock.close() def socket_churn_thread(): while not STOP_EVENT.is_set(): try: s = socket.socket(PF_CAN, socket.SOCK_RAW, CAN_RAW) s.bind((INTERFACE,)) s.setblocking(False) frame = build_can_frame(0x200, b'\xaa\xbb\xcc\xdd') try: s.send(frame) except Exception: pass s.close() except Exception: pass time.sleep(0.002) def main(): if os.geteuid() != 0: print("[-] Please run as root: sudo python3 reproduce_can_deadlock.py") sys.exit(1) print("=" * 65) print("Starting SocketCAN deadlock reproduction tool") print("=" * 65) subprocess.run(["ip", "link", "set", INTERFACE, "down"], stderr=subprocess.DEVNULL) time.sleep(0.3) subprocess.run(["ip", "link", "set", INTERFACE, "txqueuelen", "1"], check=False) subprocess.run([ "ip", "link", "set", INTERFACE, "up", "type", "can", "bitrate", "500000", "dbitrate", "500000", "fd", "on", "restart-ms", "100" ], check=False) threads = [] for i in range(3): t = threading.Thread(target=sender_thread, args=(i, i % 2 == 0), daemon=True) t.start() threads.append(t) t_recv = threading.Thread(target=receiver_thread, daemon=True) t_recv.start() threads.append(t_recv) t_churn = threading.Thread(target=socket_churn_thread, daemon=True) t_churn.start() threads.append(t_churn) loop_count = 0 try: while True: loop_count += 1 now_str = time.strftime("%H:%M:%S") sys.stdout.write(f"[{now_str}] Loop {loop_count:5d}: Bringing can0 down... ") sys.stdout.flush() t0 = time.time() p_down = subprocess.Popen(["ip", "link", "set", INTERFACE, "down"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) try: p_down.communicate(timeout=4.0) down_cost = time.time() - t0 sys.stdout.write(f"Done ({down_cost*1000:.1f}ms) -> Bringing can0 up... ") sys.stdout.flush() except subprocess.TimeoutExpired: print("\n" + "!" * 65) print("Captured deadlock! `ip link set can0 down` hung > 4s!") print("Kernel rtnl_lock is deadlocked!") print("!" * 65) DEADLOCK_DETECTED.set() break t1 = time.time() p_up = subprocess.Popen(["ip", "link", "set", INTERFACE, "up"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) try: p_up.communicate(timeout=4.0) up_cost = time.time() - t1 sys.stdout.write(f"Done ({up_cost*1000:.1f}ms)\n") sys.stdout.flush() except subprocess.TimeoutExpired: print("\n" + "!" * 65) print("Captured deadlock! `ip link set can0 up` hung > 4s!") print("!" * 65) DEADLOCK_DETECTED.set() break time.sleep(0.005) except KeyboardInterrupt: print("\n[*] Exiting test...") finally: STOP_EVENT.set() if not DEADLOCK_DETECTED.is_set(): subprocess.run(["ip", "link", "set", INTERFACE, "down"], stderr=subprocess.DEVNULL) print(f"[*] Completed {loop_count} loops.") if __name__ == "__main__": main() ``` Also, if maintainers prefer this fix to be split into separate smaller atomic patches (e.g. 1. close deadlock fix, 2. NAPI budget handling, 3. error handling NULL check), please let me know and I will gladly send a v2 patch series! Best regards, Cheng Liu