void-packages/srcpkgs/fakechroot/patches/glibc-2.34.patch

1552 lines
42 KiB
Diff

https://github.com/dex4er/fakechroot/pull/104
From 11589e1037372c5ad719e1e46d7462fd196caa56 Mon Sep 17 00:00:00 2001
From: Johannes Schauer Marin Rodrigues <josch@mister-muffin.de>
Date: Thu, 24 Jun 2021 10:38:28 +0200
Subject: [PATCH 1/9] 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 <unistd.h>
+#include <fcntl.h>
#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 <lugia.kun@gmail.com>
Date: Fri, 1 May 2020 21:14:32 +0900
Subject: [PATCH 2/9] 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 <dlfcn.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+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 <ilya.lipnitskiy@gmail.com>
Date: Mon, 22 Feb 2021 21:44:07 -0800
Subject: [PATCH 3/9] tmpnam.c: fix heap overflow
https://github.com/dex4er/fakechroot/pull/85
Signed-off-by: Ilya Lipnitskiy <ilya.lipnitskiy@gmail.com>
---
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 <ilya.lipnitskiy@gmail.com>
Date: Mon, 22 Feb 2021 21:46:36 -0800
Subject: [PATCH 4/9] declare missing bufs, remove ver from lstat
https://github.com/dex4er/fakechroot/pull/85
Signed-off-by: Ilya Lipnitskiy <ilya.lipnitskiy@gmail.com>
---
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 <ilya.lipnitskiy@gmail.com>
Date: Mon, 22 Feb 2021 21:47:09 -0800
Subject: [PATCH 5/9] fix glibc 2.33+ compatibility
https://github.com/dex4er/fakechroot/pull/85
Signed-off-by: Ilya Lipnitskiy <ilya.lipnitskiy@gmail.com>
---
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 <sys/stat.h>
+ ]], [[
+#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 <config.h>
-#ifndef HAVE___LXSTAT
+#if !defined(HAVE___LXSTAT) || NEW_GLIBC
#include <sys/stat.h>
#include <unistd.h>
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 <config.h>
#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 <config.h>
-#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 <config.h>
-#ifndef HAVE___XMKNOD
+#if !defined(HAVE___XMKNOD) || NEW_GLIBC
#include <sys/stat.h>
#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 <config.h>
-#if defined(HAVE_MKNODAT) && !defined(HAVE___XMKNODAT)
+#if defined(HAVE_MKNODAT) && (!defined(HAVE___XMKNODAT) || NEW_GLIBC)
#define _ATFILE_SOURCE
#include <sys/stat.h>
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 <config.h>
-#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 <config.h>
-#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 <neok-m4700@users.noreply.github.com>
Date: Wed, 24 Feb 2021 17:36:57 +0100
Subject: [PATCH 6/9] 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 <dexter@debian.org>
+
+ 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 <config.h>
+
+#ifdef HAVE_FSTATAT
+
+#define _ATFILE_SOURCE
+#define _POSIX_C_SOURCE 200809L
+#include <sys/stat.h>
+#include <limits.h>
+#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 <dexter@debian.org>
+
+ 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 <config.h>
+
+#ifdef HAVE_FSTATAT64
+
+#define _ATFILE_SOURCE
+#define _POSIX_C_SOURCE 200809L
+#define _LARGEFILE64_SOURCE
+#include <sys/stat.h>
+#include <limits.h>
+#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 <josch@mister-muffin.de>
Date: Wed, 24 Aug 2022 08:26:04 +0200
Subject: [PATCH 7/9] 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 <dexter@debian.org>
+
+ 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 <config.h>
+
+/*
+ * 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 <gnu/libc-version.h>
+#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 32)
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include <shadow.h>
+#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 <stdlib.h>
+#include <stdio.h>
+#include <pwd.h>
+#include <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+
+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 543e9d3b322aeb7539b0146299feeaeb147180e0 Mon Sep 17 00:00:00 2001
From: Johannes Schauer Marin Rodrigues <josch@mister-muffin.de>
Date: Tue, 1 Nov 2022 00:47:56 +0100
Subject: [PATCH 8/9] add test/t/rm.t (will fail under glibc 2.34 unless
__stat64_time64 functions are wrapped)
---
test/Makefile.am | 1 +
test/t/rm.t | 25 +++++++++++++++++++++++++
2 files changed, 26 insertions(+)
create mode 100644 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 100644
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
From e9329c3b0cf98c361b96944cadeec2a1d689d2ca Mon Sep 17 00:00:00 2001
From: Johannes Schauer Marin Rodrigues <josch@mister-muffin.de>
Date: Tue, 1 Nov 2022 00:48:23 +0100
Subject: [PATCH 9/9] 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 <dexter@debian.org>
+
+ 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 <config.h>
+
+#ifdef HAVE___FSTATAT64_TIME64
+
+#define _ATFILE_SOURCE
+#define _POSIX_C_SOURCE 200809L
+#include <sys/stat.h>
+#include <limits.h>
+#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..1637b9c6
--- /dev/null
+++ b/src/__lstat64_time64.c
@@ -0,0 +1,49 @@
+/*
+ libfakechroot -- fake chroot environment
+ Copyright (c) 2010, 2021 Piotr Roszatycki <dexter@debian.org>
+
+ 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 <config.h>
+
+#ifdef HAVE___lstat64_time64
+
+#define _ATFILE_SOURCE
+#define _POSIX_C_SOURCE 200809L
+#include <sys/stat.h>
+#include <limits.h>
+#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 <dexter@debian.org>
+
+ 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 <config.h>
+
+#ifdef HAVE___STAT64_TIME64
+
+#define _BSD_SOURCE
+#define _LARGEFILE64_SOURCE
+#define _DEFAULT_SOURCE
+#include <sys/stat.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#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 <dexter@debian.org>
+
+ 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 <config.h>
+
+#ifdef HAVE___UTIME64
+
+#define _ATFILE_SOURCE
+#define _POSIX_C_SOURCE 200809L
+#include <utime.h>
+#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 <dexter@debian.org>
+
+ 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 <config.h>
+
+#ifdef HAVE___UTIMENSAT64
+
+#define _ATFILE_SOURCE
+#define _POSIX_C_SOURCE 200809L
+#include <sys/time.h>
+#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 <dexter@debian.org>
+
+ 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 <config.h>
+
+#ifdef HAVE___UTIMES64
+
+#define _ATFILE_SOURCE
+#define _POSIX_C_SOURCE 200809L
+
+#include <sys/time.h>
+#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