From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [45.144.208.40]) by lore.proxmox.com (Postfix) with ESMTPS id 52B0D1FF09B for ; Mon, 09 Nov 2026 23:07:21 +0100 (CET) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id D2B9F21423; Mon, 09 Nov 2026 23:07:20 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=stuttgart.de; s=s1022; t=1794261591; bh=vQvV/q8XCW97PJtXxAAKUO9+WM3srbDpWphcrXlm+U4=; h=From:To:Cc:Subject:Date:From; b=jYGEWDdgAsvsk9exp4YwJPci1iOpcBpToo3nvBa3HhuTguCcp0dQBz7GdBrcEH/MG il3gKl+BttnX6QBXDv6y2ScIBUBU86fs1CM22QSi6YRqUR4JQFiJX6G71kRdx0M+MU Y1nlfdYemNnBNsGh8rI2Z0+SQ3Tmj1zRAHJyPcWzVE3RikvJm76dHW0sDuEw73nmrA INLnvdealecfna4c8Zr36DJskXX/RFQtgPjJ3OGrev4YeI3R2E2WIvDp1ouR2aLRzK UbZ60zcdsICglDJlfl9To0Y6PFGIrm5oAO18plXXnOl/SR23vpGNm2Mi8kISG28hKO M9oAAHjgj7Y7w== From: Jakob-Tobias Winter To: tobias@linuxdingsda.de, pbs-devel@lists.proxmox.com Subject: [PATCH proxmox-backup] tape: virtual drive: fix endless recursion in changer status Date: Mon, 9 Nov 2026 22:59:50 +0100 Message-ID: <20261109215950.903491-1-tobias@stuttgart.de> X-Mailer: git-send-email 2.53.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.019 Adjusted score from AWL reputation of From: address DKIM_SIGNED 0.1 Message has a DKIM or DK signature, not necessarily valid DKIM_VALID -0.1 Message has at least one valid DKIM or DK signature DKIM_VALID_AU -0.1 Message has a valid DKIM or DK signature from author's domain DKIM_VALID_EF -0.1 Message has a valid DKIM or DK signature from envelope-from domain DMARC_PASS -0.1 DMARC pass policy RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust SPF_HELO_PASS -0.001 SPF: HELO matches SPF record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: DOYVKNJHMQL7NNUDFGZ4OU7A4X7YZXGQ X-Message-ID-Hash: DOYVKNJHMQL7NNUDFGZ4OU7A4X7YZXGQ X-MailFrom: prvs=1120bca8fb=tobias@stuttgart.de X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Jakob-Tobias Winter X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox Backup Server development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: The virtual tape drive, which exists for tests and debugging only, also acts as its own changer and reports every virtual tape in its directory as a slot. To build that status it asked for the list of online media, but got the generic variant of that list, which is derived from the changer status. The two called each other until the stack overflowed, so every operation that needs the changer status of a virtual drive, like loading or unloading a tape, crashed the process. Use the list of tapes in the directory of the drive instead, as it was intended, for the status and for loading a tape from a slot. Signed-off-by: Jakob-Tobias Winter --- The recursion has been there since 46a1863f8 ("tape: improve MediaChange trait"). Reproducer, with a virtual drive 'vtape' in tape.cfg and an empty file 'tape-demo1.json' in its directory: proxmox-backup-debug api create /tape/drive/vtape/load-slot \ --source-slot 1 Tested with debug builds of current master and of 4.2.8, calling the API in-process (PROXMOX_DEBUG_API_CODE=1): the call aborts with a stack overflow without the patch and loads the tape with it. src/tape/drive/virtual_tape.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tape/drive/virtual_tape.rs b/src/tape/drive/virtual_tape.rs index a17916bab..b2febaed5 100644 --- a/src/tape/drive/virtual_tape.rs +++ b/src/tape/drive/virtual_tape.rs @@ -499,7 +499,7 @@ impl MediaChange for VirtualTapeHandle { // slot-assignment here. let mut slots = Vec::new(); - let label_texts = self.online_media_label_texts()?; + let label_texts = VirtualTapeHandle::online_media_label_texts(self)?; let max_slots = label_texts.len().div_ceil(8) * 8; for i in 0..max_slots { @@ -535,7 +535,7 @@ impl MediaChange for VirtualTapeHandle { bail!("invalid slot ID {}", slot); } - let label_texts = self.online_media_label_texts()?; + let label_texts = VirtualTapeHandle::online_media_label_texts(self)?; if slot > label_texts.len() as u64 { bail!("slot {} is empty", slot); -- 2.53.0