testsuite: fix override of stat on 32-bit architectures

When _FILE_OFFSET_BITS is 64, glibc headers turn `stat` calls into
`stat64`, and our `stat` override into a `stat64` function.  However,
because we use dlsym to get the address of libc's `stat`, we end up
calling into the "real" `stat` function, which deals with 32-bit off_t,
and we treat its result as if it were returned from stat64.  On most
architectures this seems to have been harmless, but on 32-bit mips,
st_mode's offset in struct stat and struct stat64 are different, so we
read garbage.

To fix this, explicitly unset _FILE_OFFSET_BITS in path.c, to turn off
the redirect magic in glibc headers, and override both the 32-bit and
64-bit functions so each call ends up wrapping the right libc function.

Fixes #16 (https://github.com/kmod-project/kmod/issues/16)
This commit is contained in:
Julien Cristau 2022-09-05 10:32:12 +02:00 committed by Lucas De Marchi
parent c1fb98a30d
commit b4d281f962

View File

@ -15,6 +15,10 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>. * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/ */
/* We unset _FILE_OFFSET_BITS here so we can override both stat and stat64 on
* 32-bit architectures and forward each to the right libc function */
#undef _FILE_OFFSET_BITS
#include <assert.h> #include <assert.h>
#include <dirent.h> #include <dirent.h>
#include <dlfcn.h> #include <dlfcn.h>
@ -183,23 +187,20 @@ TS_EXPORT int prefix ## stat ## suffix (int ver, \
WRAP_1ARG(DIR*, NULL, opendir); WRAP_1ARG(DIR*, NULL, opendir);
WRAP_2ARGS(FILE*, NULL, fopen, const char*); WRAP_2ARGS(FILE*, NULL, fopen, const char*);
WRAP_2ARGS(FILE*, NULL, fopen64, const char*);
WRAP_2ARGS(int, -1, mkdir, mode_t); WRAP_2ARGS(int, -1, mkdir, mode_t);
WRAP_2ARGS(int, -1, access, int); WRAP_2ARGS(int, -1, access, int);
WRAP_2ARGS(int, -1, stat, struct stat*); WRAP_2ARGS(int, -1, stat, struct stat*);
WRAP_2ARGS(int, -1, lstat, struct stat*); WRAP_2ARGS(int, -1, lstat, struct stat*);
#ifndef _FILE_OFFSET_BITS
WRAP_2ARGS(int, -1, stat64, struct stat64*); WRAP_2ARGS(int, -1, stat64, struct stat64*);
WRAP_2ARGS(int, -1, lstat64, struct stat64*); WRAP_2ARGS(int, -1, lstat64, struct stat64*);
WRAP_OPEN(64); WRAP_OPEN(64);
#endif
WRAP_OPEN(); WRAP_OPEN();
#ifdef HAVE___XSTAT #ifdef HAVE___XSTAT
WRAP_VERSTAT(__x,); WRAP_VERSTAT(__x,);
WRAP_VERSTAT(__lx,); WRAP_VERSTAT(__lx,);
#ifndef _FILE_OFFSET_BITS
WRAP_VERSTAT(__x,64); WRAP_VERSTAT(__x,64);
WRAP_VERSTAT(__lx,64); WRAP_VERSTAT(__lx,64);
#endif #endif
#endif