diff options
Diffstat (limited to '')
-rw-r--r-- | tests/common/Makefile | 14 | ||||
-rwxr-xr-x | tests/common/compare_file.pl | 116 | ||||
-rw-r--r-- | tests/common/config.sh | 121 | ||||
-rw-r--r-- | tests/common/config_chroot-i386.list | 25 | ||||
-rw-r--r-- | tests/common/config_chroot-powerpc.list | 25 | ||||
-rw-r--r-- | tests/common/fopen_failure.c | 46 | ||||
-rw-r--r-- | tests/common/link_failure.c | 51 | ||||
-rw-r--r-- | tests/common/log.sh | 46 | ||||
-rw-r--r-- | tests/common/open_RDONLY_failure.c | 51 | ||||
-rw-r--r-- | tests/common/open_RDWR_failure.c | 51 | ||||
-rw-r--r-- | tests/common/rename_failure.c | 50 | ||||
-rw-r--r-- | tests/common/rmdir_failure.c | 51 | ||||
-rw-r--r-- | tests/common/time_0.c | 16 | ||||
-rw-r--r-- | tests/common/time_past.c | 52 | ||||
-rw-r--r-- | tests/common/unlink_failure.c | 51 | ||||
-rw-r--r-- | tests/common/unlinkat_failure.c | 62 |
16 files changed, 828 insertions, 0 deletions
diff --git a/tests/common/Makefile b/tests/common/Makefile new file mode 100644 index 0000000..4ee04dd --- /dev/null +++ b/tests/common/Makefile @@ -0,0 +1,14 @@ +all: \ + fopen_failure.so \ + link_failure.so \ + open_RDONLY_failure.so \ + open_RDWR_failure.so \ + rename_failure.so \ + rmdir_failure.so \ + time_0.so \ + time_past.so \ + unlink_failure.so \ + unlinkat_failure.so + +%.so: %.c + gcc -W -Wall -pedantic -g $< -shared -ldl -o $@ diff --git a/tests/common/compare_file.pl b/tests/common/compare_file.pl new file mode 100755 index 0000000..eb498d3 --- /dev/null +++ b/tests/common/compare_file.pl @@ -0,0 +1,116 @@ +#!/usr/bin/perl + +open (TEMPLATE, $ARGV[0]) or die "Cannot open '".$ARGV[0]."': $!"; +my $template = join "", <TEMPLATE>; +open (FILE, $ARGV[1]) or die "Cannot open '".$ARGV[1]."': $!"; +my $file = join "", <FILE>; + +my $today = int(time()/(24*3600)); +$template =~ s/\@TODAY\@/$today/g; + +my $tmp = $template; +while ($tmp =~ m/^(.*?)([^\n]*):\@PASS_DES ([^:]*)\@:(.*)$/s) { + my $user = $2; + my $pass = $3; + $tmp = $4; + if ($file =~ m/^$user:/m) { + $file =~ s/^$user:([^:]*):(.*)$/$user:\@PASS_DES $pass\@:$2/m; + my $cryptpass = $1; + # Check the password + my $checkpass = qx|/usr/bin/openssl passwd -crypt -salt '$cryptpass' $pass 2>tmp/openssl.err|; + chomp $checkpass; + + system "cat tmp/openssl.err" + if ($checkpass ne $cryptpass); + system "rm -f tmp/openssl.err"; + die "Wrong password for $user: '$cryptpass'. Expected password: '$checkpass'\n" + if ($checkpass ne $cryptpass); + } else { + die "No user '$user' in ".$ARGV[1].".\n"; + } +} + +$tmp = $template; +while ($tmp =~ m/^(.*?)([^\n]*):\@PASS_MD5 ([^:]*)\@:(.*)$/s) { + my $user = $2; + my $pass = $3; + $tmp = $4; + if ($file =~ m/^$user:/m) { + $file =~ s/^$user:([^:]*):(.*)$/$user:\@PASS_MD5 $pass\@:$2/m; + my $cryptpass = $1; + # Check the password + my $salt = $cryptpass; + $salt =~ s/^\$1\$//; + $salt =~ s/\$.*$//; + my $checkpass = qx|/usr/bin/openssl passwd -1 -salt '$salt' '$pass'|; + chomp $checkpass; + + die "Wrong password for $user: '$cryptpass'. Expected password: '$checkpass'\n" + if ($checkpass ne $cryptpass); + } else { + die "No user '$user' in ".$ARGV[1].".\n"; + } +} + +$tmp = $template; +while ($tmp =~ m/^(.*?)([^\n]*):\@PASS_SHA256 ([^:]*)\@:(.*)$/s) { + my $user = $2; + my $pass = $3; + $tmp = $4; + if ($file =~ m/^$user:/m) { + $file =~ s/^$user:([^:]*):(.*)$/$user:\@PASS_SHA256 $pass\@:$2/m; + my $cryptpass = $1; + # Check the password + my $salt = $cryptpass; + $salt =~ s/^\$5\$//; + my $rounds = ""; + if ($salt =~ s/^rounds=([0-9]*)\$//) { + $rounds = "-R $1"; + } + + $salt =~ s/\$.*$//; + my $checkpass = qx!echo '$pass' | /usr/bin/mkpasswd -m sha-256 --salt '$salt' $rounds --stdin!; + chomp $checkpass; + + die "Wrong password for $user: '$cryptpass'. Expected password: '$checkpass'\n" + if ($checkpass ne $cryptpass); + } else { + die "No user '$user' in ".$ARGV[1].".\n"; + } +} + +$tmp = $template; +while ($tmp =~ m/^(.*?)([^\n]*):\@PASS_SHA512 ([^:]*)\@:(.*)$/s) { + my $user = $2; + my $pass = $3; + $tmp = $4; + if ($file =~ m/^$user:/m) { + $file =~ s/^$user:([^:]*):(.*)$/$user:\@PASS_SHA512 $pass\@:$2/m; + my $cryptpass = $1; + # Check the password + my $salt = $cryptpass; + $salt =~ s/^\$6\$//; + my $rounds = ""; + if ($salt =~ s/^rounds=([0-9]*)\$//) { + $rounds = "-R $1"; + } + + $salt =~ s/\$.*$//; + my $checkpass = qx!echo '$pass' | /usr/bin/mkpasswd -m sha-512 --salt '$salt' $rounds --stdin!; + chomp $checkpass; + + die "Wrong password for $user: '$cryptpass'. Expected password: '$checkpass'\n" + if ($checkpass ne $cryptpass); + } else { + die "No user '$user' in ".$ARGV[1].".\n"; + } +} + + +exit 0 if ($file =~ m/^\Q$template\E$/s); + +print "Files differ.\n"; + +system "diff", "-au", $ARGV[0], $ARGV[1]; + +exit 1 diff --git a/tests/common/config.sh b/tests/common/config.sh new file mode 100644 index 0000000..9b50485 --- /dev/null +++ b/tests/common/config.sh @@ -0,0 +1,121 @@ +# Generic functions to save, change, and restore configuration files + +set -e + +build_path=/root/build/shadow-4.1.5/ + +# Save the configuration files in tmp. +save_config () +{ + [ ! -d tmp ] && mkdir tmp + find config -depth -path "*/.svn/*" -prune -o -type f -print | sed -e 's/config\///' | + while read file + do + mkdir -p "tmp/$(dirname "$file")" + [ -f "/$file" ] && cp -dp "/$file" "tmp/$file" || true + done +} + +# Copy the config files from config to the system +change_config () +{ + find config -depth -path "*/.svn/*" -prune -o -type f -print | sed -e 's/config\///' | + while read file + do + cp -f "config/$file" "/$file" + done +} + +# Restored the config files in the system. +# The config files must be saved before with save_config (). +restore_config () +{ + find config -depth -path "*/.svn/*" -prune -o -type f -print | sed -e 's/config\///' | + while read file + do + if [ -f "tmp/$file" ]; then + cp -dp "tmp/$file" "/$file" + rm "tmp/$file" + else + rm -f "/$file" + fi + d="$(dirname "tmp/$file")" + while [ -n "$d" ] && [ "$d" != "." ] + do + rmdir "$d" 2>/dev/null || true + d="$(dirname "$d")" + done + done + + rmdir tmp 2>/dev/null || true +} + +prepare_chroot () +{ + mkdir tmp/root + cp -rfdp config_chroot/* tmp/root/ + find tmp/root/ -name .svn -type d -print0 | xargs -0 rm -rf + + lists=/root/tests/common/config_chroot.list + [ -f config_chroot.list ] && lists="$lists config_chroot.list" + cat $lists | grep -v "#" | while read f + do + # Create parent directory if needed + d=$(dirname tmp/root/$f) + [ -d $d ] || mkdir -p $d + # Create hard link + ln $f tmp/root/$f + done + + # Copy existing gcda + mkdir -p tmp/root$build_path/lib + mkdir -p tmp/root$build_path/libmisc + mkdir -p tmp/root$build_path/src + find "$build_path" -name "*.gcda" | while read f + do + ln $f tmp/root/$f + done +} + +clean_chroot () +{ + # Remove copied files + lists=/root/tests/common/config_chroot.list + [ -f config_chroot.list ] && lists="$lists config_chroot.list" + cat $lists | grep -v "#" | while read f + do + rm -f tmp/root/$f + # Remove parent directory if empty + d=$(dirname tmp/root/$f) + rmdir -p --ignore-fail-on-non-empty $d + done + + find "$build_path" -name "*.gcda" | while read f + do + rm -f tmp/root/$f + done + find tmp/root -name "*.gcda" | while read f + do + g=${f#tmp/root} + mv "$f" "$g" + done + rmdir tmp/root$build_path/lib + rmdir tmp/root$build_path/libmisc + rmdir tmp/root$build_path/src + rmdir tmp/root$build_path + rmdir tmp/root/root/build + rmdir tmp/root/root + + find config_chroot -type f | while read f + do + f=${f#config_chroot/} + rm -f tmp/root/$f + done + + find config_chroot -depth -type d | while read d + do + d=${d#config_chroot} + [ -d "tmp/root$d" ] && rmdir tmp/root$d + done +} + diff --git a/tests/common/config_chroot-i386.list b/tests/common/config_chroot-i386.list new file mode 100644 index 0000000..ba7bf8a --- /dev/null +++ b/tests/common/config_chroot-i386.list @@ -0,0 +1,25 @@ +/lib/i386-linux-gnu/ld-2.13.so +/lib/i386-linux-gnu/ld-linux.so.2 +/lib/ld-linux.so.2 +/lib/i386-linux-gnu/libcrypt-2.13.so +/lib/i386-linux-gnu/libcrypt.so.1 +/lib/i386-linux-gnu/libc-2.13.so +/lib/i386-linux-gnu/libc.so.6 +/lib/i386-linux-gnu/libdl-2.13.so +/lib/i386-linux-gnu/libdl.so.2 +/lib/i386-linux-gnu/libnsl-2.13.so +/lib/i386-linux-gnu/libnsl.so.1 +/lib/i386-linux-gnu/libnss_compat-2.13.so +/lib/i386-linux-gnu/libnss_compat.so.2 +/lib/i386-linux-gnu/libpamc.so.0 +/lib/i386-linux-gnu/libpamc.so.0.82.1 +/lib/i386-linux-gnu/libpam_misc.so.0 +/lib/i386-linux-gnu/libpam_misc.so.0.82.0 +/lib/i386-linux-gnu/libpam.so.0 +/lib/i386-linux-gnu/libpam.so.0.83.0 +/lib/i386-linux-gnu/libselinux.so.1 +/lib/i386-linux-gnu/security/pam_deny.so +/lib/i386-linux-gnu/security/pam_permit.so +/lib/i386-linux-gnu/security/pam_rootok.so +/lib/i386-linux-gnu/security/pam_shells.so +/lib/i386-linux-gnu/security/pam_unix.so diff --git a/tests/common/config_chroot-powerpc.list b/tests/common/config_chroot-powerpc.list new file mode 100644 index 0000000..e6c344e --- /dev/null +++ b/tests/common/config_chroot-powerpc.list @@ -0,0 +1,25 @@ +/lib/powerpc-linux-gnu/ld-2.13.so +/lib/powerpc-linux-gnu/ld.so.1 +/lib/ld.so.1 +/lib/powerpc-linux-gnu/libcrypt-2.13.so +/lib/powerpc-linux-gnu/libcrypt.so.1 +/lib/powerpc-linux-gnu/libc-2.13.so +/lib/powerpc-linux-gnu/libc.so.6 +/lib/powerpc-linux-gnu/libdl-2.13.so +/lib/powerpc-linux-gnu/libdl.so.2 +/lib/powerpc-linux-gnu/libnsl-2.13.so +/lib/powerpc-linux-gnu/libnsl.so.1 +/lib/powerpc-linux-gnu/libnss_compat-2.13.so +/lib/powerpc-linux-gnu/libnss_compat.so.2 +/lib/powerpc-linux-gnu/libpamc.so.0 +/lib/powerpc-linux-gnu/libpamc.so.0.82.1 +/lib/powerpc-linux-gnu/libpam_misc.so.0 +/lib/powerpc-linux-gnu/libpam_misc.so.0.82.0 +/lib/powerpc-linux-gnu/libpam.so.0 +/lib/powerpc-linux-gnu/libpam.so.0.83.0 +/lib/powerpc-linux-gnu/libselinux.so.1 +/lib/powerpc-linux-gnu/security/pam_deny.so +/lib/powerpc-linux-gnu/security/pam_permit.so +/lib/powerpc-linux-gnu/security/pam_rootok.so +/lib/powerpc-linux-gnu/security/pam_shells.so +/lib/powerpc-linux-gnu/security/pam_unix.so diff --git a/tests/common/fopen_failure.c b/tests/common/fopen_failure.c new file mode 100644 index 0000000..750cd66 --- /dev/null +++ b/tests/common/fopen_failure.c @@ -0,0 +1,46 @@ +/* + * gcc fopen_failure.c -o fopen_failure.so -shared -ldl + * LD_PRELOAD=./fopen_failure.so FAILURE_PATH=/etc/shadow ./test /etc/shadow + */ + +#define _GNU_SOURCE +#include <dlfcn.h> +#include <errno.h> +#include <assert.h> + +#include <stdio.h> +#include <stdlib.h> + + +typedef FILE * (*fopen_type) (const char *path, const char *mode); +static fopen_type next_fopen; + +static const char *failure_path = NULL; + +FILE *fopen64 (const char *path, const char *mode) +{ +printf ("fopen64(%s, %s)\n", path, mode); + if (NULL == next_fopen) + { + next_fopen = dlsym (RTLD_NEXT, "fopen64"); + assert (NULL != next_fopen); + } + if (NULL == failure_path) { + failure_path = getenv ("FAILURE_PATH"); + if (NULL == failure_path) { + fputs ("No FAILURE_PATH defined\n", stderr); + } + } + + if ( (NULL != path) + && (NULL != failure_path) + && (strcmp (path, failure_path) == 0)) + { + fprintf (stderr, "fopen64 FAILURE %s %s ...\n", path, mode); + errno = EIO; + return NULL; + } + + return next_fopen (path, mode); +} + diff --git a/tests/common/link_failure.c b/tests/common/link_failure.c new file mode 100644 index 0000000..8cf460a --- /dev/null +++ b/tests/common/link_failure.c @@ -0,0 +1,51 @@ +/* + * gcc link_failure.c -o link_failure.so -shared -ldl + * LD_PRELOAD=./link_failure.so FAILURE_PATH=/etc/shadow ./test /etc/shadow + */ + +#define _GNU_SOURCE +#include <dlfcn.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdarg.h> +#include <fcntl.h> +#include <string.h> +#include <errno.h> +#include <assert.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + + +typedef int (*link_type) (const char *oldpath, const char *newpath); +static link_type next_link; + +static const char *failure_path = NULL; + +int link (const char *oldpath, const char *newpath) +{ + if (NULL == next_link) + { + next_link = dlsym (RTLD_NEXT, "link"); + assert (NULL != next_link); + } + if (NULL == failure_path) { + failure_path = getenv ("FAILURE_PATH"); + if (NULL == failure_path) { + fputs ("No FAILURE_PATH defined\n", stderr); + } + } + + if ( (NULL != newpath) + && (NULL != failure_path) + && (strcmp (newpath, failure_path) == 0)) + { + fprintf (stderr, "link FAILURE %s %s\n", oldpath, newpath); + errno = EIO; + return -1; + } + + return next_link (oldpath, newpath); +} + diff --git a/tests/common/log.sh b/tests/common/log.sh new file mode 100644 index 0000000..4887970 --- /dev/null +++ b/tests/common/log.sh @@ -0,0 +1,46 @@ +# Helpers to log messages / status + +log_start () +{ + test="$1" + rationale="$2" + cat << EOF + +############################################################################### +# +# Test: $test +# +############################################################################### +# +# Rationale: $rationale +# +############################################################################### +EOF +} + +log_end () +{ + test="$1" + cat << EOF +############################################################################### +# +# End of test $test +# +############################################################################### + +EOF +} + +log_status () +{ + test="$1" + status="$2" + cat << EOF +############################################################################### +# +# Status of test $test: $status +# +############################################################################### +EOF +} + diff --git a/tests/common/open_RDONLY_failure.c b/tests/common/open_RDONLY_failure.c new file mode 100644 index 0000000..e14859f --- /dev/null +++ b/tests/common/open_RDONLY_failure.c @@ -0,0 +1,51 @@ +/* + * gcc open_RDONLY_failure.c -o open_RDONLY_failure.so -shared -ldl + * LD_PRELOAD=./open_RDONLY_failure.so FAILURE_PATH=/etc/shadow ./test /etc/shadow + */ + +#define _GNU_SOURCE +#include <dlfcn.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdarg.h> +#include <fcntl.h> +#include <string.h> +#include <errno.h> +#include <assert.h> + +#include <stdio.h> +#include <stdlib.h> + + +typedef int (*open_type) (const char *pathname, int flag, ...); +static open_type next_open64; + +static const char *failure_path = NULL; + +int open64 (const char *pathname, int flag, ...) +{ + if (NULL == next_open64) + { + next_open64 = dlsym (RTLD_NEXT, "open64"); + assert (NULL != next_open64); + } + if (NULL == failure_path) { + failure_path = getenv ("FAILURE_PATH"); + if (NULL == failure_path) { + fputs ("No FAILURE_PATH defined\n", stderr); + } + } + + if ( (NULL != pathname) + && ((flag & O_ACCMODE) == O_RDONLY) + && (NULL != failure_path) + && (strcmp (pathname, failure_path) == 0)) + { + fprintf (stderr, "open FAILURE %s %x ...\n", pathname, flag&O_ACCMODE); + errno = EIO; + return -1; + } + + return next_open64 (pathname, flag); +} + diff --git a/tests/common/open_RDWR_failure.c b/tests/common/open_RDWR_failure.c new file mode 100644 index 0000000..5bf1069 --- /dev/null +++ b/tests/common/open_RDWR_failure.c @@ -0,0 +1,51 @@ +/* + * gcc open_RDWR_failure.c -o open_RDWR_failure.so -shared -ldl + * LD_PRELOAD=./open_RDWR_failure.so FAILURE_PATH=/etc/shadow ./test /etc/shadow + */ + +#define _GNU_SOURCE +#include <dlfcn.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdarg.h> +#include <fcntl.h> +#include <string.h> +#include <errno.h> +#include <assert.h> + +#include <stdio.h> +#include <stdlib.h> + + +typedef int (*open_type) (const char *pathname, int flag, ...); +static open_type next_open64; + +static const char *failure_path = NULL; + +int open64 (const char *pathname, int flag, ...) +{ + if (NULL == next_open64) + { + next_open64 = dlsym (RTLD_NEXT, "open64"); + assert (NULL != next_open64); + } + if (NULL == failure_path) { + failure_path = getenv ("FAILURE_PATH"); + if (NULL == failure_path) { + fputs ("No FAILURE_PATH defined\n", stderr); + } + } + + if ( (NULL != pathname) + && ((flag & O_ACCMODE) == O_RDWR) + && (NULL != failure_path) + && (strcmp (pathname, failure_path) == 0)) + { + fprintf (stderr, "open FAILURE %s %x ...\n", pathname, flag&O_ACCMODE); + errno = EIO; + return -1; + } + + return next_open64 (pathname, flag); +} + diff --git a/tests/common/rename_failure.c b/tests/common/rename_failure.c new file mode 100644 index 0000000..dd02fe5 --- /dev/null +++ b/tests/common/rename_failure.c @@ -0,0 +1,50 @@ +/* + * gcc rename_failure.c -o rename_failure.so -shared -ldl + * LD_PRELOAD=./rename_failure.so FAILURE_PATH=/etc/shadow ./test /etc/shadow + */ + +#define _GNU_SOURCE +#include <dlfcn.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdarg.h> +#include <fcntl.h> +#include <string.h> +#include <errno.h> +#include <assert.h> + +#include <stdio.h> +#include <stdlib.h> + + +typedef int (*rename_type) (const char *old, const char *new); +static rename_type next_rename; + +static const char *failure_path = NULL; + +int rename (const char *old, const char *new) +{ + if (NULL == next_rename) + { + next_rename = dlsym (RTLD_NEXT, "rename"); + assert (NULL != next_rename); + } + if (NULL == failure_path) { + failure_path = getenv ("FAILURE_PATH"); + if (NULL == failure_path) { + fputs ("No FAILURE_PATH defined\n", stderr); + } + } + + if ( (NULL != new) + && (NULL != failure_path) + && (strcmp (new, failure_path) == 0)) + { + fprintf (stderr, "rename FAILURE %s %s\n", old, new); + errno = EIO; + return -1; + } + + return next_rename (old, new); +} + diff --git a/tests/common/rmdir_failure.c b/tests/common/rmdir_failure.c new file mode 100644 index 0000000..9d775b1 --- /dev/null +++ b/tests/common/rmdir_failure.c @@ -0,0 +1,51 @@ +/* + * gcc rmdir_failure.c -o rmdir_failure.so -shared -ldl + * LD_PRELOAD=./rmdir_failure.so FAILURE_PATH=/etc/shadow ./test /etc/shadow + */ + +#define _GNU_SOURCE +#include <dlfcn.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdarg.h> +#include <fcntl.h> +#include <string.h> +#include <errno.h> +#include <assert.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + + +typedef int (*rmdir_type) (const char *path); +static rmdir_type next_rmdir; + +static const char *failure_path = NULL; + +int rmdir (const char *path) +{ + if (NULL == next_rmdir) + { + next_rmdir = dlsym (RTLD_NEXT, "rmdir"); + assert (NULL != next_rmdir); + } + if (NULL == failure_path) { + failure_path = getenv ("FAILURE_PATH"); + if (NULL == failure_path) { + fputs ("No FAILURE_PATH defined\n", stderr); + } + } + + if ( (NULL != path) + && (NULL != failure_path) + && (strcmp (path, failure_path) == 0)) + { + fprintf (stderr, "rmdir FAILURE %s\n", path); + errno = EBUSY; + return -1; + } + + return next_rmdir (path); +} + diff --git a/tests/common/time_0.c b/tests/common/time_0.c new file mode 100644 index 0000000..6937361 --- /dev/null +++ b/tests/common/time_0.c @@ -0,0 +1,16 @@ +/* + * gcc time_0.c -o time_0.so -shared + * LD_PRELOAD=./time_0.so ./test + */ + +#include <stdio.h> +#include <time.h> + + +time_t time (time_t *t) +{ + fprintf (stderr, "time 0\n"); + + return (time_t)0; +} + diff --git a/tests/common/time_past.c b/tests/common/time_past.c new file mode 100644 index 0000000..d0eb741 --- /dev/null +++ b/tests/common/time_past.c @@ -0,0 +1,52 @@ +/* + * gcc time_past.c -o time_past.so -shared -ldl + * LD_PRELOAD=./time_past.so PAST_DAYS=2 ./test + */ + +#define _GNU_SOURCE +#include <dlfcn.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdarg.h> +#include <fcntl.h> +#include <string.h> +#include <errno.h> +#include <assert.h> + +#include <stdio.h> +#include <stdlib.h> + + +typedef time_t (*time_type) (time_t *t); +static time_type next_time; + +static int time_past = 0; +static char *past = NULL; + +time_t time (time_t *t) +{ + time_t res; + + if (NULL == next_time) + { + next_time = dlsym (RTLD_NEXT, "time"); + assert (NULL != next_time); + } + if (NULL == past) { + const char *past = getenv ("PAST_DAYS"); + if (NULL == past) { + fputs ("No PAST_DAYS defined\n", stderr); + } + time_past = atoi (past); + } + + res = next_time (t); + res -= 24*60*60*time_past; + + if (NULL != t) { + *t = res; + } + + return res; +} + diff --git a/tests/common/unlink_failure.c b/tests/common/unlink_failure.c new file mode 100644 index 0000000..2281c8a --- /dev/null +++ b/tests/common/unlink_failure.c @@ -0,0 +1,51 @@ +/* + * gcc unlink_failure.c -o unlink_failure.so -shared -ldl + * LD_PRELOAD=./unlink_failure.so FAILURE_PATH=/etc/shadow ./test /etc/shadow + */ + +#define _GNU_SOURCE +#include <dlfcn.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdarg.h> +#include <fcntl.h> +#include <string.h> +#include <errno.h> +#include <assert.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + + +typedef int (*unlink_type) (const char *path); +static unlink_type next_unlink; + +static const char *failure_path = NULL; + +int unlink (const char *path) +{ + if (NULL == next_unlink) + { + next_unlink = dlsym (RTLD_NEXT, "unlink"); + assert (NULL != next_unlink); + } + if (NULL == failure_path) { + failure_path = getenv ("FAILURE_PATH"); + if (NULL == failure_path) { + fputs ("No FAILURE_PATH defined\n", stderr); + } + } + + if ( (NULL != path) + && (NULL != failure_path) + && (strcmp (path, failure_path) == 0)) + { + fprintf (stderr, "unlink FAILURE %s\n", path); + errno = EBUSY; + return -1; + } + + return next_unlink (path); +} + diff --git a/tests/common/unlinkat_failure.c b/tests/common/unlinkat_failure.c new file mode 100644 index 0000000..5b8bf95 --- /dev/null +++ b/tests/common/unlinkat_failure.c @@ -0,0 +1,62 @@ +/* + * gcc unlinkat_failure.c -o unlinkat_failure.so -shared -ldl + * LD_PRELOAD=./unlinkat_failure.so FAILURE_PATH=/etc/shadow ./test /etc/shadow + */ + +#define _GNU_SOURCE +#include <dlfcn.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdarg.h> +#include <fcntl.h> +#include <string.h> +#include <errno.h> +#include <assert.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + + +typedef int (*unlinkat_type) (int dirfd, const char *pathname, int flags); +static unlinkat_type next_unlinkat; + +static const char *failure_path = NULL; +static dev_t failure_dev = -1; +static ino_t failure_ino = -1; + +int unlinkat (int dirfd, const char *pathname, int flags) +{ + if (NULL == next_unlinkat) + { + next_unlinkat = dlsym (RTLD_NEXT, "unlinkat"); + assert (NULL != next_unlinkat); + } + if (NULL == failure_path) { + struct stat sb; + failure_path = getenv ("FAILURE_PATH"); + if (NULL == failure_path) { + fputs ("No FAILURE_PATH defined\n", stderr); + } + if (lstat (failure_path, &sb) != 0) { + fputs ("Can't lstat FAILURE_PATH\n", stderr); + } + failure_dev = sb.st_dev; + failure_ino = sb.st_ino; + } + + if ( (NULL != pathname) + && (NULL != failure_path)) { + struct stat sb; + if ( (fstatat (dirfd, pathname, &sb, flags) == 0) + && (sb.st_dev == failure_dev) + && (sb.st_ino == failure_ino)) { + fprintf (stderr, "unlinkat FAILURE %s\n", failure_path); + errno = EBUSY; + return -1; + } + } + + return next_unlinkat (dirfd, pathname, flags); +} + |