From fc451a8f3d111341256f9fb3d1443614f4a09f3a Mon Sep 17 00:00:00 2001 From: Abdelrahman yossef Date: Tue, 2 Apr 2024 16:40:06 +0200 Subject: [PATCH] fs_wrapper: added stat and lstat Signed-off-by: Abdelrahman Youssef Reviewed-by: Jakub Jelen --- tests/CMakeLists.txt | 14 ++-- tests/chown_wrapper.c | 21 ----- tests/fs_wrapper.c | 173 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 180 insertions(+), 28 deletions(-) delete mode 100644 tests/chown_wrapper.c create mode 100644 tests/fs_wrapper.c diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 46c19ff7..8165c308 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -244,15 +244,15 @@ if (CLIENT_TESTING OR SERVER_TESTING) set(CHROOT_WRAPPER "${CHROOT_WRAPPER_LIBRARY}") endif() - # chown wrapper - add_library(chown_wrapper SHARED chown_wrapper.c) - set(CHOWN_WRAPPER_LIBRARY - ${libssh_BINARY_DIR}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}chown_wrapper${CMAKE_SHARED_LIBRARY_SUFFIX}) + # fs wrapper + add_library(fs_wrapper SHARED fs_wrapper.c) + set(FS_WRAPPER_LIBRARY + ${libssh_BINARY_DIR}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}fs_wrapper${CMAKE_SHARED_LIBRARY_SUFFIX}) set(TEST_TARGET_LIBRARIES ${TEST_TARGET_LIBRARIES} - chown_wrapper + fs_wrapper ) - set(CHOWN_WRAPPER "${CHOWN_WRAPPER_LIBRARY}") + set(FS_WRAPPER "${FS_WRAPPER_LIBRARY}") # ssh_ping add_executable(ssh_ping ssh_ping.c) @@ -274,7 +274,7 @@ if (CLIENT_TESTING OR SERVER_TESTING) set(TORTURE_ENVIRONMENT - "LD_PRELOAD=${SOCKET_WRAPPER_LIBRARY}:${NSS_WRAPPER_LIBRARY}:${UID_WRAPPER_LIBRARY}:${PAM_WRAPPER_LIBRARY}:${CHROOT_WRAPPER}:${CHOWN_WRAPPER}") + "LD_PRELOAD=${SOCKET_WRAPPER_LIBRARY}:${NSS_WRAPPER_LIBRARY}:${UID_WRAPPER_LIBRARY}:${PAM_WRAPPER_LIBRARY}:${CHROOT_WRAPPER}:${FS_WRAPPER}") if (priv_wrapper_FOUND) list(APPEND TORTURE_ENVIRONMENT PRIV_WRAPPER=1 PRIV_WRAPPER_CHROOT_DISABLE=1) list(APPEND TORTURE_ENVIRONMENT PRIV_WRAPPER_PRCTL_DISABLE="ALL" PRIV_WRAPPER_SETRLIMIT_DISABLE="ALL") diff --git a/tests/chown_wrapper.c b/tests/chown_wrapper.c deleted file mode 100644 index ee6910ed..00000000 --- a/tests/chown_wrapper.c +++ /dev/null @@ -1,21 +0,0 @@ -#define _GNU_SOURCE -#include -#include -#include - -typedef int (*__libc_chown)(const char *pathname, uid_t owner, gid_t group); - -/* silent gcc */ -int chown(const char *pathname, uid_t owner, gid_t group); - -int chown(const char *pathname, uid_t owner, gid_t group) -{ - __libc_chown original_chown; - if (strlen(pathname) > 7 && strncmp(pathname, "/dev/pt", 7) == 0) { - /* fake it! */ - return 0; - } - - original_chown = (__libc_chown)dlsym(RTLD_NEXT, "chown"); - return (*original_chown)(pathname, owner, group); -} diff --git a/tests/fs_wrapper.c b/tests/fs_wrapper.c new file mode 100644 index 00000000..fd7e742a --- /dev/null +++ b/tests/fs_wrapper.c @@ -0,0 +1,173 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + +void destructor(void) __attribute__((destructor)); + +struct file { + char *name; + uid_t uid; + gid_t gid; +} file = {0}; + +void +destructor(void) +{ + free(file.name); +} + +typedef int (*__libc_chown)(const char *pathname, uid_t owner, gid_t group); + +typedef int (*__libc_fchownat)(int dirfd, + const char *pathname, + uid_t owner, + gid_t group, + int flags); + +typedef int (*__libc_stat)(const char *pathname, struct stat *statbuf); + +typedef int (*__libc_xstat)(int ver, + const char *pathname, + struct stat *statbuf); + +typedef int (*__libc_lxstat)(int ver, + const char *pathname, + struct stat *statbuf); + +typedef int (*__libc_lstat)(const char *pathname, struct stat *statbuf); + +static int +chown_helper(const char *pathname, uid_t owner, gid_t group) +{ + if (strlen(pathname) > 7 && strncmp(pathname, "/dev/pt", 7) == 0) { + /* + * The OpenSSH server modified the PTY which requires root permissions + * see torture_request_pty_modes + * */ + return 0; + } + if (strlen(pathname) > 4 && strncmp(pathname, "/tmp", 4) == 0) { + /* + * faking chown because It requires root permissions to modify the owner + * under /tmp + * It's also a helper for torture_sftp_setstat + * */ + if (file.name != NULL) { + free((char *)file.name); + } + file.name = strdup(pathname); + file.uid = owner; + file.gid = group; + return 0; + } + return -1; +} + +static void +stat_helper(const char *pathname, struct stat *statbuf) +{ + if (file.name != NULL && strcmp(pathname, file.name) == 0) { + statbuf->st_uid = file.uid; + statbuf->st_gid = file.gid; + } +} + +/* silent gcc */ +int chown(const char *pathname, uid_t owner, gid_t group); + +int +chown(const char *pathname, uid_t owner, gid_t group) +{ + __libc_chown original_chown = NULL; + int rc; + + rc = chown_helper(pathname, owner, group); + if (rc == 0) { + return 0; + } + original_chown = (__libc_chown)dlsym(RTLD_NEXT, "chown"); + return (*original_chown)(pathname, owner, group); +} + +/* SFTP Server calls fchownat for symlinks */ +int +fchownat(int dirfd, const char *pathname, uid_t owner, gid_t group, int flags); + +int +fchownat(int dirfd, const char *pathname, uid_t owner, gid_t group, int flags) +{ + __libc_fchownat original_fchownat = NULL; + int rc; + + rc = chown_helper(pathname, owner, group); + if (rc == 0) { + return 0; + } + + original_fchownat = (__libc_fchownat)dlsym(RTLD_NEXT, "fchownat"); + return (*original_fchownat)(dirfd, pathname, owner, group, flags); +} +int stat(const char *pathname, struct stat *statbuf); + +int +stat(const char *pathname, struct stat *statbuf) +{ + int rc; + __libc_stat original_stat = NULL; + + original_stat = (__libc_stat)dlsym(RTLD_NEXT, "stat"); + rc = (*original_stat)(pathname, statbuf); + stat_helper(pathname, statbuf); + + return rc; +} + +/* CentOS8 calls xstat */ +int __xstat(int ver, const char *pathname, struct stat *statbuf); + +int +__xstat(int ver, const char *pathname, struct stat *statbuf) +{ + int rc; + __libc_xstat original_xstat = NULL; + + original_xstat = (__libc_xstat)dlsym(RTLD_NEXT, "__xstat"); + rc = (*original_xstat)(ver, pathname, statbuf); + stat_helper(pathname, statbuf); + + return rc; +} + +int __lxstat(int ver, const char *pathname, struct stat *statbuf); + +int +__lxstat(int ver, const char *pathname, struct stat *statbuf) +{ + int rc; + __libc_lxstat original_lxstat = NULL; + + original_lxstat = (__libc_lxstat)dlsym(RTLD_NEXT, "__lxstat"); + rc = (*original_lxstat)(ver, pathname, statbuf); + stat_helper(pathname, statbuf); + + return rc; +} +int lstat(const char *pathname, struct stat *statbuf); + +int +lstat(const char *pathname, struct stat *statbuf) +{ + int rc; + __libc_lstat original_lstat = NULL; + + original_lstat = (__libc_lstat)dlsym(RTLD_NEXT, "lstat"); + rc = (*original_lstat)(pathname, statbuf); + stat_helper(pathname, statbuf); + + return rc; +}