From: "A. Wilcox" <AWilcox@Wilcox-Tech.com>
To: "Darrick J. Wong" <djwong@kernel.org>
Cc: Andrey Albershteyn <aalbersh@redhat.com>,
Christoph Hellwig <hch@infradead.org>,
linux-xfs@vger.kernel.org
Subject: Re: [PATCH v2] xfs_scrub: fix strerror_r usage yet again
Date: Sat, 20 Sep 2025 06:21:59 -0500 [thread overview]
Message-ID: <BD23D489-C187-4100-89D4-D8159B23A385@Wilcox-Tech.com> (raw)
In-Reply-To: <20250919161400.GO8096@frogsfrogsfrogs>
> On Sep 19, 2025, at 11:14, Darrick J. Wong <djwong@kernel.org> wrote:
>
> 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 GNU version can return any random
> pointer, 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>
> ---
> v2: go the autoconf route
> ---
> configure.ac | 1 +
> include/builddefs.in | 1 +
> m4/package_libcdev.m4 | 46 ++++++++++++++++++++++++++++++++++++++++++++++
> scrub/Makefile | 4 ++++
> scrub/common.c | 8 ++++++--
> 5 files changed, 58 insertions(+), 2 deletions(-)
>
> diff --git a/configure.ac b/configure.ac
> index d2407cb5de5af2..df19379b02ba55 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -183,6 +183,7 @@ AC_CONFIG_CROND_DIR
> AC_CONFIG_UDEV_RULE_DIR
> AC_HAVE_BLKID_TOPO
> AC_HAVE_TRIVIAL_AUTO_VAR_INIT
> +AC_STRERROR_R_RETURNS_STRING
>
> if test "$enable_ubsan" = "yes" || test "$enable_ubsan" = "probe"; then
> AC_PACKAGE_CHECK_UBSAN
> diff --git a/include/builddefs.in b/include/builddefs.in
> index 93b5c75155c0f4..5aa5742bb31b9e 100644
> --- a/include/builddefs.in
> +++ b/include/builddefs.in
> @@ -241,6 +241,7 @@ CROND_DIR = @crond_dir@
> HAVE_UDEV = @have_udev@
> UDEV_RULE_DIR = @udev_rule_dir@
> HAVE_LIBURCU_ATOMIC64 = @have_liburcu_atomic64@
> +STRERROR_R_RETURNS_STRING = @strerror_r_returns_string@
>
> GCCFLAGS = -funsigned-char -fno-strict-aliasing -Wall -Werror -Wextra -Wno-unused-parameter
> # -Wbitwise -Wno-transparent-union -Wno-old-initializer -Wno-decl
> diff --git a/m4/package_libcdev.m4 b/m4/package_libcdev.m4
> index ce1ba47264659c..c5538c30d2518a 100644
> --- a/m4/package_libcdev.m4
> +++ b/m4/package_libcdev.m4
> @@ -301,3 +301,49 @@ syscall(__NR_file_getattr, 0, 0, 0, 0, 0);
> AC_MSG_RESULT(no))
> AC_SUBST(have_file_getattr)
> ])
> +
> +#
> +# Check if strerror_r returns an int, as opposed to a char *, because there are
> +# two versions of this function, with differences that are hard to detect.
> +#
> +# GNU strerror_r returns a pointer to a string on success, but the returned
> +# pointer might point to a static buffer and not buf, so you have to use the
> +# return value. The declaration has the __warn_unused_result__ attribute to
> +# enforce this.
> +#
> +# XSI strerror_r always writes to buf and returns 0 on success, -1 on error.
> +#
> +# How do you select a particular version? By defining macros, of course!
> +# _GNU_SOURCE always gets you the GNU version, and _POSIX_C_SOURCE >= 200112L
> +# gets you the XSI version but only if _GNU_SOURCE isn't defined.
> +#
> +# 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.
> +# Not definining _GNU_SOURCE breaks the build in many areas, so we'll create
> +# yet another #define for just this weird quirk so that we can patch around it
> +# in the one place we need it.
> +#
> +# Note that we have to force erroring out on the int conversion warnings
> +# because C doesn't consider it a hard error to cast a char pointer to an int
> +# even when CFLAGS contains -std=gnu11.
> +AC_DEFUN([AC_STRERROR_R_RETURNS_STRING],
> + [AC_MSG_CHECKING([if strerror_r returns char *])
> + OLD_CFLAGS="$CFLAGS"
> + CFLAGS="$CFLAGS -Wall -Werror"
> + AC_LINK_IFELSE(
> + [AC_LANG_PROGRAM([[
> +#define _GNU_SOURCE
> +#include <stdio.h>
> +#include <string.h>
> + ]], [[
> +char buf[1024];
> +puts(strerror_r(0, buf, sizeof(buf)));
> + ]])
> + ],
> + strerror_r_returns_string=yes
> + AC_MSG_RESULT(yes),
> + AC_MSG_RESULT(no))
> + CFLAGS="$OLD_CFLAGS"
> + AC_SUBST(strerror_r_returns_string)
> + ])
> diff --git a/scrub/Makefile b/scrub/Makefile
> index 3636a47942e98e..6375d77a291bcb 100644
> --- a/scrub/Makefile
> +++ b/scrub/Makefile
> @@ -105,6 +105,10 @@ CFILES += unicrash.c
> LCFLAGS += -DHAVE_LIBICU $(LIBICU_CFLAGS)
> endif
>
> +ifeq ($(STRERROR_R_RETURNS_STRING),yes)
> +LCFLAGS += -DSTRERROR_R_RETURNS_STRING
> +endif
> +
> # Automatically trigger a media scan once per month
> XFS_SCRUB_ALL_AUTO_MEDIA_SCAN_INTERVAL=1mo
>
> diff --git a/scrub/common.c b/scrub/common.c
> index 9437d0abb8698b..9a33e2a9d54ed4 100644
> --- a/scrub/common.c
> +++ b/scrub/common.c
> @@ -126,8 +126,12 @@ __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);
> +#ifdef STRERROR_R_RETURNS_STRING
> + fprintf(stream, _("%s."), strerror_r(error, buf, DESCR_BUFSZ));
> +#else
> + if (strerror_r(error, buf, DESCR_BUFSZ) == 0)
> + fprintf(stream, _("%s."), buf);
> +#endif
> } else {
> va_start(args, format);
> vfprintf(stream, format, args);
I did check *build* on glibc, but I don’t think mine had warn_unused_result yet.
(It’s an older version.)
Thanks for fixing this, looks good to me.
The commit message isn’t accurate any more though.
Reviewed-by: A. Wilcox <AWilcox@Wilcox-Tech.com>
next prev parent reply other threads:[~2025-09-20 11:29 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-19 16:14 [PATCH v2] xfs_scrub: fix strerror_r usage yet again Darrick J. Wong
2025-09-20 11:21 ` A. Wilcox [this message]
2025-09-22 17:01 ` Christoph Hellwig
2025-09-24 0:53 ` Darrick J. Wong
2025-09-25 7:23 ` Christoph Hellwig
2025-09-25 20:04 ` Darrick J. Wong
2025-09-25 20:58 ` Holger Hoffstätte
2025-09-26 16:27 ` Darrick J. Wong
2025-10-03 10:07 ` Andrey Albershteyn
2025-09-29 6:34 ` Christoph Hellwig
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=BD23D489-C187-4100-89D4-D8159B23A385@Wilcox-Tech.com \
--to=awilcox@wilcox-tech.com \
--cc=aalbersh@redhat.com \
--cc=djwong@kernel.org \
--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