mirror of
https://github.com/AuxXxilium/kmod.git
synced 2024-12-20 05:27:54 +07:00
632fb7b463
In a specific configuration (chroot with the linux32 personality), the modprobe_install_cmd_loop test failed, because the bash process handling the install command segfaulted. The backtrace showed a uname() call during libpthread initialization, at which point the environ pointer hadn't been initialized yet: Program terminated with signal SIGSEGV, Segmentation fault. #0 0x080c1591 in getenv (name=<optimized out>, name@entry=0xf775f850 "TESTSUITE_UNAME_R") at getenv.c:81 81 for (i = 0, len = strlen (name); environ[i]; i++) (gdb) bt #0 0x080c1591 in getenv (name=<optimized out>, name@entry=0xf775f850 "TESTSUITE_UNAME_R") at getenv.c:81 #1 0xf775f754 in uname (u=u@entry=0xff946350) at testsuite/uname.c:32 #2 0xf74ffc6c in is_smp_system () at ../nptl/sysdeps/unix/sysv/linux/i386/smp.h:39 #3 __pthread_initialize_minimal_internal () at nptl-init.c:460 #4 0xf74fe32c in _init () at ../sysdeps/i386/crti.S:74 #5 0x00000000 in ?? () (gdb) p environ $1 = (char **) 0x0 I don't know why it only happend in the chroot, but glibc can call its own functions and impose any restrictions before main() is started, so we have to adapt. Also, do not return error if there is an environment, but the environment variable is not found. If uname() is called by kmod, then the respective test will simply fail later. If it's something else calling uname(), then we do not want to disturb the program.
76 lines
1.9 KiB
C
76 lines
1.9 KiB
C
/*
|
|
* Copyright (C) 2012-2013 ProFUSION embedded systems
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include <errno.h>
|
|
#include <dlfcn.h>
|
|
#include <sys/utsname.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
|
|
#include "testsuite.h"
|
|
|
|
TS_EXPORT int uname(struct utsname *u)
|
|
{
|
|
static void *nextlib = NULL;
|
|
static int (*nextlib_uname)(struct utsname *u);
|
|
const char *release;
|
|
int err;
|
|
size_t sz;
|
|
|
|
if (nextlib == NULL) {
|
|
#ifdef RTLD_NEXT
|
|
nextlib = RTLD_NEXT;
|
|
#else
|
|
nextlib = dlopen("libc.so.6", RTLD_LAZY);
|
|
#endif
|
|
nextlib_uname = dlsym(nextlib, "uname");
|
|
}
|
|
|
|
err = nextlib_uname(u);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
if (!environ)
|
|
/*
|
|
* probably called from within glibc before main(); unsafe
|
|
* to call getenv()
|
|
*/
|
|
return 0;
|
|
|
|
release = getenv(S_TC_UNAME_R);
|
|
if (release == NULL) {
|
|
fprintf(stderr, "TRAP uname(): missing export %s?\n",
|
|
S_TC_UNAME_R);
|
|
return 0;
|
|
}
|
|
|
|
sz = strlen(release) + 1;
|
|
if (sz > sizeof(u->release)) {
|
|
fprintf(stderr, "uname(): sizeof release (%s) "
|
|
"is greater than available space: %zu",
|
|
release, sizeof(u->release));
|
|
errno = -EFAULT;
|
|
return -1;
|
|
}
|
|
|
|
memcpy(u->release, release, sz);
|
|
return 0;
|
|
}
|