-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
include/libzutil.h: fix misuse of strerror_l() #16916
Conversation
According to the POSIX man pages: "The behavior is undefined if the locale argument to strerror_l() is the special locale object LC_GLOBAL_LOCALE or is not a valid locale object handle." Since uselocale() could return LC_GLOBAL_LOCALE, the value must be checked before passing it to strerror_l(). This fixes a segmentation fault on systems with the musl libc. Signed-off-by: Roberto Ricci <[email protected]>
Signed-off-by: Roberto Ricci <[email protected]>
The segmentation fault on musl systems occurs during the boot process, when The same command works fine with zfs 2.2.6 and the current master branch. |
It seems to be a fallout from #15793. @rkojedzinszky @mcmilk ^^^. I don't know this area, but I suspect that |
The original intent here was to make zfs_strerror() a thread-safe function. Now as it has faults, and some of the fixes make the code behave the original way (non-thread safe), I think there is no point to keep this function as is right now. Either we should revert the first commit, or fix in a way that it really becomes thread safe. |
You are right, after all the whole point of I tried to read the documentation more carefully. The correct use of these interfaces should be something like this: locale_t loc, ret;
// create a new locale object
loc = newlocale(LC_ALL_MASK, "", (locale_t) 0);
if (loc == (locale_t) 0) {
// error
}
ret = newlocale(LC_NUMERIC_MASK, "C", loc);
if (ret == (locale_t) 0) {
freelocale(loc);
// error
}
loc = ret;
// set the locale
ret = uselocale(loc);
freelocale(loc);
if (ret == (locale_t) 0) {
// error
}
// query the locale
loc = uselocale(0);
if (loc == LC_GLOBAL_LOCALE) {
// error
} else if (loc == (locale_t) 0) {
// error
} else {
strerror_l(errnum, loc);
} My patch is incomplete also because |
Reading opengroup specs further, it is also possible that strerror() itself returns an error. strerror_l() can even return null. https://pubs.opengroup.org/onlinepubs/9799919799/functions/strerror.html# |
Or, after setting the locale with |
I've started reading actual libc implementation. Very simple, at least in FreeBSD: https://github.com/freebsd/freebsd-src/blob/main/lib/libc/string/strerror.c#L125. What if we simply create a thread local buffer (the same in with strerror_l()), call strerror() with a mutex held, and copying its result to the thread-local buffer, then release the mutex? That would preserve original strerror() behavior truly, and we could get thread-safety as well. |
Something like this?
|
Since we already depend on thread local variables in a few places that's probably a workable way to handle this. |
Resolved. Applied the change from #16923 for this issue. |
According to the POSIX man pages:
"The behavior is undefined if the locale argument to strerror_l() is the special locale object LC_GLOBAL_LOCALE or is not a valid locale object handle."
Since uselocale() could return LC_GLOBAL_LOCALE, the value must be checked before passing it to strerror_l().
This fixes a segmentation fault on systems with the musl libc.
How Has This Been Tested?
Types of changes
Checklist:
Signed-off-by
.