summaryrefslogtreecommitdiff
path: root/testing/coreutils
diff options
context:
space:
mode:
Diffstat (limited to 'testing/coreutils')
-rw-r--r--testing/coreutils/0001-ls-color-each-symlink-to-relative-name-in-properly.patch135
-rw-r--r--testing/coreutils/PKGBUILD69
-rw-r--r--testing/coreutils/coreutils-pam.patch428
-rw-r--r--testing/coreutils/coreutils.install21
-rw-r--r--testing/coreutils/su.pam9
5 files changed, 662 insertions, 0 deletions
diff --git a/testing/coreutils/0001-ls-color-each-symlink-to-relative-name-in-properly.patch b/testing/coreutils/0001-ls-color-each-symlink-to-relative-name-in-properly.patch
new file mode 100644
index 000000000..087b87cdb
--- /dev/null
+++ b/testing/coreutils/0001-ls-color-each-symlink-to-relative-name-in-properly.patch
@@ -0,0 +1,135 @@
+From 6124a3842dfa8484b52e067a8ab8105c3875a4f7 Mon Sep 17 00:00:00 2001
+From: Jim Meyering <meyering@redhat.com>
+Date: Thu, 10 May 2012 19:43:00 +0200
+Subject: [PATCH] ls: color each symlink-to-relative-name in / properly
+
+In order for ls --color to color each symlink, it must form the name
+of each referent and then stat it to see if the link is dangling, to
+a directory, to a file, etc. When the symlink is to a relative name,
+ls must concatenate the starting directory name and that relative name.
+When, in addition, the starting directory was "/" or "/some-name",
+the result was ill-formed, and the subsequent stat would usually fail,
+making the caller color it as a dangling symlink.
+* src/ls.c (make_link_name): Don't botch the case in which
+dir_name(NAME) == "/" and LINKNAME is relative.
+* tests/ls/root-rel-symlink-color: New file. Test for the above.
+* tests/Makefile.am (TESTS): Add it.
+* NEWS (Bug fixes): Mention it.
+Reported by Mike Frysinger in http://bugs.gnu.org/11453
+Bug introduced by commit v8.16-23-gbcb9078.
+---
+ NEWS | 5 ++++
+ src/ls.c | 9 +++++++-
+ tests/Makefile.am | 1 +
+ tests/ls/root-rel-symlink-color | 51 +++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 65 insertions(+), 1 deletion(-)
+ create mode 100755 tests/ls/root-rel-symlink-color
+
+diff --git a/NEWS b/NEWS
+index 6c620b3..f9e9c70 100644
+--- a/NEWS
++++ b/NEWS
+@@ -2,6 +2,11 @@ GNU coreutils NEWS -*- outline -*-
+
+ * Noteworthy changes in release ?.? (????-??-??) [?]
+
++** Bug fixes
++
++ ls --color would mis-color relative-named symlinks in /
++ [bug introduced in coreutils-8.17]
++
+
+ * Noteworthy changes in release 8.17 (2012-05-10) [stable]
+
+diff --git a/src/ls.c b/src/ls.c
+index 397e4ea..9494ae9 100644
+--- a/src/ls.c
++++ b/src/ls.c
+@@ -3213,7 +3213,14 @@ make_link_name (char const *name, char const *linkname)
+ return xstrdup (linkname);
+
+ char *p = xmalloc (prefix_len + 1 + strlen (linkname) + 1);
+- stpcpy (stpncpy (p, name, prefix_len + 1), linkname);
++
++ /* PREFIX_LEN usually specifies a string not ending in slash.
++ In that case, extend it by one, since the next byte *is* a slash.
++ Otherwise, the prefix is "/", so leave the length unchanged. */
++ if ( ! ISSLASH (name[prefix_len - 1]))
++ ++prefix_len;
++
++ stpcpy (stpncpy (p, name, prefix_len), linkname);
+ return p;
+ }
+
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index a4370a6..0bafc5f 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -449,6 +449,7 @@ TESTS = \
+ ls/proc-selinux-segfault \
+ ls/readdir-mountpoint-inode \
+ ls/recursive \
++ ls/root-rel-symlink-color \
+ ls/rt-1 \
+ ls/slink-acl \
+ ls/stat-dtype \
+diff --git a/tests/ls/root-rel-symlink-color b/tests/ls/root-rel-symlink-color
+new file mode 100755
+index 0000000..d795432
+--- /dev/null
++++ b/tests/ls/root-rel-symlink-color
+@@ -0,0 +1,51 @@
++#!/bin/sh
++# Exercise the 8.17 ls bug with coloring relative-named symlinks in "/".
++
++# Copyright (C) 2012 Free Software Foundation, Inc.
++
++# This program is free software: you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation, either version 3 of the License, or
++# (at your option) any later version.
++
++# This program 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 General Public License for more details.
++
++# You should have received a copy of the GNU General Public License
++# along with this program. If not, see <http://www.gnu.org/licenses/>.
++
++. "${srcdir=.}/init.sh"; path_prepend_ ../src
++print_ver_ ls
++
++symlink_to_rel=
++for i in /*; do
++ # Skip non-symlinks:
++ env test -h "$i" || continue
++
++ # Skip dangling symlinks:
++ env test -e "$i" || continue
++
++ # Skip any symlink-to-absolute-name:
++ case $(readlink "$i") in /*) continue ;; esac
++
++ symlink_to_rel=$i
++ break
++done
++
++test -z "$symlink_to_rel" \
++ && skip_ no relative symlink in /
++
++e='\33'
++color_code='01;36'
++c_pre="$e[0m$e[${color_code}m"
++c_post="$e[0m"
++printf "$c_pre$symlink_to_rel$c_post\n" > exp || framework_failure_
++
++env TERM=xterm LS_COLORS="ln=$color_code:or=1;31;42" \
++ ls -d --color=always "$symlink_to_rel" > out || fail=1
++
++compare exp out || fail=1
++
++Exit $fail
+--
+1.7.11.2
+
diff --git a/testing/coreutils/PKGBUILD b/testing/coreutils/PKGBUILD
new file mode 100644
index 000000000..ebc8c820a
--- /dev/null
+++ b/testing/coreutils/PKGBUILD
@@ -0,0 +1,69 @@
+# $Id: PKGBUILD 163537 2012-07-15 01:13:11Z dreisner $
+# Maintainer: Allan McRae <allan@archlinux.org>
+# Contributor: judd <jvinet@zeroflux.org>
+
+pkgname=coreutils
+pkgver=8.17
+pkgrel=2
+pkgdesc="The basic file, shell and text manipulation utilities of the GNU operating system"
+arch=('i686' 'x86_64')
+license=('GPL3')
+url="http://www.gnu.org/software/coreutils"
+groups=('base')
+depends=('glibc' 'pam' 'acl' 'gmp' 'libcap')
+replaces=('mktemp')
+backup=('etc/pam.d/su')
+install=${pkgname}.install
+options=('!emptydirs')
+source=(ftp://ftp.gnu.org/gnu/$pkgname/$pkgname-$pkgver.tar.xz{,.sig}
+ coreutils-pam.patch
+ 0001-ls-color-each-symlink-to-relative-name-in-properly.patch
+ su.pam)
+md5sums=('bbda656ce8ca2c6903948f9faa204ba3'
+ 'ebecd29b095aa21b0b2f833f1ec20d70'
+ 'aad79a2aa6d566c375d7bdd1b0767278'
+ 'd7c691898a695a6284a927e6a9426fe4'
+ 'fa85e5cce5d723275b14365ba71a8aad')
+
+build() {
+ cd ${srcdir}/${pkgname}-${pkgver}
+
+ # added su wheel group pam patch (from fedora git)
+ patch -Np1 -i ${srcdir}/coreutils-pam.patch
+
+ # fix coloring for symlinks in /
+ # upstream commit 6124a3842dfa8484b52e067a8ab8105c3875a4f7
+ patch -Np1 -i $srcdir/0001-ls-color-each-symlink-to-relative-name-in-properly.patch
+
+ autoreconf -v
+ ./configure --prefix=/usr --libexecdir=/usr/lib/coreutils \
+ --enable-install-program=su \
+ --enable-no-install-program=groups,hostname,kill,uptime \
+ --enable-pam
+ make
+}
+
+check() {
+ cd ${srcdir}/${pkgname}-${pkgver}
+ make RUN_EXPENSIVE_TESTS=yes check
+}
+
+package() {
+ cd ${srcdir}/${pkgname}-${pkgver}
+ make DESTDIR=${pkgdir} install
+
+ cd ${pkgdir}/usr/bin
+ install -dm755 ${pkgdir}/{bin,usr/sbin}
+
+ # binaries required by FHS
+ _fhs=('cat' 'chgrp' 'chmod' 'chown' 'cp' 'date' 'dd' 'df' 'echo' 'false'
+ 'ln' 'ls' 'mkdir' 'mknod' 'mv' 'pwd' 'rm' 'rmdir' 'stty' 'su' 'sync'
+ 'true' 'uname')
+ mv ${_fhs[@]} ${pkgdir}/bin
+
+ # makepkg uses the full path to this...
+ ln -s /usr/bin/du ${pkgdir}/bin/du
+
+ mv chroot ${pkgdir}/usr/sbin
+ install -Dm644 ${srcdir}/su.pam ${pkgdir}/etc/pam.d/su
+}
diff --git a/testing/coreutils/coreutils-pam.patch b/testing/coreutils/coreutils-pam.patch
new file mode 100644
index 000000000..e61908f3f
--- /dev/null
+++ b/testing/coreutils/coreutils-pam.patch
@@ -0,0 +1,428 @@
+diff -urNp coreutils-8.4-orig/configure.ac coreutils-8.4/configure.ac
+--- coreutils-8.4-orig/configure.ac 2010-01-11 18:20:42.000000000 +0100
++++ coreutils-8.4/configure.ac 2010-02-12 10:17:46.000000000 +0100
+@@ -126,6 +126,13 @@ if test "$gl_gcc_warnings" = yes; then
+ AC_SUBST([GNULIB_WARN_CFLAGS])
+ fi
+
++dnl Give the chance to enable PAM
++AC_ARG_ENABLE(pam, dnl
++[ --enable-pam Enable use of the PAM libraries],
++[AC_DEFINE(USE_PAM, 1, [Define if you want to use PAM])
++LIB_PAM="-ldl -lpam -lpam_misc"
++AC_SUBST(LIB_PAM)])
++
+ AC_FUNC_FORK
+
+ optional_bin_progs=
+diff -urNp coreutils-8.4-orig/doc/coreutils.texi coreutils-8.4/doc/coreutils.texi
+--- coreutils-8.4-orig/doc/coreutils.texi 2010-01-03 18:06:20.000000000 +0100
++++ coreutils-8.4/doc/coreutils.texi 2010-02-12 10:17:46.000000000 +0100
+@@ -15081,8 +15081,11 @@ to certain shells, etc.).
+ @findex syslog
+ @command{su} can optionally be compiled to use @code{syslog} to report
+ failed, and optionally successful, @command{su} attempts. (If the system
+-supports @code{syslog}.) However, GNU @command{su} does not check if the
+-user is a member of the @code{wheel} group; see below.
++supports @code{syslog}.)
++
++This version of @command{su} has support for using PAM for
++authentication. You can edit @file{/etc/pam.d/su} to customize its
++behaviour.
+
+ The program accepts the following options. Also see @ref{Common options}.
+
+@@ -15124,6 +15127,8 @@ environment variables except @env{TERM},
+ @env{PATH} to a compiled-in default value. Change to @var{user}'s home
+ directory. Prepend @samp{-} to the shell's name, intended to make it
+ read its login startup file(s).
++Additionaly @env{DISPLAY} and @env{XAUTHORITY} environment variables
++are preserved as well for PAM functionality.
+
+ @item -m
+ @itemx -p
+@@ -15163,33 +15168,6 @@ Exit status:
+ the exit status of the subshell otherwise
+ @end display
+
+-@cindex wheel group, not supported
+-@cindex group wheel, not supported
+-@cindex fascism
+-@subsection Why GNU @command{su} does not support the @samp{wheel} group
+-
+-(This section is by Richard Stallman.)
+-
+-@cindex Twenex
+-@cindex MIT AI lab
+-Sometimes a few of the users try to hold total power over all the
+-rest. For example, in 1984, a few users at the MIT AI lab decided to
+-seize power by changing the operator password on the Twenex system and
+-keeping it secret from everyone else. (I was able to thwart this coup
+-and give power back to the users by patching the kernel, but I
+-wouldn't know how to do that in Unix.)
+-
+-However, occasionally the rulers do tell someone. Under the usual
+-@command{su} mechanism, once someone learns the root password who
+-sympathizes with the ordinary users, he or she can tell the rest. The
+-``wheel group'' feature would make this impossible, and thus cement the
+-power of the rulers.
+-
+-I'm on the side of the masses, not that of the rulers. If you are
+-used to supporting the bosses and sysadmins in whatever they do, you
+-might find this idea strange at first.
+-
+-
+ @node timeout invocation
+ @section @command{timeout}: Run a command with a time limit
+
+diff -urNp coreutils-8.4-orig/src/Makefile.am coreutils-8.4/src/Makefile.am
+--- coreutils-8.4-orig/src/Makefile.am 2010-01-03 18:06:20.000000000 +0100
++++ coreutils-8.4/src/Makefile.am 2010-02-12 10:17:46.000000000 +0100
+@@ -361,7 +361,7 @@ factor_LDADD += $(LIB_GMP)
+ uptime_LDADD += $(GETLOADAVG_LIBS)
+
+ # for crypt
+-su_LDADD += $(LIB_CRYPT)
++su_LDADD += $(LIB_CRYPT) @LIB_PAM@
+
+ # for various ACL functions
+ copy_LDADD += $(LIB_ACL)
+diff -urNp coreutils-8.4-orig/src/su.c coreutils-8.4/src/su.c
+--- coreutils-8.4-orig/src/su.c 2010-02-12 10:15:15.000000000 +0100
++++ coreutils-8.4/src/su.c 2010-02-12 10:24:29.000000000 +0100
+@@ -37,6 +37,16 @@
+ restricts who can su to UID 0 accounts. RMS considers that to
+ be fascist.
+
++#ifdef USE_PAM
++
++ Actually, with PAM, su has nothing to do with whether or not a
++ wheel group is enforced by su. RMS tries to restrict your access
++ to a su which implements the wheel group, but PAM considers that
++ to be fascist, and gives the user/sysadmin the opportunity to
++ enforce a wheel group by proper editing of /etc/pam.conf
++
++#endif
++
+ Compile-time options:
+ -DSYSLOG_SUCCESS Log successful su's (by default, to root) with syslog.
+ -DSYSLOG_FAILURE Log failed su's (by default, to root) with syslog.
+@@ -53,6 +63,15 @@
+ #include <pwd.h>
+ #include <grp.h>
+
++#ifdef USE_PAM
++# include <signal.h>
++# include <sys/wait.h>
++# include <sys/fsuid.h>
++# include <unistd.h>
++# include <security/pam_appl.h>
++# include <security/pam_misc.h>
++#endif /* USE_PAM */
++
+ #include "system.h"
+ #include "getpass.h"
+
+@@ -120,10 +139,17 @@
+ /* The user to become if none is specified. */
+ #define DEFAULT_USER "root"
+
++#ifndef USE_PAM
+ char *crypt (char const *key, char const *salt);
++#endif
+
+-static void run_shell (char const *, char const *, char **, size_t)
++static void run_shell (char const *, char const *, char **, size_t,
++ const struct passwd *)
++#ifdef USE_PAM
++ ;
++#else
+ ATTRIBUTE_NORETURN;
++#endif
+
+ /* If true, pass the `-f' option to the subshell. */
+ static bool fast_startup;
+@@ -209,7 +235,26 @@ log_su (struct passwd const *pw, bool su
+ }
+ #endif
+
++#ifdef USE_PAM
++static pam_handle_t *pamh = NULL;
++static int retval;
++static struct pam_conv conv = {
++ misc_conv,
++ NULL
++};
++
++#define PAM_BAIL_P if (retval) { \
++ pam_end(pamh, PAM_SUCCESS); \
++ return 0; \
++}
++#define PAM_BAIL_P_VOID if (retval) { \
++ pam_end(pamh, PAM_SUCCESS); \
++return; \
++}
++#endif
++
+ /* Ask the user for a password.
++ If PAM is in use, let PAM ask for the password if necessary.
+ Return true if the user gives the correct password for entry PW,
+ false if not. Return true without asking for a password if run by UID 0
+ or if PW has an empty password. */
+@@ -217,6 +262,44 @@ log_su (struct passwd const *pw, bool su
+ static bool
+ correct_password (const struct passwd *pw)
+ {
++#ifdef USE_PAM
++ struct passwd *caller;
++ char *tty_name, *ttyn;
++ retval = pam_start(PROGRAM_NAME, pw->pw_name, &conv, &pamh);
++ PAM_BAIL_P;
++
++ if (getuid() != 0 && !isatty(0)) {
++ fprintf(stderr, "standard in must be a tty\n");
++ exit(1);
++ }
++
++ caller = getpwuid(getuid());
++ if(caller != NULL && caller->pw_name != NULL) {
++ retval = pam_set_item(pamh, PAM_RUSER, caller->pw_name);
++ PAM_BAIL_P;
++ }
++
++ ttyn = ttyname(0);
++ if (ttyn) {
++ if (strncmp(ttyn, "/dev/", 5) == 0)
++ tty_name = ttyn+5;
++ else
++ tty_name = ttyn;
++ retval = pam_set_item(pamh, PAM_TTY, tty_name);
++ PAM_BAIL_P;
++ }
++ retval = pam_authenticate(pamh, 0);
++ PAM_BAIL_P;
++ retval = pam_acct_mgmt(pamh, 0);
++ if (retval == PAM_NEW_AUTHTOK_REQD) {
++ /* password has expired. Offer option to change it. */
++ retval = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
++ PAM_BAIL_P;
++ }
++ PAM_BAIL_P;
++ /* must be authenticated if this point was reached */
++ return 1;
++#else /* !USE_PAM */
+ char *unencrypted, *encrypted, *correct;
+ #if HAVE_GETSPNAM && HAVE_STRUCT_SPWD_SP_PWDP
+ /* Shadow passwd stuff for SVR3 and maybe other systems. */
+@@ -241,6 +324,7 @@ correct_password (const struct passwd *p
+ encrypted = crypt (unencrypted, correct);
+ memset (unencrypted, 0, strlen (unencrypted));
+ return STREQ (encrypted, correct);
++#endif /* !USE_PAM */
+ }
+
+ /* Update `environ' for the new shell based on PW, with SHELL being
+@@ -254,12 +338,18 @@ modify_environment (const struct passwd
+ /* Leave TERM unchanged. Set HOME, SHELL, USER, LOGNAME, PATH.
+ Unset all other environment variables. */
+ char const *term = getenv ("TERM");
++ char const *display = getenv ("DISPLAY");
++ char const *xauthority = getenv ("XAUTHORITY");
+ if (term)
+ term = xstrdup (term);
+ environ = xmalloc ((6 + !!term) * sizeof (char *));
+ environ[0] = NULL;
+ if (term)
+ xsetenv ("TERM", term);
++ if (display)
++ xsetenv ("DISPLAY", display);
++ if (xauthority)
++ xsetenv ("XAUTHORITY", xauthority);
+ xsetenv ("HOME", pw->pw_dir);
+ xsetenv ("SHELL", shell);
+ xsetenv ("USER", pw->pw_name);
+@@ -292,8 +382,13 @@ change_identity (const struct passwd *pw
+ {
+ #ifdef HAVE_INITGROUPS
+ errno = 0;
+- if (initgroups (pw->pw_name, pw->pw_gid) == -1)
++ if (initgroups (pw->pw_name, pw->pw_gid) == -1) {
++#ifdef USE_PAM
++ pam_close_session(pamh, 0);
++ pam_end(pamh, PAM_ABORT);
++#endif
+ error (EXIT_CANCELED, errno, _("cannot set groups"));
++ }
+ endgrent ();
+ #endif
+ if (setgid (pw->pw_gid))
+@@ -302,6 +397,31 @@ change_identity (const struct passwd *pw
+ error (EXIT_CANCELED, errno, _("cannot set user id"));
+ }
+
++#ifdef USE_PAM
++static int caught=0;
++/* Signal handler for parent process later */
++static void su_catch_sig(int sig)
++{
++ ++caught;
++}
++
++int
++pam_copyenv (pam_handle_t *pamh)
++{
++ char **env;
++
++ env = pam_getenvlist(pamh);
++ if(env) {
++ while(*env) {
++ if (putenv (*env))
++ xalloc_die ();
++ env++;
++ }
++ }
++ return(0);
++}
++#endif
++
+ /* Run SHELL, or DEFAULT_SHELL if SHELL is empty.
+ If COMMAND is nonzero, pass it to the shell with the -c option.
+ Pass ADDITIONAL_ARGS to the shell as more arguments; there
+@@ -309,17 +429,49 @@ change_identity (const struct passwd *pw
+
+ static void
+ run_shell (char const *shell, char const *command, char **additional_args,
+- size_t n_additional_args)
++ size_t n_additional_args, const struct passwd *pw)
+ {
+ size_t n_args = 1 + fast_startup + 2 * !!command + n_additional_args + 1;
+ char const **args = xnmalloc (n_args, sizeof *args);
+ size_t argno = 1;
++#ifdef USE_PAM
++ int child;
++ sigset_t ourset;
++ int status;
++
++ retval = pam_open_session(pamh,0);
++ if (retval != PAM_SUCCESS) {
++ fprintf (stderr, "could not open session\n");
++ exit (1);
++ }
++
++/* do this at the last possible moment, because environment variables may
++ be passed even in the session phase
++*/
++ if(pam_copyenv(pamh) != PAM_SUCCESS)
++ fprintf (stderr, "error copying PAM environment\n");
++
++ /* Credentials should be set in the parent */
++ if (pam_setcred(pamh, PAM_ESTABLISH_CRED) != PAM_SUCCESS) {
++ pam_close_session(pamh, 0);
++ fprintf(stderr, "could not set PAM credentials\n");
++ exit(1);
++ }
++
++ child = fork();
++ if (child == 0) { /* child shell */
++ change_identity (pw);
++ pam_end(pamh, 0);
++#endif
+
+ if (simulate_login)
+ {
+ char *arg0;
+ char *shell_basename;
+
++ if(chdir(pw->pw_dir))
++ error(0, errno, _("warning: cannot change directory to %s"), pw->pw_dir);
++
+ shell_basename = last_component (shell);
+ arg0 = xmalloc (strlen (shell_basename) + 2);
+ arg0[0] = '-';
+@@ -344,6 +496,67 @@ run_shell (char const *shell, char const
+ error (0, errno, "%s", shell);
+ exit (exit_status);
+ }
++#ifdef USE_PAM
++ } else if (child == -1) {
++ fprintf(stderr, "can not fork user shell: %s", strerror(errno));
++ pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT);
++ pam_close_session(pamh, 0);
++ pam_end(pamh, PAM_ABORT);
++ exit(1);
++ }
++ /* parent only */
++ sigfillset(&ourset);
++ if (sigprocmask(SIG_BLOCK, &ourset, NULL)) {
++ fprintf(stderr, "%s: signal malfunction\n", PROGRAM_NAME);
++ caught = 1;
++ }
++ if (!caught) {
++ struct sigaction action;
++ action.sa_handler = su_catch_sig;
++ sigemptyset(&action.sa_mask);
++ action.sa_flags = 0;
++ sigemptyset(&ourset);
++ if (sigaddset(&ourset, SIGTERM)
++ || sigaddset(&ourset, SIGALRM)
++ || sigaction(SIGTERM, &action, NULL)
++ || sigprocmask(SIG_UNBLOCK, &ourset, NULL)) {
++ fprintf(stderr, "%s: signal masking malfunction\n", PROGRAM_NAME);
++ caught = 1;
++ }
++ }
++ if (!caught) {
++ do {
++ int pid;
++
++ pid = waitpid(-1, &status, WUNTRACED);
++
++ if (((pid_t)-1 != pid) && (0 != WIFSTOPPED (status))) {
++ kill(getpid(), WSTOPSIG(status));
++ /* once we get here, we must have resumed */
++ kill(pid, SIGCONT);
++ }
++ } while (0 != WIFSTOPPED(status));
++ }
++
++ if (caught) {
++ fprintf(stderr, "\nSession terminated, killing shell...");
++ kill (child, SIGTERM);
++ }
++ /* Not checking retval on this because we need to call close session */
++ pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT);
++ retval = pam_close_session(pamh, 0);
++ PAM_BAIL_P_VOID;
++ retval = pam_end(pamh, PAM_SUCCESS);
++ PAM_BAIL_P_VOID;
++ if (caught) {
++ sleep(2);
++ kill(child, SIGKILL);
++ fprintf(stderr, " ...killed.\n");
++ exit(-1);
++ }
++ exit ((0 != WIFEXITED (status)) ? WEXITSTATUS (status)
++ : WTERMSIG (status) + 128);
++#endif /* USE_PAM */
+ }
+
+ /* Return true if SHELL is a restricted shell (one not returned by
+@@ -511,9 +724,9 @@ main (int argc, char **argv)
+ shell = xstrdup (shell ? shell : pw->pw_shell);
+ modify_environment (pw, shell);
+
++#ifndef USE_PAM
+ change_identity (pw);
+- if (simulate_login && chdir (pw->pw_dir) != 0)
+- error (0, errno, _("warning: cannot change directory to %s"), pw->pw_dir);
++#endif
+
+ /* error() flushes stderr, but does not check for write failure.
+ Normally, we would catch this via our atexit() hook of
+@@ -523,5 +736,5 @@ main (int argc, char **argv)
+ if (ferror (stderr))
+ exit (EXIT_CANCELED);
+
+- run_shell (shell, command, argv + optind, MAX (0, argc - optind));
++ run_shell (shell, command, argv + optind, MAX (0, argc - optind), pw);
+ }
diff --git a/testing/coreutils/coreutils.install b/testing/coreutils/coreutils.install
new file mode 100644
index 000000000..8caae6686
--- /dev/null
+++ b/testing/coreutils/coreutils.install
@@ -0,0 +1,21 @@
+infodir=usr/share/info
+filelist=(coreutils.info)
+
+post_install() {
+ [ -x usr/bin/install-info ] || return 0
+ for file in ${filelist[@]}; do
+ usr/bin/install-info $infodir/$file.gz $infodir/dir 2> /dev/null
+ done
+}
+
+post_upgrade() {
+ post_install $1
+}
+
+pre_remove() {
+ [ -x usr/bin/install-info ] || return 0
+ for file in ${filelist[@]}; do
+ usr/bin/install-info --delete $infodir/$file.gz $infodir/dir 2> /dev/null
+ done
+}
+
diff --git a/testing/coreutils/su.pam b/testing/coreutils/su.pam
new file mode 100644
index 000000000..cf15f40f1
--- /dev/null
+++ b/testing/coreutils/su.pam
@@ -0,0 +1,9 @@
+#%PAM-1.0
+auth sufficient pam_rootok.so
+# Uncomment the following line to implicitly trust users in the "wheel" group.
+#auth sufficient pam_wheel.so trust use_uid
+# Uncomment the following line to require a user to be in the "wheel" group.
+#auth required pam_wheel.so use_uid
+auth required pam_unix.so
+account required pam_unix.so
+session required pam_unix.so