From patchwork Mon Jul 8 19:18:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 13726994 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9C2ED14B956; Mon, 8 Jul 2024 19:18:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720466321; cv=none; b=UGp9TqUJeIkqUAgoEas4w0/i3NZWzfwV+ON9NOhrUeL3yNqVTzNF5PfAM5bD4rI3dG/IpuVrNsZ2yNFuz/YqLNVo9aTHdJQ2EtBOyMAFhTtH2w/A4dUfW26QiAoX3S5OO8y9RWQMJLGvrdHabINEHSeq68jAZYl0koreHfpX+0c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720466321; c=relaxed/simple; bh=O6uIF+RFb01/GkReF4c6yk0p7sEtVWsPKR+FVmZnPi8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ML7bGwrgvlIfgBYHPgHEPSYoL3DM1Z5TqfL7sjBv2iDbhnLSXS6+tlZiBMcyTzT9h0rblIUSs/OGoWNzBTZkD5RUPK0BWmUzTGUy5FqTWJcrzJrokHyB5pbLEaiU0InwI3FcZqJkctvUCXdk9qKbmsrwBu1yw8xUHkWxXxOzUb8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=qBzSORRQ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="qBzSORRQ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 27D04C116B1; Mon, 8 Jul 2024 19:18:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1720466321; bh=O6uIF+RFb01/GkReF4c6yk0p7sEtVWsPKR+FVmZnPi8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qBzSORRQiLiff8Gt65xgdcsif3RTxeKz1s8jxuUpFcPqCg4GXqfeY60Bp5Sr6NDt6 sKm8ByWTr7nsPxBThcQ0eygZzbQTbpCYfSbOQ3Grh1Q1/B0cSm0bFBgb4YLLpLxNZe 7QtTgO0VXe5kn0ThiO9iDjja/Mt4+pBB9FoYcOUN/408klWc7JTeIJuOIfQdJGijVr FUGJlud2dIurrddrGyqjk1TGBu5yxqMJTZzOYpZLVTZRsk0uSbFD9m+4yS9QPJm7JY HbBiA53Tyrm+FS03p4QLenM8NH6KgwCPl/StdCn69LCQuH4t5Q5gwf6Q9ttbnovGPZ o3Ttn6Sviffag== From: Kees Cook To: Vlastimil Babka Cc: Kees Cook , Nick Desaulniers , Miguel Ojeda , Marco Elver , Nathan Chancellor , Hao Luo , Przemek Kitszel , Jann Horn , Tony Luck , Christoph Lameter , Pekka Enberg , David Rientjes , Joonsoo Kim , Andrew Morton , Roman Gushchin , Hyeonggon Yoo <42.hyeyoo@gmail.com>, "Guilherme G. Piccoli" , Mark Rutland , Jakub Kicinski , Petr Pavlu , Alexander Lobakin , Tony Ambardar , linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-hardening@vger.kernel.org Subject: [RFC][PATCH 1/4] compiler_types: Add integral/pointer type helper macros Date: Mon, 8 Jul 2024 12:18:35 -0700 Message-Id: <20240708191840.335463-1-kees@kernel.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240708190924.work.846-kees@kernel.org> References: <20240708190924.work.846-kees@kernel.org> Precedence: bulk X-Mailing-List: linux-hardening@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=3006; i=kees@kernel.org; h=from:subject; bh=O6uIF+RFb01/GkReF4c6yk0p7sEtVWsPKR+FVmZnPi8=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBmjDuOeb7yBgPyjlDL1Ai4m2QU+GxeSGQAOayAT TMFTIpLqQ+JAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCZow7jgAKCRCJcvTf3G3A JnhED/9Lhq1R3gm7NGEM0GLkbRQxXYQbYhq2A0e8dvTbqL1MASPu1YC5TcrbqV5beglnN39elKy 8h3QpI2J9XUnMTLYTBEg5lDLW+1z+31YXjNB25ZFCc+Ctpj+wcNCSlYnp9ANujR+cahpM0JckAj oOLtGwZ/Mx6+6qGV5Jz/BZPjL9YWUc9zLyp2s257xHqZLXH/84hL1l+i87K67lDi/EQwOTxqNGX /6QC/nozNZtNkJYrkMQpcF8AYxDlf/xCAU/ErY3CYau8FFJT+uWUpT/y/QhZhq0J4v1TWqNeySe MpPzuTkvCGc6XOLP1cu2vGfY5H5zrDvLX8CnGAQM22FrntYKLQ/XKOgULWZeO1Vb5vY9rULYjGL 4yYUDqpg2jeiYVUUyUIoLmMGtnIG+v0PqJiG5wTvdo7rTRjvKaoRyPWEvEX5wnFHyM9NldiATIQ j+cWxEy7WRl9Z3H6FGQv+UR21Ul3jIk1k8a4CQzxIE+uVMJastG3rPktpN8IpvYVJIfCPkljETR ZMhOUoc2JtV/UzFcSMe8G6dUx5ilIAuZmPNPMMYRYNx6XL7XtJGN1VpXifzym299nbhBmaUEHtG xuJ4YXvx0N7aHcyiK46IPzlAJRGalHwAm8hIfmUoBUbdZ1Ak6G0uCvYDOYTiBhB5L79fiI2Z6/y DSP5VB8ZDjqsgZA== X-Developer-Key: i=kees@kernel.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 Many compiler builtins (e.g. _Generic, __builtin_choose_expr) perform integral vs pointer argument type evaluation on outputs before evaluating the input expression. This means that all outputs must be syntactically valid for all inputs, even if the output would be otherwise filtering the types. For example, this will fail to build: #define handle_int_or_ptr(x) \ _Generic((x), \ int: handle_int(x), \ int *: handle_ptr(x)) ... handle_int_or_ptr(7); error: passing argument 1 of 'handle_ptr' makes pointer from integer without a cast [-Wint-conversion] 108 | handle_int_or_ptr(x); | ^ | | | int To deal with this, provide helpers that force expressions into the desired type, where the mismatched cases are syntactically value, but will never actually happen: #define handle_int_or_ptr(x) \ _Generic((x), \ int: handle_int(__force_integral_expr(x)), \ int *: handle_ptr(__force_ptr_expr(x))) Now handle_int() only ever sees an int, and handle_ptr() only ever sees a pointer, regardless of the input type. Signed-off-by: Kees Cook --- Cc: Nick Desaulniers Cc: Miguel Ojeda Cc: Marco Elver Cc: Nathan Chancellor Cc: Hao Luo Cc: Przemek Kitszel --- include/linux/compiler_types.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h index f14c275950b5..7754f3b6a91f 100644 --- a/include/linux/compiler_types.h +++ b/include/linux/compiler_types.h @@ -450,6 +450,29 @@ struct ftrace_likely_data { /* Are two types/vars the same type (ignoring qualifiers)? */ #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) +/* Is the variable addressable? */ +#define __is_ptr_or_array(p) \ + (__builtin_classify_type(p) == __builtin_classify_type(NULL)) + +/* Return an array decayed to a pointer. */ +#define __decay(p) \ + (&*__builtin_choose_expr(__is_ptr_or_array(p), p, NULL)) + +/* Report if variable is a pointer type. */ +#define __is_ptr(p) __same_type(p, __decay(p)) + +/* Always produce an integral expression, with specific type/vale fallback. */ +#define ___force_integral_expr(x, type, val) \ + __builtin_choose_expr(!__is_ptr(x), (x), (type)val) +#define __force_integral_expr(x) \ + ___force_integral_expr(x, int, 0) + +/* Always produce a pointer expression, with specific type/value fallback. */ +#define ___force_ptr_expr(x, type, value) \ + __builtin_choose_expr(__is_ptr(x), (x), &(type){ value }) +#define __force_ptr_expr(x) \ + __builtin_choose_expr(__is_ptr(x), (x), NULL) + /* * __unqual_scalar_typeof(x) - Declare an unqualified scalar type, leaving * non-scalar types unchanged. From patchwork Mon Jul 8 19:18:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 13726995 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9C33A14BF9B; Mon, 8 Jul 2024 19:18:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720466321; cv=none; b=M9W+2e/NKKfVS3Vb9xnA5Lfz0tTo4kdOaPnXl+ugX7bz9/tBb2Xywv1HXmDXiAwjN14suLUoT4GVvFGattcT4da6kGws2GdbujIVFXLZZFbZ2TmYpwqi+4qJ6BT0ZNrkS6QoTaoeuo3DOMwX7LIlstFY+AJTg//Ak8S8jL5y28I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720466321; c=relaxed/simple; bh=uANC145QcD7DtmOmXpWRLhF0n/zqG8SYT4uWyFnv9BY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=evWT+Vm1mzFwPF/IiUat3NW5QMRKhogDiWTZxaaq/AbizbTiSCuxlOkkvfOO5LNs2Rkz+9y/vWlnAeZpo9XKwsadi0jz6/4/pZhVMEVLvZFTafXhF5cp156yM8li3if+50V62AomPMV8SbczmFCJunT6wxWUP33+6vDQffymt+E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ut65n4tt; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ut65n4tt" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 37087C3277B; Mon, 8 Jul 2024 19:18:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1720466321; bh=uANC145QcD7DtmOmXpWRLhF0n/zqG8SYT4uWyFnv9BY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ut65n4ttGog05ECx2J7Ldhpidc1j6a0Kg5kWfNkx5hEy2XKc4T74clrOBRyrT2GJ2 CSQZtSl9G+pY2KfI2kLVU3EYynPPP960w63i+RsXCwZVSlnAzmExTguHq/jE0knrMM X7Z9+ZkzVzNMI7DgFbeHkR5RLzQVMYQKvka2ssC0ulRh9HdvY14lvLjnROkAPejfqa i3tcAgr/1wTJrgxGXnR+m3TngfcUKH9xaqrqOIC9WSVBimd+A0+lEv7nalw1ELiJ9j PInNsXUs9wMhgis609Ppl5l4djbXdb9B2flDlTDLjDaaETeJ5l72a6Wi1oM6t7XTFM uJMg0bR3VpwEQ== From: Kees Cook To: Vlastimil Babka Cc: Kees Cook , Christoph Lameter , Pekka Enberg , David Rientjes , Joonsoo Kim , Andrew Morton , Roman Gushchin , Hyeonggon Yoo <42.hyeyoo@gmail.com>, linux-mm@kvack.org, Jann Horn , Tony Luck , Nick Desaulniers , Miguel Ojeda , Marco Elver , Nathan Chancellor , Hao Luo , Przemek Kitszel , "Guilherme G. Piccoli" , Mark Rutland , Jakub Kicinski , Petr Pavlu , Alexander Lobakin , Tony Ambardar , linux-kernel@vger.kernel.org, linux-hardening@vger.kernel.org Subject: [RFC][PATCH 2/4] slab: Detect negative size values and saturate Date: Mon, 8 Jul 2024 12:18:36 -0700 Message-Id: <20240708191840.335463-2-kees@kernel.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240708190924.work.846-kees@kernel.org> References: <20240708190924.work.846-kees@kernel.org> Precedence: bulk X-Mailing-List: linux-hardening@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=2917; i=kees@kernel.org; h=from:subject; bh=uANC145QcD7DtmOmXpWRLhF0n/zqG8SYT4uWyFnv9BY=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBmjDuONss2HaGaoXnvMw6YATx2x2Smf4BEOjQW7 uHB+UwHbbiJAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCZow7jgAKCRCJcvTf3G3A JpNWEACsSqZxKHvZ7EzYarhtHgRtezUJVoSb5d0p/QDZ1pIlQRudtH/v5C446CA6MwZGgOnK+Fe gvW+lh4/Nse3mJwCt6zIp5Hmszca534ybfPGJ1f2lmqP8WC187ToIlZ18g1VuZi1YMdWUbgVHmz 1v+MGEZd7jTPa3dxhAhy0jdXamCYtyf2x3vXuPOUCtpvg5KBn1xYEQgOyOC+uD6xJumWNebym1m 23l2UgNPi43g5bg1ji+gjrMcSpiCU9vKIRqD14K/m9xaYJinwUbaJDri8UWItePlAe3/TimtaZa 9sGERC9xqNHHzmBo009EyLRyvkp635+FCCSpy1kAJVE72UTuh6v0wY6373ZpVGkeAfrAbnyrOji teF56Y//AEWe+GeeIaz+3p8pW73CyBuYf+PS0R47/zvCdzB7K5GhsvRGpEZin1Iv0BS2F9Z3dz2 XloogfHgtO+Z6ayNcm0tRMZ4napyGwOq+VUlCx15GM0Kont3N+v5gx8BJaTOIV8cvey81K3F0OE vuJtxGTSwjOjw0269OcMQHdZOQAYYZUIOjumwVkN6OnG3N8PPiiEGx/dB4ROz71ZMz+N+lqXHIb zpT7z7g4b8mnD3XnkBb9Dp+HSiqVQ747eJjuHjVjIzJ1RVf0+bMXUJwXSrHysPt7GWU7z1zaOb4 k+QYgVvnbVehHqA== X-Developer-Key: i=kees@kernel.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 The allocator will already reject giant sizes seen from negative size arguments, so this commit mainly services as an example for initial type-based filtering. The size argument is checked for negative values in signed arguments, saturating any if found instead of passing them on. For example, now the size is checked: Before: /* %rdi unchecked */ 1eb: be c0 0c 00 00 mov $0xcc0,%esi 1f0: e8 00 00 00 00 call 1f5 1f1: R_X86_64_PLT32 __kmalloc_noprof-0x4 After: 6d0: 48 63 c7 movslq %edi,%rax 6d3: 85 ff test %edi,%edi 6d5: be c0 0c 00 00 mov $0xcc0,%esi 6da: 48 c7 c2 ff ff ff ff mov $0xffffffffffffffff,%rdx 6e1: 48 0f 49 d0 cmovns %rax,%rdx 6e5: 48 89 d7 mov %rdx,%rdi 6e8: e8 00 00 00 00 call 6ed 6e9: R_X86_64_PLT32 __kmalloc_noprof-0x4 Signed-off-by: Kees Cook --- Cc: Christoph Lameter Cc: Pekka Enberg Cc: David Rientjes Cc: Joonsoo Kim Cc: Andrew Morton Cc: Vlastimil Babka Cc: Roman Gushchin Cc: Hyeonggon Yoo <42.hyeyoo@gmail.com> Cc: linux-mm@kvack.org --- include/linux/slab.h | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/include/linux/slab.h b/include/linux/slab.h index d99afce36098..7353756cbec6 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -684,7 +684,24 @@ static __always_inline __alloc_size(1) void *kmalloc_noprof(size_t size, gfp_t f } return __kmalloc_noprof(size, flags); } -#define kmalloc(...) alloc_hooks(kmalloc_noprof(__VA_ARGS__)) +#define kmalloc_sized(...) alloc_hooks(kmalloc_noprof(__VA_ARGS__)) + +#define __size_force_positive(x) \ + ({ \ + typeof(__force_integral_expr(x)) __forced_val = \ + __force_integral_expr(x); \ + __forced_val < 0 ? SIZE_MAX : __forced_val; \ + }) + +#define kmalloc(p, gfp) _Generic((p), \ + unsigned char: kmalloc_sized(__force_integral_expr(p), gfp), \ + unsigned short: kmalloc_sized(__force_integral_expr(p), gfp), \ + unsigned int: kmalloc_sized(__force_integral_expr(p), gfp), \ + unsigned long: kmalloc_sized(__force_integral_expr(p), gfp), \ + signed char: kmalloc_sized(__size_force_positive(p), gfp), \ + signed short: kmalloc_sized(__size_force_positive(p), gfp), \ + signed int: kmalloc_sized(__size_force_positive(p), gfp), \ + signed long: kmalloc_sized(__size_force_positive(p), gfp)) #define kmem_buckets_alloc(_b, _size, _flags) \ alloc_hooks(__kmalloc_node_noprof(PASS_BUCKET_PARAMS(_size, _b), _flags, NUMA_NO_NODE)) From patchwork Mon Jul 8 19:18:37 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 13726997 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B076D14C5BD; Mon, 8 Jul 2024 19:18:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720466321; cv=none; b=i7GNRSGHfnFYHCCVmtOu7qBKnHEQew+18MAu7GRHAcZRTplCnMu4e0qxx1CSJbTILXLO5ypnHN+wdypzrQHHknQZFUj3JTTqdkPBqAb4i7XKwpn1SFxFz37b+woaQbNRDfBhU33de53wWW4m+Z8W0pqbWdveZypgiYs98DoEb90= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720466321; c=relaxed/simple; bh=uZVkbgeH0EuqCqY0VzPg0KmfW7oX+qB7fM4s+/wiMwc=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=TMHzdM9F+jAttAL8ENeNp7WiLy2FB0YRYaCbI8BgBuLRxfdoKa5BSeFmQFRZI4udfdZ2i/WHrh95bCECjDvKDnt6YCFIk6inzw4gaGc+L9HQ3jSTJPsLRq50iwJPeqqgx0R6+CrbIZBHinpkwvzURauSOzdCrTyYZkaGf+DbFd4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NwLkmYW8; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="NwLkmYW8" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 41B96C4AF0D; Mon, 8 Jul 2024 19:18:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1720466321; bh=uZVkbgeH0EuqCqY0VzPg0KmfW7oX+qB7fM4s+/wiMwc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=NwLkmYW8fDSlPfZ6zg7OC+ydN9VHjamB6SV206zEE06CByDYBXL/E3kNymf8f5Z/E WXWWVI1V3oP15b7GAXdSADCafWiAMveNkB2HZ8+7NEQYI7YdmW42qR7tgMpWlporuN J6+evyd+mmMafD6umN9x6L0ddtcnOi2Z/esDflp2s17QEeO3zfTDHjjxNwRPSRfd2D N/Wx4RbcY7RYlE6239c5cLmYVj9D7kFyUZZLHE19qqTGaklfFdSuR11ywV6Sd70kIJ u0Osw7RcbBkJDMa5T0vBYml4oKCg3CzE+2hy/lCWNO73/LSIfqxrEtYHJUDtN1rpMW F4uvi02aZMKmQ== From: Kees Cook To: Vlastimil Babka Cc: Kees Cook , Christoph Lameter , Pekka Enberg , David Rientjes , Joonsoo Kim , Andrew Morton , Roman Gushchin , Hyeonggon Yoo <42.hyeyoo@gmail.com>, linux-mm@kvack.org, Jann Horn , Tony Luck , Nick Desaulniers , Miguel Ojeda , Marco Elver , Nathan Chancellor , Hao Luo , Przemek Kitszel , "Guilherme G. Piccoli" , Mark Rutland , Jakub Kicinski , Petr Pavlu , Alexander Lobakin , Tony Ambardar , linux-kernel@vger.kernel.org, linux-hardening@vger.kernel.org Subject: [RFC][PATCH 3/4] slab: Allow for type introspection during allocation Date: Mon, 8 Jul 2024 12:18:37 -0700 Message-Id: <20240708191840.335463-3-kees@kernel.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240708190924.work.846-kees@kernel.org> References: <20240708190924.work.846-kees@kernel.org> Precedence: bulk X-Mailing-List: linux-hardening@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=4343; i=kees@kernel.org; h=from:subject; bh=uZVkbgeH0EuqCqY0VzPg0KmfW7oX+qB7fM4s+/wiMwc=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBmjDuOqk8BerNUzSb5otXo2P3d37h+IoXOh1nFQ Es8spHhmLSJAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCZow7jgAKCRCJcvTf3G3A Js1KD/wJ2MAI4caQ2BMn/GB4nzrXJRJ23IazCtug/USRi+kQWodnvPYxG+OU+xrhwSce62gNZ9S znIek1BQjBppXGf28xJhr6X4LXKca7NgslCOEdUwoqIub1c++sTts9qQT0tH57ia5wamfKn6pyb CQE10/gSkeqCJt0UJuJ5/nCE10q12uZrqT3yJWH3xw2XrHBYAvGUdKKCODaz1ntjJNY30179RPL 9TfhRvm8kUACvshW0bDFQnvld+uTNyM6tGAPJqebTDc46oj5rt1MBJG/VeIJe68j6rEDiIzwsPD Fxj3qdXHzCh07JW5zueYPrNQAaPon3vbQ4oeqURGA+Ky+WTmXYUXObiGcGDk+nzW5Osma2tNXQB ezldsO8GZgleLm4WbuOE0XPe39ya0qFBrlRUDHU6w9yVcakglo92jKjgVftQkOlgHimrUSwRKrz 0CosucBmH1tXhl1rCKvcapwPwn6zI9wIKZnxexvS+E0QYWtmRm5Ck2dp8I4ID/xVzy/xaacUEFg odokjaXlY93cRzej7rDMtDo9xGQRxb+K1OpBiyNjuiieHati+E+xNlxzSQZXu+6tfd82Dk7BcDk YVMVnnig8SN4IU2Yzai3pznlTfzu7/X0wPowK80xVs4df6Al6nIE33Dk0eP1JiMtnDb/jzShLKL ylIoTkHjI1WSlnA== X-Developer-Key: i=kees@kernel.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 There is currently no way for the slab to know what type is being allocated, and this hampers the development of any logic that would need this information including basic type checking, alignment need analysis, etc. Allow the size argument to optionally be a variable, from which the type (and there by the size, alignment, or any other features) can be determined at compile-time. This allows for the incremental replacement of the classic code pattern: obj = kmalloc(sizeof(*obj), gfp); into: obj = kmalloc(obj, gfp); As an additional build-time safety feature, the return value of kmalloc() also becomes typed so that the assignment and first argument cannot drift, doing away with the other, more fragile, classic code pattern: obj = kmalloc(sizeof(struct the_object), gfp); into: obj = kmalloc(obj, gfp); And any accidental variable drift will not be masked by the traditional default "void *" return value: obj = kmalloc(something_else, gfp); error: assignment to 'struct the_object *' from incompatible pointer type 'struct foo *' [-Wincompatible-pointer-types] 71 | obj = kmalloc(something_else, gfp); | ^ This also opens the door for a proposed heap hardening feature that would randomize the starting offset of the allocated object within its power-of-2 bucket. Without being able to introspect the type for alignment needs, this can't be done safely (or cannot be done without significant memory usage overhead). For example, a 132 byte structure with an 8 byte alignment could be randomized into 15 locations within the 256 byte bucket: (256 - 132) / 8. Signed-off-by: Kees Cook --- Cc: Christoph Lameter Cc: Pekka Enberg Cc: David Rientjes Cc: Joonsoo Kim Cc: Andrew Morton Cc: Vlastimil Babka Cc: Roman Gushchin Cc: Hyeonggon Yoo <42.hyeyoo@gmail.com> Cc: linux-mm@kvack.org --- include/linux/slab.h | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/include/linux/slab.h b/include/linux/slab.h index 7353756cbec6..4a7350bbcfe7 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -685,6 +685,7 @@ static __always_inline __alloc_size(1) void *kmalloc_noprof(size_t size, gfp_t f return __kmalloc_noprof(size, flags); } #define kmalloc_sized(...) alloc_hooks(kmalloc_noprof(__VA_ARGS__)) +#define kmalloc_aligned(size, align, gfp) alloc_hooks(kmalloc_noprof(size, gfp)) #define __size_force_positive(x) \ ({ \ @@ -701,7 +702,10 @@ static __always_inline __alloc_size(1) void *kmalloc_noprof(size_t size, gfp_t f signed char: kmalloc_sized(__size_force_positive(p), gfp), \ signed short: kmalloc_sized(__size_force_positive(p), gfp), \ signed int: kmalloc_sized(__size_force_positive(p), gfp), \ - signed long: kmalloc_sized(__size_force_positive(p), gfp)) + signed long: kmalloc_sized(__size_force_positive(p), gfp), \ + default: (typeof(__force_ptr_expr(p)))kmalloc_aligned( \ + sizeof(*__force_ptr_expr(p)), \ + __alignof__(*__force_ptr_expr(p)), gfp)) #define kmem_buckets_alloc(_b, _size, _flags) \ alloc_hooks(__kmalloc_node_noprof(PASS_BUCKET_PARAMS(_size, _b), _flags, NUMA_NO_NODE)) @@ -816,14 +820,11 @@ static inline __alloc_size(1, 2) void *kmalloc_array_node_noprof(size_t n, size_ /** * kzalloc - allocate memory. The memory is set to zero. - * @size: how many bytes of memory are required. + * @p: either a pointer to an object to be allocated or bytes of memory are required. * @flags: the type of memory to allocate (see kmalloc). */ -static inline __alloc_size(1) void *kzalloc_noprof(size_t size, gfp_t flags) -{ - return kmalloc_noprof(size, flags | __GFP_ZERO); -} -#define kzalloc(...) alloc_hooks(kzalloc_noprof(__VA_ARGS__)) +#define kzalloc(_p, _flags) kmalloc(_p, (_flags)|__GFP_ZERO) +#define kzalloc_noprof(_size, _flags) kmalloc_noprof(_size, (_flags)|__GFP_ZERO) #define kzalloc_node(_size, _flags, _node) kmalloc_node(_size, (_flags)|__GFP_ZERO, _node) void *__kvmalloc_node_noprof(DECL_BUCKET_PARAMS(size, b), gfp_t flags, int node) __alloc_size(1); From patchwork Mon Jul 8 19:18:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 13726996 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AE07C14C5B5; Mon, 8 Jul 2024 19:18:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720466321; cv=none; b=bEEoXSH7vyATM2dSYcLk3EsYw/LRGVGE+j9HJc6IvUC/HK6+XH17BQtJIR521pNmfprL2/YNER/+u+AnVZMIRcSqLpiXNne0Yw2kbs9ISkihO1d6jFprvyRc1xAC0Ea1rq0No1yMeDq7Zr2SNhThWHYNMz5mbTD6Xq+FwVTYnLk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720466321; c=relaxed/simple; bh=fvRlIwowaF9/LBzfEGVnkRN2BeFqeZ8hAGZLXhTB0Rk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Gq1iJv5bh3fEvEcAa66VChUf1oNnwtY84MG5AbloHKBWdjq0Rb8Xu7COwWz7cHeXRfR8/a/pDnPMhr0GVrn/x7uUjxGnZ8NdyNfaIwQsHIvC7AHE5nBAMw5Ys1xActShYn8vpvNGR1aY8LYjEBBZJsN1p/NkrlM2wpSoIkRIkJg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=gfAubh4v; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="gfAubh4v" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4DAEDC4AF17; Mon, 8 Jul 2024 19:18:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1720466321; bh=fvRlIwowaF9/LBzfEGVnkRN2BeFqeZ8hAGZLXhTB0Rk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gfAubh4vdFbZlhDJOkduJGAqtq4TRKB8ZZxx7chKka/17RGOfga2LdRJPnigStdgh aqSD1mvdHlQqjsXnKH0lMRKL1O1re3Jhnol8lNR9YLyzZVXbE9NQ5kLZ4X37DQh8F/ KosUIK5QKo63xy9213Pq1FOZ+SC+Qfs3Sy/iuSNU6Z8PopCvsGEpAtAH1WR0a2BLpF lEbEReGdJ2aai8mgey5MSf1XlyKHHsduE7kPsOj72eUSM3y7eHfzeyH9IYY0KFrlIJ rIdfaUlYSw+WMXmtO5GNJ6LQ+NCAygm3NHCFbKChlkh+papvqh+3tTjcKNHL4NfAkr 1o0EbCNw6xKYQ== From: Kees Cook To: Vlastimil Babka Cc: Kees Cook , Tony Luck , "Guilherme G. Piccoli" , linux-hardening@vger.kernel.org, Jann Horn , Nick Desaulniers , Miguel Ojeda , Marco Elver , Nathan Chancellor , Hao Luo , Przemek Kitszel , Christoph Lameter , Pekka Enberg , David Rientjes , Joonsoo Kim , Andrew Morton , Roman Gushchin , Hyeonggon Yoo <42.hyeyoo@gmail.com>, Mark Rutland , Jakub Kicinski , Petr Pavlu , Alexander Lobakin , Tony Ambardar , linux-kernel@vger.kernel.org, linux-mm@kvack.org Subject: [RFC][PATCH 4/4] pstore: Replace classic kmalloc code pattern with typed argument Date: Mon, 8 Jul 2024 12:18:38 -0700 Message-Id: <20240708191840.335463-4-kees@kernel.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240708190924.work.846-kees@kernel.org> References: <20240708190924.work.846-kees@kernel.org> Precedence: bulk X-Mailing-List: linux-hardening@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=3200; i=kees@kernel.org; h=from:subject; bh=fvRlIwowaF9/LBzfEGVnkRN2BeFqeZ8hAGZLXhTB0Rk=; b=owEBbQKS/ZANAwAKAYly9N/cbcAmAcsmYgBmjDuOIMJSOfezmI7F7aWAtc3Jd3uJ1pxI/qwE2 X/jjfpapACJAjMEAAEKAB0WIQSlw/aPIp3WD3I+bhOJcvTf3G3AJgUCZow7jgAKCRCJcvTf3G3A Ju/pD/9jE2sUjkU0LDQMn2KwGX2yZsbWJ5NO7+g3aGS+vs2V//QT/bnGfFzfd1De6giGp0M2kHm P0ODwqfZv69aT5o0x9p7Hb393ZH1Bbq/3ATW79p6VHI85Blp6qLckXX9HkdcdAMCBsQo2Xuj7Wd IX634YZ1O8v+G8u7LZvqYndpeVOeCa9oPw9S5XCCHQ0xv+ViQ8cip0Bk/ctV/zeEyHX0eWjGtJF 8dcGd2uslfUqdLlyHhJFrHJxQx1MsSOKWygJ5m0lnD25WD5V7jmoRJBW6O05+R1rrRnXDYbSKPm rdnkT0OnLjJQQq9sLSBIlqYDGE4Df9H9H2L+atoDC/NXyB0T7ovyJUomc1xqB8SwuV0MpGF+YYv Z5U8TN5M4I0yojNTfsQXnLl3xNbIKvL2/3YWgUIBgNKiAMF+PW7OhsAOf7DffaT/Rrt2lEPCkRN R3mwvksK9PqYinrloTlRfVGth1VEUmAwk1HJP7AsLvierItqfSxtTMjFQOipLcrZOJM2fZ8KXQH oQS0dWvgNmyT70TKWTtW4mevrcJg7FBIinAI4QUch3X/b8ZrnBTlTVaNwHLjZusj/a/2VU+TjY+ dy6GwLfOgm71EQqo+Pt/X9+FaWC2Q6mNvKmpnxFYR6DvBelFg+qFu3/7iz7wLW4yyXq58WazK1N 26/45pC7RBdRDmQ== X-Developer-Key: i=kees@kernel.org; a=openpgp; fpr=A5C3F68F229DD60F723E6E138972F4DFDC6DC026 Using a short Coccinelle script, it is possible to replace the classic kmalloc code patterns with the typed information: @alloc@ type TYPE; TYPE *P; expression GFP; identifier ALLOC =~ "k[mz]alloc"; @@ P = ALLOC( - \(sizeof(*P)\|sizeof(TYPE)\), GFP) + P, GFP) Show this just for kmalloc/kzalloc usage in fs/pstore as an example. Doing this for all allocator calls in the kernel touches much more: 11941 files changed, 22459 insertions(+), 22345 deletions(-) And obviously requires some more wrappers for kv*alloc, devm_*alloc, etc. Signed-off-by: Kees Cook --- Cc: Tony Luck Cc: "Guilherme G. Piccoli" Cc: linux-hardening@vger.kernel.org --- fs/pstore/blk.c | 2 +- fs/pstore/platform.c | 2 +- fs/pstore/ram.c | 3 +-- fs/pstore/ram_core.c | 2 +- fs/pstore/zone.c | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/fs/pstore/blk.c b/fs/pstore/blk.c index de8cf5d75f34..7bb9cacb380f 100644 --- a/fs/pstore/blk.c +++ b/fs/pstore/blk.c @@ -297,7 +297,7 @@ static int __init __best_effort_init(void) return -EINVAL; } - best_effort_dev = kzalloc(sizeof(*best_effort_dev), GFP_KERNEL); + best_effort_dev = kzalloc(best_effort_dev, GFP_KERNEL); if (!best_effort_dev) return -ENOMEM; diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 03425928d2fb..4e527c3ea530 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -682,7 +682,7 @@ void pstore_get_backend_records(struct pstore_info *psi, struct pstore_record *record; int rc; - record = kzalloc(sizeof(*record), GFP_KERNEL); + record = kzalloc(record, GFP_KERNEL); if (!record) { pr_err("out of memory creating record\n"); break; diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index b1a455f42e93..a0665a98b135 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -228,8 +228,7 @@ static ssize_t ramoops_pstore_read(struct pstore_record *record) */ struct persistent_ram_zone *tmp_prz, *prz_next; - tmp_prz = kzalloc(sizeof(struct persistent_ram_zone), - GFP_KERNEL); + tmp_prz = kzalloc(tmp_prz, GFP_KERNEL); if (!tmp_prz) return -ENOMEM; prz = tmp_prz; diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c index f1848cdd6d34..01ddf1be6c3a 100644 --- a/fs/pstore/ram_core.c +++ b/fs/pstore/ram_core.c @@ -588,7 +588,7 @@ struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size, struct persistent_ram_zone *prz; int ret = -ENOMEM; - prz = kzalloc(sizeof(struct persistent_ram_zone), GFP_KERNEL); + prz = kzalloc(prz, GFP_KERNEL); if (!prz) { pr_err("failed to allocate persistent ram zone\n"); goto err; diff --git a/fs/pstore/zone.c b/fs/pstore/zone.c index 694db616663f..8df890bb4db9 100644 --- a/fs/pstore/zone.c +++ b/fs/pstore/zone.c @@ -1165,7 +1165,7 @@ static struct pstore_zone *psz_init_zone(enum pstore_type_id type, return ERR_PTR(-ENOMEM); } - zone = kzalloc(sizeof(struct pstore_zone), GFP_KERNEL); + zone = kzalloc(zone, GFP_KERNEL); if (!zone) return ERR_PTR(-ENOMEM);