diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0cdb0ea04f49acf5c3933bf42376cd575b340f10..1a4a3b0908f8eb38745da3ab4063366d209f020d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,3 +1,4 @@ +--- variables: GIT_DEPTH: 3 BUILD_IMAGES_PROJECT: cmocka/gitlab-build-images @@ -7,18 +8,24 @@ variables: MINGW_BUILD: buildenv-mingw UBUNTU_BUILD: buildenv-ubuntu +stages: + - build + - test + - analysis + centos7/x86_64: + stage: test image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS7_BUILD script: - - mkdir -p obj && cd obj && cmake3 - -DCMAKE_BUILD_TYPE=RelWithDebInfo - -DPICKY_DEVELOPER=ON - -DUNIT_TESTING=ON .. && - make -j$(nproc) && ctest --output-on-failure + - mkdir -p obj && cd obj && cmake3 + -DCMAKE_BUILD_TYPE=RelWithDebInfo + -DPICKY_DEVELOPER=ON + -DUNIT_TESTING=ON .. && + make -j$(nproc) && ctest --output-on-failure tags: - - shared + - shared except: - - tags + - tags artifacts: expire_in: 1 week when: on_failure @@ -26,18 +33,19 @@ centos7/x86_64: - obj/ fedora/x86_64: + stage: test image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD script: - - mkdir -p obj && cd obj && cmake - -DCMAKE_INSTALL_PREFIX=/tmp/local - -DCMAKE_BUILD_TYPE=RelWithDebInfo - -DPICKY_DEVELOPER=ON - -DUNIT_TESTING=ON .. && - make -j$(nproc) && ctest --output-on-failure && make install + - mkdir -p obj && cd obj && cmake + -DCMAKE_INSTALL_PREFIX=/tmp/local + -DCMAKE_BUILD_TYPE=RelWithDebInfo + -DPICKY_DEVELOPER=ON + -DUNIT_TESTING=ON .. && + make -j$(nproc) && ctest --output-on-failure && make install tags: - - shared + - shared except: - - tags + - tags artifacts: expire_in: 1 week when: on_failure @@ -45,17 +53,18 @@ fedora/x86_64: - obj/ fedora/address-sanitizer: + stage: build image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD script: - - mkdir -p obj && cd obj && cmake - -DCMAKE_BUILD_TYPE=AddressSanitizer - -DPICKY_DEVELOPER=ON - -DUNIT_TESTING=ON .. && - make -j$(nproc) && ctest --output-on-failure + - mkdir -p obj && cd obj && cmake + -DCMAKE_BUILD_TYPE=AddressSanitizer + -DPICKY_DEVELOPER=ON + -DUNIT_TESTING=ON .. && + make -j$(nproc) && ctest --output-on-failure tags: - - shared + - shared except: - - tags + - tags artifacts: expire_in: 1 week when: on_failure @@ -63,16 +72,36 @@ fedora/address-sanitizer: - obj/ fedora/undefined-sanitizer: + stage: analysis image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD script: - - mkdir -p obj && cd obj && cmake - -DCMAKE_BUILD_TYPE=UndefinedSanitizer - -DUNIT_TESTING=ON .. - && make -j$(nproc) && ctest --output-on-failure + - mkdir -p obj && cd obj && cmake + -DCMAKE_BUILD_TYPE=UndefinedSanitizer + -DUNIT_TESTING=ON .. + && make -j$(nproc) && ctest --output-on-failure + tags: + - shared + except: + - tags + artifacts: + expire_in: 1 week + when: on_failure + paths: + - obj/ + +fedora/thread-sanitizer: + stage: analysis + image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD + script: + - mkdir -p obj && cd obj && cmake + -DCMAKE_BUILD_TYPE=ThreadSanitizer + -DPICKY_DEVELOPER=ON + -DUNIT_TESTING=ON .. && + make -j$(nproc) && ctest --output-on-failure tags: - - shared + - shared except: - - tags + - tags artifacts: expire_in: 1 week when: on_failure @@ -80,32 +109,33 @@ fedora/undefined-sanitizer: - obj/ fedora/csbuild: + stage: analysis variables: GIT_DEPTH: 20 image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD script: - - | - if [[ -z "$CI_COMMIT_BEFORE_SHA" ]]; then - export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~15") - fi - - # Check if the commit exists in this branch - # This is not the case for a force push - git branch --contains $CI_COMMIT_BEFORE_SHA 2>/dev/null || export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~15") - - export CI_COMMIT_RANGE="$CI_COMMIT_BEFORE_SHA..$CI_COMMIT_SHA" - - - csbuild - --build-dir=obj-csbuild - --prep-cmd="cmake -DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON @SRCDIR@" - --build-cmd "make clean && make -j$(nproc)" - --git-commit-range $CI_COMMIT_RANGE - --color - --print-current --print-fixed + - | + if [[ -z "$CI_COMMIT_BEFORE_SHA" ]]; then + export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~15") + fi + + # Check if the commit exists in this branch + # This is not the case for a force push + git branch --contains $CI_COMMIT_BEFORE_SHA 2>/dev/null || export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~15") + + export CI_COMMIT_RANGE="$CI_COMMIT_BEFORE_SHA..$CI_COMMIT_SHA" + + - csbuild + --build-dir=obj-csbuild + --prep-cmd="cmake -DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON @SRCDIR@" + --build-cmd "make clean && make -j$(nproc)" + --git-commit-range $CI_COMMIT_RANGE + --color + --print-current --print-fixed tags: - - shared + - shared except: - - tags + - tags artifacts: expire_in: 1 week when: on_failure @@ -113,20 +143,22 @@ fedora/csbuild: - obj-csbuild/ freebsd/x86_64: + stage: test image: script: - - mkdir -p obj && cd obj && cmake - -DCMAKE_BUILD_TYPE=RelWithDebInfo - -DPICKY_DEVELOPER=ON - -DUNIT_TESTING=ON .. && - make && ctest --output-on-failure + - mkdir -p obj && cd obj && cmake + -DCMAKE_BUILD_TYPE=RelWithDebInfo + -DPICKY_DEVELOPER=ON + -DUNIT_TESTING=ON .. && + make && ctest --output-on-failure tags: - - freebsd + - freebsd except: - - tags + - tags only: - - branches@cwrap/uid_wrapper - - branches@cryptomilk/uid_wrapper + - branches@cwrap/uid_wrapper + - branches@cryptomilk/uid_wrapper + - branches@metze/uid_wrapper artifacts: expire_in: 1 week when: on_failure @@ -134,17 +166,18 @@ freebsd/x86_64: - obj/ tumbleweed/x86_64/gcc: + stage: test image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD script: - - mkdir -p obj && cd obj && cmake - -DCMAKE_BUILD_TYPE=RelWithDebInfo - -DPICKY_DEVELOPER=ON - -DUNIT_TESTING=ON .. && - make -j$(nproc) && ctest --output-on-failure + - mkdir -p obj && cd obj && cmake + -DCMAKE_BUILD_TYPE=RelWithDebInfo + -DPICKY_DEVELOPER=ON + -DUNIT_TESTING=ON .. && + make -j$(nproc) && ctest --output-on-failure tags: - - shared + - shared except: - - tags + - tags artifacts: expire_in: 1 week when: on_failure @@ -152,18 +185,19 @@ tumbleweed/x86_64/gcc: - obj/ tumbleweed/x86_64/gcc7: + stage: test image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD script: - - mkdir -p obj && cd obj && cmake - -DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7 - -DCMAKE_BUILD_TYPE=RelWithDebInfo - -DPICKY_DEVELOPER=ON - -DUNIT_TESTING=ON .. && - make -j$(nproc) && ctest --output-on-failure + - mkdir -p obj && cd obj && cmake + -DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7 + -DCMAKE_BUILD_TYPE=RelWithDebInfo + -DPICKY_DEVELOPER=ON + -DUNIT_TESTING=ON .. && + make -j$(nproc) && ctest --output-on-failure tags: - - shared + - shared except: - - tags + - tags artifacts: expire_in: 1 week when: on_failure @@ -171,18 +205,19 @@ tumbleweed/x86_64/gcc7: - obj/ tumbleweed/x86_64/clang: + stage: test image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD script: - - mkdir -p obj && cd obj && cmake - -DCMAKE_BUILD_TYPE=RelWithDebInfo - -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ - -DPICKY_DEVELOPER=ON - -DUNIT_TESTING=ON .. && - make -j$(nproc) && ctest --output-on-failure + - mkdir -p obj && cd obj && cmake + -DCMAKE_BUILD_TYPE=RelWithDebInfo + -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ + -DPICKY_DEVELOPER=ON + -DUNIT_TESTING=ON .. && + make -j$(nproc) && ctest --output-on-failure tags: - - shared + - shared except: - - tags + - tags artifacts: expire_in: 1 week when: on_failure @@ -190,20 +225,21 @@ tumbleweed/x86_64/clang: - obj/ tumbleweed/static-analysis: + stage: analysis image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD script: - - export CCC_CC=clang - - export CCC_CXX=clang++ - - mkdir -p obj && cd obj && scan-build cmake - -DCMAKE_BUILD_TYPE=Debug - -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ - -DPICKY_DEVELOPER=ON - -DUNIT_TESTING=ON .. && - scan-build --status-bugs -o scan make -j$(nproc) + - export CCC_CC=clang + - export CCC_CXX=clang++ + - mkdir -p obj && cd obj && scan-build cmake + -DCMAKE_BUILD_TYPE=Debug + -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ + -DPICKY_DEVELOPER=ON + -DUNIT_TESTING=ON .. && + scan-build --status-bugs -o scan make -j$(nproc) tags: - - shared + - shared except: - - tags + - tags artifacts: expire_in: 1 week when: on_failure @@ -211,17 +247,18 @@ tumbleweed/static-analysis: - obj/scan ubuntu/x86_64: + stage: test image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$UBUNTU_BUILD script: - - mkdir -p obj && cd obj && cmake - -DCMAKE_BUILD_TYPE=RelWithDebInfo - -DPICKY_DEVELOPER=ON - -DUNIT_TESTING=ON .. && - make -j$(nproc) && ctest --output-on-failure + - mkdir -p obj && cd obj && cmake + -DCMAKE_BUILD_TYPE=RelWithDebInfo + -DPICKY_DEVELOPER=ON + -DUNIT_TESTING=ON .. && + make -j$(nproc) && ctest --output-on-failure tags: - - shared + - shared except: - - tags + - tags artifacts: expire_in: 1 week when: on_failure diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake index e299f6e49fb3144f08a7eb3774dd80c06f4e2152..32011318060e501de079ca57a5d2cd231fa3a6cc 100644 --- a/ConfigureChecks.cmake +++ b/ConfigureChecks.cmake @@ -68,6 +68,8 @@ check_function_exists(getgroups HAVE_GETGROUPS) check_function_exists(__getgroups_chk HAVE___GETGROUPS_CHK) check_function_exists(setgroups HAVE_SETGROUPS) +check_function_exists(getprogname HAVE_GETPROGNAME) + if (HAVE_SETGROUPS) check_prototype_definition(setgroups "int setgroups(int size, const gid_t *list)" diff --git a/cmake/Modules/DefineCompilerFlags.cmake b/cmake/Modules/DefineCompilerFlags.cmake index 3277b990b6f50b28f4580660feed330f96990348..c92182d570406a6bde9b1113635891cee92adb31 100644 --- a/cmake/Modules/DefineCompilerFlags.cmake +++ b/cmake/Modules/DefineCompilerFlags.cmake @@ -34,4 +34,16 @@ if (UNIX AND NOT WIN32) CACHE STRING "Flags used by the linker during the creation of shared libraries during UNDEFINEDSANITIZER builds.") set(CMAKE_EXEC_LINKER_FLAGS_UNDEFINEDSANITIZER "-fsanitize=undefined" CACHE STRING "Flags used by the linker during UNDEFINEDSANITIZER builds.") + + # Activate with: -DCMAKE_BUILD_TYPE=ThreadSanitizer + set(CMAKE_C_FLAGS_THREADSANITIZER "-g -O1 -fsanitize=thread" + CACHE STRING "Flags used by the C compiler during THREADSANITIZER builds.") + set(CMAKE_CXX_FLAGS_THREADSANITIZER "-g -O1 -fsanitize=thread" + CACHE STRING "Flags used by the CXX compiler during THREADSANITIZER builds.") + set(CMAKE_SHARED_LINKER_FLAGS_THREADSANITIZER "-fsanitize=thread" + CACHE STRING "Flags used by the linker during the creation of shared libraries during THREADSANITIZER builds.") + set(CMAKE_MODULE_LINKER_FLAGS_THREADSANITIZER "-fsanitize=thread" + CACHE STRING "Flags used by the linker during the creation of shared libraries during THREADSANITIZER builds.") + set(CMAKE_EXEC_LINKER_FLAGS_THREADSANITIZER "-fsanitize=thread" + CACHE STRING "Flags used by the linker during THREADSANITIZER builds.") endif() diff --git a/config.h.cmake b/config.h.cmake index 5b342e3a15bb0a5c081c54844c19ae934fb2a8a4..dde70ec3eeaf8986340446026198a8f506d94b1d 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -53,6 +53,9 @@ #cmakedefine HAVE_SYSCALL 1 #cmakedefine HAVE_SYSCALL_INT 1 +/* Define to 1 if you have the `getprogname' function. */ +#cmakedefine HAVE_GETPROGNAME 1 + /*************************** LIBRARIES ***************************/ /**************************** OPTIONS ****************************/ diff --git a/src/uid_wrapper.c b/src/uid_wrapper.c index f04642af11a143a9e610b2b31225edd8012a1a81..16c03c966e8bc6bee4c0fa281092d08922596ccd 100644 --- a/src/uid_wrapper.c +++ b/src/uid_wrapper.c @@ -44,25 +44,6 @@ # define UWRAP_THREAD #endif -# define UWRAP_LOCK(m) do { \ - pthread_mutex_lock(&( m ## _mutex)); \ -} while(0) - -# define UWRAP_UNLOCK(m) do { \ - pthread_mutex_unlock(&( m ## _mutex)); \ -} while(0) - -/* Add new global locks here please */ -# define UWRAP_LOCK_ALL \ - UWRAP_LOCK(uwrap_id); \ - UWRAP_LOCK(libc_symbol_binding); \ - UWRAP_LOCK(libpthread_symbol_binding) - -# define UWRAP_UNLOCK_ALL \ - UWRAP_UNLOCK(libpthread_symbol_binding); \ - UWRAP_UNLOCK(libc_symbol_binding); \ - UWRAP_UNLOCK(uwrap_id) - #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE #define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor)) #else @@ -142,6 +123,19 @@ enum uwrap_dbglvl_e { UWRAP_LOG_TRACE }; +#ifndef HAVE_GETPROGNAME +static const char *getprogname(void) +{ +#if defined(HAVE_PROGRAM_INVOCATION_SHORT_NAME) + return program_invocation_short_name; +#elif defined(HAVE_GETEXECNAME) + return getexecname(); +#else + return NULL; +#endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */ +} +#endif /* HAVE_GETPROGNAME */ + static void uwrap_log(enum uwrap_dbglvl_e dbglvl, const char *function, const char *format, ...) PRINTF_ATTRIBUTE(3, 4); # define UWRAP_LOG(dbglvl, ...) uwrap_log((dbglvl), __func__, __VA_ARGS__) @@ -152,6 +146,7 @@ static void uwrap_log(enum uwrap_dbglvl_e dbglvl, const char *function, const ch const char *d; unsigned int lvl = 0; const char *prefix = "UWRAP"; + const char *progname = getprogname(); d = getenv("UID_WRAPPER_DEBUGLEVEL"); if (d != NULL) { @@ -181,9 +176,14 @@ static void uwrap_log(enum uwrap_dbglvl_e dbglvl, const char *function, const ch break; } + if (progname == NULL) { + progname = ""; + } + fprintf(stderr, - "%s(%d) - %s: %s\n", + "%s[%s (%u)] - %s: %s\n", prefix, + progname, (int)getpid(), function, buffer); @@ -298,6 +298,27 @@ struct uwrap_libc_symbols { }; #undef UWRAP_SYMBOL_ENTRY +#define UWRAP_SYMBOL_ENTRY(i) \ + union { \ + __rtld_default_##i f; \ + void *obj; \ + } _rtld_default_##i + +#ifdef HAVE_SYSCALL +typedef bool (*__rtld_default_socket_wrapper_syscall_valid)(long int sysno); +typedef long int (*__rtld_default_socket_wrapper_syscall_va)(long int sysno, va_list va); +#endif + +struct uwrap_rtld_default_symbols { +#ifdef HAVE_SYSCALL + UWRAP_SYMBOL_ENTRY(socket_wrapper_syscall_valid); + UWRAP_SYMBOL_ENTRY(socket_wrapper_syscall_va); +#else + uint8_t dummy; +#endif +}; +#undef UWRAP_SYMBOL_ENTRY + /***************** * LIBPTHREAD *****************/ @@ -347,6 +368,10 @@ struct uwrap { struct uwrap_libc_symbols symbols; } libc; + struct { + struct uwrap_rtld_default_symbols symbols; + } rtld_default; + struct { void *handle; struct uwrap_libpthread_symbols symbols; @@ -369,11 +394,85 @@ static UWRAP_THREAD struct uwrap_thread *uwrap_tls_id; /* The mutex or accessing the id */ static pthread_mutex_t uwrap_id_mutex = PTHREAD_MUTEX_INITIALIZER; -/* The mutex for accessing the global libc.symbols */ -static pthread_mutex_t libc_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER; +#define uwrap_init_mutex(m) _uwrap_init_mutex(m, #m) +static int _uwrap_init_mutex(pthread_mutex_t *m, const char *name) +{ + pthread_mutexattr_t ma; + bool need_destroy = false; + int ret = 0; -/* The mutex for accessing the global libpthread.symbols */ -static pthread_mutex_t libpthread_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER; +#define __CHECK(cmd) do { \ + ret = cmd; \ + if (ret != 0) { \ + UWRAP_LOG(UWRAP_LOG_ERROR, \ + "%s: %s - failed %d", \ + name, #cmd, ret); \ + goto done; \ + } \ +} while(0) + + *m = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER; + __CHECK(pthread_mutexattr_init(&ma)); + need_destroy = true; + __CHECK(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK)); + __CHECK(pthread_mutex_init(m, &ma)); +done: + if (need_destroy) { + pthread_mutexattr_destroy(&ma); + } + return ret; +} + + +#define uwrap_mutex_lock(m) _uwrap_mutex_lock(m, #m, __func__, __LINE__) +static void _uwrap_mutex_lock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line) +{ + int ret; + + ret = pthread_mutex_lock(mutex); + if (ret != 0) { + UWRAP_LOG(UWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't lock pthread mutex(%s) - %s", + getpid(), getppid(), caller, line, name, strerror(ret)); + abort(); + } +} + +#define uwrap_mutex_unlock(m) _uwrap_mutex_unlock(m, #m, __func__, __LINE__) +static void _uwrap_mutex_unlock(pthread_mutex_t *mutex, const char *name, const char *caller, unsigned line) +{ + int ret; + + ret = pthread_mutex_unlock(mutex); + if (ret != 0) { + UWRAP_LOG(UWRAP_LOG_ERROR, "PID(%d):PPID(%d): %s(%u): Couldn't unlock pthread mutex(%s) - %s", + getpid(), getppid(), caller, line, name, strerror(ret)); + abort(); + } +} + +# define UWRAP_LOCK(m) do {\ + uwrap_mutex_lock(&(m ## _mutex)); \ +} while(0) + +# define UWRAP_UNLOCK(m) do { \ + uwrap_mutex_unlock(&(m ## _mutex)); \ +} while(0) + +/* Add new global locks here please */ +# define UWRAP_REINIT_ALL do { \ + int ret; \ + ret = uwrap_init_mutex(&uwrap_id_mutex); \ + if (ret != 0) exit(-1); \ +} while(0) + +/* Add new global locks here please */ +# define UWRAP_LOCK_ALL do { \ + UWRAP_LOCK(uwrap_id); \ +} while(0) + +# define UWRAP_UNLOCK_ALL do { \ + UWRAP_UNLOCK(uwrap_id); \ +} while(0) /********************************************************* * UWRAP PROTOTYPES @@ -396,8 +495,6 @@ void uwrap_destructor(void) DESTRUCTOR_ATTRIBUTE; enum uwrap_lib { UWRAP_LIBC, - UWRAP_LIBNSL, - UWRAP_LIBSOCKET, UWRAP_LIBPTHREAD, }; @@ -430,8 +527,6 @@ static void *uwrap_load_lib_handle(enum uwrap_lib lib) #endif switch (lib) { - case UWRAP_LIBNSL: - case UWRAP_LIBSOCKET: case UWRAP_LIBC: handle = uwrap.libc.handle; if (handle == NULL) { @@ -458,7 +553,16 @@ static void *uwrap_load_lib_handle(enum uwrap_lib lib) case UWRAP_LIBPTHREAD: handle = uwrap.libpthread.handle; if (handle == NULL) { +#ifdef RTLD_NEXT + /* + * Because thread sanatizer also overloads + * pthread_create() and pthread_exit() we need + * use RTLD_NEXT instead of libpthread.so.0 + */ + handle = uwrap.libpthread.handle = RTLD_NEXT; +#else handle = dlopen("libpthread.so.0", flags); +#endif if (handle != NULL) { break; } @@ -468,7 +572,14 @@ static void *uwrap_load_lib_handle(enum uwrap_lib lib) if (handle == NULL) { #ifdef RTLD_NEXT - handle = uwrap.libc.handle = RTLD_NEXT; + switch (lib) { + case UWRAP_LIBC: + handle = uwrap.libc.handle = RTLD_NEXT; + break; + case UWRAP_LIBPTHREAD: + handle = uwrap.libpthread.handle = RTLD_NEXT; + break; + } #else fprintf(stderr, "Failed to dlopen library: %s\n", @@ -499,20 +610,74 @@ static void *_uwrap_bind_symbol(enum uwrap_lib lib, const char *fn_name) } #define uwrap_bind_symbol_libc(sym_name) \ - UWRAP_LOCK(libc_symbol_binding); \ if (uwrap.libc.symbols._libc_##sym_name.obj == NULL) { \ uwrap.libc.symbols._libc_##sym_name.obj = \ _uwrap_bind_symbol(UWRAP_LIBC, #sym_name); \ - } \ - UWRAP_UNLOCK(libc_symbol_binding) + } #define uwrap_bind_symbol_libpthread(sym_name) \ - UWRAP_LOCK(libpthread_symbol_binding); \ if (uwrap.libpthread.symbols._libpthread_##sym_name.obj == NULL) { \ uwrap.libpthread.symbols._libpthread_##sym_name.obj = \ _uwrap_bind_symbol(UWRAP_LIBPTHREAD, #sym_name); \ - } \ - UWRAP_UNLOCK(libpthread_symbol_binding) + } + +#define uwrap_bind_symbol_rtld_default_optional(sym_name) \ + if (uwrap.rtld_default.symbols._rtld_default_##sym_name.obj == NULL) { \ + uwrap.rtld_default.symbols._rtld_default_##sym_name.obj = \ + dlsym(RTLD_DEFAULT, #sym_name); \ + } + +/* DO NOT call this function during library initialization! */ +static void __uwrap_bind_symbol_all_once(void) +{ + uwrap_bind_symbol_libc(setuid); + uwrap_bind_symbol_libc(getuid); +#ifdef HAVE_SETEUID + uwrap_bind_symbol_libc(seteuid); +#endif +#ifdef HAVE_SETREUID + uwrap_bind_symbol_libc(setreuid); +#endif +#ifdef HAVE_SETRESUID + uwrap_bind_symbol_libc(setresuid); +#endif +#ifdef HAVE_GETRESUID + uwrap_bind_symbol_libc(getresuid); +#endif + uwrap_bind_symbol_libc(geteuid); + uwrap_bind_symbol_libc(setgid); + uwrap_bind_symbol_libc(getgid); +#ifdef HAVE_SETEGID + uwrap_bind_symbol_libc(setegid); +#endif +#ifdef HAVE_SETREGID + uwrap_bind_symbol_libc(setregid); +#endif + +#ifdef HAVE_SETRESGID + uwrap_bind_symbol_libc(setresgid); +#endif +#ifdef HAVE_GETRESGID + uwrap_bind_symbol_libc(setresgid); +#endif + uwrap_bind_symbol_libc(getegid); + uwrap_bind_symbol_libc(getgroups); + uwrap_bind_symbol_libc(setgroups); +#ifdef HAVE_SYSCALL + uwrap_bind_symbol_libc(syscall); + uwrap_bind_symbol_rtld_default_optional(socket_wrapper_syscall_valid); + uwrap_bind_symbol_rtld_default_optional(socket_wrapper_syscall_va); +#endif + uwrap_bind_symbol_libpthread(pthread_create); + uwrap_bind_symbol_libpthread(pthread_exit); +} + +static void uwrap_bind_symbol_all(void) +{ + static pthread_once_t all_symbol_binding_once = PTHREAD_ONCE_INIT; + + pthread_once(&all_symbol_binding_once, __uwrap_bind_symbol_all_once); +} /* * IMPORTANT @@ -524,14 +689,14 @@ static void *_uwrap_bind_symbol(enum uwrap_lib lib, const char *fn_name) */ static int libc_setuid(uid_t uid) { - uwrap_bind_symbol_libc(setuid); + uwrap_bind_symbol_all(); return uwrap.libc.symbols._libc_setuid.f(uid); } static uid_t libc_getuid(void) { - uwrap_bind_symbol_libc(getuid); + uwrap_bind_symbol_all(); return uwrap.libc.symbols._libc_getuid.f(); } @@ -539,7 +704,7 @@ static uid_t libc_getuid(void) #ifdef HAVE_SETEUID static int libc_seteuid(uid_t euid) { - uwrap_bind_symbol_libc(seteuid); + uwrap_bind_symbol_all(); return uwrap.libc.symbols._libc_seteuid.f(euid); } @@ -548,7 +713,7 @@ static int libc_seteuid(uid_t euid) #ifdef HAVE_SETREUID static int libc_setreuid(uid_t ruid, uid_t euid) { - uwrap_bind_symbol_libc(setreuid); + uwrap_bind_symbol_all(); return uwrap.libc.symbols._libc_setreuid.f(ruid, euid); } @@ -557,7 +722,7 @@ static int libc_setreuid(uid_t ruid, uid_t euid) #ifdef HAVE_SETRESUID static int libc_setresuid(uid_t ruid, uid_t euid, uid_t suid) { - uwrap_bind_symbol_libc(setresuid); + uwrap_bind_symbol_all(); return uwrap.libc.symbols._libc_setresuid.f(ruid, euid, suid); } @@ -566,7 +731,7 @@ static int libc_setresuid(uid_t ruid, uid_t euid, uid_t suid) #ifdef HAVE_GETRESUID static int libc_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid) { - uwrap_bind_symbol_libc(getresuid); + uwrap_bind_symbol_all(); return uwrap.libc.symbols._libc_getresuid.f(ruid, euid, suid); } @@ -574,21 +739,21 @@ static int libc_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid) static uid_t libc_geteuid(void) { - uwrap_bind_symbol_libc(geteuid); + uwrap_bind_symbol_all(); return uwrap.libc.symbols._libc_geteuid.f(); } static int libc_setgid(gid_t gid) { - uwrap_bind_symbol_libc(setgid); + uwrap_bind_symbol_all(); return uwrap.libc.symbols._libc_setgid.f(gid); } static gid_t libc_getgid(void) { - uwrap_bind_symbol_libc(getgid); + uwrap_bind_symbol_all(); return uwrap.libc.symbols._libc_getgid.f(); } @@ -596,7 +761,7 @@ static gid_t libc_getgid(void) #ifdef HAVE_SETEGID static int libc_setegid(gid_t egid) { - uwrap_bind_symbol_libc(setegid); + uwrap_bind_symbol_all(); return uwrap.libc.symbols._libc_setegid.f(egid); } @@ -605,7 +770,7 @@ static int libc_setegid(gid_t egid) #ifdef HAVE_SETREGID static int libc_setregid(gid_t rgid, gid_t egid) { - uwrap_bind_symbol_libc(setregid); + uwrap_bind_symbol_all(); return uwrap.libc.symbols._libc_setregid.f(rgid, egid); } @@ -614,7 +779,7 @@ static int libc_setregid(gid_t rgid, gid_t egid) #ifdef HAVE_SETRESGID static int libc_setresgid(gid_t rgid, gid_t egid, gid_t sgid) { - uwrap_bind_symbol_libc(setresgid); + uwrap_bind_symbol_all(); return uwrap.libc.symbols._libc_setresgid.f(rgid, egid, sgid); } @@ -623,7 +788,7 @@ static int libc_setresgid(gid_t rgid, gid_t egid, gid_t sgid) #ifdef HAVE_GETRESGID static int libc_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid) { - uwrap_bind_symbol_libc(setresgid); + uwrap_bind_symbol_all(); return uwrap.libc.symbols._libc_getresgid.f(rgid, egid, sgid); } @@ -631,14 +796,14 @@ static int libc_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid) static gid_t libc_getegid(void) { - uwrap_bind_symbol_libc(getegid); + uwrap_bind_symbol_all(); return uwrap.libc.symbols._libc_getegid.f(); } static int libc_getgroups(int size, gid_t list[]) { - uwrap_bind_symbol_libc(getgroups); + uwrap_bind_symbol_all(); return uwrap.libc.symbols._libc_getgroups.f(size, list); } @@ -656,7 +821,7 @@ static int libc___getgroups_chk(int size, gid_t list[], size_t listlen) static int libc_setgroups(size_t size, const gid_t *list) { - uwrap_bind_symbol_libc(setgroups); + uwrap_bind_symbol_all(); return uwrap.libc.symbols._libc_setgroups.f(size, list); } @@ -669,7 +834,7 @@ static long int libc_vsyscall(long int sysno, va_list va) long int rc; int i; - uwrap_bind_symbol_libc(syscall); + uwrap_bind_symbol_all(); for (i = 0; i < 8; i++) { args[i] = va_arg(va, long int); @@ -687,15 +852,57 @@ static long int libc_vsyscall(long int sysno, va_list va) return rc; } + +static bool uwrap_swrap_syscall_valid(long int sysno) +{ + uwrap_bind_symbol_all(); + + if (uwrap.rtld_default.symbols._rtld_default_socket_wrapper_syscall_valid.f == NULL) { + return false; + } + + return uwrap.rtld_default.symbols._rtld_default_socket_wrapper_syscall_valid.f( + sysno); +} + +DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE +static long int uwrap_swrap_syscall_va(long int sysno, va_list va) +{ + uwrap_bind_symbol_all(); + + if (uwrap.rtld_default.symbols._rtld_default_socket_wrapper_syscall_va.f == NULL) { + /* + * Fallback to libc, if socket_wrapper_vsyscall is not + * available. + */ + return libc_vsyscall(sysno, va); + } + + return uwrap.rtld_default.symbols._rtld_default_socket_wrapper_syscall_va.f( + sysno, + va); +} #endif +static int libpthread_pthread_create(pthread_t *thread, + const pthread_attr_t *attr, + void *(*start_routine) (void *), + void *arg) +{ + uwrap_bind_symbol_all(); + return uwrap.libpthread.symbols._libpthread_pthread_create.f(thread, + attr, + start_routine, + arg); +} + /* * This part is "optimistic". * Thread can ends without pthread_exit call. */ static void libpthread_pthread_exit(void *retval) { - uwrap_bind_symbol_libpthread(pthread_exit); + uwrap_bind_symbol_all(); uwrap.libpthread.symbols._libpthread_pthread_exit.f(retval); } @@ -735,18 +942,6 @@ void pthread_exit(void *retval) exit(666); } -static int libpthread_pthread_create(pthread_t *thread, - const pthread_attr_t *attr, - void *(*start_routine) (void *), - void *arg) -{ - uwrap_bind_symbol_libpthread(pthread_create); - return uwrap.libpthread.symbols._libpthread_pthread_create.f(thread, - attr, - start_routine, - arg); -} - struct uwrap_pthread_create_args { struct uwrap_thread *id; void *(*start_routine) (void *); @@ -952,6 +1147,13 @@ static void uwrap_thread_prepare(void) { struct uwrap_thread *id = uwrap_tls_id; + /* + * We bind all symobls to avoid deadlocks of the fork is + * interrupted by a signal handler using a symbol of this + * library. + */ + uwrap_bind_symbol_all(); + UWRAP_LOCK_ALL; /* uid_wrapper is loaded but not enabled */ @@ -988,9 +1190,10 @@ static void uwrap_thread_child(void) struct uwrap_thread *id = uwrap_tls_id; struct uwrap_thread *u = uwrap.ids; + UWRAP_REINIT_ALL; + /* uid_wrapper is loaded but not enabled */ if (id == NULL) { - UWRAP_UNLOCK_ALL; return; } @@ -1017,8 +1220,6 @@ static void uwrap_thread_child(void) uwrap_export_ids(id); id->enabled = true; - - UWRAP_UNLOCK_ALL; } static unsigned long uwrap_get_xid_from_env(const char *envname) @@ -2180,6 +2381,118 @@ int __getgroups_chk(int size, gid_t *list, size_t listlen) #if (defined(HAVE_SYS_SYSCALL_H) || defined(HAVE_SYSCALL_H)) \ && (defined(SYS_setreuid) || defined(SYS_setreuid32)) +static bool uwrap_is_uwrap_related_syscall(long int sysno) +{ + switch (sysno) { + /* gid */ +#ifdef __alpha__ + case SYS_getxgid: + return true; +#else + case SYS_getgid: + return true; +#endif +#ifdef HAVE_LINUX_32BIT_SYSCALLS + case SYS_getgid32: + return true; +#endif +#ifdef SYS_getegid + case SYS_getegid: + return true; +#ifdef HAVE_LINUX_32BIT_SYSCALLS + case SYS_getegid32: + return true; +#endif +#endif /* SYS_getegid */ + case SYS_setgid: + return true; +#ifdef HAVE_LINUX_32BIT_SYSCALLS + case SYS_setgid32: + return true; +#endif + case SYS_setregid: + return true; +#ifdef HAVE_LINUX_32BIT_SYSCALLS + case SYS_setregid32: + return true; +#endif +#ifdef SYS_setresgid + case SYS_setresgid: + return true; +#ifdef HAVE_LINUX_32BIT_SYSCALLS + case SYS_setresgid32: + return true; +#endif +#endif /* SYS_setresgid */ +#if defined(SYS_getresgid) && defined(HAVE_GETRESGID) + case SYS_getresgid: + return true; +#ifdef HAVE_LINUX_32BIT_SYSCALLS + case SYS_getresgid32: + return true; +#endif +#endif /* SYS_getresgid && HAVE_GETRESGID */ + + /* uid */ +#ifdef __alpha__ + case SYS_getxuid: + return true; +#else + case SYS_getuid: + return true; +#endif +#ifdef HAVE_LINUX_32BIT_SYSCALLS + case SYS_getuid32: + return true; +#endif +#ifdef SYS_geteuid + case SYS_geteuid: + return true; +#ifdef HAVE_LINUX_32BIT_SYSCALLS + case SYS_geteuid32: + return true; +#endif +#endif /* SYS_geteuid */ + case SYS_setuid: + return true; +#ifdef HAVE_LINUX_32BIT_SYSCALLS + case SYS_setuid32: + return true; +#endif + case SYS_setreuid: + return true; +#ifdef HAVE_LINUX_32BIT_SYSCALLS + case SYS_setreuid32: + return true; +#endif +#ifdef SYS_setresuid + case SYS_setresuid: + return true; +#ifdef HAVE_LINUX_32BIT_SYSCALLS + case SYS_setresuid32: + return true; +#endif +#endif /* SYS_setresuid */ +#if defined(SYS_getresuid) && defined(HAVE_GETRESUID) + case SYS_getresuid: + return true; +#ifdef HAVE_LINUX_32BIT_SYSCALLS + case SYS_getresuid32: + return true; +#endif +#endif /* SYS_getresuid && HAVE_GETRESUID*/ + /* groups */ + case SYS_setgroups: + return true; +#ifdef HAVE_LINUX_32BIT_SYSCALLS + case SYS_setgroups32: + return true; +#endif + default: + return false; + } +} + static long int uwrap_syscall (long int sysno, va_list vp) { long int rc; @@ -2343,11 +2656,8 @@ static long int uwrap_syscall (long int sysno, va_list vp) } break; default: - UWRAP_LOG(UWRAP_LOG_DEBUG, - "UID_WRAPPER calling non-wrapped syscall %lu", - sysno); - - rc = libc_vsyscall(sysno, vp); + rc = -1; + errno = ENOSYS; break; } @@ -2370,6 +2680,28 @@ long int syscall (long int sysno, ...) va_start(va, sysno); + /* + * we need to check for uwrap related + * syscall numbers before calling uid_wrapper_enabled() + * otherwise we'd deadlock during the freebsd libc fork() + * which calls syscall() after invoking uwrap_thread_prepare(). + */ + if (!uwrap_is_uwrap_related_syscall(sysno)) { + /* + * We need to give socket_wrapper a + * chance to take over... + */ + if (uwrap_swrap_syscall_valid(sysno)) { + rc = uwrap_swrap_syscall_va(sysno, va); + va_end(va); + return rc; + } + + rc = libc_vsyscall(sysno, va); + va_end(va); + return rc; + } + if (!uid_wrapper_enabled()) { rc = libc_vsyscall(sysno, va); va_end(va); @@ -2382,6 +2714,39 @@ long int syscall (long int sysno, ...) return rc; } + +/* used by socket_wrapper */ +bool uid_wrapper_syscall_valid(long int sysno); +bool uid_wrapper_syscall_valid(long int sysno) +{ + if (!uwrap_is_uwrap_related_syscall(sysno)) { + return false; + } + + if (!uid_wrapper_enabled()) { + return false; + } + + return true; +} + +/* used by socket_wrapper */ +long int uid_wrapper_syscall_va(long int sysno, va_list va); +long int uid_wrapper_syscall_va(long int sysno, va_list va) +{ + if (!uwrap_is_uwrap_related_syscall(sysno)) { + errno = ENOSYS; + return -1; + } + + if (!uid_wrapper_enabled()) { + return libc_vsyscall(sysno, va); + } + + uwrap_init(); + + return uwrap_syscall(sysno, va); +} #endif /* HAVE_SYSCALL */ #endif /* HAVE_SYS_SYSCALL_H || HAVE_SYSCALL_H */ @@ -2412,6 +2777,8 @@ void uwrap_constructor(void) } glibc_malloc_lock_bug[0] = '\0'; + UWRAP_REINIT_ALL; + /* * If we hold a lock and the application forks, then the child * is not able to unlock the mutex and we are in a deadlock. @@ -2453,11 +2820,19 @@ void uwrap_destructor(void) } - if (uwrap.libc.handle != NULL) { + if (uwrap.libc.handle != NULL +#ifdef RTLD_NEXT + && uwrap.libc.handle != RTLD_NEXT +#endif + ) { dlclose(uwrap.libc.handle); } - if (uwrap.libpthread.handle != NULL) { + if (uwrap.libpthread.handle != NULL +#ifdef RTLD_NEXT + && uwrap.libpthread.handle != RTLD_NEXT +#endif + ) { dlclose(uwrap.libpthread.handle); } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1ae3d86de4d2e8a6310a27debca4c8e1040a9474..635e86e17a017d1cb306b3707ff8778a264dddc4 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,5 +1,14 @@ project(tests C) +add_library(uwrap_fake_socket_wrapper SHARED uwrap_fake_socket_wrapper.c) +target_compile_options(uwrap_fake_socket_wrapper + PRIVATE + ${DEFAULT_C_COMPILE_FLAGS} + -D_GNU_SOURCE) +target_include_directories(uwrap_fake_socket_wrapper + PRIVATE ${CMAKE_BINARY_DIR} ${CMOCKA_INCLUDE_DIR}) +set(UWRAP_FAKE_SOCKET_WRAPPER_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}uwrap_fake_socket_wrapper${CMAKE_SHARED_LIBRARY_SUFFIX}") + function(ADD_CMOCKA_TEST_ENVIRONMENT _TEST_NAME) if (CMAKE_BUILD_TYPE) string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER) @@ -19,6 +28,7 @@ function(ADD_CMOCKA_TEST_ENVIRONMENT _TEST_NAME) if (ASAN_LIBRARY) list(APPEND PRELOAD_LIBRARIES ${ASAN_LIBRARY}) endif() + list(APPEND PRELOAD_LIBRARIES ${UWRAP_FAKE_SOCKET_WRAPPER_LOCATION}) list(APPEND PRELOAD_LIBRARIES ${UID_WRAPPER_LOCATION}) if (OSX) @@ -30,6 +40,15 @@ function(ADD_CMOCKA_TEST_ENVIRONMENT _TEST_NAME) list(APPEND TORTURE_ENVIRONMENT UID_WRAPPER=1) + if (CMAKE_BUILD_TYPE) + string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER) + if (CMAKE_BUILD_TYPE_LOWER STREQUAL "addresssanitizer" OR + CMAKE_BUILD_TYPE_LOWER STREQUAL "threadsanitizer" OR + CMAKE_BUILD_TYPE_LOWER STREQUAL "undefinedsanitizer") + list(APPEND TORTURE_ENVIRONMENT "UID_WRAPPER_DISABLE_DEEPBIND=1") + endif() + endif() + foreach(_arg ${ARGN}) list(APPEND TORTURE_ENVIRONMENT ${_arg}) endforeach() @@ -95,6 +114,7 @@ set(UWRAP_TESTS ${UWRAP_GID_TESTS} test_setgroups test_syscall + test_syscall_swrap ${UWRAP_SYSCALL_UID_TESTS} test_syscall_gid) diff --git a/tests/test_syscall_swrap.c b/tests/test_syscall_swrap.c new file mode 100644 index 0000000000000000000000000000000000000000..fb3d26b47983f09c118d2d09c503f683ed90e3f6 --- /dev/null +++ b/tests/test_syscall_swrap.c @@ -0,0 +1,50 @@ +#include "config.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_SYS_SYSCALL_H +#include +#endif +#ifdef HAVE_SYSCALL_H +#include +#endif + +#include "uwrap_fake_socket_wrapper.h" + +static void test_uwrap_syscall_swrap(void **state) +{ + long int rc; + + (void) state; /* unused */ + + rc = syscall(__FAKE_SOCKET_WRAPPER_SYSCALL_NO); + assert_int_equal(rc, __FAKE_SOCKET_WRAPPER_SYSCALL_RC); + + signal(SIGSYS, SIG_IGN); + rc = syscall(__FAKE_SOCKET_WRAPPER_SYSCALL_NO+1); + signal(SIGSYS, SIG_DFL); + assert_int_equal(rc, -1); + assert_int_equal(errno, ENOSYS); +} + +int main(void) { + int rc; + + const struct CMUnitTest uwrap_tests[] = { + cmocka_unit_test(test_uwrap_syscall_swrap), + }; + + rc = cmocka_run_group_tests(uwrap_tests, NULL, NULL); + + return rc; +} diff --git a/tests/test_thread_setuid.c b/tests/test_thread_setuid.c index 8b52c3834661cbd0b41b98294447257652b0b774..db65c969a467d27b588c4a63ab819c3e0d8add7a 100644 --- a/tests/test_thread_setuid.c +++ b/tests/test_thread_setuid.c @@ -25,8 +25,8 @@ #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) -static pthread_mutex_t wait_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t sleep_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t uwrap_getuid_sync_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t uwrap_setuid_sync_mutex = PTHREAD_MUTEX_INITIALIZER; static void *uwrap_getuid_sync(void *arg) { @@ -34,12 +34,12 @@ static void *uwrap_getuid_sync(void *arg) (void) arg; /* unused */ - pthread_mutex_unlock(&sleep_mutex); - pthread_mutex_lock(&wait_mutex); + pthread_mutex_lock(&uwrap_getuid_sync_mutex); u = getuid(); assert_int_equal(u, 888); + pthread_mutex_unlock(&uwrap_getuid_sync_mutex); return NULL; } @@ -49,9 +49,12 @@ static void *uwrap_setuid_sync(void *arg) (void) arg; /* unused */ + pthread_mutex_lock(&uwrap_setuid_sync_mutex); + rc = setuid(888); assert_int_equal(rc, 0); + pthread_mutex_unlock(&uwrap_setuid_sync_mutex); return NULL; } @@ -62,8 +65,8 @@ static void test_real_sync_setuid(void **state) (void) state; /* unused */ - pthread_mutex_lock(&wait_mutex); - pthread_mutex_lock(&sleep_mutex); + pthread_mutex_lock(&uwrap_getuid_sync_mutex); + pthread_mutex_lock(&uwrap_setuid_sync_mutex); /* Create thread which will wait for change. */ pthread_create(&threads[0], @@ -71,16 +74,16 @@ static void test_real_sync_setuid(void **state) uwrap_getuid_sync, NULL); - pthread_mutex_lock(&sleep_mutex); - pthread_create(&threads[1], NULL, uwrap_setuid_sync, NULL); + pthread_mutex_unlock(&uwrap_setuid_sync_mutex); + pthread_join(threads[1], NULL); - pthread_mutex_unlock(&wait_mutex); + pthread_mutex_unlock(&uwrap_getuid_sync_mutex); pthread_join(threads[0], NULL); diff --git a/tests/test_thread_sync_setreuid.c b/tests/test_thread_sync_setreuid.c index a30e8a3806a01be995e5eca3f2ba833836be4ea5..720a707053386dce09cb721602d7027637f6e261 100644 --- a/tests/test_thread_sync_setreuid.c +++ b/tests/test_thread_sync_setreuid.c @@ -27,8 +27,10 @@ struct parm { int id; int ready; + pthread_cond_t cond; }; +pthread_mutex_t cond_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t msg_mutex = PTHREAD_MUTEX_INITIALIZER; static void *syscall_setreuid(void *arg) @@ -84,7 +86,10 @@ static void *sync_setreuid(void *arg) syscall_setreuid(arg); + pthread_mutex_lock(&cond_mutex); p->ready = 1; + pthread_cond_signal(&p->cond); + pthread_mutex_unlock(&cond_mutex); pthread_mutex_lock(&msg_mutex); @@ -103,6 +108,7 @@ static void test_sync_setreuid(void **state) struct parm *p; int rc; int i; + struct timespec ts; (void) state; /* unused */ @@ -116,6 +122,7 @@ static void test_sync_setreuid(void **state) for (i = 0; i < NUM_THREADS; i++) { p[i].id = i; p[i].ready = 0; + p[i].cond = (pthread_cond_t)PTHREAD_COND_INITIALIZER; pthread_create(&threads[i], &pthread_custom_attr, @@ -124,11 +131,17 @@ static void test_sync_setreuid(void **state) } /* wait for the threads to set euid to 0 */ + + pthread_mutex_lock(&cond_mutex); + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += NUM_THREADS; for (i = 0; i < NUM_THREADS; i++) { while (p[i].ready != 1) { - sleep(1); + rc = pthread_cond_timedwait(&p[i].cond, &cond_mutex, &ts); + assert_int_equal(rc, 0); } } + pthread_mutex_unlock(&cond_mutex); rc = setreuid(-1, 42); assert_int_equal(rc, 0); diff --git a/tests/uwrap_fake_socket_wrapper.c b/tests/uwrap_fake_socket_wrapper.c new file mode 100644 index 0000000000000000000000000000000000000000..657873a76d8e719263305c96f0137a788c4f2d0e --- /dev/null +++ b/tests/uwrap_fake_socket_wrapper.c @@ -0,0 +1,44 @@ +#include "config.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef HAVE_SYS_SYSCALL_H +#include +#endif +#ifdef HAVE_SYSCALL_H +#include +#endif + +#include "uwrap_fake_socket_wrapper.h" + +/* simulate socket_wrapper hooks */ +bool socket_wrapper_syscall_valid(long int sysno) +{ + if (sysno == __FAKE_SOCKET_WRAPPER_SYSCALL_NO) { + return true; + } + + return false; +} + +long int socket_wrapper_syscall_va(long int sysno, va_list va) +{ + (void) va; /* unused */ + + if (sysno == __FAKE_SOCKET_WRAPPER_SYSCALL_NO) { + errno = 0; + return __FAKE_SOCKET_WRAPPER_SYSCALL_RC; + } + + errno = ENOSYS; + return -1; +} diff --git a/tests/uwrap_fake_socket_wrapper.h b/tests/uwrap_fake_socket_wrapper.h new file mode 100644 index 0000000000000000000000000000000000000000..63e423a63f8b35b06388ae1d52517a4854508152 --- /dev/null +++ b/tests/uwrap_fake_socket_wrapper.h @@ -0,0 +1,7 @@ +#include + +/* simulate socket_wrapper hooks */ +#define __FAKE_SOCKET_WRAPPER_SYSCALL_NO 123456789 +#define __FAKE_SOCKET_WRAPPER_SYSCALL_RC 987654321 +bool socket_wrapper_syscall_valid(long int sysno); +long int socket_wrapper_syscall_va(long int sysno, va_list va);