From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) by lore.proxmox.com (Postfix) with ESMTPS id 91E6B1FF143 for ; Sat, 25 Apr 2026 12:10:35 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 63DA5276D6; Sat, 25 Apr 2026 12:10:35 +0200 (CEST) From: Christian Ebner To: pbs-devel@lists.proxmox.com Subject: [PATCH proxmox-backup] sync: pull: fix double blob decoding when decrypting Date: Sat, 25 Apr 2026 12:10:15 +0200 Message-ID: <20260425101015.437816-1-c.ebner@proxmox.com> X-Mailer: git-send-email 2.47.3 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1777111736923 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.070 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: 43PTN6X4GYFBK2QSVANMX5UIXMHXGRYM X-Message-ID-Hash: 43PTN6X4GYFBK2QSVANMX5UIXMHXGRYM X-MailFrom: c.ebner@proxmox.com 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 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: Commit 2f94320db ("sync: pull: decrypt blob files on pull if encryption key is configured") introduced the logic to decrypt encrypted data blob contents from the source on the fly when pulling with a matching decryption key. This however incorrectly performs a double blob decoding, as the DataBlobReader already checks and strips the header while reading the raw data from file, the DataBlob::load_from_reader() therefore chocking when trying to check the now missing header. Fix this by fully relying on the DataBlobReader to check, decode and decrypt the blob, and add the still missing finish() call to verify the reader state after decoding. Only then construct the new decrypted blob and pass individual slices for checksum calculation and writing to file, as the former consumes the slice. Reported-by: Markus Frank Reported-by: Erik Fastermann Reported-by: Shan Shaji Reported-by: Dominik Csapak Fixes: 2f94320db ("sync: pull: decrypt blob files on pull if encryption key is configured") Signed-off-by: Christian Ebner --- src/server/pull.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/server/pull.rs b/src/server/pull.rs index b4882718e..67ab70348 100644 --- a/src/server/pull.rs +++ b/src/server/pull.rs @@ -2,7 +2,7 @@ use std::collections::hash_map::Entry; use std::collections::{HashMap, HashSet}; -use std::io::{BufReader, Seek}; +use std::io::{Read, Seek}; use std::os::fd::AsRawFd; use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering}; use std::sync::{Arc, Mutex}; @@ -582,12 +582,15 @@ async fn pull_single_archive<'a>( let (csum, size) = tokio::task::spawn_blocking(move || { // must rewind again since after verifying cursor is at the end of the file tmpfile.rewind()?; - let mut reader = BufReader::new(DataBlobReader::new(tmpfile, crypt_config)?); - let blob = DataBlob::load_from_reader(&mut reader)?; - let mut raw_blob = blob.raw_data(); + let mut reader = DataBlobReader::new(tmpfile, crypt_config)?; + let mut dec_raw_data = Vec::new(); + reader.read_to_end(&mut dec_raw_data)?; + reader.finish()?; - let (csum, size) = sha256(&mut raw_blob)?; - replace_file(tmp_dec_path, raw_blob, CreateOptions::new(), true)?; + let blob = DataBlob::encode(&dec_raw_data, None, true)?; + + let (csum, size) = sha256(&mut blob.raw_data())?; + replace_file(tmp_dec_path, blob.raw_data(), CreateOptions::new(), true)?; Ok((csum, size)) }) .await? -- 2.47.3