From 11589e1037372c5ad719e1e46d7462fd196caa56 Mon Sep 17 00:00:00 2001 From: Johannes Schauer Marin Rodrigues Date: Thu, 24 Jun 2021 10:38:28 +0200 Subject: [PATCH 01/11] src/lckpwdf.c: create an empty /etc/.pwd.lock --- src/lckpwdf.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/lckpwdf.c b/src/lckpwdf.c index dc0e68b5..66a058de 100644 --- a/src/lckpwdf.c +++ b/src/lckpwdf.c @@ -22,12 +22,37 @@ #ifdef HAVE_LCKPWDF +#include +#include #include "libfakechroot.h" +#include "open.h" wrapper(lckpwdf, int, (void)) { + char fakechroot_abspath[FAKECHROOT_PATH_MAX]; + char fakechroot_buf[FAKECHROOT_PATH_MAX]; + + int file; debug("lckpwdf()"); + // lckpwdf will create an empty /etc/.pwd.lock + // if that file doesn't exist yet, we create it here as well + char* pwdlockfile = "/etc/.pwd.lock"; + expand_chroot_path(pwdlockfile); + + if ((file = nextcall(open)(pwdlockfile, O_RDONLY)) == 0) { + // if the file already exists, don't touch it + close(file); + return 0; + } + + if ((file = nextcall(open)(pwdlockfile, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)) == -1) { + // we ignore any errors (maybe /etc doesn't exist or we don't have the + // necessary permissions) + return 0; + } + // the file remains empty + close(file); return 0; } From 3cdb9b5426ef508c9220b4b0316954e3b7dff9ac Mon Sep 17 00:00:00 2001 From: Hajime Yoshimori Date: Fri, 1 May 2020 21:14:32 +0900 Subject: [PATCH 02/11] check return value of dladdr https://github.com/dex4er/fakechroot/pull/70 --- src/dladdr.c | 12 +++++++----- test/Makefile.am | 1 + test/src/Makefile.am | 1 + test/src/test-dladdr.c | 14 ++++++++++++++ test/t/dladdr.t | 14 ++++++++++++++ 5 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 test/src/test-dladdr.c create mode 100755 test/t/dladdr.t diff --git a/src/dladdr.c b/src/dladdr.c index fef32579..3dffdb3f 100644 --- a/src/dladdr.c +++ b/src/dladdr.c @@ -36,11 +36,13 @@ wrapper(dladdr, int, (const void * addr, Dl_info * info)) ret = nextcall(dladdr)(addr, info); - if (info->dli_fname) { - narrow_chroot_path(info->dli_fname); - } - if (info->dli_sname) { - narrow_chroot_path(info->dli_sname); + if (ret != 0) { + if (info->dli_fname) { + narrow_chroot_path(info->dli_fname); + } + if (info->dli_sname) { + narrow_chroot_path(info->dli_sname); + } } return ret; diff --git a/test/Makefile.am b/test/Makefile.am index aba29538..0021b0a1 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -9,6 +9,7 @@ TESTS = \ t/cmd-subst.t \ t/cp.t \ t/dedotdot.t \ + t/dladdr.t \ t/execlp.t \ t/execve-elfloader.t \ t/execve-null-envp.t \ diff --git a/test/src/Makefile.am b/test/src/Makefile.am index 7fb3075b..5f5fde8d 100644 --- a/test/src/Makefile.am +++ b/test/src/Makefile.am @@ -3,6 +3,7 @@ check_PROGRAMS = \ test-chroot \ test-clearenv \ test-dedotdot \ + test-dladdr \ test-execlp \ test-execve-null-envp \ test-fts \ diff --git a/test/src/test-dladdr.c b/test/src/test-dladdr.c new file mode 100644 index 00000000..5ec8d248 --- /dev/null +++ b/test/src/test-dladdr.c @@ -0,0 +1,14 @@ +#define _GNU_SOURCE +#include +#include +#include +#include + +int main(int argc, char** argv) +{ + Dl_info info; + memset(&info, 0xfe, sizeof(info)); /* fill with inaccessible address */ + int ret = dladdr(NULL, &info); + printf("%ld\n", ret); + return 0; +} diff --git a/test/t/dladdr.t b/test/t/dladdr.t new file mode 100755 index 00000000..fc7f9397 --- /dev/null +++ b/test/t/dladdr.t @@ -0,0 +1,14 @@ +#!/bin/sh + +srcdir=${srcdir:-.} +. $srcdir/common.inc.sh + +prepare 1 + +PATH=$srcdir/bin:$PATH + +t=`$srcdir/fakechroot.sh $testtree /bin/test-dladdr` +[ "$t" != "0" ] && not +ok "dladdr returns" $t + +cleanup From 63c2cbed6dca6196940b439736ca2c069cb9358b Mon Sep 17 00:00:00 2001 From: Ilya Lipnitskiy Date: Mon, 22 Feb 2021 21:44:07 -0800 Subject: [PATCH 03/11] tmpnam.c: fix heap overflow https://github.com/dex4er/fakechroot/pull/85 Signed-off-by: Ilya Lipnitskiy --- src/tmpnam.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tmpnam.c b/src/tmpnam.c index ce60817a..917ee6b7 100644 --- a/src/tmpnam.c +++ b/src/tmpnam.c @@ -42,7 +42,7 @@ wrapper(tmpnam, char *, (char * s)) expand_chroot_path(ptr); - ptr2 = malloc(strlen(ptr)); + ptr2 = malloc(strlen(ptr) + 1); if (ptr2 == NULL) return NULL; strcpy(ptr2, ptr); From be3a291ef37ace606ec2845f6c1b645b981805cb Mon Sep 17 00:00:00 2001 From: Ilya Lipnitskiy Date: Mon, 22 Feb 2021 21:46:36 -0800 Subject: [PATCH 04/11] declare missing bufs, remove ver from lstat https://github.com/dex4er/fakechroot/pull/85 Signed-off-by: Ilya Lipnitskiy --- src/lstat.c | 8 +++++--- src/lstat.h | 2 +- src/mknod.c | 2 ++ src/stat.c | 2 ++ src/stat64.c | 2 ++ 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/lstat.c b/src/lstat.c index 3f6d819f..54e3263f 100644 --- a/src/lstat.c +++ b/src/lstat.c @@ -28,9 +28,11 @@ #include "lstat.h" -wrapper(lstat, int, (int ver, const char * filename, struct stat * buf)) +wrapper(lstat, int, (const char * filename, struct stat * buf)) { - debug("lstat(%d, \"%s\", &buf)", ver, filename); + char fakechroot_abspath[FAKECHROOT_PATH_MAX]; + char fakechroot_buf[FAKECHROOT_PATH_MAX]; + debug("lstat(\"%s\", &buf)", filename); if (!fakechroot_localdir(filename)) { if (filename != NULL) { @@ -40,7 +42,7 @@ wrapper(lstat, int, (int ver, const char * filename, struct stat * buf)) } } - return lstat_rel(ver, filename, buf); + return lstat_rel(filename, buf); } diff --git a/src/lstat.h b/src/lstat.h index 751c1ead..ee483033 100644 --- a/src/lstat.h +++ b/src/lstat.h @@ -26,7 +26,7 @@ #ifndef HAVE___LXSTAT -wrapper_proto(lstat, int, (int, const char *, struct stat *)); +wrapper_proto(lstat, int, (const char *, struct stat *)); int lstat_rel(const char *, struct stat *); diff --git a/src/mknod.c b/src/mknod.c index 52fd33b2..27710372 100644 --- a/src/mknod.c +++ b/src/mknod.c @@ -28,6 +28,8 @@ wrapper(mknod, int, (const char * pathname, mode_t mode, dev_t dev)) { + char fakechroot_abspath[FAKECHROOT_PATH_MAX]; + char fakechroot_buf[FAKECHROOT_PATH_MAX]; debug("mknod(\"%s\", 0%o, %ld)", pathname, mode, dev); expand_chroot_path(pathname); return nextcall(mknod)(pathname, mode, dev); diff --git a/src/stat.c b/src/stat.c index 78456620..7b377933 100644 --- a/src/stat.c +++ b/src/stat.c @@ -33,6 +33,8 @@ wrapper(stat, int, (const char * file_name, struct stat * buf)) { + char fakechroot_abspath[FAKECHROOT_PATH_MAX]; + char fakechroot_buf[FAKECHROOT_PATH_MAX]; debug("stat(\"%s\", &buf)", file_name); expand_chroot_path(file_name); return nextcall(stat)(file_name, buf); diff --git a/src/stat64.c b/src/stat64.c index aac9c75f..a360f66f 100644 --- a/src/stat64.c +++ b/src/stat64.c @@ -34,6 +34,8 @@ wrapper(stat64, int, (const char * file_name, struct stat64 * buf)) { + char fakechroot_abspath[FAKECHROOT_PATH_MAX]; + char fakechroot_buf[FAKECHROOT_PATH_MAX]; debug("stat64(\"%s\", &buf)", file_name); expand_chroot_path(file_name); return nextcall(stat64)(file_name, buf); From 26f69c2c3120b9b059209c7566850ef5187de56a Mon Sep 17 00:00:00 2001 From: Ilya Lipnitskiy Date: Mon, 22 Feb 2021 21:47:09 -0800 Subject: [PATCH 05/11] fix glibc 2.33+ compatibility https://github.com/dex4er/fakechroot/pull/85 Signed-off-by: Ilya Lipnitskiy --- configure.ac | 20 ++++++++++++++++++++ src/ftw.c | 2 +- src/ftw64.c | 14 +++++++++++--- src/libfakechroot.h | 15 +++++++++++++++ src/lstat.c | 2 +- src/lstat.h | 2 +- src/lstat64.c | 2 +- src/mknod.c | 2 +- src/mknodat.c | 2 +- src/stat.c | 2 +- src/stat64.c | 2 +- 11 files changed, 54 insertions(+), 11 deletions(-) diff --git a/configure.ac b/configure.ac index f8cdb323..9cc2e779 100644 --- a/configure.ac +++ b/configure.ac @@ -75,6 +75,26 @@ ACX_CHECK_C_ATTRIBUTE_VISIBILITY # Checks for libraries. AC_CHECK_LIB([dl], [dlsym]) +AH_TEMPLATE([NEW_GLIBC], [glibc >= 2.33]) +AC_MSG_CHECKING([for glibc 2.33+]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #include + ]], [[ +#ifdef __GLIBC__ +#if !__GLIBC_PREREQ(2,33) +#error glibc<2.33 +#endif +#else +#error not glibc +#endif + ]])],[ + AC_DEFINE(NEW_GLIBC,1) + AC_MSG_RESULT([yes]) + ],[ + AC_DEFINE(NEW_GLIBC,0) + AC_MSG_RESULT([no]) + ]) + # Checks for header files. AC_HEADER_DIRENT AC_HEADER_STDC diff --git a/src/ftw.c b/src/ftw.c index 92fc126c..a9abc853 100644 --- a/src/ftw.c +++ b/src/ftw.c @@ -185,7 +185,7 @@ int rpl_lstat (const char *, struct stat *); # define NFTW_NEW_NAME __new_nftw # define INO_T ino_t # define STAT stat -# ifdef _LIBC +# if defined(_LIBC) && !NEW_GLIBC # define LXSTAT __lxstat # define XSTAT __xstat # define FXSTATAT __fxstatat diff --git a/src/ftw64.c b/src/ftw64.c index 7cc8cdfd..cee1f2bc 100644 --- a/src/ftw64.c +++ b/src/ftw64.c @@ -18,6 +18,8 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include "config.h" + #define __FTW64_C #define FTW_NAME ftw64 #define NFTW_NAME nftw64 @@ -25,9 +27,15 @@ #define NFTW_NEW_NAME __new_nftw64 #define INO_T ino64_t #define STAT stat64 -#define LXSTAT __lxstat64 -#define XSTAT __xstat64 -#define FXSTATAT __fxstatat64 +#if NEW_GLIBC +# define LXSTAT(V,f,sb) lstat64 (f,sb) +# define XSTAT(V,f,sb) stat64 (f,sb) +# define FXSTATAT(V,d,f,sb,m) fstatat64 (d, f, sb, m) +#else +# define LXSTAT __lxstat64 +# define XSTAT __xstat64 +# define FXSTATAT __fxstatat64 +#endif #define FTW_FUNC_T __ftw64_func_t #define NFTW_FUNC_T __nftw64_func_t diff --git a/src/libfakechroot.h b/src/libfakechroot.h index 4cf199ff..64ff15fb 100644 --- a/src/libfakechroot.h +++ b/src/libfakechroot.h @@ -200,6 +200,21 @@ # endif #endif +#ifndef _STAT_VER + #if defined (__aarch64__) + #define _STAT_VER 0 + #elif defined (__powerpc__) && __WORDSIZE == 64 + #define _STAT_VER 1 + #elif defined (__riscv) && __riscv_xlen==64 + #define _STAT_VER 0 + #elif defined (__s390x__) + #define _STAT_VER 1 + #elif defined (__x86_64__) + #define _STAT_VER 1 + #else + #define _STAT_VER 3 + #endif +#endif typedef void (*fakechroot_wrapperfn_t)(void); diff --git a/src/lstat.c b/src/lstat.c index 54e3263f..fa383234 100644 --- a/src/lstat.c +++ b/src/lstat.c @@ -20,7 +20,7 @@ #include -#ifndef HAVE___LXSTAT +#if !defined(HAVE___LXSTAT) || NEW_GLIBC #include #include diff --git a/src/lstat.h b/src/lstat.h index ee483033..c46a2b9b 100644 --- a/src/lstat.h +++ b/src/lstat.h @@ -24,7 +24,7 @@ #include #include "libfakechroot.h" -#ifndef HAVE___LXSTAT +#if !defined(HAVE___LXSTAT) || NEW_GLIBC wrapper_proto(lstat, int, (const char *, struct stat *)); diff --git a/src/lstat64.c b/src/lstat64.c index b6212fc8..a332d7c3 100644 --- a/src/lstat64.c +++ b/src/lstat64.c @@ -20,7 +20,7 @@ #include -#if defined(HAVE_LSTAT64) && !defined(HAVE___LXSTAT64) +#if defined(HAVE_LSTAT64) && (!defined(HAVE___LXSTAT64) || NEW_GLIBC) #define _LARGEFILE64_SOURCE #define _BSD_SOURCE diff --git a/src/mknod.c b/src/mknod.c index 27710372..aeb750b0 100644 --- a/src/mknod.c +++ b/src/mknod.c @@ -20,7 +20,7 @@ #include -#ifndef HAVE___XMKNOD +#if !defined(HAVE___XMKNOD) || NEW_GLIBC #include #include "libfakechroot.h" diff --git a/src/mknodat.c b/src/mknodat.c index 732a22bc..3239b357 100644 --- a/src/mknodat.c +++ b/src/mknodat.c @@ -20,7 +20,7 @@ #include -#if defined(HAVE_MKNODAT) && !defined(HAVE___XMKNODAT) +#if defined(HAVE_MKNODAT) && (!defined(HAVE___XMKNODAT) || NEW_GLIBC) #define _ATFILE_SOURCE #include diff --git a/src/stat.c b/src/stat.c index 7b377933..5ef57bab 100644 --- a/src/stat.c +++ b/src/stat.c @@ -20,7 +20,7 @@ #include -#ifndef HAVE___XSTAT +#if !defined(HAVE___XSTAT) || NEW_GLIBC #define _BSD_SOURCE #define _DEFAULT_SOURCE diff --git a/src/stat64.c b/src/stat64.c index a360f66f..993ce808 100644 --- a/src/stat64.c +++ b/src/stat64.c @@ -20,7 +20,7 @@ #include -#if defined(HAVE_STAT64) && !defined(HAVE___XSTAT64) +#if defined(HAVE_STAT64) && (!defined(HAVE___XSTAT64) || NEW_GLIBC) #define _BSD_SOURCE #define _LARGEFILE64_SOURCE From 5366e9a366b213b879abf0f0a3aeb3409d3b57ed Mon Sep 17 00:00:00 2001 From: neok-m4700 Date: Wed, 24 Feb 2021 17:36:57 +0100 Subject: [PATCH 06/11] wrap fstatat and fstatat64 https://github.com/dex4er/fakechroot/pull/86 --- configure.ac | 2 ++ src/Makefile.am | 2 ++ src/fstatat.c | 42 ++++++++++++++++++++++++++++++++++++++++++ src/fstatat64.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 89 insertions(+) create mode 100644 src/fstatat.c create mode 100644 src/fstatat64.c diff --git a/configure.ac b/configure.ac index 9cc2e779..5b3053e1 100644 --- a/configure.ac +++ b/configure.ac @@ -218,6 +218,8 @@ AC_CHECK_FUNCS(m4_normalize([ freopen64 fstat fstat64 + fstatat + fstatat64 fts_children fts_open fts_read diff --git a/src/Makefile.am b/src/Makefile.am index 60663452..eb311c0a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -61,6 +61,8 @@ libfakechroot_la_SOURCES = \ fopen64.c \ freopen.c \ freopen64.c \ + fstatat.c \ + fstatat64.c \ fts.c \ fts64.c \ ftw.c \ diff --git a/src/fstatat.c b/src/fstatat.c new file mode 100644 index 00000000..ca7578b3 --- /dev/null +++ b/src/fstatat.c @@ -0,0 +1,42 @@ +/* + libfakechroot -- fake chroot environment + Copyright (c) 2010, 2021 Piotr Roszatycki + + This library 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 library 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include + +#ifdef HAVE_FSTATAT + +#define _ATFILE_SOURCE +#define _POSIX_C_SOURCE 200809L +#include +#include +#include "libfakechroot.h" + +wrapper(fstatat, int, (int dirfd, const char *pathname, struct stat *buf, int flags)) +{ + char fakechroot_abspath[FAKECHROOT_PATH_MAX]; + char fakechroot_buf[FAKECHROOT_PATH_MAX]; + debug("fstatat(%d, \"%s\", &buf, %d)", dirfd, pathname, flags); + expand_chroot_path_at(dirfd, pathname); + return nextcall(fstatat)(dirfd, pathname, buf, flags); +} + +#else +typedef int empty_translation_unit; +#endif diff --git a/src/fstatat64.c b/src/fstatat64.c new file mode 100644 index 00000000..18633725 --- /dev/null +++ b/src/fstatat64.c @@ -0,0 +1,43 @@ +/* + libfakechroot -- fake chroot environment + Copyright (c) 2010, 2021 Piotr Roszatycki + + This library 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 library 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include + +#ifdef HAVE_FSTATAT64 + +#define _ATFILE_SOURCE +#define _POSIX_C_SOURCE 200809L +#define _LARGEFILE64_SOURCE +#include +#include +#include "libfakechroot.h" + +wrapper(fstatat64, int, (int dirfd, const char *pathname, struct stat64 *buf, int flags)) +{ + char fakechroot_abspath[FAKECHROOT_PATH_MAX]; + char fakechroot_buf[FAKECHROOT_PATH_MAX]; + debug("fstatat64(%d, \"%s\", &buf, %d)", dirfd, pathname, flags); + expand_chroot_path_at(dirfd, pathname); + return nextcall(fstatat64)(dirfd, pathname, buf, flags); +} + +#else +typedef int empty_translation_unit; +#endif From bc7ef087c17a475ec03768053fa22c2193ae7fc2 Mon Sep 17 00:00:00 2001 From: Johannes Schauer Marin Rodrigues Date: Wed, 24 Aug 2022 08:26:04 +0200 Subject: [PATCH 07/11] Wrap all functions accessing /etc/passwd, /etc/group and /etc/shadow Starting with glibc 2.32 the compat nss module for getpwnam calls __nss_files_fopen (which is a GLIBC_PRIVATE symbol provided by glibc) instead of fopen (see 299210c1fa67e2dfb564475986fce11cd33db9ad). This leads to getpwnam calls accessing /etc/passwd from *outside* the chroot and as a result programs like adduser do not work correctly anymore under fakechroot. Starting with glibc 2.34 the __nss_files_fopen was moved from nss to libc.so and thus wrapping it with LD_PRELOAD has no affect anymore (see 6212bb67f4695962748a5981e1b9fea105af74f6). So now we also wrap all the functions accessing /etc/passwd, /etc/group and /etc/shadow. This solution will ignore NIS, LDAP or other local files as potentially configured in /etc/nsswitch.conf. https://github.com/dex4er/fakechroot/pull/98 --- src/Makefile.am | 1 + src/passwd.c | 296 +++++++++++++++++++++++++++++++++++++++++ test/Makefile.am | 1 + test/src/Makefile.am | 1 + test/src/test-passwd.c | 28 ++++ test/t/passwd.t | 23 ++++ test/testtree.sh | 6 + 7 files changed, 356 insertions(+) create mode 100644 src/passwd.c create mode 100644 test/src/test-passwd.c create mode 100755 test/t/passwd.t diff --git a/src/Makefile.am b/src/Makefile.am index eb311c0a..6e9d9ae1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -120,6 +120,7 @@ libfakechroot_la_SOURCES = \ openat64.c \ opendir.c \ opendir.h \ + passwd.c \ pathconf.c \ popen.c \ posix_spawn.c \ diff --git a/src/passwd.c b/src/passwd.c new file mode 100644 index 00000000..d4cee86c --- /dev/null +++ b/src/passwd.c @@ -0,0 +1,296 @@ +/* + libfakechroot -- fake chroot environment + Copyright (c) 2010, 2013 Piotr Roszatycki + + This library 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 library 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include + +/* + * Starting with glibc 2.32 the compat nss module for getpwnam calls + * __nss_files_fopen (which is a GLIBC_PRIVATE symbol provided by glibc) + * instead of fopen (see 299210c1fa67e2dfb564475986fce11cd33db9ad). This + * leads to getpwnam calls accessing /etc/passwd from *outside* the chroot + * and as a result programs like adduser do not work correctly anymore + * under fakechroot. + * + * Starting with glibc 2.34 the __nss_files_fopen was moved from nss to + * libc.so and thus wrapping it with LD_PRELOAD has no affect anymore + * (see 6212bb67f4695962748a5981e1b9fea105af74f6). + * + * So now we also wrap all the functions accessing /etc/passwd, /etc/group + * and /etc/shadow. This solution will ignore NIS, LDAP or other local files + * as potentially configured in /etc/nsswitch.conf. + */ + +#include +#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 32) + +#include +#include +#include +#include +#include +#include +#include "libfakechroot.h" + +/* getpwent, setpwent, endpwent, getpwuid, getpwnam */ + +static FILE *pw_f; + +wrapper(getpwent, struct passwd *, (void)) +{ + if (!pw_f) pw_f = fopen("/etc/passwd", "rbe"); + if (!pw_f) return 0; + return fgetpwent(pw_f); +} + +wrapper (getpwent_r, int, (struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp)) +{ + if (!pw_f) pw_f = fopen("/etc/passwd", "rbe"); + if (!pw_f) return 0; + return fgetpwent_r(pw_f, pwbuf, buf, buflen, pwbufp); +} + +wrapper(setpwent, void, (void)) +{ + if (pw_f) fclose(pw_f); + pw_f = 0; +} + +wrapper(endpwent, void, (void)) +{ + if (pw_f) fclose(pw_f); + pw_f = 0; +} + +wrapper(getpwuid, struct passwd *, (uid_t uid)) +{ + debug("getpwuid(\"%ul\")", uid); + FILE *f = fopen("/etc/passwd", "rbe"); + if (!f) { + return NULL; + } + struct passwd *res = NULL; + while ((res = fgetpwent(f))) { + if (res->pw_uid == uid) + break; + } + fclose(f); + return res; +} + +wrapper(getpwuid_r, int, (uid_t uid, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result)) +{ + debug("getpwuid_r(\"%ul\")", uid); + FILE *f = fopen("/etc/passwd", "rbe"); + if (!f) { + return errno; + } + int res; + while (!(res = fgetpwent_r(f, pwd, buf, buflen, result))) { + if (pwd->pw_uid == uid) + break; + } + fclose(f); + return res; +} + +wrapper(getpwnam, struct passwd *, (const char *name)) +{ + debug("getpwnam(\"%s\")", name); + FILE *f = fopen("/etc/passwd", "rbe"); + if (!f) { + return NULL; + } + struct passwd *res = NULL; + while ((res = fgetpwent(f))) { + if (name && !strcmp(name, res->pw_name)) + break; + } + fclose(f); + return res; +} + +wrapper(getpwnam_r, int, (const char *name, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result)) +{ + debug("getpwnam_r(\"%s\")", name); + FILE *f = fopen("/etc/passwd", "rbe"); + if (!f) { + return errno; + } + int res; + while (!(res = fgetpwent_r(f, pwd, buf, buflen, result))) { + if (name && !strcmp(name, pwd->pw_name)) + break; + } + fclose(f); + return res; +} + +/* getgrent, setgrent, endgrent, getgrgid, getgrnam */ + +static FILE *gr_f; + +wrapper(getgrent, struct group *, (void)) +{ + if (!gr_f) gr_f = fopen("/etc/group", "rbe"); + if (!gr_f) return 0; + return fgetgrent(gr_f); +} + +wrapper (getgrent_r, int, (struct group *gbuf, char *buf, size_t buflen, struct group **gbufp)) +{ + if (!gr_f) gr_f = fopen("/etc/group", "rbe"); + if (!gr_f) return 0; + return fgetgrent_r(gr_f, gbuf, buf, buflen, gbufp); +} + +wrapper(setgrent, void, (void)) +{ + if (gr_f) fclose(gr_f); + gr_f = 0; +} + +wrapper(endgrent, void, (void)) +{ + if (gr_f) fclose(gr_f); + gr_f = 0; +} + +wrapper(getgrgid, struct group *, (gid_t gid)) +{ + debug("getgrgid(\"%ul\")", gid); + FILE *f = fopen("/etc/group", "rbe"); + if (!f) { + return NULL; + } + struct group *res = NULL; + while ((res = fgetgrent(f))) { + if (res->gr_gid == gid) + break; + } + fclose(f); + return res; +} + +wrapper(getgrgid_r, int, (gid_t gid, struct group *grp, char *buf, size_t buflen, struct group **result)) +{ + debug("getgrgid_r(\"%ul\")", gid); + FILE *f = fopen("/etc/group", "rbe"); + if (!f) { + return errno; + } + int res; + while (!(res = fgetgrent_r(f, grp, buf, buflen, result))) { + if (grp->gr_gid == gid) + break; + } + fclose(f); + return res; +} + +wrapper(getgrnam, struct group *, (const char *name)) +{ + debug("getgrnam(\"%s\")", name); + FILE *f = fopen("/etc/group", "rbe"); + if (!f) { + return NULL; + } + struct group *res = NULL; + while ((res = fgetgrent(f))) { + if (name && !strcmp(name, res->gr_name)) + break; + } + fclose(f); + return res; +} + +wrapper(getgrnam_r, int, (const char *name, struct group *grp, char *buf, size_t buflen, struct group **result)) +{ + debug("getgrnam_r(\"%s\")", name); + FILE *f = fopen("/etc/group", "rbe"); + if (!f) { + return errno; + } + int res; + while (!(res = fgetgrent_r(f, grp, buf, buflen, result))) { + if (name && !strcmp(name, grp->gr_name)) + break; + } + fclose(f); + return res; +} + +/* getspent, setspent, endspent, getspnam */ + +static FILE *sp_f; + +wrapper(getspent, struct spwd *, (void)) +{ + if (!sp_f) sp_f = fopen("/etc/shadow", "rbe"); + if (!sp_f) return 0; + return fgetspent(sp_f); +} + +wrapper(setspent, void, (void)) +{ + if (sp_f) fclose(sp_f); + sp_f = 0; +} + +wrapper(endspent, void, (void)) +{ + if (sp_f) fclose(sp_f); + sp_f = 0; +} + +wrapper(getspnam, struct spwd *, (const char *name)) +{ + debug("getspnam(\"%s\")", name); + FILE *f = fopen("/etc/shadow", "rbe"); + if (!f) { + return NULL; + } + struct spwd *res = NULL; + while ((res = fgetspent(f))) { + if (name && !strcmp(name, res->sp_namp)) + break; + } + fclose(f); + return res; +} + +wrapper(getspnam_r, int, (const char *name, struct spwd *spbuf, char *buf, size_t buflen, struct spwd **spbufp)) +{ + debug("getspnam_r(\"%s\")", name); + FILE *f = fopen("/etc/shadow", "rbe"); + if (!f) { + return errno; + } + int res; + while (!(res = fgetspent_r(f, spbuf, buf, buflen, spbufp))) { + if (name && !strcmp(name, spbuf->sp_namp)) + break; + } + fclose(f); + return res; +} + +#else +typedef int empty_translation_unit; +#endif diff --git a/test/Makefile.am b/test/Makefile.am index 0021b0a1..a1ec743d 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -22,6 +22,7 @@ TESTS = \ t/mkstemps.t \ t/mktemp.t \ t/opendir.t \ + t/passwd.t \ t/popen.t \ t/posix_spawn.t \ t/posix_spawnp.t \ diff --git a/test/src/Makefile.am b/test/src/Makefile.am index 5f5fde8d..594a8e0f 100644 --- a/test/src/Makefile.am +++ b/test/src/Makefile.am @@ -15,6 +15,7 @@ check_PROGRAMS = \ test-mkstemps \ test-mktemp \ test-opendir \ + test-passwd \ test-popen \ test-posix_spawn \ test-posix_spawnp \ diff --git a/test/src/test-passwd.c b/test/src/test-passwd.c new file mode 100644 index 00000000..fb9c8c4c --- /dev/null +++ b/test/src/test-passwd.c @@ -0,0 +1,28 @@ +#include +#include +#include +#include +#include +#include + +int main (int argc, char *argv[]) { + struct passwd *pwd; + + if (argc != 2) { + fprintf(stderr, "Usage: %s username\n", argv[0]); + exit(EXIT_FAILURE); + } + + pwd = getpwnam(argv[1]); + if (pwd == NULL) { + if (errno == 0) { + printf("Not found\n"); + } else { + perror("getpwnam"); + } + exit(EXIT_FAILURE); + } + + printf("%jd\n", (intmax_t)(pwd->pw_uid)); + exit(EXIT_SUCCESS); +} diff --git a/test/t/passwd.t b/test/t/passwd.t new file mode 100755 index 00000000..5c3414e0 --- /dev/null +++ b/test/t/passwd.t @@ -0,0 +1,23 @@ +#!/bin/sh + +srcdir=${srcdir:-.} +. $srcdir/common.inc.sh + +prepare 4 + +for chroot in chroot fakechroot; do + if [ $chroot = "chroot" ] && ! is_root; then + skip $(( $tap_plan / 2 )) "not root" + else + + t=`$srcdir/$chroot.sh $testtree /bin/test-passwd user 2>&1` + test "$t" = "1337" || not + ok "$chroot uid is" $t + + t=`$srcdir/$chroot.sh $testtree getent group user 2>&1` + test "$t" = "user:x:1337:" || not + ok "$chroot getent group user is" $t + fi +done + +cleanup diff --git a/test/testtree.sh b/test/testtree.sh index ee35fc26..d857a195 100755 --- a/test/testtree.sh +++ b/test/testtree.sh @@ -32,6 +32,10 @@ do mkdir -p $destdir/$d done +echo "user:x:1337:1337:user:/home/user:/bin/bash" > $destdir/etc/passwd +echo "root:x:0:" > $destdir/etc/group +echo "user:x:1337:" >> $destdir/etc/group + for d in \ /dev \ /proc @@ -64,6 +68,7 @@ for p in \ '/usr/bin/dirname' \ '/usr/bin/env' \ '/usr/bin/find' \ + '/usr/bin/getent' \ '/usr/bin/id' \ '/usr/bin/ischroot' \ '/usr/bin/less' \ @@ -116,6 +121,7 @@ for p in \ 'libm.so.*' \ 'libncurses.so.*' \ 'libncursesw.so.*' \ + 'libnss_*.so.*' \ 'libpcre*.so.*' \ 'libpthread.so.*' \ 'libreadline.so.*' \ From d9a47178203931231987d10117acb5684d12ed4c Mon Sep 17 00:00:00 2001 From: Johannes Schauer Marin Rodrigues Date: Tue, 1 Nov 2022 00:47:56 +0100 Subject: [PATCH 08/11] add test/t/rm.t and amend test/t/touch.t with --no-dereference test - test/t/rm.t will fail under glibc 2.34 unless __stat64_time64 functions are wrapped - test/t/touch.t will fail under glibc 2.34 unless __lstat64_time64 is wrapped --- test/Makefile.am | 1 + test/t/rm.t | 25 +++++++++++++++++++++++++ test/t/touch.t | 17 +++++++++++++++-- 3 files changed, 41 insertions(+), 2 deletions(-) create mode 100755 test/t/rm.t diff --git a/test/Makefile.am b/test/Makefile.am index a1ec743d..88e740e5 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -29,6 +29,7 @@ TESTS = \ t/pwd.t \ t/readlink.t \ t/realpath.t \ + t/rm.t \ t/socket-af_unix.t \ t/statfs.t \ t/statvfs.t \ diff --git a/test/t/rm.t b/test/t/rm.t new file mode 100755 index 00000000..9ecf88c9 --- /dev/null +++ b/test/t/rm.t @@ -0,0 +1,25 @@ +#!/bin/sh + +srcdir=${srcdir:-.} +. $srcdir/common.inc.sh + +prepare 2 + +for chroot in chroot fakechroot; do + + if [ $chroot = "chroot" ] && ! is_root; then + skip $(( $tap_plan / 2 )) "not root" + else + + mkdir -p $testtree/dir-$chroot + echo 'something' > $testtree/dir-$chroot/file + + $srcdir/$chroot.sh $testtree /bin/sh -c "rm -r /dir-$chroot" + test -e $testtree/dir-$chroot && not + ok "$chroot rm -r /dir-$chroot:" $t + + fi + +done + +cleanup diff --git a/test/t/touch.t b/test/t/touch.t index fbea316b..cc05a2ba 100755 --- a/test/t/touch.t +++ b/test/t/touch.t @@ -3,12 +3,12 @@ srcdir=${srcdir:-.} . $srcdir/common.inc.sh -prepare 16 +prepare 24 . $srcdir/touch.inc.sh if [ -z "$touch" ]; then - skip 16 "touch not found" + skip 24 "touch not found" else for chroot in chroot fakechroot; do @@ -37,6 +37,19 @@ else sleep 1 + # with --no-dereference, on 32bit, touch will use __lstat64_time64 + t=`$srcdir/$chroot.sh $testtree $touch -h -r /tmp/$chroot-touch.txt /tmp/$chroot-touch2.txt 2>&1` + test "$t" = "" || not + ok "$chroot touch -r" $t + test -f $testtree/tmp/$chroot-touch2.txt || not + ok "$chroot $chroot-touch2.txt exists" + test $testtree/tmp/$chroot-touch2.txt -nt $testtree/tmp/$chroot-touch.txt && not + ok "$chroot $chroot-touch2.txt is not newer than touch.txt" + test $testtree/tmp/$chroot-touch2.txt -ot $testtree/tmp/$chroot-touch.txt && not + ok "$chroot $chroot-touch2.txt is not older than $chroot-touch.txt" + + sleep 1 + t=`$srcdir/$chroot.sh $testtree $touch -m /tmp/$chroot-touch.txt 2>&1` test "$t" = "" || not ok "$chroot touch -m" $t From dac74cd68cfb6eeaae9cd13bdc48737a44980df9 Mon Sep 17 00:00:00 2001 From: Johannes Schauer Marin Rodrigues Date: Tue, 1 Nov 2022 00:48:23 +0100 Subject: [PATCH 09/11] support glibc 2.34 by wrapping __{f,l,}stat{at,}64_time64 and__utime{nsat,s,}64 These functions are only wrapped on 32 bit platforms like i386, armel or armhf. On 64 bit platforms, the corresponding HAVE_* macros will not be defined. * __fstatat64_time64 * __lstat64_time64 * __stat64_time64 * __utime64 * __utimensat64 * __utimes64 --- configure.ac | 6 +++++ src/Makefile.am | 6 +++++ src/__fstatat64_time64.c | 44 ++++++++++++++++++++++++++++++++++++ src/__lstat64_time64.c | 49 ++++++++++++++++++++++++++++++++++++++++ src/__stat64_time64.c | 47 ++++++++++++++++++++++++++++++++++++++ src/__utime64.c | 41 +++++++++++++++++++++++++++++++++ src/__utimensat64.c | 42 ++++++++++++++++++++++++++++++++++ src/__utimes64.c | 42 ++++++++++++++++++++++++++++++++++ 8 files changed, 277 insertions(+) create mode 100644 src/__fstatat64_time64.c create mode 100644 src/__lstat64_time64.c create mode 100644 src/__stat64_time64.c create mode 100644 src/__utime64.c create mode 100644 src/__utimensat64.c create mode 100644 src/__utimes64.c diff --git a/configure.ac b/configure.ac index 5b3053e1..26c06116 100644 --- a/configure.ac +++ b/configure.ac @@ -158,11 +158,13 @@ ACX_CHECK_FTS_NAME_TYPE # Checks for library functions. AC_CHECK_FUNCS(m4_normalize([ __chk_fail + __fstatat64_time64 __fxstat64 __fxstatat __fxstatat64 __getcwd_chk __getwd_chk + __lstat64_time64 __lxstat __lxstat64 __open @@ -175,7 +177,11 @@ AC_CHECK_FUNCS(m4_normalize([ __realpath_chk __readlink_chk __readlinkat_chk + __stat64_time64 __statfs + __utime64 + __utimensat64 + __utimes64 __xmknod __xmknodat __xstat diff --git a/src/Makefile.am b/src/Makefile.am index 6e9d9ae1..55193a96 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,9 +1,11 @@ pkglib_LTLIBRARIES = libfakechroot.la libfakechroot_la_SOURCES = \ + __fstatat64_time64.c \ __fxstatat.c \ __fxstatat64.c \ __getcwd_chk.c \ __getwd_chk.c \ + __lstat64_time64.c \ __lxstat.c \ __lxstat64.c \ __lxstat64.h \ @@ -18,7 +20,11 @@ libfakechroot_la_SOURCES = \ __readlinkat_chk.c \ __realpath_chk.c \ __realpath_chk.h \ + __stat64_time64.c \ __statfs.c \ + __utime64.c \ + __utimensat64.c \ + __utimes64.c \ __xmknod.c \ __xmknodat.c \ __xstat.c \ diff --git a/src/__fstatat64_time64.c b/src/__fstatat64_time64.c new file mode 100644 index 00000000..47a401f2 --- /dev/null +++ b/src/__fstatat64_time64.c @@ -0,0 +1,44 @@ +/* + libfakechroot -- fake chroot environment + Copyright (c) 2010, 2021 Piotr Roszatycki + + This library 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 library 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include + +#ifdef HAVE___FSTATAT64_TIME64 + +#define _ATFILE_SOURCE +#define _POSIX_C_SOURCE 200809L +#include +#include +#include "libfakechroot.h" + +struct __stat64_t64; + +wrapper(__fstatat64_time64, int, (int dirfd, const char *pathname, struct __stat64_t64 *buf, int flags)) +{ + char fakechroot_abspath[FAKECHROOT_PATH_MAX]; + char fakechroot_buf[FAKECHROOT_PATH_MAX]; + debug("__fstatat64_time64(%d, \"%s\", &buf, %d)", dirfd, pathname, flags); + expand_chroot_path_at(dirfd, pathname); + return nextcall(__fstatat64_time64)(dirfd, pathname, buf, flags); +} + +#else +typedef int empty_translation_unit; +#endif diff --git a/src/__lstat64_time64.c b/src/__lstat64_time64.c new file mode 100644 index 00000000..e3e84002 --- /dev/null +++ b/src/__lstat64_time64.c @@ -0,0 +1,49 @@ +/* + libfakechroot -- fake chroot environment + Copyright (c) 2010, 2021 Piotr Roszatycki + + This library 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 library 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include + +#ifdef HAVE___LSTAT64_TIME64 + +#define _ATFILE_SOURCE +#define _POSIX_C_SOURCE 200809L +#include +#include +#include "libfakechroot.h" + +struct __stat64_t64; + +wrapper(__lstat64_time64, int, (const char *filename, struct __stat64_t64 *buf)) +{ + char fakechroot_abspath[FAKECHROOT_PATH_MAX]; + char fakechroot_buf[FAKECHROOT_PATH_MAX]; + char resolved[FAKECHROOT_PATH_MAX]; + debug("__lstat64_time64(\"%s\", &buf)", filename); + if (rel2abs(filename, resolved) == NULL) { + return -1; + } + filename = resolved; + expand_chroot_path(filename); + return nextcall(__lstat64_time64)(filename, buf); +} + +#else +typedef int empty_translation_unit; +#endif diff --git a/src/__stat64_time64.c b/src/__stat64_time64.c new file mode 100644 index 00000000..1b65345e --- /dev/null +++ b/src/__stat64_time64.c @@ -0,0 +1,47 @@ +/* + libfakechroot -- fake chroot environment + Copyright (c) 2010-2015 Piotr Roszatycki + + This library 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 library 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include + +#ifdef HAVE___STAT64_TIME64 + +#define _BSD_SOURCE +#define _LARGEFILE64_SOURCE +#define _DEFAULT_SOURCE +#include +#include +#include + +#include "libfakechroot.h" + +struct __stat64_t64; + +wrapper(__stat64_time64, int, (const char * file_name, struct __stat64_t64 * buf)) +{ + char fakechroot_abspath[FAKECHROOT_PATH_MAX]; + char fakechroot_buf[FAKECHROOT_PATH_MAX]; + debug("__stat64_time64(\"%s\", &buf)", file_name); + expand_chroot_path(file_name); + return nextcall(__stat64_time64)(file_name, buf); +} + +#else +typedef int empty_translation_unit; +#endif diff --git a/src/__utime64.c b/src/__utime64.c new file mode 100644 index 00000000..65d6e831 --- /dev/null +++ b/src/__utime64.c @@ -0,0 +1,41 @@ +/* + libfakechroot -- fake chroot environment + Copyright (c) 2010, 2013 Piotr Roszatycki + + This library 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 library 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include + +#ifdef HAVE___UTIME64 + +#define _ATFILE_SOURCE +#define _POSIX_C_SOURCE 200809L +#include +#include "libfakechroot.h" + +wrapper(__utime64, int, (const char * filename, const struct utimbuf * buf)) +{ + char fakechroot_abspath[FAKECHROOT_PATH_MAX]; + char fakechroot_buf[FAKECHROOT_PATH_MAX]; + debug("__utime64(\"%s\", &buf)", filename); + expand_chroot_path(filename); + return nextcall(__utime64)(filename, buf); +} + +#else +typedef int empty_translation_unit; +#endif diff --git a/src/__utimensat64.c b/src/__utimensat64.c new file mode 100644 index 00000000..3973d64c --- /dev/null +++ b/src/__utimensat64.c @@ -0,0 +1,42 @@ +/* + libfakechroot -- fake chroot environment + Copyright (c) 2010, 2013 Piotr Roszatycki + + This library 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 library 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include + +#ifdef HAVE___UTIMENSAT64 + +#define _ATFILE_SOURCE +#define _POSIX_C_SOURCE 200809L +#include +#include "libfakechroot.h" + + +wrapper(__utimensat64, int, (int dirfd, const char * pathname, const struct timespec times [2], int flags)) +{ + char fakechroot_abspath[FAKECHROOT_PATH_MAX]; + char fakechroot_buf[FAKECHROOT_PATH_MAX]; + debug("utimeat(%d, \"%s\", &buf, %d)", dirfd, pathname, flags); + expand_chroot_path_at(dirfd, pathname); + return nextcall(__utimensat64)(dirfd, pathname, times, flags); +} + +#else +typedef int empty_translation_unit; +#endif diff --git a/src/__utimes64.c b/src/__utimes64.c new file mode 100644 index 00000000..03e57d16 --- /dev/null +++ b/src/__utimes64.c @@ -0,0 +1,42 @@ +/* + libfakechroot -- fake chroot environment + Copyright (c) 2010, 2013 Piotr Roszatycki + + This library 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 library 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include + +#ifdef HAVE___UTIMES64 + +#define _ATFILE_SOURCE +#define _POSIX_C_SOURCE 200809L + +#include +#include "libfakechroot.h" + +wrapper(__utimes64, int, (const char * filename, UTIMES_TYPE_ARG2(tv))) +{ + char fakechroot_abspath[FAKECHROOT_PATH_MAX]; + char fakechroot_buf[FAKECHROOT_PATH_MAX]; + debug("__utimes64(\"%s\", &tv)", filename); + expand_chroot_path(filename); + return nextcall(__utimes64)(filename, tv); +} + +#else +typedef int empty_translation_unit; +#endif From 117d2e6e741bc4ff47e41e6879ca9e9821755ffd Mon Sep 17 00:00:00 2001 From: Johannes Schauer Marin Rodrigues Date: Tue, 31 Jan 2023 11:43:33 +0100 Subject: [PATCH 10/11] also investigate .interp section for architectures that do not list the linker in `objdump -p` like mips64el, ppc64el and s390x --- scripts/ldd.fakechroot.pl | 33 +++++++++++++++++++++++++++++++++ test/Makefile.am | 1 + test/t/ldd_interp.t | 26 ++++++++++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100755 test/t/ldd_interp.t diff --git a/scripts/ldd.fakechroot.pl b/scripts/ldd.fakechroot.pl index b4bb2a8c..13a94540 100755 --- a/scripts/ldd.fakechroot.pl +++ b/scripts/ldd.fakechroot.pl @@ -124,6 +124,38 @@ sub objdump { } } +# mips64el, ppc64el and s390x do not list the linker itself +# if it's missing, obtain it from the .interp section +# +# mips64el: /lib64/ld.so.1 +# ppc64el: /lib64/ld64.so.2 +# s390x: /lib/ld64.so.1 +sub elfinterp { + my $file = shift; + my $res = ''; + local *PIPE; + open PIPE, "objdump -sj .interp '$file' 2>/dev/null |"; + while (my $line = ) { + if ( $line !~ /^ [a-f0-9]+ ([a-f0-9][a-f0-9][a-f0-9 ]{6} [a-f0-9 ]{8} [a-f0-9 ]{8} [a-f0-9 ]{8}) /) { + next; + } + $line = $1; + $line =~ s/ //g; + $line =~ s/(..)/chr(hex($1))/eg; + $res .= $line; + } + close PIPE; + + # remove trailing NUL byte + $res =~ s/\000$//; + + # only add if it is missing + if ( $res && !exists $Libs{$res} ) { + push @Libs, $res; + $Libs{$res} = ''; + } +} + sub load_ldsoconf { my ($file) = @_; @@ -191,6 +223,7 @@ sub load_ldsoconf { } objdump($file); + elfinterp($file_in_chroot); if ($Dynamic == 0) { print "\tnot a dynamic executable\n"; diff --git a/test/Makefile.am b/test/Makefile.am index 88e740e5..d7f98f03 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -19,6 +19,7 @@ TESTS = \ t/host.t \ t/java.t \ t/jemalloc.t \ + t/ldd_interp.t \ t/mkstemps.t \ t/mktemp.t \ t/opendir.t \ diff --git a/test/t/ldd_interp.t b/test/t/ldd_interp.t new file mode 100755 index 00000000..7c968bb8 --- /dev/null +++ b/test/t/ldd_interp.t @@ -0,0 +1,26 @@ +#!/bin/sh + +srcdir=${srcdir:-.} +. $srcdir/common.inc.sh + +plan 1 + +pwd=`dirname $0` +abs_top_srcdir=${abs_top_srcdir:-`cd "$pwd/../.." 2>/dev/null && pwd -P`} + +interp_file=$(file /bin/true | sed 's/^.*, interpreter \([^,]\+\), .*$/\1/') +interp_readelf=$(readelf --string-dump=.interp /bin/true | sed -ne 's/^ \[ \+[0-9]\+\] //p') + +# diag "$interp_file" "$interp_readelf" + +test "$interp_file" = "$interp_readelf" || not + +# ldd /bin/true | diag + +ldd /bin/true | grep --quiet "^[[:space:]]$interp_file (" || not + +# "$abs_top_srcdir/scripts/ldd.fakechroot" /bin/true | diag + +"$abs_top_srcdir/scripts/ldd.fakechroot" /bin/true | grep --quiet "^[[:space:]]$interp_file (" || not + +ok "ldd lists interpreter $interp_file" From 1617833d4bfa415cbe2fc1e961cb751e47697c24 Mon Sep 17 00:00:00 2001 From: Johannes Schauer Marin Rodrigues Date: Mon, 6 Feb 2023 10:42:40 +0100 Subject: [PATCH 11/11] test/touch.inc.sh: use testtree variable - the variable is set in test/common.inc.sh and includes `basename $0 .t` - otherwise test/t/touch.t will always get skipped --- test/touch.inc.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/touch.inc.sh b/test/touch.inc.sh index 25e0dc01..76c21321 100644 --- a/test/touch.inc.sh +++ b/test/touch.inc.sh @@ -1,6 +1,6 @@ -if [ -x testtree/usr/bin/touch ]; then +if [ -x $testtree/usr/bin/touch ]; then touch=/usr/bin/touch -elif [ -x testtree/bin/touch ]; then +elif [ -x $testtree/bin/touch ]; then touch=/bin/touch else touch=