From nobody Tue Oct 7 08:53:20 2025 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 74F8D288CC; Fri, 11 Jul 2025 01:56:44 +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=1752199004; cv=none; b=eTQr9VVBznFmnlqQ2Gmz8NAfLmbZmMQvH2Y9jFOPZa8nu991rVJpz2dJAdMgRN8QlmgGnvuSWis/zUGVDm7Khg/Jt2D4QR5V3plEZK7v96c47lCRS+mNbddx0DnMbq04+zpg0xi7RJiauDQlWieURusYVNOiLpsvwGvSNnyYqiE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752199004; c=relaxed/simple; bh=id+QRz7CKCBHQtj9/ZPFhaypU90NRPk861KL3FVr7UQ=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=sL6jXbbP2xxNqSdSE1kXZ3mmzf7nyWUEG9y4IssR4Nb0p1LPmkzGVKNi2hqmM/XJKJS9Aod+www6HJZdAgqbaNfB6/EwOkvwTZMe+gWnKjDgZGFtwn4v3MuokCBohRmgztQJuaUUsy6K0R0R7sCRhca4f2H0gzst/nrM4NgkQKI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=XCgw+aiM; 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="XCgw+aiM" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B075FC4CEE3; Fri, 11 Jul 2025 01:56:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1752199004; bh=id+QRz7CKCBHQtj9/ZPFhaypU90NRPk861KL3FVr7UQ=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=XCgw+aiMYtjB84bt6EC3wc5P2d1CBZM27lAcVpwvVnIdPKXIUDmxpwkpOpPvJgMjU z8YyEkxjP+KgWynJZrfmHnkLGkM3HRGozNvNmIGiRL2w9eajrrc/xU9XSXQTOuMxKl uk7EbWg2bpAdOVWAwso8DalSOrjHPpOs5sZy5he2AcWFVrtKYIlp008it8h85tzeiK g/uirUmElownoNiKUXepy0UugdCJ0vXBTA72x5M003exeqp1LtjT7qdO37l+S2n1nE RjMbTdxnxVVOG18yOEDnnb4bdpNV1wQFfxMJVVB4cKVQ/AHoDWKelVdfziOB21k1CE 15LVNNWguugVg== Date: Fri, 11 Jul 2025 03:56:38 +0200 From: Alejandro Colomar To: linux-mm@kvack.org, linux-hardening@vger.kernel.org Cc: Alejandro Colomar , Kees Cook , Christopher Bazley , shadow <~hallyn/shadow@lists.sr.ht>, linux-kernel@vger.kernel.org, Andrew Morton , kasan-dev@googlegroups.com, Dmitry Vyukov , Alexander Potapenko , Marco Elver , Christoph Lameter , David Rientjes , Vlastimil Babka , Roman Gushchin , Harry Yoo , Andrew Clayton , Rasmus Villemoes , Michal Hocko , Linus Torvalds , Al Viro , Martin Uecker , Sam James , Andrew Pinski Subject: [RFC v6 1/8] vsprintf: Add [v]sprintf_trunc() Message-ID: X-Mailer: git-send-email 2.50.0 References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" sprintf_trunc() is a function similar to strscpy(). It truncates the string, and returns an error code on truncation or error. On success, it returns the length of the new string. Cc: Kees Cook Cc: Christopher Bazley Cc: Rasmus Villemoes Cc: Marco Elver Cc: Michal Hocko Cc: Linus Torvalds Cc: Al Viro Signed-off-by: Alejandro Colomar --- include/linux/sprintf.h | 2 ++ lib/vsprintf.c | 53 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/include/linux/sprintf.h b/include/linux/sprintf.h index 51cab2def9ec..5ea6ec9c2e59 100644 --- a/include/linux/sprintf.h +++ b/include/linux/sprintf.h @@ -13,6 +13,8 @@ __printf(3, 4) int snprintf(char *buf, size_t size, const= char *fmt, ...); __printf(3, 0) int vsnprintf(char *buf, size_t size, const char *fmt, va_l= ist args); __printf(3, 4) int scnprintf(char *buf, size_t size, const char *fmt, ...); __printf(3, 0) int vscnprintf(char *buf, size_t size, const char *fmt, va_= list args); +__printf(3, 4) int sprintf_trunc(char *buf, size_t size, const char *fmt, = ...); +__printf(3, 0) int vsprintf_trunc(char *buf, size_t size, const char *fmt,= va_list args); __printf(2, 3) __malloc char *kasprintf(gfp_t gfp, const char *fmt, ...); __printf(2, 0) __malloc char *kvasprintf(gfp_t gfp, const char *fmt, va_li= st args); __printf(2, 0) const char *kvasprintf_const(gfp_t gfp, const char *fmt, va= _list args); diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 01699852f30c..15e780942c56 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -2923,6 +2923,34 @@ int vscnprintf(char *buf, size_t size, const char *f= mt, va_list args) } EXPORT_SYMBOL(vscnprintf); =20 +/** + * vsprintf_trunc - va_list string truncate print formatted + * @buf: The buffer to place the result into + * @size: The size of the buffer, including the trailing null space + * @fmt: The format string to use + * @args: Arguments for the format string + * + * The return value is the length of the string. + * If the string is truncated, the function returns -E2BIG. + * If @size is invalid, the function returns -EOVERFLOW. + * + * See the vsnprintf() documentation for format string extensions over C99. + */ +int vsprintf_trunc(char *buf, size_t size, const char *fmt, va_list args) +{ + int len; + + if (WARN_ON_ONCE(size =3D=3D 0 || size > INT_MAX)) + return -EOVERFLOW; + + len =3D vsnprintf(buf, size, fmt, args); + if (unlikely(len >=3D size)) + return -E2BIG; + + return len; +} +EXPORT_SYMBOL(vsprintf_trunc); + /** * snprintf - Format a string and place it in a buffer * @buf: The buffer to place the result into @@ -2974,6 +3002,31 @@ int scnprintf(char *buf, size_t size, const char *fm= t, ...) } EXPORT_SYMBOL(scnprintf); =20 +/** + * sprintf_trunc - string truncate print formatted + * @buf: The buffer to place the result into + * @size: The size of the buffer, including the trailing null space + * @fmt: The format string to use + * @...: Arguments for the format string + * + * The return value is the length of the string. + * If the string is truncated, the function returns -E2BIG. + * If @size is invalid, the function returns -EOVERFLOW. + */ + +int sprintf_trunc(char *buf, size_t size, const char *fmt, ...) +{ + int len; + va_list args; + + va_start(args, fmt); + len =3D vsprintf_trunc(buf, size, fmt, args); + va_end(args); + + return len; +} +EXPORT_SYMBOL(sprintf_trunc); + /** * vsprintf - Format a string and place it in a buffer * @buf: The buffer to place the result into --=20 2.50.0 From nobody Tue Oct 7 08:53:20 2025 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 52472288CC; Fri, 11 Jul 2025 01:56:50 +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=1752199011; cv=none; b=j3ema35u2k6cmJ6FUqOzDEFyx6kXczHJHJ1l0Nfx62JFcw9TBdmriSUEKmohdctmiwmcuJWkNs9CD+GowyPFO5QEyv34deO9G8/gtxtuCfEWjF5psFw1Ydqpaqn/0OZ4AEUwHRiawf52IYdB7gJClDGkMt9sQ0+z9f070IBKoMQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752199011; c=relaxed/simple; bh=SDtvVojw1lKkC1ixgqUR/M7GavSPKQ3ZRDqLgxzNGuk=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=SaOwgvyOdi9cpmb4JEl7g11g6pUcOOaAsA/M9+pNF0iphDUHuLHaLC9hG5sqePbS8iRuZflx32kbppD7azC8wl7NWjZTiX9M2gqzYFxDalmd/p5wvf2BJDR2z1XpLNur7qwPi697qpUQCV4htb6d3PUVEHj6afXy+R0q3F5las4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bYvIpIqe; 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="bYvIpIqe" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 52A27C4CEF5; Fri, 11 Jul 2025 01:56:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1752199010; bh=SDtvVojw1lKkC1ixgqUR/M7GavSPKQ3ZRDqLgxzNGuk=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=bYvIpIqeRtL/++EgjV6eCZYSY5E07NzGsJ+Z4rbB41rkdxvNUGIwYD6aE58aadV0z fs7AQROuNsZRt+2ezIahVjGCHSH8YoCqBUpSfUcW0eiY6VxyWIG11P65G4YhxMrF/K aYeaJgZia5Zo2qh+2dmOCRWHRvB3kL1XloZSuGsSyfLbpYBFRlkHBJeH8HmizIy1IZ R2FzvZoQtSEV+kKsjGVuLrNbFfukR9rsdSlFpaDwp+4JOjySSEe0d10SVNlOfkoz0U l0WIXQaRyA0B7Pcj5+Pvw1xuv3Nem2HJA0oZt10hNpTNgSxQjPa7cdWchV5X8b/EBz J0sTuQkEgIUWg== Date: Fri, 11 Jul 2025 03:56:44 +0200 From: Alejandro Colomar To: linux-mm@kvack.org, linux-hardening@vger.kernel.org Cc: Alejandro Colomar , Kees Cook , Christopher Bazley , shadow <~hallyn/shadow@lists.sr.ht>, linux-kernel@vger.kernel.org, Andrew Morton , kasan-dev@googlegroups.com, Dmitry Vyukov , Alexander Potapenko , Marco Elver , Christoph Lameter , David Rientjes , Vlastimil Babka , Roman Gushchin , Harry Yoo , Andrew Clayton , Rasmus Villemoes , Michal Hocko , Linus Torvalds , Al Viro , Martin Uecker , Sam James , Andrew Pinski Subject: [RFC v6 2/8] vsprintf: Add [v]sprintf_end() Message-ID: X-Mailer: git-send-email 2.50.0 References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" sprintf_end() is a function similar to stpcpy(3) in the sense that it returns a pointer that is suitable for chaining to other copy operations. It takes a pointer to the end of the buffer as a sentinel for when to truncate, which unlike a size, doesn't need to be updated after every call. This makes it much more ergonomic, avoiding manually calculating the size after each copy, which is error prone. It also makes error handling much easier, by reporting truncation with a null pointer, which is accepted and transparently passed down by subsequent sprintf_end() calls. This results in only needing to report errors once after a chain of sprintf_end() calls, unlike snprintf(3), which requires checking after every call. p =3D buf; e =3D buf + countof(buf); p =3D sprintf_end(p, e, foo); p =3D sprintf_end(p, e, bar); if (p =3D=3D NULL) goto trunc; vs len =3D 0; size =3D countof(buf); len +=3D snprintf(buf + len, size - len, foo); if (len >=3D size) goto trunc; len +=3D snprintf(buf + len, size - len, bar); if (len >=3D size) goto trunc; And also better than scnprintf() calls: len =3D 0; size =3D countof(buf); len +=3D scnprintf(buf + len, size - len, foo); len +=3D scnprintf(buf + len, size - len, bar); // No ability to check. It seems aparent that it's a more elegant approach to string catenation. These functions will soon be proposed for standardization as [v]seprintf() into C2y, and they exist in Plan9 as seprint(2) --but the Plan9 implementation has important bugs--. Link: Cc: Kees Cook Cc: Christopher Bazley Cc: Rasmus Villemoes Cc: Marco Elver Cc: Michal Hocko Cc: Linus Torvalds Cc: Al Viro Signed-off-by: Alejandro Colomar --- include/linux/sprintf.h | 2 ++ lib/vsprintf.c | 54 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/include/linux/sprintf.h b/include/linux/sprintf.h index 5ea6ec9c2e59..8dfc37713747 100644 --- a/include/linux/sprintf.h +++ b/include/linux/sprintf.h @@ -15,6 +15,8 @@ __printf(3, 4) int scnprintf(char *buf, size_t size, cons= t char *fmt, ...); __printf(3, 0) int vscnprintf(char *buf, size_t size, const char *fmt, va_= list args); __printf(3, 4) int sprintf_trunc(char *buf, size_t size, const char *fmt, = ...); __printf(3, 0) int vsprintf_trunc(char *buf, size_t size, const char *fmt,= va_list args); +__printf(3, 4) char *sprintf_end(char *p, const char end[0], const char *f= mt, ...); +__printf(3, 0) char *vsprintf_end(char *p, const char end[0], const char *= fmt, va_list args); __printf(2, 3) __malloc char *kasprintf(gfp_t gfp, const char *fmt, ...); __printf(2, 0) __malloc char *kvasprintf(gfp_t gfp, const char *fmt, va_li= st args); __printf(2, 0) const char *kvasprintf_const(gfp_t gfp, const char *fmt, va= _list args); diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 15e780942c56..5d0c5a0d60fd 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -2951,6 +2951,35 @@ int vsprintf_trunc(char *buf, size_t size, const cha= r *fmt, va_list args) } EXPORT_SYMBOL(vsprintf_trunc); =20 +/** + * vsprintf_end - va_list string end-delimited print formatted + * @p: The buffer to place the result into + * @end: A pointer to one past the last character in the buffer + * @fmt: The format string to use + * @args: Arguments for the format string + * + * The return value is a pointer to the trailing '\0'. + * If @p is NULL, the function returns NULL. + * If the string is truncated, the function returns NULL. + * If @end <=3D @p, the function returns NULL. + * + * See the vsnprintf() documentation for format string extensions over C99. + */ +char *vsprintf_end(char *p, const char end[0], const char *fmt, va_list ar= gs) +{ + int len; + + if (unlikely(p =3D=3D NULL)) + return NULL; + + len =3D vsprintf_trunc(p, end - p, fmt, args); + if (unlikely(len < 0)) + return NULL; + + return p + len; +} +EXPORT_SYMBOL(vsprintf_end); + /** * snprintf - Format a string and place it in a buffer * @buf: The buffer to place the result into @@ -3027,6 +3056,31 @@ int sprintf_trunc(char *buf, size_t size, const char= *fmt, ...) } EXPORT_SYMBOL(sprintf_trunc); =20 +/** + * sprintf_end - string end-delimited print formatted + * @p: The buffer to place the result into + * @end: A pointer to one past the last character in the buffer + * @fmt: The format string to use + * @...: Arguments for the format string + * + * The return value is a pointer to the trailing '\0'. + * If @buf is NULL, the function returns NULL. + * If the string is truncated, the function returns NULL. + * If @end <=3D @p, the function returns NULL. + */ + +char *sprintf_end(char *p, const char end[0], const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + p =3D vsprintf_end(p, end, fmt, args); + va_end(args); + + return p; +} +EXPORT_SYMBOL(sprintf_end); + /** * vsprintf - Format a string and place it in a buffer * @buf: The buffer to place the result into --=20 2.50.0 From nobody Tue Oct 7 08:53:20 2025 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 D6223141987; Fri, 11 Jul 2025 01:56:57 +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=1752199017; cv=none; b=hu5qAe5PIPMq76KHTdfLigKrmw4JvyHUMHdYZCoQ/YYHOnGmAcO9wWdaQZFmFMK9QPMYg2//oaBeQ+5/qP+XwJzYhYvCuXU6WqOnZnVToX5T5Q4+oARLeLYAWz6iJhnSKasJS5Bs6fc5+IxnUktGp7Sluzk3OFK9h1nN8m64j7s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752199017; c=relaxed/simple; bh=ZJDxyoHVxpXrXiiFeB/cS1+32e1KaIZe9xa0hULilH0=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=Q52P7NhHzy+b13ULzea8g6CO4CCh4asTFwIYTmaC9QNjWUfTvlWACdH0RWvmYGTBNs6R3N/Y8+OO9BAOLxMiinzw8SvyDcgKMig22YtA8bJRlzLT10UyM0K3NQvT52alHIC9ueozxtpoi76P2cLkgA5Fv6qay2GTJpiw9il4/Ns= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ts7eRZFX; 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="ts7eRZFX" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DC406C4CEE3; Fri, 11 Jul 2025 01:56:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1752199017; bh=ZJDxyoHVxpXrXiiFeB/cS1+32e1KaIZe9xa0hULilH0=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=ts7eRZFXC+hTZVEFRgDt2D9q5siZFqf1bAIA+BV4yYoGKyCqhum9H5nH/wnnDWLuD AxlWW10ozY+fZ27zw6+BLSbjLzvoaCnD2qpZ2PS2TVPhJe84p6N4ZbzQcf9q69v0pH MHcofgmtzyrHi+wlXAYO0i/jjiGwAQWS4hTjnH9Q+qz6qMyv80CUFhD/YMW/naL4xm Lzl6Ob4LiiYFr7qFiuDb8A7U1f4s+9k+ph3bBe4ulLHpnd3rEDF8tDu0h0sRbjbyrH IY11kxEVhLQLSk1SSGfq01IKieR4Co0wn1vDOig6r4P2VEFzFpJQaHRak/PBPOHy3a WglLx3iQ0L3Dw== Date: Fri, 11 Jul 2025 03:56:51 +0200 From: Alejandro Colomar To: linux-mm@kvack.org, linux-hardening@vger.kernel.org Cc: Alejandro Colomar , Kees Cook , Christopher Bazley , shadow <~hallyn/shadow@lists.sr.ht>, linux-kernel@vger.kernel.org, Andrew Morton , kasan-dev@googlegroups.com, Dmitry Vyukov , Alexander Potapenko , Marco Elver , Christoph Lameter , David Rientjes , Vlastimil Babka , Roman Gushchin , Harry Yoo , Andrew Clayton , Rasmus Villemoes , Michal Hocko , Linus Torvalds , Al Viro , Martin Uecker , Sam James , Andrew Pinski Subject: [RFC v6 3/8] sprintf: Add [v]sprintf_array() Message-ID: <9348d5df2d9f3a64be70a161f7af39ba30a0edc2.1752193588.git.alx@kernel.org> X-Mailer: git-send-email 2.50.0 References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" These macros take the end of the array argument implicitly to avoid programmer mistakes. This guarantees that the input is an array, unlike snprintf(buf, sizeof(buf), ...); which is dangerous if the programmer passes a pointer instead of an array. These macros are essentially the same as the 2-argument version of strscpy(), but with a formatted string. Cc: Rasmus Villemoes Cc: Marco Elver Cc: Michal Hocko Cc: Linus Torvalds Cc: Al Viro Signed-off-by: Alejandro Colomar --- include/linux/sprintf.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/linux/sprintf.h b/include/linux/sprintf.h index 8dfc37713747..bd8174224a4a 100644 --- a/include/linux/sprintf.h +++ b/include/linux/sprintf.h @@ -4,6 +4,10 @@ =20 #include #include +#include + +#define sprintf_array(a, fmt, ...) sprintf_trunc(a, ARRAY_SIZE(a), fmt, #= #__VA_ARGS__) +#define vsprintf_array(a, fmt, ap) vsprintf_trunc(a, ARRAY_SIZE(a), fmt, = ap) =20 int num_to_str(char *buf, int size, unsigned long long num, unsigned int w= idth); =20 --=20 2.50.0 From nobody Tue Oct 7 08:53:20 2025 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 BB05F1482E7; Fri, 11 Jul 2025 01:57:04 +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=1752199024; cv=none; b=ZNmVMEOFP1NT19LVJj00dIF4StfcFekkgwo+nq+XsMeP9D2Kdc3ita2ynMP5CuVPxhbotsaPXhvl+yPixrO0ajW5EeBZCaSowQX3oHAwvx1Aed0/Msy1iZzcDA2IJvIa5FnLV0L/SBIJqEwC8BlNu5hOrTazgC9S1hfTNfdxlJo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752199024; c=relaxed/simple; bh=KFeH759S2pXUEgcinWQTZzWHu8P8w4ivkJjMDXMeyRQ=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=aIIjgmU7vWEuj4HoTI8eqAyP3m06Q3KzZehcHMwdevWGhDJZyDzT4KuFffRIOx0ZyewliWiauRYvnrBFJWlmbo6DtIoWFXs1Egh6rVhYEGE3gxJ8unBxPuMyW2MkOykJnHR6UKeL/vgjb6bGfpziEYZ2XyE++yJpBT12mrn+uiA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=b+yrik1Y; 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="b+yrik1Y" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6BD82C4CEF6; Fri, 11 Jul 2025 01:56:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1752199024; bh=KFeH759S2pXUEgcinWQTZzWHu8P8w4ivkJjMDXMeyRQ=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=b+yrik1Y7oQkJfNLgirKR+t+05Nr58BhPynA5GRvDE3dWL8dPFJxRPU/bK1SphqTI jvrRfyb2yeA1HvF5IQL1+rcY6ivhXJ8Mt+BvUBoZKD2BtH8AUqPgTZuuRvuOSLQvW4 W77M+enNSb+dvC8ziwysEDVyn0pd5qks1TkAzefJ/zpVaK5BoJDPVQ358UVhcxOfEP kv+Ovf3a+dKCSD9OhppknH5doJg5s5bVR1TyvAPBuHkfHQVVqOBa+HySpvvTr/xme1 VKqGqaCgIgtW71h6PNlgCxyVkRrnH1k6eqiH4eN6clJIhz4E6tT9ycqcwo5d1aB2L1 dk3mUG45HJgag== Date: Fri, 11 Jul 2025 03:56:57 +0200 From: Alejandro Colomar To: linux-mm@kvack.org, linux-hardening@vger.kernel.org Cc: Alejandro Colomar , Kees Cook , Christopher Bazley , shadow <~hallyn/shadow@lists.sr.ht>, linux-kernel@vger.kernel.org, Andrew Morton , kasan-dev@googlegroups.com, Dmitry Vyukov , Alexander Potapenko , Marco Elver , Christoph Lameter , David Rientjes , Vlastimil Babka , Roman Gushchin , Harry Yoo , Andrew Clayton , Rasmus Villemoes , Michal Hocko , Linus Torvalds , Al Viro , Martin Uecker , Sam James , Andrew Pinski Subject: [RFC v6 4/8] stacktrace, stackdepot: Add sprintf_end()-like variants of functions Message-ID: <6c5d8e6012f06f595fbb30e3c25a88a400538ad8.1752193588.git.alx@kernel.org> X-Mailer: git-send-email 2.50.0 References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Cc: Kees Cook Cc: Christopher Bazley Cc: Rasmus Villemoes Cc: Marco Elver Cc: Michal Hocko Cc: Linus Torvalds Cc: Al Viro Signed-off-by: Alejandro Colomar --- include/linux/stackdepot.h | 13 +++++++++++++ include/linux/stacktrace.h | 3 +++ kernel/stacktrace.c | 28 ++++++++++++++++++++++++++++ lib/stackdepot.c | 13 +++++++++++++ 4 files changed, 57 insertions(+) diff --git a/include/linux/stackdepot.h b/include/linux/stackdepot.h index 2cc21ffcdaf9..76182e874f67 100644 --- a/include/linux/stackdepot.h +++ b/include/linux/stackdepot.h @@ -219,6 +219,19 @@ void stack_depot_print(depot_stack_handle_t stack); int stack_depot_snprint(depot_stack_handle_t handle, char *buf, size_t siz= e, int spaces); =20 +/** + * stack_depot_sprint_end - Print a stack trace from stack depot into a bu= ffer + * + * @handle: Stack depot handle returned from stack_depot_save() + * @p: Pointer to the print buffer + * @end: Pointer to one past the last element in the buffer + * @spaces: Number of leading spaces to print + * + * Return: Pointer to trailing '\0'; or NULL on truncation + */ +char *stack_depot_sprint_end(depot_stack_handle_t handle, char *p, + const char end[0], int spaces); + /** * stack_depot_put - Drop a reference to a stack trace from stack depot * diff --git a/include/linux/stacktrace.h b/include/linux/stacktrace.h index 97455880ac41..79ada795d479 100644 --- a/include/linux/stacktrace.h +++ b/include/linux/stacktrace.h @@ -67,6 +67,9 @@ void stack_trace_print(const unsigned long *trace, unsign= ed int nr_entries, int spaces); int stack_trace_snprint(char *buf, size_t size, const unsigned long *entri= es, unsigned int nr_entries, int spaces); +char *stack_trace_sprint_end(char *p, const char end[0], + const unsigned long *entries, + unsigned int nr_entries, int spaces); unsigned int stack_trace_save(unsigned long *store, unsigned int size, unsigned int skipnr); unsigned int stack_trace_save_tsk(struct task_struct *task, diff --git a/kernel/stacktrace.c b/kernel/stacktrace.c index afb3c116da91..f389647d8e44 100644 --- a/kernel/stacktrace.c +++ b/kernel/stacktrace.c @@ -70,6 +70,34 @@ int stack_trace_snprint(char *buf, size_t size, const un= signed long *entries, } EXPORT_SYMBOL_GPL(stack_trace_snprint); =20 +/** + * stack_trace_sprint_end - Print the entries in the stack trace into a bu= ffer + * @p: Pointer to the print buffer + * @end: Pointer to one past the last element in the buffer + * @entries: Pointer to storage array + * @nr_entries: Number of entries in the storage array + * @spaces: Number of leading spaces to print + * + * Return: Pointer to the trailing '\0'; or NULL on truncation. + */ +char *stack_trace_sprint_end(char *p, const char end[0], + const unsigned long *entries, unsigned int nr_entries, + int spaces) +{ + unsigned int i; + + if (WARN_ON(!entries)) + return 0; + + for (i =3D 0; i < nr_entries; i++) { + p =3D sprintf_end(p, end, "%*c%pS\n", 1 + spaces, ' ', + (void *)entries[i]); + } + + return p; +} +EXPORT_SYMBOL_GPL(stack_trace_sprint_end); + #ifdef CONFIG_ARCH_STACKWALK =20 struct stacktrace_cookie { diff --git a/lib/stackdepot.c b/lib/stackdepot.c index 73d7b50924ef..48e5c0ff37e8 100644 --- a/lib/stackdepot.c +++ b/lib/stackdepot.c @@ -771,6 +771,19 @@ int stack_depot_snprint(depot_stack_handle_t handle, c= har *buf, size_t size, } EXPORT_SYMBOL_GPL(stack_depot_snprint); =20 +char *stack_depot_sprint_end(depot_stack_handle_t handle, char *p, + const char end[0], int spaces) +{ + unsigned long *entries; + unsigned int nr_entries; + + nr_entries =3D stack_depot_fetch(handle, &entries); + return nr_entries ? + stack_trace_sprint_end(p, end, entries, nr_entries, spaces) + : sprintf_end(p, end, ""); +} +EXPORT_SYMBOL_GPL(stack_depot_sprint_end); + depot_stack_handle_t __must_check stack_depot_set_extra_bits( depot_stack_handle_t handle, unsigned int extra_bits) { --=20 2.50.0 From nobody Tue Oct 7 08:53:20 2025 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 F38C114BFA2; Fri, 11 Jul 2025 01:57:11 +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=1752199032; cv=none; b=GROpZNKYUgKKECfz/UU6l1TWl1Vj/bNDeOZ35jDpuQopo76k8ZwhCDCq/wtFI+Im5/mIWidLGupuW/Tuu4iFRG/e9jLqgNc9aD14q8vTvR/HkteU3vbkeAiWu+/DjhxmYHDCXpPdjzJaGggxwBegdXpqt/QDaMDYQFWluF5tIyI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752199032; c=relaxed/simple; bh=stTpsWR5B9qnU4lcgeg0tYr2I54PzkVTHHPWz1Iz+X8=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=CQzEc/E9jOGM/dmFHAOH6V7N08GCmLyMQcuj3ZHjjGfKumfKih0c5p0G3ghSAKDkaFEPTM6FcctsayPuhoJpuDSouunmYtsQDlfugfd/HpMkCk7vFd7eWnthDnfC1MMBEPlAnoQJxWbkcIZlFoICILTdlYg18Zw8Bk4RVmOTbRA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NHhCnKgm; 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="NHhCnKgm" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3E2D8C4CEE3; Fri, 11 Jul 2025 01:57:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1752199031; bh=stTpsWR5B9qnU4lcgeg0tYr2I54PzkVTHHPWz1Iz+X8=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=NHhCnKgmG9jHKzaW9+iAljhm/h50l3wWsWTMssrurSEQzbFcDMsxQYw4EGK69U+3G Uajs6mZ0vvgIt/Z/z3/GwqaDBuFliwl9W5xbEnqkZn3i8s0YsrwJ5pm4usNyvvzjpt acUWRGkJNk/ilaTNM0FkzzxXz8g/21TFz7iak2WywEYviNC+/jTYtEyclexGZ+iu6K YG1GeVk1GfNVCTmGVZxm28IWh27RONOXcQKTM4FspjeAvPNvEktbDlbWMhqO31GnsJ 9x/E8KUXayy9rWiJspo+aFLL7b9PKiPeEfws3rcunNSfy89u6+yNUz8TbY9A22uZGy ikR2FuLZZ9JYg== Date: Fri, 11 Jul 2025 03:57:04 +0200 From: Alejandro Colomar To: linux-mm@kvack.org, linux-hardening@vger.kernel.org Cc: Alejandro Colomar , Kees Cook , Christopher Bazley , shadow <~hallyn/shadow@lists.sr.ht>, linux-kernel@vger.kernel.org, Andrew Morton , kasan-dev@googlegroups.com, Dmitry Vyukov , Alexander Potapenko , Marco Elver , Christoph Lameter , David Rientjes , Vlastimil Babka , Roman Gushchin , Harry Yoo , Andrew Clayton , Rasmus Villemoes , Michal Hocko , Linus Torvalds , Al Viro , Martin Uecker , Sam James , Andrew Pinski , Sven Schnelle , Heiko Carstens , Tvrtko Ursulin , Christophe JAILLET , Hyeonggon Yoo <42.hyeyoo@gmail.com>, Chao Yu Subject: [RFC v6 5/8] mm: Use sprintf_end() instead of less ergonomic APIs Message-ID: <8a0ffc1bf43d60e1654c10546b9f615c38f604f0.1752193588.git.alx@kernel.org> X-Mailer: git-send-email 2.50.0 References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" While doing this, I detected some anomalies in the existing code: mm/kfence/kfence_test.c: - The last call to scnprintf() did increment 'cur', but it's unused after that, so it was dead code. I've removed the dead code in this patch. - 'end' is calculated as end =3D &expect[0][sizeof(expect[0] - 1)]; However, the '-1' doesn't seem to be necessary. When passing $2 to scnprintf(), the size was specified as 'end - cur'. And scnprintf() --just like snprintf(3)--, won't write more than $2 bytes (including the null byte). That means that scnprintf() wouldn't write more than &expect[0][sizeof(expect[0]) - 1] - expect[0] which simplifies to sizeof(expect[0]) - 1 bytes. But we have sizeof(expect[0]) bytes available, so we're wasting one byte entirely. This is a benign off-by-one bug. The two occurrences of this bug will be fixed in a following patch in this series. mm/kmsan/kmsan_test.c: The same benign off-by-one bug calculating the remaining size. mm/mempolicy.c: This file uses the 'p +=3D snprintf()' anti-pattern. That will overflow the pointer on truncation, which has undefined behavior. Using sprintf_end(), this bug is fixed. As in the previous file, here there was also dead code in the last scnprintf() call, by incrementing a pointer that is not used after the call. I've removed the dead code. mm/page_owner.c: Within print_page_owner(), there are some calls to scnprintf(), which do report truncation. And then there are other calls to snprintf(), where we handle errors (there are two 'goto err'). I've kept the existing error handling, as I trust it's there for a good reason (i.e., we may want to avoid calling print_page_owner_memcg() if we truncated before). Please review if this amount of error handling is the right one, or if we want to add or remove some. For sprintf_end(), a single test for null after the last call is enough to detect truncation. mm/slub.c: Again, the 'p +=3D snprintf()' anti-pattern. This is UB, and by using sprintf_end() we've fixed the bug. Cc: Kees Cook Cc: Christopher Bazley Cc: Sven Schnelle Cc: Marco Elver Cc: Heiko Carstens Cc: Tvrtko Ursulin Cc: Andrew Morton Cc: Linus Torvalds Cc: David Rientjes Cc: Christophe JAILLET Cc: Hyeonggon Yoo <42.hyeyoo@gmail.com> Cc: Chao Yu Cc: Vlastimil Babka Cc: Rasmus Villemoes Cc: Michal Hocko Cc: Al Viro Signed-off-by: Alejandro Colomar --- mm/kfence/kfence_test.c | 24 ++++++++++++------------ mm/kmsan/kmsan_test.c | 4 ++-- mm/mempolicy.c | 18 +++++++++--------- mm/page_owner.c | 32 +++++++++++++++++--------------- mm/slub.c | 5 +++-- 5 files changed, 43 insertions(+), 40 deletions(-) diff --git a/mm/kfence/kfence_test.c b/mm/kfence/kfence_test.c index 00034e37bc9f..bae382eca4ab 100644 --- a/mm/kfence/kfence_test.c +++ b/mm/kfence/kfence_test.c @@ -113,26 +113,26 @@ static bool report_matches(const struct expect_report= *r) end =3D &expect[0][sizeof(expect[0]) - 1]; switch (r->type) { case KFENCE_ERROR_OOB: - cur +=3D scnprintf(cur, end - cur, "BUG: KFENCE: out-of-bounds %s", + cur =3D sprintf_end(cur, end, "BUG: KFENCE: out-of-bounds %s", get_access_type(r)); break; case KFENCE_ERROR_UAF: - cur +=3D scnprintf(cur, end - cur, "BUG: KFENCE: use-after-free %s", + cur =3D sprintf_end(cur, end, "BUG: KFENCE: use-after-free %s", get_access_type(r)); break; case KFENCE_ERROR_CORRUPTION: - cur +=3D scnprintf(cur, end - cur, "BUG: KFENCE: memory corruption"); + cur =3D sprintf_end(cur, end, "BUG: KFENCE: memory corruption"); break; case KFENCE_ERROR_INVALID: - cur +=3D scnprintf(cur, end - cur, "BUG: KFENCE: invalid %s", + cur =3D sprintf_end(cur, end, "BUG: KFENCE: invalid %s", get_access_type(r)); break; case KFENCE_ERROR_INVALID_FREE: - cur +=3D scnprintf(cur, end - cur, "BUG: KFENCE: invalid free"); + cur =3D sprintf_end(cur, end, "BUG: KFENCE: invalid free"); break; } =20 - scnprintf(cur, end - cur, " in %pS", r->fn); + sprintf_end(cur, end, " in %pS", r->fn); /* The exact offset won't match, remove it; also strip module name. */ cur =3D strchr(expect[0], '+'); if (cur) @@ -144,26 +144,26 @@ static bool report_matches(const struct expect_report= *r) =20 switch (r->type) { case KFENCE_ERROR_OOB: - cur +=3D scnprintf(cur, end - cur, "Out-of-bounds %s at", get_access_typ= e(r)); + cur =3D sprintf_end(cur, end, "Out-of-bounds %s at", get_access_type(r)); addr =3D arch_kfence_test_address(addr); break; case KFENCE_ERROR_UAF: - cur +=3D scnprintf(cur, end - cur, "Use-after-free %s at", get_access_ty= pe(r)); + cur =3D sprintf_end(cur, end, "Use-after-free %s at", get_access_type(r)= ); addr =3D arch_kfence_test_address(addr); break; case KFENCE_ERROR_CORRUPTION: - cur +=3D scnprintf(cur, end - cur, "Corrupted memory at"); + cur =3D sprintf_end(cur, end, "Corrupted memory at"); break; case KFENCE_ERROR_INVALID: - cur +=3D scnprintf(cur, end - cur, "Invalid %s at", get_access_type(r)); + cur =3D sprintf_end(cur, end, "Invalid %s at", get_access_type(r)); addr =3D arch_kfence_test_address(addr); break; case KFENCE_ERROR_INVALID_FREE: - cur +=3D scnprintf(cur, end - cur, "Invalid free of"); + cur =3D sprintf_end(cur, end, "Invalid free of"); break; } =20 - cur +=3D scnprintf(cur, end - cur, " 0x%p", (void *)addr); + sprintf_end(cur, end, " 0x%p", (void *)addr); =20 spin_lock_irqsave(&observed.lock, flags); if (!report_available()) diff --git a/mm/kmsan/kmsan_test.c b/mm/kmsan/kmsan_test.c index 9733a22c46c1..e48ca1972ff3 100644 --- a/mm/kmsan/kmsan_test.c +++ b/mm/kmsan/kmsan_test.c @@ -107,9 +107,9 @@ static bool report_matches(const struct expect_report *= r) cur =3D expected_header; end =3D &expected_header[sizeof(expected_header) - 1]; =20 - cur +=3D scnprintf(cur, end - cur, "BUG: KMSAN: %s", r->error_type); + cur =3D sprintf_end(cur, end, "BUG: KMSAN: %s", r->error_type); =20 - scnprintf(cur, end - cur, " in %s", r->symbol); + sprintf_end(cur, end, " in %s", r->symbol); /* The exact offset won't match, remove it; also strip module name. */ cur =3D strchr(expected_header, '+'); if (cur) diff --git a/mm/mempolicy.c b/mm/mempolicy.c index b28a1e6ae096..6beb2710f97c 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -3359,6 +3359,7 @@ int mpol_parse_str(char *str, struct mempolicy **mpol) void mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol) { char *p =3D buffer; + char *e =3D buffer + maxlen; nodemask_t nodes =3D NODE_MASK_NONE; unsigned short mode =3D MPOL_DEFAULT; unsigned short flags =3D 0; @@ -3384,33 +3385,32 @@ void mpol_to_str(char *buffer, int maxlen, struct m= empolicy *pol) break; default: WARN_ON_ONCE(1); - snprintf(p, maxlen, "unknown"); + sprintf_end(p, e, "unknown"); return; } =20 - p +=3D snprintf(p, maxlen, "%s", policy_modes[mode]); + p =3D sprintf_end(p, e, "%s", policy_modes[mode]); =20 if (flags & MPOL_MODE_FLAGS) { - p +=3D snprintf(p, buffer + maxlen - p, "=3D"); + p =3D sprintf_end(p, e, "=3D"); =20 /* * Static and relative are mutually exclusive. */ if (flags & MPOL_F_STATIC_NODES) - p +=3D snprintf(p, buffer + maxlen - p, "static"); + p =3D sprintf_end(p, e, "static"); else if (flags & MPOL_F_RELATIVE_NODES) - p +=3D snprintf(p, buffer + maxlen - p, "relative"); + p =3D sprintf_end(p, e, "relative"); =20 if (flags & MPOL_F_NUMA_BALANCING) { if (!is_power_of_2(flags & MPOL_MODE_FLAGS)) - p +=3D snprintf(p, buffer + maxlen - p, "|"); - p +=3D snprintf(p, buffer + maxlen - p, "balancing"); + p =3D sprintf_end(p, e, "|"); + p =3D sprintf_end(p, e, "balancing"); } } =20 if (!nodes_empty(nodes)) - p +=3D scnprintf(p, buffer + maxlen - p, ":%*pbl", - nodemask_pr_args(&nodes)); + sprintf_end(p, e, ":%*pbl", nodemask_pr_args(&nodes)); } =20 #ifdef CONFIG_SYSFS diff --git a/mm/page_owner.c b/mm/page_owner.c index cc4a6916eec6..c00b3be01540 100644 --- a/mm/page_owner.c +++ b/mm/page_owner.c @@ -496,7 +496,7 @@ void pagetypeinfo_showmixedcount_print(struct seq_file = *m, /* * Looking for memcg information and print it out */ -static inline int print_page_owner_memcg(char *kbuf, size_t count, int ret, +static inline char *print_page_owner_memcg(char *p, const char end[0], struct page *page) { #ifdef CONFIG_MEMCG @@ -511,8 +511,7 @@ static inline int print_page_owner_memcg(char *kbuf, si= ze_t count, int ret, goto out_unlock; =20 if (memcg_data & MEMCG_DATA_OBJEXTS) - ret +=3D scnprintf(kbuf + ret, count - ret, - "Slab cache page\n"); + p =3D sprintf_end(p, end, "Slab cache page\n"); =20 memcg =3D page_memcg_check(page); if (!memcg) @@ -520,7 +519,7 @@ static inline int print_page_owner_memcg(char *kbuf, si= ze_t count, int ret, =20 online =3D (memcg->css.flags & CSS_ONLINE); cgroup_name(memcg->css.cgroup, name, sizeof(name)); - ret +=3D scnprintf(kbuf + ret, count - ret, + p =3D sprintf_end(p, end, "Charged %sto %smemcg %s\n", PageMemcgKmem(page) ? "(via objcg) " : "", online ? "" : "offline ", @@ -529,7 +528,7 @@ static inline int print_page_owner_memcg(char *kbuf, si= ze_t count, int ret, rcu_read_unlock(); #endif /* CONFIG_MEMCG */ =20 - return ret; + return p; } =20 static ssize_t @@ -538,14 +537,16 @@ print_page_owner(char __user *buf, size_t count, unsi= gned long pfn, depot_stack_handle_t handle) { int ret, pageblock_mt, page_mt; - char *kbuf; + char *kbuf, *p, *e; =20 count =3D min_t(size_t, count, PAGE_SIZE); kbuf =3D kmalloc(count, GFP_KERNEL); if (!kbuf) return -ENOMEM; =20 - ret =3D scnprintf(kbuf, count, + p =3D kbuf; + e =3D kbuf + count; + p =3D sprintf_end(p, e, "Page allocated via order %u, mask %#x(%pGg), pid %d, tgid %d (%s), ts = %llu ns\n", page_owner->order, page_owner->gfp_mask, &page_owner->gfp_mask, page_owner->pid, @@ -555,7 +556,7 @@ print_page_owner(char __user *buf, size_t count, unsign= ed long pfn, /* Print information relevant to grouping pages by mobility */ pageblock_mt =3D get_pageblock_migratetype(page); page_mt =3D gfp_migratetype(page_owner->gfp_mask); - ret +=3D scnprintf(kbuf + ret, count - ret, + p =3D sprintf_end(p, e, "PFN 0x%lx type %s Block %lu type %s Flags %pGp\n", pfn, migratetype_names[page_mt], @@ -563,22 +564,23 @@ print_page_owner(char __user *buf, size_t count, unsi= gned long pfn, migratetype_names[pageblock_mt], &page->flags); =20 - ret +=3D stack_depot_snprint(handle, kbuf + ret, count - ret, 0); - if (ret >=3D count) - goto err; + p =3D stack_depot_sprint_end(handle, p, e, 0); + if (p =3D=3D NULL) + goto err; // XXX: Should we remove this error handling? =20 if (page_owner->last_migrate_reason !=3D -1) { - ret +=3D scnprintf(kbuf + ret, count - ret, + p =3D sprintf_end(p, e, "Page has been migrated, last migrate reason: %s\n", migrate_reason_names[page_owner->last_migrate_reason]); } =20 - ret =3D print_page_owner_memcg(kbuf, count, ret, page); + p =3D print_page_owner_memcg(p, e, page); =20 - ret +=3D snprintf(kbuf + ret, count - ret, "\n"); - if (ret >=3D count) + p =3D sprintf_end(p, e, "\n"); + if (p =3D=3D NULL) goto err; =20 + ret =3D p - kbuf; if (copy_to_user(buf, kbuf, ret)) ret =3D -EFAULT; =20 diff --git a/mm/slub.c b/mm/slub.c index be8b09e09d30..dcc857676857 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -7451,6 +7451,7 @@ static char *create_unique_id(struct kmem_cache *s) { char *name =3D kmalloc(ID_STR_LENGTH, GFP_KERNEL); char *p =3D name; + char *e =3D name + ID_STR_LENGTH; =20 if (!name) return ERR_PTR(-ENOMEM); @@ -7475,9 +7476,9 @@ static char *create_unique_id(struct kmem_cache *s) *p++ =3D 'A'; if (p !=3D name + 1) *p++ =3D '-'; - p +=3D snprintf(p, ID_STR_LENGTH - (p - name), "%07u", s->size); + p =3D sprintf_end(p, e, "%07u", s->size); =20 - if (WARN_ON(p > name + ID_STR_LENGTH - 1)) { + if (WARN_ON(p =3D=3D NULL)) { kfree(name); return ERR_PTR(-EINVAL); } --=20 2.50.0 From nobody Tue Oct 7 08:53:20 2025 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 C928913D531; Fri, 11 Jul 2025 01:57:18 +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=1752199038; cv=none; b=MN9ZKOWUL2Ssf+fvFN/pUU1SPNedoP9L33oUabts5XYPdxQqEIjx8R6xWsDqYuiXpQ2RnfctOqpRBPTXKvL24CmQgyIOgBR4whOatl8GLy6tNA8LEWQJ+eEHtqGl9XH/TEDYrjm37MiiIkG4cYFPHCdSmSqc+v0BLSyI8DseMow= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752199038; c=relaxed/simple; bh=rA+UPFYPuwoFgyGzULq9cIi8t0p+DMJsALzl86HNlek=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=ebQjDpU+vFh9kDfsgN6dP3KHMAUyyFUxxGntk35czbu/LHE8HcTdWSdAThDp5SauF+4U9byJ2d4XyieRSA9108DQdReEPektIiRnbt1z5wkixDP3No6qs97mLIIImnxa9zVHiRTa5FC8HeH/HHbs2mGcAH/GR7lw/sqCYe6DA3Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NLhTvbdN; 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="NLhTvbdN" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0D0C2C4CEE3; Fri, 11 Jul 2025 01:57:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1752199038; bh=rA+UPFYPuwoFgyGzULq9cIi8t0p+DMJsALzl86HNlek=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=NLhTvbdNgrS960NEQxlWk0IVVXJt/aRKdQ8OVhbhrfIMKyoZEeIZMrKuBezSoYVyv ZKzGLWxG8qRSd/nwR+JV/xwTEtjvwdwnCO/bLMSXfDmAXPvmunK6v3hErIbEwTzRij YaOJ6/iMD0EbonjcIxOqqbuuVpVpQWa7O6ka0O9B7g7FO2JiNiTAwvgbAN/F3Ck7ci JjNE+AxoJFDeYdXMuHCR1+0OlCBvh2xRQh5kBEmxqf9fxlVlSeNwzl4BO1PnlxhNQC 7AUsmdAVBE4EYgDHXyIOZ8TB0POq1yaJICtauOk6eOorPS6EEfdYbEwGnR9GP0l8Yr exFYh78CmR5Dw== Date: Fri, 11 Jul 2025 03:57:12 +0200 From: Alejandro Colomar To: linux-mm@kvack.org, linux-hardening@vger.kernel.org Cc: Alejandro Colomar , Kees Cook , Christopher Bazley , shadow <~hallyn/shadow@lists.sr.ht>, linux-kernel@vger.kernel.org, Andrew Morton , kasan-dev@googlegroups.com, Dmitry Vyukov , Alexander Potapenko , Marco Elver , Christoph Lameter , David Rientjes , Vlastimil Babka , Roman Gushchin , Harry Yoo , Andrew Clayton , Rasmus Villemoes , Michal Hocko , Linus Torvalds , Al Viro , Martin Uecker , Sam James , Andrew Pinski Subject: [RFC v6 6/8] array_size.h: Add ENDOF() Message-ID: <37b1088dbd01a21d2f9d460aa510726119b3bcb0.1752193588.git.alx@kernel.org> X-Mailer: git-send-email 2.50.0 References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This macro is useful to calculate the second argument to sprintf_end(), avoiding off-by-one bugs. Cc: Kees Cook Cc: Christopher Bazley Cc: Rasmus Villemoes Cc: Marco Elver Cc: Michal Hocko Cc: Linus Torvalds Cc: Al Viro Signed-off-by: Alejandro Colomar --- include/linux/array_size.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/linux/array_size.h b/include/linux/array_size.h index 06d7d83196ca..781bdb70d939 100644 --- a/include/linux/array_size.h +++ b/include/linux/array_size.h @@ -10,4 +10,10 @@ */ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(= arr)) =20 +/** + * ENDOF - get a pointer to one past the last element in array @a + * @a: array + */ +#define ENDOF(a) (a + ARRAY_SIZE(a)) + #endif /* _LINUX_ARRAY_SIZE_H */ --=20 2.50.0 From nobody Tue Oct 7 08:53:20 2025 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 A22B013D531; Fri, 11 Jul 2025 01:57:25 +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=1752199045; cv=none; b=Jrtx2xx5gkMkonxwLzEM+uDGm3BXPHYvHWRfQzaooFWxUDrgastZRL8iVoLT7DucLheCjLMUvCk5dQhys9WAWOhaeDOrky49SFsEmzu4DSlb9F5nCVVt2Y5VK5fCG9D9fPNeOSxW9a5ZBr3KqTtySODocqScpQhdPpsEKugNBgw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752199045; c=relaxed/simple; bh=wFPXfnEZslZWUhJFarJBIrU2i1EIAu502D8Y+SMDH6M=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=dKpbpgrxdbV3XbAVSWtwB6wctRXM+WNadPAYz/1+yNKoH9sY5f8IfCjDdjLfVXlGaGVdGbYVmHmz0MpYR5cueWiFQWXNbE+gZRcYP/oLHgr2Q0rie5klYZBpUCtL7Xkjie8Nfu+b148cbBhzRL3WhKi9UgolC+vyEOmzcxoYd20= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=roC9g9PB; 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="roC9g9PB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 922DFC4CEF6; Fri, 11 Jul 2025 01:57:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1752199045; bh=wFPXfnEZslZWUhJFarJBIrU2i1EIAu502D8Y+SMDH6M=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=roC9g9PB77gNhNlj66Cup0sdQVFzv8n2cuImhV6NeWw054uR2YtdJ5w3gv13YNayC T+qeUiJwBXOnpGCeA8HuQMJSBuYSrLJji3PGOyXDrykwfQzgcVhGnxXjd8G9Kw5Qd9 iieOWBYqaD2apefAviM+gfdhQlL10dMjz1T4qvZFE8Hz4gpm5cehM3ztxYUKBOfoIF Dq18+S6bwzcE2N+FPwtdb8pjhQ0Q/WYGMdH4JoeQystSeFf9zdaaetuL6UKHouVovh R7ZFtlsDBqGdDnclfYfxTgHOguR8tzufFeG0IEeesnKtzR3R4mf3TL31WxnR2eWuMO 6TfugDFBAVfJA== Date: Fri, 11 Jul 2025 03:57:18 +0200 From: Alejandro Colomar To: linux-mm@kvack.org, linux-hardening@vger.kernel.org Cc: Alejandro Colomar , Kees Cook , Christopher Bazley , shadow <~hallyn/shadow@lists.sr.ht>, linux-kernel@vger.kernel.org, Andrew Morton , kasan-dev@googlegroups.com, Dmitry Vyukov , Alexander Potapenko , Marco Elver , Christoph Lameter , David Rientjes , Vlastimil Babka , Roman Gushchin , Harry Yoo , Andrew Clayton , Rasmus Villemoes , Michal Hocko , Linus Torvalds , Al Viro , Martin Uecker , Sam James , Andrew Pinski , Jann Horn Subject: [RFC v6 7/8] mm: Fix benign off-by-one bugs Message-ID: X-Mailer: git-send-email 2.50.0 References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" We were wasting a byte due to an off-by-one bug. s[c]nprintf() doesn't write more than $2 bytes including the null byte, so trying to pass 'size-1' there is wasting one byte. Now that we use sprintf_end(), the situation isn't different: sprintf_end() will stop writing *before* 'end' --that is, at most the terminating null byte will be written at 'end-1'--. Acked-by: Marco Elver Cc: Kees Cook Cc: Christopher Bazley Cc: Alexander Potapenko Cc: Dmitry Vyukov Cc: Alexander Potapenko Cc: Jann Horn Cc: Andrew Morton Cc: Linus Torvalds Cc: Rasmus Villemoes Cc: Marco Elver Cc: Michal Hocko Cc: Al Viro Signed-off-by: Alejandro Colomar --- mm/kfence/kfence_test.c | 4 ++-- mm/kmsan/kmsan_test.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mm/kfence/kfence_test.c b/mm/kfence/kfence_test.c index bae382eca4ab..c635aa9d478b 100644 --- a/mm/kfence/kfence_test.c +++ b/mm/kfence/kfence_test.c @@ -110,7 +110,7 @@ static bool report_matches(const struct expect_report *= r) =20 /* Title */ cur =3D expect[0]; - end =3D &expect[0][sizeof(expect[0]) - 1]; + end =3D ENDOF(expect[0]); switch (r->type) { case KFENCE_ERROR_OOB: cur =3D sprintf_end(cur, end, "BUG: KFENCE: out-of-bounds %s", @@ -140,7 +140,7 @@ static bool report_matches(const struct expect_report *= r) =20 /* Access information */ cur =3D expect[1]; - end =3D &expect[1][sizeof(expect[1]) - 1]; + end =3D ENDOF(expect[1]); =20 switch (r->type) { case KFENCE_ERROR_OOB: diff --git a/mm/kmsan/kmsan_test.c b/mm/kmsan/kmsan_test.c index e48ca1972ff3..9bda55992e3d 100644 --- a/mm/kmsan/kmsan_test.c +++ b/mm/kmsan/kmsan_test.c @@ -105,7 +105,7 @@ static bool report_matches(const struct expect_report *= r) =20 /* Title */ cur =3D expected_header; - end =3D &expected_header[sizeof(expected_header) - 1]; + end =3D ENDOF(expected_header); =20 cur =3D sprintf_end(cur, end, "BUG: KMSAN: %s", r->error_type); =20 --=20 2.50.0 From nobody Tue Oct 7 08:53:20 2025 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 2E362288CC; Fri, 11 Jul 2025 01:57:31 +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=1752199052; cv=none; b=nq4atulPwFH/mHLjAFMl74tBfpO1nZ/pJ/u+/WXEkXJbCUNHNVJkmAK0pyxQa7AGyH0phyDJ4huyHQL4oEjdEfS6GDGsBiPofBk4d+0AX3kTdfcloqaakKInO8+iscmNFvs2DIxjgwBc8GLh2ILzoSfcjOvYt6+9LoJkVyVB7xU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752199052; c=relaxed/simple; bh=VJYVfYb5aKbK4eQQkUA5lmVUT/3A2ehIMDd21vB14NU=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=VDitLjZZ53RbN1uX1qJ3hUvit+8c50t5R+DY7ggrbL/paLcohm6TXrao9Lgp32YENhPQEOxXdpB6z8a88WotRwsqsP9Hk1WXoim06vM2/4YchjKKXdprMvApDTtezRpovnas27IHDtoNv93NMnBaotqVLJlNqzQ8t7NLLra0e4Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=AmQHu3Fm; 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="AmQHu3Fm" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3A25DC4CEE3; Fri, 11 Jul 2025 01:57:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1752199051; bh=VJYVfYb5aKbK4eQQkUA5lmVUT/3A2ehIMDd21vB14NU=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=AmQHu3FmSKNE0tW16KCLyS8PJ9u6i78loWUZWX6+tH+CUGh4xEzytl97R4ZQpudFK BrdiZKCqo+h8P1sBvWX5rVtOFes4MXbSKzp9Kn/DVBNAQVW/hByQhmwtso4NBaUJRF LjjQIdOxVuXrdr5qARCLtddx5TbJfIGpbN4OlKK7AYuuhcL24ILD05MUwFly7Hkgg0 Z8mVmdu2tAMjeHqOnFhnS+nnSTpH+Grgp4h60slJPRmHHO5GJGbHwh21zrMr6LBrwW JwHXpV18Bu/u7hdCNe6C0kAA5VWZW7mKF5H4R2mJUSnrcnxULXhcw6FAfOeqA0qx4U gFl9a2897/KEw== Date: Fri, 11 Jul 2025 03:57:25 +0200 From: Alejandro Colomar To: linux-mm@kvack.org, linux-hardening@vger.kernel.org Cc: Alejandro Colomar , Kees Cook , Christopher Bazley , shadow <~hallyn/shadow@lists.sr.ht>, linux-kernel@vger.kernel.org, Andrew Morton , kasan-dev@googlegroups.com, Dmitry Vyukov , Alexander Potapenko , Marco Elver , Christoph Lameter , David Rientjes , Vlastimil Babka , Roman Gushchin , Harry Yoo , Andrew Clayton , Rasmus Villemoes , Michal Hocko , Linus Torvalds , Al Viro , Martin Uecker , Sam James , Andrew Pinski Subject: [RFC v6 8/8] mm: Use [v]sprintf_array() to avoid specifying the array size Message-ID: X-Mailer: git-send-email 2.50.0 References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Cc: Rasmus Villemoes Cc: Marco Elver Cc: Michal Hocko Cc: Linus Torvalds Cc: Al Viro Signed-off-by: Alejandro Colomar --- mm/backing-dev.c | 2 +- mm/cma.c | 4 ++-- mm/cma_debug.c | 2 +- mm/hugetlb.c | 3 +-- mm/hugetlb_cgroup.c | 2 +- mm/hugetlb_cma.c | 2 +- mm/kasan/report.c | 3 +-- mm/memblock.c | 4 ++-- mm/percpu.c | 2 +- mm/shrinker_debug.c | 2 +- mm/zswap.c | 2 +- 11 files changed, 13 insertions(+), 15 deletions(-) diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 783904d8c5ef..c4e588135aea 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -1090,7 +1090,7 @@ int bdi_register_va(struct backing_dev_info *bdi, con= st char *fmt, va_list args) if (bdi->dev) /* The driver needs to use separate queues per device */ return 0; =20 - vsnprintf(bdi->dev_name, sizeof(bdi->dev_name), fmt, args); + vsprintf_array(bdi->dev_name, fmt, args); dev =3D device_create(&bdi_class, NULL, MKDEV(0, 0), bdi, bdi->dev_name); if (IS_ERR(dev)) return PTR_ERR(dev); diff --git a/mm/cma.c b/mm/cma.c index c04be488b099..61d97a387670 100644 --- a/mm/cma.c +++ b/mm/cma.c @@ -237,9 +237,9 @@ static int __init cma_new_area(const char *name, phys_a= ddr_t size, cma_area_count++; =20 if (name) - snprintf(cma->name, CMA_MAX_NAME, "%s", name); + sprintf_array(cma->name, "%s", name); else - snprintf(cma->name, CMA_MAX_NAME, "cma%d\n", cma_area_count); + sprintf_array(cma->name, "cma%d\n", cma_area_count); =20 cma->available_count =3D cma->count =3D size >> PAGE_SHIFT; cma->order_per_bit =3D order_per_bit; diff --git a/mm/cma_debug.c b/mm/cma_debug.c index fdf899532ca0..751eae9f6364 100644 --- a/mm/cma_debug.c +++ b/mm/cma_debug.c @@ -186,7 +186,7 @@ static void cma_debugfs_add_one(struct cma *cma, struct= dentry *root_dentry) rangedir =3D debugfs_create_dir("ranges", tmp); for (r =3D 0; r < cma->nranges; r++) { cmr =3D &cma->ranges[r]; - snprintf(rdirname, sizeof(rdirname), "%d", r); + sprintf_array(rdirname, "%d", r); dir =3D debugfs_create_dir(rdirname, rangedir); debugfs_create_file("base_pfn", 0444, dir, &cmr->base_pfn, &cma_debugfs_fops); diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 6a3cf7935c14..70acc8b3cbb8 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -4780,8 +4780,7 @@ void __init hugetlb_add_hstate(unsigned int order) for (i =3D 0; i < MAX_NUMNODES; ++i) INIT_LIST_HEAD(&h->hugepage_freelists[i]); INIT_LIST_HEAD(&h->hugepage_activelist); - snprintf(h->name, HSTATE_NAME_LEN, "hugepages-%lukB", - huge_page_size(h)/SZ_1K); + sprintf_array(h->name, "hugepages-%lukB", huge_page_size(h)/SZ_1K); =20 parsed_hstate =3D h; } diff --git a/mm/hugetlb_cgroup.c b/mm/hugetlb_cgroup.c index 58e895f3899a..0953cea93759 100644 --- a/mm/hugetlb_cgroup.c +++ b/mm/hugetlb_cgroup.c @@ -822,7 +822,7 @@ hugetlb_cgroup_cfttypes_init(struct hstate *h, struct c= ftype *cft, for (i =3D 0; i < tmpl_size; cft++, tmpl++, i++) { *cft =3D *tmpl; /* rebuild the name */ - snprintf(cft->name, MAX_CFTYPE_NAME, "%s.%s", buf, tmpl->name); + sprintf_array(cft->name, "%s.%s", buf, tmpl->name); /* rebuild the private */ cft->private =3D MEMFILE_PRIVATE(idx, tmpl->private); /* rebuild the file_offset */ diff --git a/mm/hugetlb_cma.c b/mm/hugetlb_cma.c index e0f2d5c3a84c..bae82a97a43c 100644 --- a/mm/hugetlb_cma.c +++ b/mm/hugetlb_cma.c @@ -211,7 +211,7 @@ void __init hugetlb_cma_reserve(int order) =20 size =3D round_up(size, PAGE_SIZE << order); =20 - snprintf(name, sizeof(name), "hugetlb%d", nid); + sprintf_array(name, "hugetlb%d", nid); /* * Note that 'order per bit' is based on smallest size that * may be returned to CMA allocator in the case of diff --git a/mm/kasan/report.c b/mm/kasan/report.c index 8357e1a33699..3b40225e7873 100644 --- a/mm/kasan/report.c +++ b/mm/kasan/report.c @@ -486,8 +486,7 @@ static void print_memory_metadata(const void *addr) char buffer[4 + (BITS_PER_LONG / 8) * 2]; char metadata[META_BYTES_PER_ROW]; =20 - snprintf(buffer, sizeof(buffer), - (i =3D=3D 0) ? ">%px: " : " %px: ", row); + sprintf_array(buffer, (i =3D=3D 0) ? ">%px: " : " %px: ", row); =20 /* * We should not pass a shadow pointer to generic diff --git a/mm/memblock.c b/mm/memblock.c index 0e9ebb8aa7fe..3eea7a177330 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -2021,7 +2021,7 @@ static void __init_memblock memblock_dump(struct memb= lock_type *type) flags =3D rgn->flags; #ifdef CONFIG_NUMA if (numa_valid_node(memblock_get_region_node(rgn))) - snprintf(nid_buf, sizeof(nid_buf), " on node %d", + sprintf_array(nid_buf, " on node %d", memblock_get_region_node(rgn)); #endif pr_info(" %s[%#x]\t[%pa-%pa], %pa bytes%s flags: %#x\n", @@ -2379,7 +2379,7 @@ int reserve_mem_release_by_name(const char *name) =20 start =3D phys_to_virt(map->start); end =3D start + map->size - 1; - snprintf(buf, sizeof(buf), "reserve_mem:%s", name); + sprintf_array(buf, "reserve_mem:%s", name); free_reserved_area(start, end, 0, buf); map->size =3D 0; =20 diff --git a/mm/percpu.c b/mm/percpu.c index b35494c8ede2..a467102c2405 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -3186,7 +3186,7 @@ int __init pcpu_page_first_chunk(size_t reserved_size= , pcpu_fc_cpu_to_node_fn_t int upa; int nr_g0_units; =20 - snprintf(psize_str, sizeof(psize_str), "%luK", PAGE_SIZE >> 10); + sprintf_array(psize_str, "%luK", PAGE_SIZE >> 10); =20 ai =3D pcpu_build_alloc_info(reserved_size, 0, PAGE_SIZE, NULL); if (IS_ERR(ai)) diff --git a/mm/shrinker_debug.c b/mm/shrinker_debug.c index 20eaee3e97f7..f529ac29557c 100644 --- a/mm/shrinker_debug.c +++ b/mm/shrinker_debug.c @@ -176,7 +176,7 @@ int shrinker_debugfs_add(struct shrinker *shrinker) return id; shrinker->debugfs_id =3D id; =20 - snprintf(buf, sizeof(buf), "%s-%d", shrinker->name, id); + sprintf_array(buf, "%s-%d", shrinker->name, id); =20 /* create debugfs entry */ entry =3D debugfs_create_dir(buf, shrinker_debugfs_root); diff --git a/mm/zswap.c b/mm/zswap.c index 204fb59da33c..e66b5c5b1ecf 100644 --- a/mm/zswap.c +++ b/mm/zswap.c @@ -271,7 +271,7 @@ static struct zswap_pool *zswap_pool_create(char *type,= char *compressor) return NULL; =20 /* unique name for each pool specifically required by zsmalloc */ - snprintf(name, 38, "zswap%x", atomic_inc_return(&zswap_pools_count)); + sprintf_array(name, "zswap%x", atomic_inc_return(&zswap_pools_count)); pool->zpool =3D zpool_create_pool(type, name, gfp); if (!pool->zpool) { pr_err("%s zpool not available\n", type); --=20 2.50.0