From mboxrd@z Thu Jan 1 00:00:00 1970 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 1E00A2E7179 for ; Mon, 16 Mar 2026 18:33:37 +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=1773686018; cv=none; b=sEwnEjihytrOyN+T0YdL/9kvf2ySMbr8ufZTJ13IzgjgYPnUTRigpiW0ZMsIstaM3VJGgWSZ8shx5O8XuZ5syMohlq8wyu7Q/JDOjvDCrBFec5YLf9Nwxt8wYXrXXaXi8onahQt1uL4qrOIrAT+q/Dv0lykptlzsBaxJo/9qHa0= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773686018; c=relaxed/simple; bh=tgR8R8EQtHwb+2VRWDaMQ8AHB1Uxxzt3SOGOleIyZEs=; h=Date:From:To:Cc:Subject:Message-ID:MIME-Version:Content-Type: Content-Disposition; b=Iw3Gkoq7r8xgthweJKzb9bN9a5B3ADSAec+yTfydsp445lMwrqqg8elXUVTWUDQFVWatIkfoqKeUP+zDoWPlzL5Ki5GA2JNUTNANfjxRO+fNbwiDhUFsdWK5wqO0b6/x+NfeKqcc0xWtUEYJtFDW8tFsjoXbpEvp7Ugmqkwdz2s= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=qTUc7dv6; 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="qTUc7dv6" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 966BFC2BC87; Mon, 16 Mar 2026 18:33:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773686017; bh=tgR8R8EQtHwb+2VRWDaMQ8AHB1Uxxzt3SOGOleIyZEs=; h=Date:From:To:Cc:Subject:From; b=qTUc7dv6btyrznQUSq8+y96hkCuQgf1iLRUGAQH+laiRS/nLj2JIJXW2drydPzKB7 sw+VeudfqQAhrZF65dMXd1CYv8hTg5KbmaJ8yUWi+psHlIipaUNWQoSlyQnwO52iJa 2SMdH5iat8grTR4zdzXCZxaSFlkasCVlDkYshL41IDTDJw8aprsu5xvI+R//5+/MJ/ Nj+1TqDgyJn/XaiZPQP6T1f8SDJ98OSi/ZAQJn6eXWpv3JUMLjwUbqdYG+cnwkpBYU A8ssRZcvAyYYuGdNx6/hfyUbmnFBdF59Eg4tbo7eY2vILvWqx7sV1r7ndKArQygYug NUePYWgGRS34g== Date: Mon, 16 Mar 2026 19:33:34 +0100 From: Alejandro Colomar To: LKML , Kees Cook Cc: corbet@lwn.net, serge@hallyn.com, Martin Uecker Subject: kalloc_objs() may not be as safe as it seems Message-ID: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="qlnf3peuwsss76c6" Content-Disposition: inline --qlnf3peuwsss76c6 Content-Type: text/plain; protected-headers=v1; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable From: Alejandro Colomar To: LKML , Kees Cook Cc: corbet@lwn.net, serge@hallyn.com, Martin Uecker Subject: kalloc_objs() may not be as safe as it seems Message-ID: MIME-Version: 1.0 Hi Kees, I just learnt about kalloc_objs() et al. from . ptr =3D kmalloc_obj(*ptr); ptr =3D kmalloc_objs(*ptr, n); This resembles a lot the macro we have in shadow-utils, malloc_T(), which would be used as (to resemble the above): ptr =3D malloc_T(1, typeof(*ptr)); // But we'd really pass the type ptr =3D malloc_T(n, typeof(*ptr)); // But we'd really pass the type But I've noticed some design mistakes that make it not as safe as it seems. Default arguments ~~~~~~~~~~~~~~~~~ I tend to think it's simpler to have a single API that works for both 1 element and multiple elements. The special-casing of 1 element seems unnecessary, and having a literal 1 works just fine. I think the combination of having the macros be variadic (for gfp) with having two very similar APIs that differ in number of arguments, and all those arguments being integer types, is prone to errors. Consider the case where one would accidentally write ptr =3D kmalloc_obj(*ptr, n); // Bogus instead of ptr =3D kmalloc_objs(*ptr, n); The compiler wouldn't realize at all. That's a strong argument in favour of having default arguments be required to be explicit, with an empty argument: ptr =3D kmalloc_obj(*ptr,); ptr =3D kmalloc_objs(*ptr, n,); I know you (and Linus too, FWIW) have previously claimed that it looks weird to the eye. But I'm pretty sure you could get used to it. That's certainly going to be safer. With mandatory empty arguments, the compiler would easily distinguish mistakes like the one above. Type safety ~~~~~~~~~~~ Apart from the issues with the above, the ability to pass a variable instead of a type name is also a bad choice. In shadow-utils, we require a type name, and a variable is rejected. We implement that with the typeas() macro: #define typeas(T) typeof((T){0}) This macro works exactly like typeof(), but it requires that the input is also a type. Passing a variable is a syntax error. We implement malloc_T() with it: // malloc_T - malloc type-safe #define malloc_T_(n, T) \ ({ \ (typeas(T) *){reallocarray(n, sizeof(T))}; \ }) which is used as (taking some arbitrary examples from shadow-utils): lp =3D xmalloc_T(1, struct link_name); targs =3D xmalloc_T(n_args + 3, char *); Some reasons for passing a type name instead of a variable are: - It allows grepping for all allocations of a given type. - It adds readability. It's similar to declaring variables with some explicit type, vs. using 'auto' (__auto_type) everywhere. But there's also a safety aspect. Consider we want to allocate an array of 42 ints. And consider the programmer accidentally swaps arguments. int *p =3D malloc_T(int, 42); // syntax error int *p =3D malloc_T(42, int); vs int *p =3D kmalloc_objs(*p, 42); int *p =3D kmalloc_objs(42, *p); // Bogus The latter is dereferencing an uninitialized pointer. If for some reason the pointer had a value before this call, you'd be allocating as many elements as *p says, which would be bogus, and since typeof(42) is the same as typeof(*p), the return type would be valid, so this would still compile. Have a lovely night! Alex --=20 --qlnf3peuwsss76c6 Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEES7Jt9u9GbmlWADAi64mZXMKQwqkFAmm4TPcACgkQ64mZXMKQ wqm7uQ//fbeu6LKxYy59GBOqqzCIq1CgJ+NY30qKSZThf+XzC+mCu1BJ0AXF7511 501nKNKpPa2d/NSuUsRsiBv2BgV5TpGYr6j9YHfmgFpUSkML+ZP7+oaFeTbBfmBX 82dciq9AmzOyZWVpzFryQdphXwNJSTBifqyx+1aMpqnLhV9aZ/zcOHuTxu5zwLyg lxRI3RV3KAmhcHXJYvbxso3HdKZc8ua4awQ1/LmmGnU5Npgh5szDD3jW5Z1S6P5l ro+RL3QJc+lGit38hg7FGN5FnsmPDrxBO1wFd++HZqrL+ldEYeD0StfVGHQRzq/a CTXcbNOABdBN1CzXZ7cs+Ejs2mBirs6ZlTXy7p6w2U5F6AdUNWI2f5FoiBI6Qa9l KjnXNf2RF0qq2S1fSh4J8jlElQ3kQTchMR4QuTTiwyDp2mxXhd7yZ9qqkhGX43Ey WQgPIY4qPda3oPaeb3i06OklJHhjGfFvxobLRPy7xGWnCaY36Ynh1JUuo7RQ47Kq URY7tWhrg253o939yUYo2xEYowbKsFtB3hukeGEhG/6vJfK//BD67yoifqopjx48 y7r0QNONtI3S3TJeOhbDypvATS7HyntdWESbFhMNOLTbDvs3Eu+ox8zhykjghn+k v+s8RCcE7/pzFEgwwpdieLCNOn7kQLYGxmWkPQ0wnNrD7hFPyFU= =iyeI -----END PGP SIGNATURE----- --qlnf3peuwsss76c6--