From patchwork Sun Jul 30 01:29:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boqun Feng X-Patchwork-Id: 13333329 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id CF478C04A6A for ; Sun, 30 Jul 2023 01:29:56 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 0EBE68D0003; Sat, 29 Jul 2023 21:29:56 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 09D108D0001; Sat, 29 Jul 2023 21:29:56 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id E31768D0003; Sat, 29 Jul 2023 21:29:55 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0016.hostedemail.com [216.40.44.16]) by kanga.kvack.org (Postfix) with ESMTP id D3A678D0001 for ; Sat, 29 Jul 2023 21:29:55 -0400 (EDT) Received: from smtpin19.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay01.hostedemail.com (Postfix) with ESMTP id 9C9531C9458 for ; Sun, 30 Jul 2023 01:29:55 +0000 (UTC) X-FDA: 81066546750.19.55222A9 Received: from mail-ej1-f47.google.com (mail-ej1-f47.google.com [209.85.218.47]) by imf26.hostedemail.com (Postfix) with ESMTP id 65941140006 for ; Sun, 30 Jul 2023 01:29:53 +0000 (UTC) Authentication-Results: imf26.hostedemail.com; dkim=pass header.d=gmail.com header.s=20221208 header.b=lZMgU3gj; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (imf26.hostedemail.com: domain of boqun.feng@gmail.com designates 209.85.218.47 as permitted sender) smtp.mailfrom=boqun.feng@gmail.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1690680593; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=9OgITT2yiqZUUNG1U4xDDumpCjudK5Ub6jXVaWbbuKI=; b=H0D6tlz30J3h7kPELdQoFgPax0kNV9UPdtXJ80fNO1FDqUuvO9a/mp2oCZCXFkisID4cme VXHuSbH7xO7mcD8XBz/W0mcH6zqiaqHvhNCIC2XOA71dWFajvg6Uip75meSCsnRu+J6ADR bh4R6VGAWQ5g7EFZ7Jd3F+aFtdI5CLo= ARC-Authentication-Results: i=1; imf26.hostedemail.com; dkim=pass header.d=gmail.com header.s=20221208 header.b=lZMgU3gj; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (imf26.hostedemail.com: domain of boqun.feng@gmail.com designates 209.85.218.47 as permitted sender) smtp.mailfrom=boqun.feng@gmail.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1690680593; a=rsa-sha256; cv=none; b=59yXQSRgk8oSlfmQdMpXwsElcunHRJ9t7HQV+QYLOGy/Jd9nY8CJI4GWuXwEnfb2TO6Qtf o66WLp1GWtJBYb5Ry7UkOj/L/5TwyLuv282cjJZQusQ7ihnJZoVUNVDOhw3QCDQN7g1sfZ 1CG/3vDJMLvFUffHxOlweE6FNlzFiJs= Received: by mail-ej1-f47.google.com with SMTP id a640c23a62f3a-99bc0a20b54so527377066b.1 for ; Sat, 29 Jul 2023 18:29:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1690680592; x=1691285392; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:feedback-id:from:to:cc:subject :date:message-id:reply-to; bh=9OgITT2yiqZUUNG1U4xDDumpCjudK5Ub6jXVaWbbuKI=; b=lZMgU3gjYlD/diNHnqBRZUPy+ReTapzTL8Hv9c4ilG8HeXJNSg2rFnNGnV3ZzAGg7w IL8+AAVY4nLIBHOo+upAu+tEy1C1iCWvP8NhXcjU9iY/k+l1v5XEyXY2U+bBD9Bk0gkS tHIjW2ktEvoAN7ly0mxkm4JLak3mt6oZKjYDyy2hxzfzhn+SunbC9syqdmYOD4kAIQ30 rq+4qDFtBRZryd194tNihVvhhQUg6CIN+6X5AMaLfovokf5ZtROyHVa7sTZe8/9PvEY8 gBWTjKrD1Eo9nqbpMzlZFiqzeTUHGVOL+EWw/+cLY0/v395htQ1L5LajaG3ZwHFskWl8 ettw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1690680592; x=1691285392; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:feedback-id:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=9OgITT2yiqZUUNG1U4xDDumpCjudK5Ub6jXVaWbbuKI=; b=i6dCQBWJw4XtwhG+JzfjqZgoSN4wHbzXmCNmhEQzW1LgeoW7ZjAjAOBxTo5P91IN29 yO6qMokth8WLEoQ1Y1KkVpM3RKDEVdz5YQqFD2dhKtnvy4bqG9/lYZdlSdOfbhpoJL5y wsmzklT50H489HbIi4aeYt2F2ALujqwIB3td6Rzb6uND8TBdrzGtDf6k52NuutP1z3VH Ly/HadTnjvjGfBkFjnEn3JmCFtXAsv9uxNg28tb86TxI2vCRTJjD8SPUn071HFxEC3Iu 4yrkZ8oCeKs4/7FvphF4s5aJ6wJnLYw/9DpgWbL2hHfaDE3w89JP/z9DlrnQZ1uqSMX9 XlgQ== X-Gm-Message-State: ABy/qLbGvEToNTRA2U1vX7soaFpGhAn4txsuRsUIkaaGDhKsTwnA3mNW 3uRiLj65e4MbNS/pRSCg/Svyt0l7BoE= X-Google-Smtp-Source: APBJJlFTQMGWBtK8SuCFhD9DwEnEvBYfJNamT3jZ0CGl1sRmkV+QglVHxqdJsDKKHLYXGG7Mx8AM1g== X-Received: by 2002:a17:906:8a5c:b0:991:37d2:c9f0 with SMTP id gx28-20020a1709068a5c00b0099137d2c9f0mr3658931ejc.68.1690680591709; Sat, 29 Jul 2023 18:29:51 -0700 (PDT) Received: from auth2-smtp.messagingengine.com (auth2-smtp.messagingengine.com. [66.111.4.228]) by smtp.gmail.com with ESMTPSA id ks18-20020a170906f85200b00977ca5de275sm4046161ejb.13.2023.07.29.18.29.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 29 Jul 2023 18:29:51 -0700 (PDT) Received: from compute5.internal (compute5.nyi.internal [10.202.2.45]) by mailauth.nyi.internal (Postfix) with ESMTP id 372F827C005B; Sat, 29 Jul 2023 21:29:48 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute5.internal (MEProxy); Sat, 29 Jul 2023 21:29:48 -0400 X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedviedrieelgdegiecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenuc fjughrpefhvfevufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpeeuohhquhhn ucfhvghnghcuoegsohhquhhnrdhfvghnghesghhmrghilhdrtghomheqnecuggftrfgrth htvghrnhepgeeljeeitdehvdehgefgjeevfeejjeekgfevffeiueejhfeuiefggeeuheeg gefgnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomhepsg hoqhhunhdomhgvshhmthhprghuthhhphgvrhhsohhnrghlihhthidqieelvdeghedtieeg qddujeejkeehheehvddqsghoqhhunhdrfhgvnhhgpeepghhmrghilhdrtghomhesfhhigi hmvgdrnhgrmhgv X-ME-Proxy: Feedback-ID: iad51458e:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sat, 29 Jul 2023 21:29:47 -0400 (EDT) From: Boqun Feng To: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org Cc: Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Martin Rodriguez Reboredo , Alice Ryhl , Dariusz Sosnowski , Geoffrey Thomas , Fox Chen , John Baublitz , Christoph Lameter , Pekka Enberg , David Rientjes , Joonsoo Kim , Andrew Morton , Vlastimil Babka , Roman Gushchin , Hyeonggon Yoo <42.hyeyoo@gmail.com>, Kees Cook , stable@vger.kernel.org, Andreas Hindborg Subject: [PATCH 1/3] rust: allocator: Prevent mis-aligned allocation Date: Sat, 29 Jul 2023 18:29:02 -0700 Message-ID: <20230730012905.643822-2-boqun.feng@gmail.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230730012905.643822-1-boqun.feng@gmail.com> References: <20230730012905.643822-1-boqun.feng@gmail.com> MIME-Version: 1.0 X-Rspam-User: X-Rspamd-Server: rspam12 X-Rspamd-Queue-Id: 65941140006 X-Stat-Signature: gir9zmujbffd3ro44fo39o73ynbi1p8y X-HE-Tag: 1690680593-201220 X-HE-Meta: U2FsdGVkX1+lKrGcYGZ8W/iMkp4ZWPjt4rYxzgSCQKo2vFgcgemCm8Cf+4geDitnoCoMvHuY5FN49dOmC0KqvvRtePTlmma/pDmWije7CZQg97n5lhLftToA1mfJYrqJ87SumEorpqOxN3TKY/8bM3rnrFUE6MzX5AEdd9sOUqPWtQfZmk32rfho61xsD/sd62SaRQwZd/jrYaAq5FzPqKUnMyPhuTaWp3wxTblEFpO3aST/IUMeggs4MILZ56FqoFiJC792ajvQ/22MWGKaJtl/OataKTamj1O4GT1E4Cz1nD5GfFzHxM91tZeulLijnvSg0BTgBC1OVmg4/3XZ0M2kOWhMq9hGDtNMclPI7DTD01jfxJSUp2WDh9lbmmIPSczqDUWDTQJlzOph0JrNk+VhxMtcGnB/QjxA2w3hjapPDtwwkw8eDZ/KautyDAxoge5w+rcZADldz62BU89yBUD0r8k3kaCnXZqVr1zb79Jvmhj999U+hZXPdnjJwSGAQ0npbCfNdj/Fp0A1RNQxZlFHQFIAAzG/COnMzAw83dpC7E8eBCZs9c4Tm9pFb301dRh06bWPBvzzSmcxbl65OUAqIpndvqn82Z15L5g/17eBZjy9a28rH4T4uNNWCpfxZV6b1UFYY5OGKGlVy78jYYFCXYUbv9KGxxfXcquLk2QLzi5xgMYkkCIJZAPgIw9zyxQS6luSTltIK8c2pJfw4/fm/EEQJi/pLxdqhLiRtpoMc3oCGnME6BBsFf7d1Rn+KNGBEyWisgmnNGepsHDT7QOGyeTuR5z1ezCAXyJSs4NZTGDNJFwM20CUgwb6qeNBc6Pq8ObyYUEul2jeJsjAKmwkHQ44wxYDk1fSOJJ8bIKKuGXj8v4TLptXXCJbMLzw4wBEy5Q6gd2gTzmxTQ6W035o6aMFSWC8Ddir8a5fu1FUO9fhsmWZvhwbvxL0DWUZJTjPA8dmKgzH1/a5N3K 9QG49IXW B2wLlsWvG7FZNkaEDgOg1ET9U0aqO5OrhqpLPcyI6pHGFFMgEKxtUx57EpnMExznvP7C14HDJDbHSZxHVOdaZiW57/g07TgyDER/5d3uHMut5Rkq08PA6yxsmmNkyJUVTknzqpZ4kqDjHVGqdnk2UU5pNNHiT/lldG/Dwfpm1WZLxXOsvuSTbphnm7ZBdqxFfFIfSpBFAioauiQda8m+21B+GJM4wzhHcZmKmVNATsQ20e9Vh0EX61gwX30iZ7Vuf9y7DZEFzriirS/UXe7ORetYdW+IUZj4diXYTJpe7vK7yNoIKwTmjArUWc5v40iEuI1TwrGAf0DvUIzkXHpUgat4pd/JKzhio1gojazz6nH+e2jhCEnIhMCNxL8cWEWwws3wSNnG3bneyND4HJgYiiPrYm+9Ji2iRwspDOisv0EXNA1WUeSvf1QfuyHKaBYMPrOBPPNJajoM1+x0rS6KLcN+BYGpP6+/u6QP01IfsTNwo+Wy9JGEvKPOmJTs5v0ZY079WLrg9MSS+AdYBHMwt5faLTW3kvxgWVE1uypiGHSXxSyTR/J0VEmmpAogIcP5tRjSYxtxjzRdWmwAm/YIxG43cDg== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: Currently the rust allocator simply passes the size of the type Layout to krealloc(), and in theory the alignment requirement from the type Layout may be larger than the guarantee provided by SLAB, which means the allocated object is mis-aligned. Fix this by adjusting the allocation size to the nearest power of two, which SLAB always guarantees a size-aligned allocation. And because Rust guarantees that the original size must be a multiple of alignment and the alignment must be a power of two, then the alignment requirement is satisfied. Suggested-by: Vlastimil Babka Co-developed-by: Andreas Hindborg (Samsung) Signed-off-by: Andreas Hindborg (Samsung) Signed-off-by: Boqun Feng Cc: stable@vger.kernel.org # v6.1+ Acked-by: Vlastimil Babka --- rust/bindings/bindings_helper.h | 1 + rust/kernel/allocator.rs | 74 ++++++++++++++++++++++++++------- 2 files changed, 60 insertions(+), 15 deletions(-) diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 3e601ce2548d..058954961bfc 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -13,5 +13,6 @@ #include /* `bindgen` gets confused at certain things. */ +const size_t BINDINGS_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN; const gfp_t BINDINGS_GFP_KERNEL = GFP_KERNEL; const gfp_t BINDINGS___GFP_ZERO = __GFP_ZERO; diff --git a/rust/kernel/allocator.rs b/rust/kernel/allocator.rs index 397a3dd57a9b..fae11d1fdba7 100644 --- a/rust/kernel/allocator.rs +++ b/rust/kernel/allocator.rs @@ -9,6 +9,36 @@ struct KernelAllocator; +/// Calls `krealloc` with a proper size to alloc a new object aligned to `new_layout`'s alignment. +/// +/// # Safety +/// +/// - `ptr` can be either null or a pointer which has been allocated by this allocator. +/// - `new_layout` must have a non-zero size. +unsafe fn krealloc_aligned(ptr: *mut u8, new_layout: Layout, flags: bindings::gfp_t) -> *mut u8 { + // Customized layouts from `Layout::from_size_align()` can have size < align, so pad first. + let layout = new_layout.pad_to_align(); + + let mut size = layout.size(); + + if layout.align() > bindings::BINDINGS_ARCH_SLAB_MINALIGN { + // The alignment requirement exceeds the slab guarantee, thus try to enlarge the size + // to use the "power-of-two" size/alignment guarantee (see comments in `kmalloc()` for + // more information). + // + // Note that `layout.size()` (after padding) is guaranteed to be a multiple of + // `layout.align()`, so `next_power_of_two` gives enough alignment guarantee. + size = size.next_power_of_two(); + } + + // SAFETY: + // - `ptr` is either null or a pointer returned from a previous `k{re}alloc()` by the + // function safety requirement. + // - `size` is greater than 0 since it's either a `layout.size()` (which cannot be zero + // according to the function safety requirement) or a result from `next_power_of_two()`. + unsafe { bindings::krealloc(ptr as *const core::ffi::c_void, size, flags) as *mut u8 } +} + unsafe impl GlobalAlloc for KernelAllocator { unsafe fn alloc(&self, layout: Layout) -> *mut u8 { // `krealloc()` is used instead of `kmalloc()` because the latter is @@ -30,10 +60,20 @@ unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { // to extract the object file that has them from the archive. For the moment, // let's generate them ourselves instead. // +// Note: Although these are *safe* functions, but they are only generated at +// `GlobalAlloc` callsites, hence we assume the parameters obey the same +// `GlobalAlloc` function safety requirements: size and align should form a +// valid layout, and size is greater than 0. +// // Note that `#[no_mangle]` implies exported too, nowadays. #[no_mangle] -fn __rust_alloc(size: usize, _align: usize) -> *mut u8 { - unsafe { bindings::krealloc(core::ptr::null(), size, bindings::GFP_KERNEL) as *mut u8 } +fn __rust_alloc(size: usize, align: usize) -> *mut u8 { + // SAFETY: See assumption above. + let layout = unsafe { Layout::from_size_align_unchecked(size, align) }; + + // SAFETY: `ptr::null_mut()` is null, per assumption above the size of `layout` is greater + // than 0. + unsafe { krealloc_aligned(ptr::null_mut(), layout, bindings::GFP_KERNEL) } } #[no_mangle] @@ -42,23 +82,27 @@ fn __rust_dealloc(ptr: *mut u8, _size: usize, _align: usize) { } #[no_mangle] -fn __rust_realloc(ptr: *mut u8, _old_size: usize, _align: usize, new_size: usize) -> *mut u8 { - unsafe { - bindings::krealloc( - ptr as *const core::ffi::c_void, - new_size, - bindings::GFP_KERNEL, - ) as *mut u8 - } +fn __rust_realloc(ptr: *mut u8, _old_size: usize, align: usize, new_size: usize) -> *mut u8 { + // SAFETY: See assumption above. + let new_layout = unsafe { Layout::from_size_align_unchecked(new_size, align) }; + + // SAFETY: Per assumption above, `ptr` is allocated by `__rust_*` before, and the size of + // `new_layout` is greater than 0. + unsafe { krealloc_aligned(ptr, new_layout, bindings::GFP_KERNEL) } } #[no_mangle] -fn __rust_alloc_zeroed(size: usize, _align: usize) -> *mut u8 { +fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8 { + // SAFETY: See assumption above. + let layout = unsafe { Layout::from_size_align_unchecked(size, align) }; + + // SAFETY: `ptr::null_mut()` is null, per assumption above the size of `layout` is greater + // than 0. unsafe { - bindings::krealloc( - core::ptr::null(), - size, + krealloc_aligned( + ptr::null_mut(), + layout, bindings::GFP_KERNEL | bindings::__GFP_ZERO, - ) as *mut u8 + ) } }