From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [IPv6:2a0f:8001:1:32::40]) by lore.proxmox.com (Postfix) with ESMTPS id B89B61FF0E4 for ; Tue, 11 Aug 2026 17:03:09 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id 6F92E21573; Tue, 11 Aug 2026 17:03:09 +0200 (CEST) From: Robert Obkircher To: pbs-devel@lists.proxmox.com Subject: [PATCH v1 proxmox 1/6] uuid: avoid potential null dereference and memory leaks Date: Tue, 11 Aug 2026 17:02:00 +0200 Message-ID: <20260811150237.527116-2-r.obkircher@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260811150237.527116-1-r.obkircher@proxmox.com> References: <20260811150237.527116-1-r.obkircher@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1786460571718 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.849 Adjusted score from AWL reputation of From: address DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment (newer systems) RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust 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: RRP6AY5A2XZQFIJOYD2D4ER6FMBSVGMW X-Message-ID-Hash: RRP6AY5A2XZQFIJOYD2D4ER6FMBSVGMW X-MailFrom: r.obkircher@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: Avoid null pointer dereferences on allocation failures and do not leak memory on the error paths. I'm also not fully convinced that writing to uninitialized memory via assingment instead of ptr::write was guaranteed to be safe, but Miri doesn't complain about it. See the link for some additional context. Link: https://github.com/rust-lang/unsafe-code-guidelines/issues/346 Signed-off-by: Robert Obkircher --- proxmox-uuid/src/lib.rs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/proxmox-uuid/src/lib.rs b/proxmox-uuid/src/lib.rs index f2658ec6..59750a3a 100644 --- a/proxmox-uuid/src/lib.rs +++ b/proxmox-uuid/src/lib.rs @@ -61,10 +61,9 @@ pub struct Uuid(Box<[u8; 16]>); impl Uuid { /// Generate a uuid with `uuid_generate(3)`. pub fn generate() -> Self { - use std::alloc::{Layout, alloc}; - let uuid = unsafe { alloc(Layout::new::<[u8; 16]>()) as *mut [u8; 16] }; - unsafe { uuid_generate(uuid) }; - Self(unsafe { Box::from_raw(uuid) }) + let mut uuid = Box::new_uninit(); + unsafe { uuid_generate(uuid.as_mut_ptr()) }; + Self(unsafe { uuid.assume_init() }) } /// Get a reference to the internal 16 byte array. @@ -92,12 +91,10 @@ impl Uuid { /// assert_eq!(uuid1, uuid2); /// ``` pub fn parse_str(src: &str) -> Result { - use std::alloc::{Layout, alloc}; - let uuid: *mut [u8; 16] = unsafe { alloc(Layout::new::<[u8; 16]>()) as *mut [u8; 16] }; + let mut uuid = [0; 16]; if src.len() == 36 { // Unfortunately the manpage of `uuid_parse(3)` states that it technically requires a // terminating null byte at the end, which we don't have, so do this manually: - let uuid: &mut [u8] = unsafe { &mut (&mut *uuid)[..] }; let src = src.as_bytes(); if src[8] != b'-' || src[13] != b'-' || src[18] != b'-' || src[23] != b'-' { return Err(UuidError); @@ -118,7 +115,6 @@ impl Uuid { uuid[i] = (hex_digit(src[2 * i + 4])? << 4) | hex_digit(src[2 * i + 5])?; } } else if src.len() == 32 { - let uuid: &mut [u8] = unsafe { &mut (&mut *uuid)[..] }; let src = src.as_bytes(); for i in 0..16 { uuid[i] = (hex_digit(src[2 * i])? << 4) | hex_digit(src[2 * i + 1])?; @@ -126,7 +122,7 @@ impl Uuid { } else { return Err(UuidError); } - Ok(Self(unsafe { Box::from_raw(uuid) })) + Ok(Self(Box::new(uuid))) } } -- 2.47.3