File Linux-PAM-git-20140127.diff of Package pam.8944

diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Linux-PAM-1.1.8/ChangeLog new/linux-pam-1.1.8/ChangeLog
--- old/Linux-PAM-1.1.8/ChangeLog	2013-09-19 11:33:00.000000000 +0200
+++ new/linux-pam-1.1.8/ChangeLog	2014-01-27 15:04:04.000000000 +0100
@@ -1,3 +1,272 @@
+2014-01-27  Dmitry V. Levin  <ldv@altlinux.org>
+
+	Fix gratuitous use of strdup and x_strdup.
+	There is no need to copy strings passed as arguments to execve,
+	the only potentially noticeable effect of using strdup/x_strdup
+	would be a malformed argument list in case of memory allocation error.
+
+	Also, x_strdup, being a thin wrapper around strdup, is of no benefit
+	when its argument is known to be non-NULL, and should not be used in
+	such cases.
+
+	* modules/pam_cracklib/pam_cracklib.c (password_check): Use strdup
+	instead of x_strdup, the latter is of no benefit in this case.
+	* modules/pam_ftp/pam_ftp.c (lookup): Likewise.
+	* modules/pam_userdb/pam_userdb.c (user_lookup): Likewise.
+	* modules/pam_userdb/pam_userdb.h (x_strdup): Remove.
+	* modules/pam_mkhomedir/pam_mkhomedir.c (create_homedir): Do not use
+	x_strdup for strings passed as arguments to execve.
+	* modules/pam_unix/pam_unix_acct.c (_unix_run_verify_binary): Likewise.
+	* modules/pam_unix/pam_unix_passwd.c (_unix_run_update_binary): Likewise.
+	* modules/pam_unix/support.c (_unix_run_helper_binary): Likewise.
+	(_unix_verify_password): Use strdup instead of x_strdup, the latter
+	is of no benefit in this case.
+	* modules/pam_xauth/pam_xauth.c (run_coprocess): Do not use strdup for
+	strings passed as arguments to execv.
+
+	pam_userdb: fix password hash comparison.
+	Starting with commit Linux-PAM-0-77-28-g0b3e583 that introduced hashed
+	passwords support in pam_userdb, hashes are compared case-insensitively.
+	This bug leads to accepting hashes for completely different passwords in
+	addition to those that should be accepted.
+
+	Additionally, commit Linux-PAM-1_1_6-13-ge2a8187 that added support for
+	modern password hashes with different lengths and settings, did not
+	update the hash comparison accordingly, which leads to accepting
+	computed hashes longer than stored hashes when the latter is a prefix
+	of the former.
+
+	* modules/pam_userdb/pam_userdb.c (user_lookup): Reject the computed
+	hash whose length differs from the stored hash length.
+	Compare computed and stored hashes case-sensitively.
+	Fixes CVE-2013-7041.
+
+	Bug-Debian: http://bugs.debian.org/731368
+
+2014-01-24  Dmitry V. Levin  <ldv@altlinux.org>
+
+	pam_xauth: log fatal errors preventing xauth process execution.
+	* modules/pam_xauth/pam_xauth.c (run_coprocess): Log errors from pipe()
+	and fork() calls.
+
+2014-01-22  Dmitry V. Levin  <ldv@altlinux.org>
+
+	pam_loginuid: cleanup loginuid buffer initialization.
+	* modules/pam_loginuid/pam_loginuid.c (set_loginuid): Move loginuid
+	buffer initialization closer to its first use.
+
+	libpam_misc: fix an inconsistency in handling memory allocation errors.
+	When misc_conv fails to allocate memory for pam_response array, it
+	returns PAM_CONV_ERR.  However, when read_string fails to allocate
+	memory for a response string, it loses the response string and silently
+	ignores the error, with net result as if EOF has been read.
+
+	* libpam_misc/misc_conv.c (read_string): Use strdup instead of x_strdup,
+	the latter is of no benefit in this case.
+	Do not ignore potential memory allocation errors returned by strdup,
+	forward them to misc_conv.
+
+2014-01-20  Dmitry V. Levin  <ldv@altlinux.org>
+
+	pam_limits: fix utmp->ut_user handling.
+	ut_user member of struct utmp is a string that is not necessarily
+	null-terminated, so extra care should be taken when using it.
+
+	* modules/pam_limits/pam_limits.c (check_logins): Convert ut->UT_USER to
+	a null-terminated string and consistently use it where a null-terminated
+	string is expected.
+
+	pam_mkhomedir: check and create home directory for the same user (ticket #22)
+	Before pam_mkhomedir helper was introduced in commit
+	7b14630ef39e71f603aeca0c47edf2f384717176, pam_mkhomedir was checking for
+	existance and creating the same directory - the home directory of the
+	user NAME returned by pam_get_item(PAM_USER).
+
+	The change in behaviour accidentally introduced along with
+	mkhomedir_helper is not consistent: while the module still checks for
+	getpwnam(NAME)->pw_dir, the directory created by mkhomedir_helper is
+	getpwnam(getpwnam(NAME)->pw_name)->pw_dir, which is not necessarily
+	the same as the directory being checked.
+
+	This change brings check and creation back in sync, both handling
+	getpwnam(NAME)->pw_dir.
+
+	* modules/pam_mkhomedir/pam_mkhomedir.c (create_homedir): Replace
+	"struct passwd *" argument with user's name and home directory.
+	Pass user's name to MKHOMEDIR_HELPER.
+	(pam_sm_open_session): Update create_homedir call.
+
+2014-01-20  Tomas Mraz  <tmraz@fedoraproject.org>
+
+	pam_limits: detect and ignore stale utmp entries.
+	Original idea by Christopher Hailey
+
+	* modules/pam_limits/pam_limits.c (check_logins): Use kill() to
+	detect if pid of the utmp entry is still running and ignore the entry
+	if it is not.
+
+2014-01-19  St├ęphane Graber  <stgraber@ubuntu.com>
+
+	pam_loginuid: Always return PAM_IGNORE in userns.
+	The previous patch to support user namespaces works fine with containers
+	that are started from a desktop/terminal session but fails when dealing
+	with containers that were started from a remote session such as ssh.
+
+	I haven't looked at the exact reason for that in the kernel but on the
+	userspace side of things, the difference is that containers started from
+	an ssh session will happily let pam open /proc/self/loginuid read-write,
+	will let it read its content but will then fail with EPERM when trying
+	to write to it.
+
+	So to make the userns support bullet proof, this commit moves the userns
+	check earlier in the function (which means a small performance impact as
+	it'll now happen everytime on kernels that have userns support) and will
+	set rc = PAM_IGNORE instead of rc = PAM_ERROR.
+
+	The rest of the code is still executed in the event that PAM is run on a
+	future kernel where we have some kind of audit namespace that includes a
+	working loginuid.
+
+2014-01-15  Steve Langasek  <vorlon@debian.org>
+
+	pam_namespace: don't use bashisms in default namespace.init script.
+	* modules/pam_namespace/pam_namespace.c: call setuid() before execing the
+	namespace init script, so that scripts run with maximum privilege regardless
+	of the shell implementation.
+	* modules/pam_namespace/namespace.init: drop the '-p' bashism from the
+	shebang line
+
+	This is not a POSIX standard option, it's a bashism.  The bash manpage says
+	that it's used to prevent the effective user id from being reset to the real
+	user id on startup, and to ignore certain unsafe variables from the
+	environment.
+
+	In the case of pam_namespace, the -p is not necessary for environment
+	sanitizing because the PAM module (properly) sanitizes the environment
+	before execing the script.
+
+	The stated reason given in CVS history for passing -p is to "preserve euid
+	when called from setuid apps (su, newrole)."  This should be done more
+	portably, by calling setuid() before spawning the shell.
+
+	Bug-Debian: http://bugs.debian.org/624842
+	Bug-Ubuntu: https://bugs.launchpad.net/bugs/1081323
+
+2014-01-10  St├ęphane Graber  <stgraber@ubuntu.com>
+
+	pam_loginuid: Ignore failure in user namespaces.
+	When running pam_loginuid in a container using the user namespaces, even
+	uid 0 isn't allowed to set the loginuid property.
+
+	This change catches the EACCES from opening loginuid, checks if the user
+	is in the host namespace (by comparing the uid_map with the host's one)
+	and only if that's the case, sets rc to 1.
+
+	Should uid_map not exist or be unreadable for some reason, it'll be
+	assumed that the process is running on the host's namespace.
+
+	The initial reason behind this change was failure to ssh into an
+	unprivileged container (using a 3.13 kernel and current LXC) when using
+	a standard pam profile for sshd (which requires success from
+	pam_loginuid).
+
+	I believe this solution doesn't have any drawback and will allow people
+	to use unprivileged containers normally. An alternative would be to have
+	all distros set pam_loginuid as optional but that'd be bad for any of
+	the other potential failure case which people may care about.
+
+	There has also been some discussions to get some of the audit features
+	tied with the user namespaces but currently none of that has been merged
+	upstream and the currently proposed implementation doesn't cover
+	loginuid (nor is it clear how this should even work when loginuid is set
+	as immutable after initial write).
+
+2014-01-10  Dmitry V. Levin  <ldv@altlinux.org>
+
+	pam_loginuid: return PAM_IGNORE when /proc/self/loginuid does not exist.
+	When /proc/self/loginuid does not exist, return PAM_IGNORE instead of
+	PAM_SUCCESS, so that we can distinguish between "loginuid set
+	successfully" and "loginuid not set, but this is expected".
+
+	Suggested by Steve Langasek.
+
+	* modules/pam_loginuid/pam_loginuid.c (set_loginuid): Change return
+	code semantics: return PAM_SUCCESS on success, PAM_IGNORE when loginuid
+	does not exist, PAM_SESSION_ERR in case of any other error.
+	(_pam_loginuid): Forward the PAM error code returned by set_loginuid.
+
+2013-11-20  Dmitry V. Levin  <ldv@altlinux.org>
+
+	pam_access: fix debug level logging (ticket #19)
+	* modules/pam_access/pam_access.c (group_match): Log the group token
+	passed to the function, not an uninitialized data on the stack.
+
+	pam_warn: log flags passed to the module (ticket #25)
+	* modules/pam_warn/pam_warn.c (log_items): Take "flags" argument and
+	log it using pam_syslog.
+	(pam_sm_authenticate, pam_sm_setcred, pam_sm_chauthtok,
+	pam_sm_acct_mgmt, pam_sm_open_session, pam_sm_close_session): Pass
+	"flags" argument to log_items.
+
+	Modernize AM_INIT_AUTOMAKE invocation.
+	Before this change, automake complained that two- and three-arguments
+	forms of AM_INIT_AUTOMAKE are deprecated.
+
+	* configure.in: Pass PACKAGE and VERSION arguments to AC_INIT instead
+	of AM_INIT_AUTOMAKE.
+
+	Fix autoconf warnings.
+	Before this change, autoconf complained that AC_COMPILE_IFELSE
+	and AC_RUN_IFELSE was called before AC_USE_SYSTEM_EXTENSIONS.
+
+	* configure.in: Call AC_USE_SYSTEM_EXTENSIONS before LT_INIT.
+
+	pam_securetty: check return value of fgets.
+	Checking return value of fgets not only silences the warning from glibc
+	but also leads to a cleaner code.
+
+	* modules/pam_securetty/pam_securetty.c (securetty_perform_check):
+	Check return value of fgets.
+
+	pam_lastlog: fix format string.
+	gcc -Wformat justly complains:
+	format '%d' expects argument of type 'int', but argument 5 has type 'time_t'
+
+	* modules/pam_lastlog/pam_lastlog.c (pam_sm_authenticate): Fix format
+	string.
+
+2013-11-20  Darren Tucker  <dtucker@zip.com.au>
+
+	If the correct loginuid is set already, skip writing it.
+	modules/pam_loginuid/pam_loginuid.c (set_loginuid): Read the current loginuid
+	and skip writing if already correctly set.
+
+2013-11-11  Thorsten Kukuk  <kukuk@thkukuk.de>
+
+		Always ask for old password if changing NIS account.
+		* modules/pam_unix/pam_unix_passwd.c (pam_sm_chauthtok): ask
+		for old password if NIS account.
+
+2013-11-08  Thorsten Kukuk  <kukuk@thkukuk.de>
+
+	Allow DES as compatibility option for /etc/login.defs.
+	* modules/pam_unix/support.h: Add UNIX_DES
+
+2013-10-14  Tomas Mraz  <tmraz@fedoraproject.org>
+
+	Docfix: pam_prompt() and pam_vprompt() return int.
+	doc/man/pam_prompt.3.xml: pam_prompt() and pam_vprompt() return int.
+
+	Make pam_tty_audit work with old kernels not supporting log_passwd.
+	modules/pam_tty_audit/pam_tty_audit.c(nl_recv): Pad result with zeros
+	if message is short from older kernel.
+
+2013-09-25  Tomas Mraz  <tmraz@fedoraproject.org>
+
+	Fix pam_tty_audit log_passwd support and regression.
+	modules/pam_tty_audit/pam_tty_audit.c: Add missing "config.h" include.
+	(pam_sm_open_session): Always copy the old status as initialization of new.
+
 2013-09-19  Thorsten Kukuk  <kukuk@thkukuk.de>
 
 	Release version 1.1.8.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Linux-PAM-1.1.8/doc/man/pam_prompt.3.xml new/linux-pam-1.1.8/doc/man/pam_prompt.3.xml
--- old/Linux-PAM-1.1.8/doc/man/pam_prompt.3.xml	2013-06-18 16:11:21.000000000 +0200
+++ new/linux-pam-1.1.8/doc/man/pam_prompt.3.xml	2013-11-08 14:33:32.000000000 +0100
@@ -22,7 +22,7 @@
     <funcsynopsis>
       <funcsynopsisinfo>#include &lt;security/pam_ext.h&gt;</funcsynopsisinfo>
       <funcprototype>
-        <funcdef>void <function>pam_prompt</function></funcdef>
+        <funcdef>int <function>pam_prompt</function></funcdef>
         <paramdef>pam_handle_t *<parameter>pamh</parameter></paramdef>
         <paramdef>int <parameter>style</parameter></paramdef>
         <paramdef>char **<parameter>response</parameter></paramdef>
@@ -30,7 +30,7 @@
         <paramdef><parameter>...</parameter></paramdef>
       </funcprototype>
       <funcprototype>
-        <funcdef>void <function>pam_vprompt</function></funcdef>
+        <funcdef>int <function>pam_vprompt</function></funcdef>
         <paramdef>pam_handle_t *<parameter>pamh</parameter></paramdef>
         <paramdef>int <parameter>style</parameter></paramdef>
         <paramdef>char **<parameter>response</parameter></paramdef>
@@ -75,7 +75,7 @@
         <term>PAM_SUCCESS</term>
         <listitem>
            <para>
-             Transaction was successful created.
+              Conversation succeded, response is set.
           </para>
         </listitem>
       </varlistentry>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Linux-PAM-1.1.8/libpam_misc/misc_conv.c new/linux-pam-1.1.8/libpam_misc/misc_conv.c
--- old/Linux-PAM-1.1.8/libpam_misc/misc_conv.c	2013-06-18 16:11:21.000000000 +0200
+++ new/linux-pam-1.1.8/libpam_misc/misc_conv.c	2014-01-25 07:35:59.000000000 +0100
@@ -210,8 +210,12 @@
 		    }
 		    line[nc] = '\0';
 		}
-		*retstr = x_strdup(line);
+		*retstr = strdup(line);
 		_pam_overwrite(line);
+		if (!*retstr) {
+		    D(("no memory for response string"));
+		    nc = -1;
+		}
 
 		goto cleanexit;                /* return malloc()ed string */
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Linux-PAM-1.1.8/modules/pam_access/pam_access.c new/linux-pam-1.1.8/modules/pam_access/pam_access.c
--- old/Linux-PAM-1.1.8/modules/pam_access/pam_access.c	2013-06-18 16:11:21.000000000 +0200
+++ new/linux-pam-1.1.8/modules/pam_access/pam_access.c	2014-01-09 16:28:39.000000000 +0100
@@ -573,7 +573,7 @@
 
     if (debug)
         pam_syslog (pamh, LOG_DEBUG,
-		    "group_match: grp=%s, user=%s", grptok, usr);
+		    "group_match: grp=%s, user=%s", tok, usr);
 
     if (strlen(tok) < 3)
         return NO;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Linux-PAM-1.1.8/modules/pam_cracklib/pam_cracklib.c new/linux-pam-1.1.8/modules/pam_cracklib/pam_cracklib.c
--- old/Linux-PAM-1.1.8/modules/pam_cracklib/pam_cracklib.c	2013-06-18 16:11:21.000000000 +0200
+++ new/linux-pam-1.1.8/modules/pam_cracklib/pam_cracklib.c	2014-01-27 15:02:50.000000000 +0100
@@ -619,16 +619,16 @@
 	    return msg;
 	}
 
-	newmono = str_lower(x_strdup(new));
+	newmono = str_lower(strdup(new));
 	if (!newmono)
 		msg = _("memory allocation error");
 
-	usermono = str_lower(x_strdup(user));
+	usermono = str_lower(strdup(user));
 	if (!usermono)
 		msg = _("memory allocation error");
 
 	if (!msg && old) {
-		oldmono = str_lower(x_strdup(old));
+		oldmono = str_lower(strdup(old));
 		if (oldmono)
 			wrapped = malloc(strlen(oldmono) * 2 + 1);
 		if (wrapped) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Linux-PAM-1.1.8/modules/pam_ftp/pam_ftp.c new/linux-pam-1.1.8/modules/pam_ftp/pam_ftp.c
--- old/Linux-PAM-1.1.8/modules/pam_ftp/pam_ftp.c	2013-06-18 16:11:21.000000000 +0200
+++ new/linux-pam-1.1.8/modules/pam_ftp/pam_ftp.c	2014-01-27 15:02:50.000000000 +0100
@@ -81,7 +81,7 @@
 	char *list_copy, *x;
 	char *sptr = NULL;
 
-	list_copy = x_strdup(list);
+	list_copy = strdup(list);
 	x = list_copy;
 	while (list_copy && (l = strtok_r(x, ",", &sptr))) {
 	    x = NULL;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Linux-PAM-1.1.8/modules/pam_lastlog/pam_lastlog.c new/linux-pam-1.1.8/modules/pam_lastlog/pam_lastlog.c
--- old/Linux-PAM-1.1.8/modules/pam_lastlog/pam_lastlog.c	2013-06-18 16:11:21.000000000 +0200
+++ new/linux-pam-1.1.8/modules/pam_lastlog/pam_lastlog.c	2013-11-28 11:37:54.000000000 +0100
@@ -628,7 +628,8 @@
     lltime = (time(NULL) - lltime) / (24*60*60);
 
     if (lltime > inactive_days) {
-        pam_syslog(pamh, LOG_INFO, "user %s inactive for %d days - denied", user, lltime);
+        pam_syslog(pamh, LOG_INFO, "user %s inactive for %ld days - denied",
+		   user, (long) lltime);
         return PAM_AUTH_ERR;
     }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Linux-PAM-1.1.8/modules/pam_limits/pam_limits.c new/linux-pam-1.1.8/modules/pam_limits/pam_limits.c
--- old/Linux-PAM-1.1.8/modules/pam_limits/pam_limits.c	2013-06-18 16:11:21.000000000 +0200
+++ new/linux-pam-1.1.8/modules/pam_limits/pam_limits.c	2014-01-25 07:35:59.000000000 +0100
@@ -27,6 +27,7 @@
 #include <errno.h>
 #include <syslog.h>
 #include <stdarg.h>
+#include <signal.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/resource.h>
@@ -269,16 +270,27 @@
             continue;
 	}
         if (!pl->flag_numsyslogins) {
+	    char user[sizeof(ut->UT_USER) + 1];
+	    user[0] = '\0';
+	    strncat(user, ut->UT_USER, sizeof(ut->UT_USER));
+
 	    if (((pl->login_limit_def == LIMITS_DEF_USER)
 	         || (pl->login_limit_def == LIMITS_DEF_GROUP)
 		 || (pl->login_limit_def == LIMITS_DEF_DEFAULT))
-		&& strncmp(name, ut->UT_USER, sizeof(ut->UT_USER)) != 0) {
+		&& strcmp(name, user) != 0) {
                 continue;
 	    }
 	    if ((pl->login_limit_def == LIMITS_DEF_ALLGROUP)
-		&& !pam_modutil_user_in_group_nam_nam(pamh, ut->UT_USER, pl->login_group)) {
+		&& !pam_modutil_user_in_group_nam_nam(pamh, user, pl->login_group)) {
                 continue;
 	    }
+	    if (kill(ut->ut_pid, 0) == -1 && errno == ESRCH) {
+		/* process does not exist anymore */
+		pam_syslog(pamh, LOG_WARNING,
+			   "Stale utmp entry (pid %d) for '%s' ignored",
+			   ut->ut_pid, user);
+		continue;
+	    }
 	}
 	if (++count > limit) {
 	    break;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Linux-PAM-1.1.8/modules/pam_loginuid/pam_loginuid.c new/linux-pam-1.1.8/modules/pam_loginuid/pam_loginuid.c
--- old/Linux-PAM-1.1.8/modules/pam_loginuid/pam_loginuid.c	2013-06-18 16:11:21.000000000 +0200
+++ new/linux-pam-1.1.8/modules/pam_loginuid/pam_loginuid.c	2014-01-25 07:35:59.000000000 +0100
@@ -47,25 +47,50 @@
 
 /*
  * This function writes the loginuid to the /proc system. It returns
- * 0 on success and 1 on failure.
+ * PAM_SUCCESS on success,
+ * PAM_IGNORE when /proc/self/loginuid does not exist,
+ * PAM_SESSION_ERR in case of any other error.
  */
 static int set_loginuid(pam_handle_t *pamh, uid_t uid)
 {
-	int fd, count, rc = 0;
-	char loginuid[24];
+	int fd, count, rc = PAM_SESSION_ERR;
+	char loginuid[24], buf[24];
+	static const char host_uid_map[] = "         0          0 4294967295\n";
+	char uid_map[sizeof(host_uid_map)];
+
+	/* loginuid in user namespaces currently isn't writable and in some
+	   case, not even readable, so consider any failure as ignorable (but try
+	   anyway, in case we hit a kernel which supports it). */
+	fd = open("/proc/self/uid_map", O_RDONLY);
+	if (fd >= 0) {
+		count = pam_modutil_read(fd, uid_map, sizeof(uid_map));
+		if (strncmp(uid_map, host_uid_map, count) != 0)
+			rc = PAM_IGNORE;
+		close(fd);
+	}
 
-	count = snprintf(loginuid, sizeof(loginuid), "%lu", (unsigned long)uid);
-	fd = open("/proc/self/loginuid", O_NOFOLLOW|O_WRONLY|O_TRUNC);
+	fd = open("/proc/self/loginuid", O_NOFOLLOW|O_RDWR);
 	if (fd < 0) {
-		if (errno != ENOENT) {
-			rc = 1;
+		if (errno == ENOENT) {
+			rc = PAM_IGNORE;
+		}
+		if (rc != PAM_IGNORE) {
 			pam_syslog(pamh, LOG_ERR,
 				   "Cannot open /proc/self/loginuid: %m");
 		}
 		return rc;
 	}
-	if (pam_modutil_write(fd, loginuid, count) != count)
-		rc = 1;
+
+	count = snprintf(loginuid, sizeof(loginuid), "%lu", (unsigned long)uid);
+	if (pam_modutil_read(fd, buf, sizeof(buf)) == count &&
+	    memcmp(buf, loginuid, count) == 0) {
+		rc = PAM_SUCCESS;
+		goto done;	/* already correct */
+	}
+	if (lseek(fd, 0, SEEK_SET) == 0 && ftruncate(fd, 0) == 0 &&
+	    pam_modutil_write(fd, loginuid, count) == count)
+		rc = PAM_SUCCESS;
+ done:
 	close(fd);
 	return rc;
 }
@@ -165,6 +190,7 @@
 {
         const char *user = NULL;
 	struct passwd *pwd;
+	int ret;
 #ifdef HAVE_LIBAUDIT
 	int require_auditd = 0;
 #endif
@@ -183,9 +209,14 @@
 		return PAM_SESSION_ERR;
 	}
 
-	if (set_loginuid(pamh, pwd->pw_uid)) {
-		pam_syslog(pamh, LOG_ERR, "set_loginuid failed\n");
-		return PAM_SESSION_ERR;
+	ret = set_loginuid(pamh, pwd->pw_uid);
+	switch (ret) {
+		case PAM_SUCCESS:
+		case PAM_IGNORE:
+			break;
+		default:
+			pam_syslog(pamh, LOG_ERR, "set_loginuid failed");
+			return ret;
 	}
 
 #ifdef HAVE_LIBAUDIT
@@ -195,11 +226,12 @@
 		argv++;
 	}
 
-	if (require_auditd)
-		return check_auditd();
-	else
+	if (require_auditd) {
+		int rc = check_auditd();
+		return rc != PAM_SUCCESS ? rc : ret;
+	} else
 #endif
-		return PAM_SUCCESS;
+		return ret;
 }
 
 /*
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Linux-PAM-1.1.8/modules/pam_mkhomedir/pam_mkhomedir.c new/linux-pam-1.1.8/modules/pam_mkhomedir/pam_mkhomedir.c
--- old/Linux-PAM-1.1.8/modules/pam_mkhomedir/pam_mkhomedir.c	2013-06-18 16:11:21.000000000 +0200
+++ new/linux-pam-1.1.8/modules/pam_mkhomedir/pam_mkhomedir.c	2014-01-27 15:02:50.000000000 +0100
@@ -103,14 +103,14 @@
 /* Do the actual work of creating a home dir */
 static int
 create_homedir (pam_handle_t *pamh, options_t *opt,
-		const struct passwd *pwd)
+		const char *user, const char *dir)
 {
    int retval, child;
    struct sigaction newsa, oldsa;
 
    /* Mention what is happening, if the notification fails that is OK */
    if (!(opt->ctrl & MKHOMEDIR_QUIET))
-      pam_info(pamh, _("Creating directory '%s'."), pwd->pw_dir);
+      pam_info(pamh, _("Creating directory '%s'."), dir);
 
 
    D(("called."));
@@ -134,7 +134,7 @@
         int i;
         struct rlimit rlim;
 	static char *envp[] = { NULL };
-	char *args[] = { NULL, NULL, NULL, NULL, NULL };
+	const char *args[] = { NULL, NULL, NULL, NULL, NULL };
 
 	if (getrlimit(RLIMIT_NOFILE, &rlim)==0) {
           if (rlim.rlim_max >= MAX_FD_NO)
@@ -145,12 +145,12 @@
 	}
 
 	/* exec the mkhomedir helper */
-	args[0] = x_strdup(MKHOMEDIR_HELPER);
-	args[1] = pwd->pw_name;
-	args[2] = x_strdup(opt->umask);
-	args[3] = x_strdup(opt->skeldir);
+	args[0] = MKHOMEDIR_HELPER;
+	args[1] = user;
+	args[2] = opt->umask;
+	args[3] = opt->skeldir;
 
-	execve(MKHOMEDIR_HELPER, args, envp);
+	execve(MKHOMEDIR_HELPER, (char *const *) args, envp);
 
 	/* should not get here: exit with error */
 	D(("helper binary is not available"));
@@ -181,7 +181,7 @@
 
    if (retval != PAM_SUCCESS && !(opt->ctrl & MKHOMEDIR_QUIET)) {
 	pam_error(pamh, _("Unable to create and initialize directory '%s'."),
-	    pwd->pw_dir);
+		  dir);
    }
 
    D(("returning %d", retval));
@@ -230,7 +230,7 @@
       return PAM_SUCCESS;
    }
 
-   return create_homedir(pamh, &opt, pwd);
+   return create_homedir(pamh, &opt, user, pwd->pw_dir);
 }
 
 /* Ignore */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Linux-PAM-1.1.8/modules/pam_namespace/namespace.init new/linux-pam-1.1.8/modules/pam_namespace/namespace.init
--- old/Linux-PAM-1.1.8/modules/pam_namespace/namespace.init	2013-06-18 16:11:21.000000000 +0200
+++ new/linux-pam-1.1.8/modules/pam_namespace/namespace.init	2014-01-25 07:35:59.000000000 +0100
@@ -1,4 +1,4 @@
-#!/bin/sh -p
+#!/bin/sh
 # It receives polydir path as $1, the instance path as $2,
 # a flag whether the instance dir was newly created (0 - no, 1 - yes) in $3,
 # and user name in $4.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Linux-PAM-1.1.8/modules/pam_namespace/pam_namespace.c new/linux-pam-1.1.8/modules/pam_namespace/pam_namespace.c
--- old/Linux-PAM-1.1.8/modules/pam_namespace/pam_namespace.c	2013-06-18 16:11:21.000000000 +0200
+++ new/linux-pam-1.1.8/modules/pam_namespace/pam_namespace.c	2014-01-25 07:35:59.000000000 +0100
@@ -1205,6 +1205,11 @@
 						_exit(1);
 				}
 #endif
+				/* Pass maximum privs when we exec() */
+				if (setuid(geteuid()) < 0) {
+					/* ignore failures, they don't matter */
+				}
+
 				if (execle(init_script, init_script,
 					polyptr->dir, ipath, newdir?"1":"0", idata->user, NULL, envp) < 0)
 					_exit(1);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Linux-PAM-1.1.8/modules/pam_securetty/pam_securetty.c new/linux-pam-1.1.8/modules/pam_securetty/pam_securetty.c
--- old/Linux-PAM-1.1.8/modules/pam_securetty/pam_securetty.c	2013-06-18 16:11:21.000000000 +0200
+++ new/linux-pam-1.1.8/modules/pam_securetty/pam_securetty.c	2013-11-28 11:37:54.000000000 +0100
@@ -159,11 +159,10 @@
         if (cmdlinefile != NULL) {
             char line[LINE_MAX], *p;
 
-            line[0] = 0;
-            fgets(line, sizeof(line), cmdlinefile);
+            p = fgets(line, sizeof(line), cmdlinefile);
             fclose(cmdlinefile);
 
-            for (p = line; p; p = strstr(p+1, "console=")) {
+            for (; p; p = strstr(p+1, "console=")) {
                 char *e;
 
                 /* Test whether this is a beginning of a word? */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Linux-PAM-1.1.8/modules/pam_tty_audit/pam_tty_audit.c new/linux-pam-1.1.8/modules/pam_tty_audit/pam_tty_audit.c
--- old/Linux-PAM-1.1.8/modules/pam_tty_audit/pam_tty_audit.c	2013-08-28 10:53:40.000000000 +0200
+++ new/linux-pam-1.1.8/modules/pam_tty_audit/pam_tty_audit.c	2013-11-08 14:33:32.000000000 +0100
@@ -36,6 +36,7 @@
    USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
    DAMAGE. */
 
+#include "config.h"
 #include <errno.h>
 #include <fnmatch.h>
 #include <stdlib.h>
@@ -108,7 +109,7 @@
   struct msghdr msg;
   struct nlmsghdr nlm;
   struct iovec iov[2];
-  ssize_t res;
+  ssize_t res, resdiff;
 
  again:
   iov[0].iov_base = &nlm;
@@ -160,12 +161,17 @@
   res = recvmsg (fd, &msg, 0);
   if (res == -1)
     return -1;
-  if ((size_t)res != NLMSG_LENGTH (size)
+  resdiff = NLMSG_LENGTH(size) - (size_t)res;
+  if (resdiff < 0
       || nlm.nlmsg_type != type)
     {
       errno = EIO;
       return -1;
     }
+  else if (resdiff > 0)
+    {
+      memset((char *)buf + size - resdiff, 0, resdiff);
+    }
   return 0;
 }
 
@@ -275,6 +281,8 @@
       return PAM_SESSION_ERR;
     }
 
+  memcpy(&new_status, old_status, sizeof(new_status));
+
   new_status.enabled = (command == CMD_ENABLE ? 1 : 0);
 #ifdef HAVE_STRUCT_AUDIT_TTY_STATUS_LOG_PASSWD
   new_status.log_passwd = log_passwd;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Linux-PAM-1.1.8/modules/pam_unix/pam_unix_acct.c new/linux-pam-1.1.8/modules/pam_unix/pam_unix_acct.c
--- old/Linux-PAM-1.1.8/modules/pam_unix/pam_unix_acct.c	2013-09-16 11:11:51.000000000 +0200
+++ new/linux-pam-1.1.8/modules/pam_unix/pam_unix_acct.c	2014-01-27 15:02:50.000000000 +0100
@@ -101,7 +101,7 @@
     int i=0;
     struct rlimit rlim;
     static char *envp[] = { NULL };
-    char *args[] = { NULL, NULL, NULL, NULL };
+    const char *args[] = { NULL, NULL, NULL, NULL };
 
     /* reopen stdout as pipe */
     dup2(fds[1], STDOUT_FILENO);
@@ -130,11 +130,11 @@
     }
 
     /* exec binary helper */
-    args[0] = x_strdup(CHKPWD_HELPER);
-    args[1] = x_strdup(user);
-    args[2] = x_strdup("chkexpiry");
+    args[0] = CHKPWD_HELPER;
+    args[1] = user;
+    args[2] = "chkexpiry";
 
-    execve(CHKPWD_HELPER, args, envp);
+    execve(CHKPWD_HELPER, (char *const *) args, envp);
 
     pam_syslog(pamh, LOG_ERR, "helper binary execve failed: %m");
     /* should not get here: exit with error */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Linux-PAM-1.1.8/modules/pam_unix/pam_unix_passwd.c new/linux-pam-1.1.8/modules/pam_unix/pam_unix_passwd.c
--- old/Linux-PAM-1.1.8/modules/pam_unix/pam_unix_passwd.c	2013-09-16 11:09:47.000000000 +0200
+++ new/linux-pam-1.1.8/modules/pam_unix/pam_unix_passwd.c	2014-01-27 15:02:50.000000000 +0100
@@ -204,7 +204,7 @@
         int i=0;
         struct rlimit rlim;
 	static char *envp[] = { NULL };
-	char *args[] = { NULL, NULL, NULL, NULL, NULL, NULL };
+	const char *args[] = { NULL, NULL, NULL, NULL, NULL, NULL };
         char buffer[16];
 
 	/* XXX - should really tidy up PAM here too */
@@ -222,18 +222,18 @@
 	}
 
 	/* exec binary helper */
-	args[0] = x_strdup(UPDATE_HELPER);
-	args[1] = x_strdup(user);
-	args[2] = x_strdup("update");
+	args[0] = UPDATE_HELPER;
+	args[1] = user;
+	args[2] = "update";
 	if (on(UNIX_SHADOW, ctrl))
-		args[3] = x_strdup("1");
+		args[3] = "1";
 	else
-		args[3] = x_strdup("0");
+		args[3] = "0";
 
         snprintf(buffer, sizeof(buffer), "%d", remember);
-        args[4] = x_strdup(buffer);
+        args[4] = buffer;
 
-	execve(UPDATE_HELPER, args, envp);
+	execve(UPDATE_HELPER, (char *const *) args, envp);
 
 	/* should not get here: exit with error */
 	D(("helper binary is not available"));
@@ -614,7 +614,8 @@
 
 		if (_unix_blankpasswd(pamh, ctrl, user)) {
 			return PAM_SUCCESS;
-		} else if (off(UNIX__IAMROOT, ctrl)) {
+		} else if (off(UNIX__IAMROOT, ctrl) ||
+			   (on(UNIX_NIS, ctrl) && _unix_comesfromsource(pamh, user, 0, 1))) {
 			/* instruct user what is happening */
 			if (asprintf(&Announce, _("Changing password for %s."),
 				user) < 0) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Linux-PAM-1.1.8/modules/pam_unix/support.c new/linux-pam-1.1.8/modules/pam_unix/support.c
--- old/Linux-PAM-1.1.8/modules/pam_unix/support.c	2013-09-16 11:11:51.000000000 +0200
+++ new/linux-pam-1.1.8/modules/pam_unix/support.c	2014-01-27 15:02:50.000000000 +0100
@@ -567,7 +567,7 @@
         int i=0;
         struct rlimit rlim;
 	static char *envp[] = { NULL };
-	char *args[] = { NULL, NULL, NULL, NULL };
+	const char *args[] = { NULL, NULL, NULL, NULL };
 
 	/* XXX - should really tidy up PAM here too */
 
@@ -593,15 +593,15 @@
 	}
 
 	/* exec binary helper */
-	args[0] = strdup(CHKPWD_HELPER);
-	args[1] = x_strdup(user);
+	args[0] = CHKPWD_HELPER;
+	args[1] = user;
 	if (off(UNIX__NONULL, ctrl)) {	/* this means we've succeeded */
-	  args[2]=strdup("nullok");
+	  args[2]="nullok";
 	} else {
-	  args[2]=strdup("nonull");
+	  args[2]="nonull";
 	}
 
-	execve(CHKPWD_HELPER, args, envp);
+	execve(CHKPWD_HELPER, (char *const *) args, envp);
 
 	/* should not get here: exit with error */
 	D(("helper binary is not available"));
@@ -788,10 +788,10 @@
 				login_name = "";
 			    }
 
-			        new->user = x_strdup(name ? name : "");
+			        new->user = strdup(name ? name : "");
 				new->uid = getuid();
 				new->euid = geteuid();
-				new->name = x_strdup(login_name);
+				new->name = strdup(login_name);
 
 				/* any previous failures for this user ? */
 				if (pam_get_data(pamh, data_name, &void_old)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Linux-PAM-1.1.8/modules/pam_unix/support.h new/linux-pam-1.1.8/modules/pam_unix/support.h
--- old/Linux-PAM-1.1.8/modules/pam_unix/support.h	2013-06-18 16:24:05.000000000 +0200
+++ new/linux-pam-1.1.8/modules/pam_unix/support.h	2014-01-27 15:02:38.000000000 +0100
@@ -97,8 +97,9 @@
 					   password hash algorithms */
 #define UNIX_BLOWFISH_PASS       26	/* new password hashes will use blowfish */
 #define UNIX_MIN_PASS_LEN        27	/* min length for password */
+#define UNIX_DES                 28     /* DES, default */
 /* -------------- */
-#define UNIX_CTRLS_              28	/* number of ctrl arguments defined */
+#define UNIX_CTRLS_              29	/* number of ctrl arguments defined */
 
 #define UNIX_DES_CRYPT(ctrl)	(off(UNIX_MD5_PASS,ctrl)&&off(UNIX_BIGCRYPT,ctrl)&&off(UNIX_SHA256_PASS,ctrl)&&off(UNIX_SHA512_PASS,ctrl)&&off(UNIX_BLOWFISH_PASS,ctrl))
 
@@ -135,6 +136,7 @@
 /* UNIX_ALGO_ROUNDS */     {"rounds=",         _ALL_ON_,          0100000000, 0},
 /* UNIX_BLOWFISH_PASS */   {"blowfish",    _ALL_ON_^(0260420000), 0200000000, 1},
 /* UNIX_MIN_PASS_LEN */    {"minlen=",		_ALL_ON_,         0400000000, 0},
+/* UNIX_DES */             {"des",             _ALL_ON_^(0260420000),      0, 1},
 };
 
 #define UNIX_DEFAULTS  (unix_args[UNIX__NONULL].flag)
 .\" -----------------------------------------------------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Linux-PAM-1.1.8/modules/pam_userdb/pam_userdb.c new/linux-pam-1.1.8/modules/pam_userdb/pam_userdb.c
--- old/Linux-PAM-1.1.8/modules/pam_userdb/pam_userdb.c	2013-06-18 16:11:21.000000000 +0200
+++ new/linux-pam-1.1.8/modules/pam_userdb/pam_userdb.c	2014-01-27 15:02:50.000000000 +0100
@@ -184,7 +184,7 @@
 	else
 	    key.dsize = strlen(key.dptr);
     } else {
-        key.dptr = x_strdup(user);
+        key.dptr = strdup(user);
         key.dsize = strlen(user);
     }
 
@@ -222,12 +222,15 @@
 	  } else {
 	    cryptpw = crypt (pass, data.dptr);
 
-	    if (cryptpw) {
-	      compare = strncasecmp (data.dptr, cryptpw, data.dsize);
+	    if (cryptpw && strlen(cryptpw) == (size_t)data.dsize) {
+	      compare = memcmp(data.dptr, cryptpw, data.dsize);
 	    } else {
 	      compare = -2;
 	      if (ctrl & PAM_DEBUG_ARG) {
-		pam_syslog(pamh, LOG_INFO, "crypt() returned NULL");
+		if (cryptpw)
+		  pam_syslog(pamh, LOG_INFO, "lengths of computed and stored hashes differ");
+		else
+		  pam_syslog(pamh, LOG_INFO, "crypt() returned NULL");
 	      }
 	    };
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Linux-PAM-1.1.8/modules/pam_userdb/pam_userdb.h new/linux-pam-1.1.8/modules/pam_userdb/pam_userdb.h
--- old/Linux-PAM-1.1.8/modules/pam_userdb/pam_userdb.h	2013-06-18 16:11:21.000000000 +0200
+++ new/linux-pam-1.1.8/modules/pam_userdb/pam_userdb.h	2014-01-27 15:02:50.000000000 +0100
@@ -15,9 +15,6 @@
 #define PAM_USE_FPASS_ARG	0x0040
 #define PAM_TRY_FPASS_ARG	0x0080
 
-/* Useful macros */
-#define  x_strdup(s)  ( (s) ? strdup(s):NULL )
-
 /* The name of the module we are compiling */
 #ifndef MODULE_NAME
 #define MODULE_NAME	"pam_userdb"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Linux-PAM-1.1.8/modules/pam_warn/pam_warn.c new/linux-pam-1.1.8/modules/pam_warn/pam_warn.c
--- old/Linux-PAM-1.1.8/modules/pam_warn/pam_warn.c	2013-06-18 16:11:21.000000000 +0200
+++ new/linux-pam-1.1.8/modules/pam_warn/pam_warn.c	2013-11-28 11:37:54.000000000 +0100
@@ -33,7 +33,7 @@
      value = value ? value : default_value ;                    \
 } while (0)
 
-static void log_items(pam_handle_t *pamh, const char *function)
+static void log_items(pam_handle_t *pamh, const char *function, int flags)
 {
      const void *service=NULL, *user=NULL, *terminal=NULL,
 	 *rhost=NULL, *ruser=NULL;
@@ -45,8 +45,8 @@
      OBTAIN(PAM_RHOST, rhost, "<unknown>");
 
      pam_syslog(pamh, LOG_NOTICE,
-		"function=[%s] service=[%s] terminal=[%s] user=[%s]"
-		" ruser=[%s] rhost=[%s]\n", function,
+		"function=[%s] flags=%#x service=[%s] terminal=[%s] user=[%s]"
+		" ruser=[%s] rhost=[%s]\n", function, flags,
 		(const char *) service, (const char *) terminal,
 		(const char *) user, (const char *) ruser,
 		(const char *) rhost);
@@ -55,52 +55,52 @@
 /* --- authentication management functions (only) --- */
 
 PAM_EXTERN
-int pam_sm_authenticate(pam_handle_t *pamh, int flags UNUSED,
+int pam_sm_authenticate(pam_handle_t *pamh, int flags,
 			int argc UNUSED, const char **argv UNUSED)
 {
-    log_items(pamh, __FUNCTION__);
+    log_items(pamh, __FUNCTION__, flags);
     return PAM_IGNORE;
 }
 
 PAM_EXTERN
-int pam_sm_setcred(pam_handle_t *pamh, int flags UNUSED,
+int pam_sm_setcred(pam_handle_t *pamh, int flags,
 		   int argc UNUSED, const char **argv UNUSED)
 {
-    log_items(pamh, __FUNCTION__);
+    log_items(pamh, __FUNCTION__, flags);
     return PAM_IGNORE;
 }
 
 /* password updating functions */
 
 PAM_EXTERN
-int pam_sm_chauthtok(pam_handle_t *pamh, int flags UNUSED,
+int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
 		     int argc UNUSED, const char **argv UNUSED)
 {
-    log_items(pamh, __FUNCTION__);
+    log_items(pamh, __FUNCTION__, flags);
     return PAM_IGNORE;
 }
 
 PAM_EXTERN int
-pam_sm_acct_mgmt(pam_handle_t *pamh, int flags UNUSED,
+pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
 		 int argc UNUSED, const char **argv UNUSED)
 {
-    log_items(pamh, __FUNCTION__);
+    log_items(pamh, __FUNCTION__, flags);
     return PAM_IGNORE;
 }
 
 PAM_EXTERN int
-pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED,
+pam_sm_open_session(pam_handle_t *pamh, int flags,
 		    int argc UNUSED, const char **argv UNUSED)
 {
-    log_items(pamh, __FUNCTION__);
+    log_items(pamh, __FUNCTION__, flags);
     return PAM_IGNORE;
 }
 
 PAM_EXTERN int
-pam_sm_close_session(pam_handle_t *pamh, int flags UNUSED,
+pam_sm_close_session(pam_handle_t *pamh, int flags,
 		     int argc UNUSED, const char **argv UNUSED)
 {
-    log_items(pamh, __FUNCTION__);
+    log_items(pamh, __FUNCTION__, flags);
     return PAM_IGNORE;
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Linux-PAM-1.1.8/modules/pam_xauth/pam_xauth.c new/linux-pam-1.1.8/modules/pam_xauth/pam_xauth.c
--- old/Linux-PAM-1.1.8/modules/pam_xauth/pam_xauth.c	2013-06-18 16:11:21.000000000 +0200
+++ new/linux-pam-1.1.8/modules/pam_xauth/pam_xauth.c	2014-01-27 15:02:50.000000000 +0100
@@ -103,9 +103,11 @@
 
 	/* Create stdio pipery. */
 	if (pipe(ipipe) == -1) {
+		pam_syslog(pamh, LOG_ERR, "Could not create pipe: %m");
 		return -1;
 	}
 	if (pipe(opipe) == -1) {
+		pam_syslog(pamh, LOG_ERR, "Could not create pipe: %m");
 		close(ipipe[0]);
 		close(ipipe[1]);
 		return -1;
@@ -114,6 +116,7 @@
 	/* Fork off a child. */
 	child = fork();
 	if (child == -1) {
+		pam_syslog(pamh, LOG_ERR, "Could not fork: %m");
 		close(ipipe[0]);
 		close(ipipe[1]);
 		close(opipe[0]);
@@ -124,8 +127,7 @@
 	if (child == 0) {
 		/* We're the child. */
 		size_t j;
-		char *args[10];
-		const char *tmp;
+		const char *args[10];
 		int maxopened;
 		/* Drop privileges. */
 		if (setgid(gid) == -1)
@@ -163,16 +165,15 @@
 		}
 		/* Convert the varargs list into a regular array of strings. */
 		va_start(ap, command);
-		args[0] = strdup(command);
+		args[0] = command;
 		for (j = 1; j < ((sizeof(args) / sizeof(args[0])) - 1); j++) {
-			tmp = va_arg(ap, const char*);
-			if (tmp == NULL) {
+			args[j] = va_arg(ap, const char*);
+			if (args[j] == NULL) {
 				break;
 			}
-			args[j] = strdup(tmp);
 		}
 		/* Run the command. */
-		execv(command, args);
+		execv(command, (char *const *) args);
 		/* Never reached. */
 		_exit(1);
 	}
openSUSE Build Service is sponsored by