Linux XFS filesystem development
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <djwong@kernel.org>
To: "A. Wilcox" <AWilcox@wilcox-tech.com>,
	Andrey Albershteyn <aalbersh@redhat.com>
Cc: Christoph Hellwig <hch@infradead.org>, linux-xfs@vger.kernel.org
Subject: [PATCH] xfs_scrub: fix strerror_r usage yet again
Date: Thu, 18 Sep 2025 12:48:36 -0700	[thread overview]
Message-ID: <20250918194836.GK8096@frogsfrogsfrogs> (raw)

From: Darrick J. Wong <djwong@kernel.org>

In commit 75faf2bc907584, someone tried to fix scrub to use the POSIX
version of strerror_r so that the build would work with musl.
Unfortunately, neither the author nor myself remembered that GNU libc
imposes its own version any time _GNU_SOURCE is defined, which
builddefs.in always does.  Regrettably, the POSIX and GNU versions have
different return types and the glibc version can return any random
pointer and ignore the buffer, so now this code is broken on glibc.

"Fix" this standards body own goal by casting the return value to
intptr_t and employing some gross heuristics to guess at the location of
the actual error string.

Fixes: 75faf2bc907584 ("xfs_scrub: Use POSIX-conformant strerror_r")
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
 scrub/common.c |   27 +++++++++++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/scrub/common.c b/scrub/common.c
index 0a5970f9c066f7..030beadb1767fb 100644
--- a/scrub/common.c
+++ b/scrub/common.c
@@ -126,8 +126,31 @@ __str_out(
 	fprintf(stream, "%s%s: %s: ", stream_start(stream),
 			_(err_levels[level].string), descr);
 	if (error) {
-		strerror_r(error, buf, DESCR_BUFSZ);
-		fprintf(stream, _("%s."), buf);
+		intptr_t res;
+
+		/*
+		 * GNU strerror_r returns a pointer to a string on success, but
+		 * the returned pointer might point to a static buffer and not
+		 * buf.  XSI strerror_r returns 0 on success, -1 on error.
+		 * Magic #defines influence which variant you might get.
+		 *
+		 * The build system #defines _GNU_SOURCE unconditionally, so
+		 * when compiling against glibc we get the GNU version.
+		 * However, when compiling against musl, the _GNU_SOURCE
+		 * definition does nothing and we get the XSI version anyway.
+		 *
+		 * To handle all this, we set buf to an empty string, and if
+		 * the function returns zero but buf now contains a non-empty
+		 * string, we assume the XSI version and print buf.  If the
+		 * function returns a positive value, we assume that's a
+		 * pointer to a string and print whatever the return value is.
+		 */
+		buf[0] = 0;
+		res = (intptr_t)strerror_r(error, buf, DESCR_BUFSZ);
+		if (res == 0 && strlen(buf) > 0)
+			fprintf(stream, _("%s."), buf);
+		else if (res > 0)
+			fprintf(stream, _("%s."), (char *)res);
 	} else {
 		va_start(args, format);
 		vfprintf(stream, format, args);

             reply	other threads:[~2025-09-18 19:48 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-09-18 19:48 Darrick J. Wong [this message]
2025-09-19 14:47 ` [PATCH] xfs_scrub: fix strerror_r usage yet again Christoph Hellwig
2025-09-19 16:06   ` Darrick J. Wong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250918194836.GK8096@frogsfrogsfrogs \
    --to=djwong@kernel.org \
    --cc=AWilcox@wilcox-tech.com \
    --cc=aalbersh@redhat.com \
    --cc=hch@infradead.org \
    --cc=linux-xfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox