[linux-pam] Change tarball name back to "Linux-PAM"
by Dmitry V. Levin
commit 316e993f24778395b4769f5e8f49ea03227446e4
Author: Dmitry V. Levin <ldv(a)altlinux.org>
Date: Tue Jan 28 15:01:24 2014 +0000
Change tarball name back to "Linux-PAM"
As a side effect of commit Linux-PAM-1_1_8-11-g3fa23ce, tarball name
changed accidentally from "Linux-PAM" to "linux-pam".
This change brings it back to "Linux-PAM".
* configure.in (AC_INIT): Explicitly specify TARNAME argument.
configure.in | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
---
diff --git a/configure.in b/configure.in
index a161e20..2597802 100644
--- a/configure.in
+++ b/configure.in
@@ -1,5 +1,5 @@
dnl Process this file with autoconf to produce a configure script.
-AC_INIT([Linux-PAM], [1.1.8])
+AC_INIT([Linux-PAM], [1.1.8], , [Linux-PAM])
AC_CONFIG_SRCDIR([conf/pam_conv1/pam_conv_y.y])
AC_CONFIG_AUX_DIR([build-aux])
AM_INIT_AUTOMAKE
10 years, 3 months
[linux-pam] Introduce pam_modutil_sanitize_helper_fds
by Dmitry V. Levin
commit b0ec5d1e472a0cd74972bfe9575dcf6a3d0cad1c
Author: Dmitry V. Levin <ldv(a)altlinux.org>
Date: Fri Jan 24 15:32:08 2014 +0000
Introduce pam_modutil_sanitize_helper_fds
This change introduces pam_modutil_sanitize_helper_fds - a new function
that redirects standard descriptors and closes all other descriptors.
pam_modutil_sanitize_helper_fds supports three types of input and output
redirection:
- PAM_MODUTIL_IGNORE_FD: do not redirect at all.
- PAM_MODUTIL_PIPE_FD: redirect to a pipe. For stdin, it is implemented
by creating a pipe, closing its write end, and redirecting stdin to
its read end. Likewise, for stdout/stderr it is implemented by
creating a pipe, closing its read end, and redirecting to its write
end. Unlike stdin redirection, stdout/stderr redirection to a pipe
has a side effect that a process writing to such descriptor should be
prepared to handle SIGPIPE appropriately.
- PAM_MODUTIL_NULL_FD: redirect to /dev/null. For stdin, it is
implemented via PAM_MODUTIL_PIPE_FD because there is no functional
difference. For stdout/stderr, it is classic redirection to
/dev/null.
PAM_MODUTIL_PIPE_FD is usually more suitable due to linux kernel
security restrictions, but when the helper process might be writing to
the corresponding descriptor and termination of the helper process by
SIGPIPE is not desirable, one should choose PAM_MODUTIL_NULL_FD.
* libpam/pam_modutil_sanitize.c: New file.
* libpam/Makefile.am (libpam_la_SOURCES): Add it.
* libpam/include/security/pam_modutil.h (pam_modutil_redirect_fd,
pam_modutil_sanitize_helper_fds): New declarations.
* libpam/libpam.map (LIBPAM_MODUTIL_1.1.9): New interface.
* modules/pam_exec/pam_exec.c (call_exec): Use
pam_modutil_sanitize_helper_fds.
* modules/pam_mkhomedir/pam_mkhomedir.c (create_homedir): Likewise.
* 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.
* modules/pam_xauth/pam_xauth.c (run_coprocess): Likewise.
* modules/pam_unix/support.h (MAX_FD_NO): Remove.
libpam/Makefile.am | 2 +-
libpam/include/security/pam_modutil.h | 13 +++
libpam/libpam.map | 5 +
libpam/pam_modutil_sanitize.c | 175 +++++++++++++++++++++++++++++++++
modules/pam_exec/pam_exec.c | 34 ++-----
modules/pam_mkhomedir/pam_mkhomedir.c | 15 +--
modules/pam_unix/pam_unix_acct.c | 23 ++---
modules/pam_unix/pam_unix_passwd.c | 20 ++--
modules/pam_unix/support.c | 20 ++--
modules/pam_unix/support.h | 2 -
modules/pam_xauth/pam_xauth.c | 26 +++--
11 files changed, 251 insertions(+), 84 deletions(-)
---
diff --git a/libpam/Makefile.am b/libpam/Makefile.am
index 417ca77..685a797 100644
--- a/libpam/Makefile.am
+++ b/libpam/Makefile.am
@@ -43,4 +43,4 @@ libpam_la_SOURCES = pam_account.c pam_auth.c pam_data.c pam_delay.c \
pam_modutil_cleanup.c pam_modutil_getpwnam.c pam_modutil_ioloop.c \
pam_modutil_getgrgid.c pam_modutil_getpwuid.c pam_modutil_getgrnam.c \
pam_modutil_getspnam.c pam_modutil_getlogin.c pam_modutil_ingroup.c \
- pam_modutil_priv.c
+ pam_modutil_priv.c pam_modutil_sanitize.c
diff --git a/libpam/include/security/pam_modutil.h b/libpam/include/security/pam_modutil.h
index 8087ba1..4ce8c55 100644
--- a/libpam/include/security/pam_modutil.h
+++ b/libpam/include/security/pam_modutil.h
@@ -129,6 +129,19 @@ extern int PAM_NONNULL((1,2))
pam_modutil_regain_priv(pam_handle_t *pamh,
struct pam_modutil_privs *p);
+enum pam_modutil_redirect_fd {
+ PAM_MODUTIL_IGNORE_FD, /* do not redirect */
+ PAM_MODUTIL_PIPE_FD, /* redirect to a pipe */
+ PAM_MODUTIL_NULL_FD, /* redirect to /dev/null */
+};
+
+/* redirect standard descriptors, close all other descriptors. */
+extern int PAM_NONNULL((1))
+pam_modutil_sanitize_helper_fds(pam_handle_t *pamh,
+ enum pam_modutil_redirect_fd redirect_stdin,
+ enum pam_modutil_redirect_fd redirect_stdout,
+ enum pam_modutil_redirect_fd redirect_stderr);
+
#ifdef __cplusplus
}
#endif
diff --git a/libpam/libpam.map b/libpam/libpam.map
index b0885d6..d6835b4 100644
--- a/libpam/libpam.map
+++ b/libpam/libpam.map
@@ -67,3 +67,8 @@ LIBPAM_MODUTIL_1.1.3 {
pam_modutil_drop_priv;
pam_modutil_regain_priv;
} LIBPAM_MODUTIL_1.1;
+
+LIBPAM_MODUTIL_1.1.9 {
+ global:
+ pam_modutil_sanitize_helper_fds;
+} LIBPAM_MODUTIL_1.1.3;
diff --git a/libpam/pam_modutil_sanitize.c b/libpam/pam_modutil_sanitize.c
new file mode 100644
index 0000000..65f85d0
--- /dev/null
+++ b/libpam/pam_modutil_sanitize.c
@@ -0,0 +1,175 @@
+/*
+ * This file implements the following functions:
+ * pam_modutil_sanitize_helper_fds:
+ * redirects standard descriptors, closes all other descriptors.
+ */
+
+#include "pam_modutil_private.h"
+#include <security/pam_ext.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <sys/resource.h>
+
+/*
+ * Creates a pipe, closes its write end, redirects fd to its read end.
+ * Returns fd on success, -1 otherwise.
+ */
+static int
+redirect_in_pipe(pam_handle_t *pamh, int fd, const char *name)
+{
+ int in[2];
+
+ if (pipe(in) < 0) {
+ pam_syslog(pamh, LOG_ERR, "Could not create pipe: %m");
+ return -1;
+ }
+
+ close(in[1]);
+
+ if (in[0] == fd)
+ return fd;
+
+ if (dup2(in[0], fd) != fd) {
+ pam_syslog(pamh, LOG_ERR, "dup2 of %s failed: %m", name);
+ fd = -1;
+ }
+
+ close(in[0]);
+ return fd;
+}
+
+/*
+ * Creates a pipe, closes its read end, redirects fd to its write end.
+ * Returns fd on success, -1 otherwise.
+ */
+static int
+redirect_out_pipe(pam_handle_t *pamh, int fd, const char *name)
+{
+ int out[2];
+
+ if (pipe(out) < 0) {
+ pam_syslog(pamh, LOG_ERR, "Could not create pipe: %m");
+ return -1;
+ }
+
+ close(out[0]);
+
+ if (out[1] == fd)
+ return fd;
+
+ if (dup2(out[1], fd) != fd) {
+ pam_syslog(pamh, LOG_ERR, "dup2 of %s failed: %m", name);
+ fd = -1;
+ }
+
+ close(out[1]);
+ return fd;
+}
+
+/*
+ * Opens /dev/null for writing, redirects fd there.
+ * Returns fd on success, -1 otherwise.
+ */
+static int
+redirect_out_null(pam_handle_t *pamh, int fd, const char *name)
+{
+ int null = open("/dev/null", O_WRONLY);
+
+ if (null < 0) {
+ pam_syslog(pamh, LOG_ERR, "open of %s failed: %m", "/dev/null");
+ return -1;
+ }
+
+ if (null == fd)
+ return fd;
+
+ if (dup2(null, fd) != fd) {
+ pam_syslog(pamh, LOG_ERR, "dup2 of %s failed: %m", name);
+ fd = -1;
+ }
+
+ close(null);
+ return fd;
+}
+
+static int
+redirect_out(pam_handle_t *pamh, enum pam_modutil_redirect_fd mode,
+ int fd, const char *name)
+{
+ switch (mode) {
+ case PAM_MODUTIL_PIPE_FD:
+ if (redirect_out_pipe(pamh, fd, name) < 0)
+ return -1;
+ break;
+ case PAM_MODUTIL_NULL_FD:
+ if (redirect_out_null(pamh, fd, name) < 0)
+ return -1;
+ break;
+ case PAM_MODUTIL_IGNORE_FD:
+ break;
+ }
+ return fd;
+}
+
+/* Closes all descriptors after stderr. */
+static void
+close_fds(void)
+{
+ /*
+ * An arbitrary upper limit for the maximum file descriptor number
+ * returned by RLIMIT_NOFILE.
+ */
+ const int MAX_FD_NO = 65535;
+
+ /* The lower limit is the same as for _POSIX_OPEN_MAX. */
+ const int MIN_FD_NO = 20;
+
+ int fd;
+ struct rlimit rlim;
+
+ if (getrlimit(RLIMIT_NOFILE, &rlim) || rlim.rlim_max > MAX_FD_NO)
+ fd = MAX_FD_NO;
+ else if (rlim.rlim_max < MIN_FD_NO)
+ fd = MIN_FD_NO;
+ else
+ fd = rlim.rlim_max - 1;
+
+ for (; fd > STDERR_FILENO; --fd)
+ close(fd);
+}
+
+int
+pam_modutil_sanitize_helper_fds(pam_handle_t *pamh,
+ enum pam_modutil_redirect_fd stdin_mode,
+ enum pam_modutil_redirect_fd stdout_mode,
+ enum pam_modutil_redirect_fd stderr_mode)
+{
+ if (stdin_mode != PAM_MODUTIL_IGNORE_FD &&
+ redirect_in_pipe(pamh, STDIN_FILENO, "stdin") < 0) {
+ return -1;
+ }
+
+ if (redirect_out(pamh, stdout_mode, STDOUT_FILENO, "stdout") < 0)
+ return -1;
+
+ /*
+ * If stderr should not be ignored and
+ * redirect mode for stdout and stderr are the same,
+ * optimize by redirecting stderr to stdout.
+ */
+ if (stderr_mode != PAM_MODUTIL_IGNORE_FD &&
+ stdout_mode == stderr_mode) {
+ if (dup2(STDOUT_FILENO, STDERR_FILENO) != STDERR_FILENO) {
+ pam_syslog(pamh, LOG_ERR,
+ "dup2 of %s failed: %m", "stderr");
+ return -1;
+ }
+ } else {
+ if (redirect_out(pamh, stderr_mode, STDERR_FILENO, "stderr") < 0)
+ return -1;
+ }
+
+ close_fds();
+ return 0;
+}
diff --git a/modules/pam_exec/pam_exec.c b/modules/pam_exec/pam_exec.c
index b56e4b2..12c4444 100644
--- a/modules/pam_exec/pam_exec.c
+++ b/modules/pam_exec/pam_exec.c
@@ -302,6 +302,10 @@ call_exec (const char *pam_type, pam_handle_t *pamh,
char **envlist, **tmp;
int envlen, nitems;
char *envstr;
+ enum pam_modutil_redirect_fd redirect_stdin =
+ expose_authtok ? PAM_MODUTIL_IGNORE_FD : PAM_MODUTIL_PIPE_FD;
+ enum pam_modutil_redirect_fd redirect_stdout =
+ (use_stdout || logfile) ? PAM_MODUTIL_IGNORE_FD : PAM_MODUTIL_NULL_FD;
/* First, move all the pipes off of stdin, stdout, and stderr, to ensure
* that calls to dup2 won't close them. */
@@ -330,18 +334,6 @@ call_exec (const char *pam_type, pam_handle_t *pamh,
_exit (err);
}
}
- else
- {
- close (STDIN_FILENO);
-
- /* New stdin. */
- if ((i = open ("/dev/null", O_RDWR)) < 0)
- {
- int err = errno;
- pam_syslog (pamh, LOG_ERR, "open of /dev/null failed: %m");
- _exit (err);
- }
- }
/* Set up stdout. */
@@ -374,26 +366,18 @@ call_exec (const char *pam_type, pam_handle_t *pamh,
free (buffer);
}
}
- else
- {
- close (STDOUT_FILENO);
- if ((i = open ("/dev/null", O_RDWR)) < 0)
- {
- int err = errno;
- pam_syslog (pamh, LOG_ERR, "open of /dev/null failed: %m");
- _exit (err);
- }
- }
- if (dup2 (STDOUT_FILENO, STDERR_FILENO) == -1)
+ if ((use_stdout || logfile) &&
+ dup2 (STDOUT_FILENO, STDERR_FILENO) == -1)
{
int err = errno;
pam_syslog (pamh, LOG_ERR, "dup2 failed: %m");
_exit (err);
}
- for (i = 3; i < sysconf (_SC_OPEN_MAX); i++)
- close (i);
+ if (pam_modutil_sanitize_helper_fds(pamh, redirect_stdin,
+ redirect_stdout, redirect_stdout) < 0)
+ _exit(1);
if (call_setuid)
if (setuid (geteuid ()) == -1)
diff --git a/modules/pam_mkhomedir/pam_mkhomedir.c b/modules/pam_mkhomedir/pam_mkhomedir.c
index a867a73..c922089 100644
--- a/modules/pam_mkhomedir/pam_mkhomedir.c
+++ b/modules/pam_mkhomedir/pam_mkhomedir.c
@@ -58,8 +58,6 @@
#include <security/pam_modutil.h>
#include <security/pam_ext.h>
-#define MAX_FD_NO 10000
-
/* argument parsing */
#define MKHOMEDIR_DEBUG 020 /* be verbose about things */
#define MKHOMEDIR_QUIET 040 /* keep quiet about things */
@@ -131,18 +129,13 @@ create_homedir (pam_handle_t *pamh, options_t *opt,
/* fork */
child = fork();
if (child == 0) {
- int i;
- struct rlimit rlim;
static char *envp[] = { NULL };
const char *args[] = { NULL, NULL, NULL, NULL, NULL };
- if (getrlimit(RLIMIT_NOFILE, &rlim)==0) {
- if (rlim.rlim_max >= MAX_FD_NO)
- rlim.rlim_max = MAX_FD_NO;
- for (i=0; i < (int)rlim.rlim_max; i++) {
- close(i);
- }
- }
+ if (pam_modutil_sanitize_helper_fds(pamh, PAM_MODUTIL_PIPE_FD,
+ PAM_MODUTIL_PIPE_FD,
+ PAM_MODUTIL_PIPE_FD) < 0)
+ _exit(PAM_SYSTEM_ERR);
/* exec the mkhomedir helper */
args[0] = MKHOMEDIR_HELPER;
diff --git a/modules/pam_unix/pam_unix_acct.c b/modules/pam_unix/pam_unix_acct.c
index dc505e7..2799845 100644
--- a/modules/pam_unix/pam_unix_acct.c
+++ b/modules/pam_unix/pam_unix_acct.c
@@ -98,24 +98,21 @@ int _unix_run_verify_binary(pam_handle_t *pamh, unsigned int ctrl,
/* fork */
child = fork();
if (child == 0) {
- int i=0;
- struct rlimit rlim;
static char *envp[] = { NULL };
const char *args[] = { NULL, NULL, NULL, NULL };
- /* reopen stdout as pipe */
- dup2(fds[1], STDOUT_FILENO);
-
/* XXX - should really tidy up PAM here too */
- if (getrlimit(RLIMIT_NOFILE,&rlim)==0) {
- if (rlim.rlim_max >= MAX_FD_NO)
- rlim.rlim_max = MAX_FD_NO;
- for (i=0; i < (int)rlim.rlim_max; i++) {
- if (i != STDOUT_FILENO) {
- close(i);
- }
- }
+ /* reopen stdout as pipe */
+ if (dup2(fds[1], STDOUT_FILENO) != STDOUT_FILENO) {
+ pam_syslog(pamh, LOG_ERR, "dup2 of %s failed: %m", "stdout");
+ _exit(PAM_AUTHINFO_UNAVAIL);
+ }
+
+ if (pam_modutil_sanitize_helper_fds(pamh, PAM_MODUTIL_PIPE_FD,
+ PAM_MODUTIL_IGNORE_FD,
+ PAM_MODUTIL_PIPE_FD) < 0) {
+ _exit(PAM_AUTHINFO_UNAVAIL);
}
if (geteuid() == 0) {
diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c
index 5f3a3db..606071e 100644
--- a/modules/pam_unix/pam_unix_passwd.c
+++ b/modules/pam_unix/pam_unix_passwd.c
@@ -201,8 +201,6 @@ static int _unix_run_update_binary(pam_handle_t *pamh, unsigned int ctrl, const
/* fork */
child = fork();
if (child == 0) {
- int i=0;
- struct rlimit rlim;
static char *envp[] = { NULL };
const char *args[] = { NULL, NULL, NULL, NULL, NULL, NULL };
char buffer[16];
@@ -210,15 +208,15 @@ static int _unix_run_update_binary(pam_handle_t *pamh, unsigned int ctrl, const
/* XXX - should really tidy up PAM here too */
/* reopen stdin as pipe */
- dup2(fds[0], STDIN_FILENO);
-
- if (getrlimit(RLIMIT_NOFILE,&rlim)==0) {
- if (rlim.rlim_max >= MAX_FD_NO)
- rlim.rlim_max = MAX_FD_NO;
- for (i=0; i < (int)rlim.rlim_max; i++) {
- if (i != STDIN_FILENO)
- close(i);
- }
+ if (dup2(fds[0], STDIN_FILENO) != STDIN_FILENO) {
+ pam_syslog(pamh, LOG_ERR, "dup2 of %s failed: %m", "stdin");
+ _exit(PAM_AUTHINFO_UNAVAIL);
+ }
+
+ if (pam_modutil_sanitize_helper_fds(pamh, PAM_MODUTIL_IGNORE_FD,
+ PAM_MODUTIL_PIPE_FD,
+ PAM_MODUTIL_PIPE_FD) < 0) {
+ _exit(PAM_AUTHINFO_UNAVAIL);
}
/* exec binary helper */
diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c
index 3a849c8..fdb45c2 100644
--- a/modules/pam_unix/support.c
+++ b/modules/pam_unix/support.c
@@ -564,23 +564,21 @@ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd,
/* fork */
child = fork();
if (child == 0) {
- int i=0;
- struct rlimit rlim;
static char *envp[] = { NULL };
const char *args[] = { NULL, NULL, NULL, NULL };
/* XXX - should really tidy up PAM here too */
/* reopen stdin as pipe */
- dup2(fds[0], STDIN_FILENO);
-
- if (getrlimit(RLIMIT_NOFILE,&rlim)==0) {
- if (rlim.rlim_max >= MAX_FD_NO)
- rlim.rlim_max = MAX_FD_NO;
- for (i=0; i < (int)rlim.rlim_max; i++) {
- if (i != STDIN_FILENO)
- close(i);
- }
+ if (dup2(fds[0], STDIN_FILENO) != STDIN_FILENO) {
+ pam_syslog(pamh, LOG_ERR, "dup2 of %s failed: %m", "stdin");
+ _exit(PAM_AUTHINFO_UNAVAIL);
+ }
+
+ if (pam_modutil_sanitize_helper_fds(pamh, PAM_MODUTIL_IGNORE_FD,
+ PAM_MODUTIL_PIPE_FD,
+ PAM_MODUTIL_PIPE_FD) < 0) {
+ _exit(PAM_AUTHINFO_UNAVAIL);
}
if (geteuid() == 0) {
diff --git a/modules/pam_unix/support.h b/modules/pam_unix/support.h
index 6f5b2eb..cd6ddb7 100644
--- a/modules/pam_unix/support.h
+++ b/modules/pam_unix/support.h
@@ -141,8 +141,6 @@ static const UNIX_Ctrls unix_args[UNIX_CTRLS_] =
#define UNIX_DEFAULTS (unix_args[UNIX__NONULL].flag)
-#define MAX_FD_NO 2000000
-
/* use this to free strings. ESPECIALLY password strings */
#define _pam_delete(xx) \
diff --git a/modules/pam_xauth/pam_xauth.c b/modules/pam_xauth/pam_xauth.c
index c7ce55a..2be4351 100644
--- a/modules/pam_xauth/pam_xauth.c
+++ b/modules/pam_xauth/pam_xauth.c
@@ -128,7 +128,6 @@ run_coprocess(pam_handle_t *pamh, const char *input, char **output,
/* We're the child. */
size_t j;
const char *args[10];
- int maxopened;
/* Drop privileges. */
if (setgid(gid) == -1)
{
@@ -150,19 +149,26 @@ run_coprocess(pam_handle_t *pamh, const char *input, char **output,
(unsigned long) geteuid ());
_exit (err);
}
- /* Initialize the argument list. */
- memset(args, 0, sizeof(args));
/* Set the pipe descriptors up as stdin and stdout, and close
* everything else, including the original values for the
* descriptors. */
- dup2(ipipe[0], STDIN_FILENO);
- dup2(opipe[1], STDOUT_FILENO);
- maxopened = (int)sysconf(_SC_OPEN_MAX);
- for (i = 0; i < maxopened; i++) {
- if ((i != STDIN_FILENO) && (i != STDOUT_FILENO)) {
- close(i);
- }
+ if (dup2(ipipe[0], STDIN_FILENO) != STDIN_FILENO) {
+ int err = errno;
+ pam_syslog(pamh, LOG_ERR, "dup2 of %s failed: %m", "stdin");
+ _exit(err);
}
+ if (dup2(opipe[1], STDOUT_FILENO) != STDOUT_FILENO) {
+ int err = errno;
+ pam_syslog(pamh, LOG_ERR, "dup2 of %s failed: %m", "stdout");
+ _exit(err);
+ }
+ if (pam_modutil_sanitize_helper_fds(pamh, PAM_MODUTIL_IGNORE_FD,
+ PAM_MODUTIL_IGNORE_FD,
+ PAM_MODUTIL_NULL_FD) < 0) {
+ _exit(1);
+ }
+ /* Initialize the argument list. */
+ memset(args, 0, sizeof(args));
/* Convert the varargs list into a regular array of strings. */
va_start(ap, command);
args[0] = command;
10 years, 3 months
[linux-pam] pam_xauth: avoid potential SIGPIPE when writing to xauth process
by Dmitry V. Levin
commit 47db675c910a065fa9602753a904b050b0322f29
Author: Dmitry V. Levin <ldv(a)altlinux.org>
Date: Fri Jan 24 13:38:38 2014 +0000
pam_xauth: avoid potential SIGPIPE when writing to xauth process
Similar issue in pam_unix was fixed by commit Linux-PAM-0-73~8.
* modules/pam_xauth/pam_xauth.c (run_coprocess): In the parent process,
close the read end of input pipe after writing to its write end.
modules/pam_xauth/pam_xauth.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
---
diff --git a/modules/pam_xauth/pam_xauth.c b/modules/pam_xauth/pam_xauth.c
index 7075547..c7ce55a 100644
--- a/modules/pam_xauth/pam_xauth.c
+++ b/modules/pam_xauth/pam_xauth.c
@@ -179,12 +179,12 @@ run_coprocess(pam_handle_t *pamh, const char *input, char **output,
}
/* We're the parent, so close the other ends of the pipes. */
- close(ipipe[0]);
close(opipe[1]);
/* Send input to the process (if we have any), then send an EOF. */
if (input) {
(void)pam_modutil_write(ipipe[1], input, strlen(input));
}
+ close(ipipe[0]); /* close here to avoid possible SIGPIPE above */
close(ipipe[1]);
/* Read data output until we run out of stuff to read. */
10 years, 3 months
[linux-pam] pam_loginuid: log significant loginuid write errors
by Dmitry V. Levin
commit 256b50e1fce2f785f1032a1949dd2d1dbc17e250
Author: Dmitry V. Levin <ldv(a)altlinux.org>
Date: Sun Jan 19 14:12:59 2014 +0000
pam_loginuid: log significant loginuid write errors
* modules/pam_loginuid/pam_loginuid.c (set_loginuid): Log those errors
during /proc/self/loginuid update that are not ignored.
modules/pam_loginuid/pam_loginuid.c | 12 +++++++++---
1 files changed, 9 insertions(+), 3 deletions(-)
---
diff --git a/modules/pam_loginuid/pam_loginuid.c b/modules/pam_loginuid/pam_loginuid.c
index c476f7b..73c42f9 100644
--- a/modules/pam_loginuid/pam_loginuid.c
+++ b/modules/pam_loginuid/pam_loginuid.c
@@ -75,8 +75,8 @@ static int set_loginuid(pam_handle_t *pamh, uid_t uid)
rc = PAM_IGNORE;
}
if (rc != PAM_IGNORE) {
- pam_syslog(pamh, LOG_ERR,
- "Cannot open /proc/self/loginuid: %m");
+ pam_syslog(pamh, LOG_ERR, "Cannot open %s: %m",
+ "/proc/self/loginuid");
}
return rc;
}
@@ -88,8 +88,14 @@ static int set_loginuid(pam_handle_t *pamh, uid_t uid)
goto done; /* already correct */
}
if (lseek(fd, 0, SEEK_SET) == 0 && ftruncate(fd, 0) == 0 &&
- pam_modutil_write(fd, loginuid, count) == count)
+ pam_modutil_write(fd, loginuid, count) == count) {
rc = PAM_SUCCESS;
+ } else {
+ if (rc != PAM_IGNORE) {
+ pam_syslog(pamh, LOG_ERR, "Error writing %s: %m",
+ "/proc/self/loginuid");
+ }
+ }
done:
close(fd);
return rc;
10 years, 3 months
[linux-pam] Fix gratuitous use of strdup and x_strdup
by Dmitry V. Levin
commit 154c00e1a480d2bac7e8aba3b13888eb909f8e7f
Author: Dmitry V. Levin <ldv(a)altlinux.org>
Date: Fri Jan 24 23:53:09 2014 +0000
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.
modules/pam_cracklib/pam_cracklib.c | 6 +++---
modules/pam_ftp/pam_ftp.c | 2 +-
modules/pam_mkhomedir/pam_mkhomedir.c | 12 ++++++------
modules/pam_unix/pam_unix_acct.c | 10 +++++-----
modules/pam_unix/pam_unix_passwd.c | 16 ++++++++--------
modules/pam_unix/support.c | 16 ++++++++--------
modules/pam_userdb/pam_userdb.c | 2 +-
modules/pam_userdb/pam_userdb.h | 3 ---
modules/pam_xauth/pam_xauth.c | 12 +++++-------
9 files changed, 37 insertions(+), 42 deletions(-)
---
diff --git a/modules/pam_cracklib/pam_cracklib.c b/modules/pam_cracklib/pam_cracklib.c
index 5691347..5eefd0b 100644
--- a/modules/pam_cracklib/pam_cracklib.c
+++ b/modules/pam_cracklib/pam_cracklib.c
@@ -619,16 +619,16 @@ static const char *password_check(pam_handle_t *pamh, struct cracklib_options *o
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 --git a/modules/pam_ftp/pam_ftp.c b/modules/pam_ftp/pam_ftp.c
index 896a1dd..221d8f8 100644
--- a/modules/pam_ftp/pam_ftp.c
+++ b/modules/pam_ftp/pam_ftp.c
@@ -81,7 +81,7 @@ static int lookup(const char *name, const char *list, const char **_user)
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 --git a/modules/pam_mkhomedir/pam_mkhomedir.c b/modules/pam_mkhomedir/pam_mkhomedir.c
index 0b5fc75..a867a73 100644
--- a/modules/pam_mkhomedir/pam_mkhomedir.c
+++ b/modules/pam_mkhomedir/pam_mkhomedir.c
@@ -134,7 +134,7 @@ create_homedir (pam_handle_t *pamh, options_t *opt,
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 @@ create_homedir (pam_handle_t *pamh, options_t *opt,
}
/* exec the mkhomedir helper */
- args[0] = x_strdup(MKHOMEDIR_HELPER);
- args[1] = (char *) user;
- 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"));
diff --git a/modules/pam_unix/pam_unix_acct.c b/modules/pam_unix/pam_unix_acct.c
index 8ec4449..dc505e7 100644
--- a/modules/pam_unix/pam_unix_acct.c
+++ b/modules/pam_unix/pam_unix_acct.c
@@ -101,7 +101,7 @@ int _unix_run_verify_binary(pam_handle_t *pamh, unsigned int ctrl,
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 @@ int _unix_run_verify_binary(pam_handle_t *pamh, unsigned int ctrl,
}
/* 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 --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c
index 0cfc0f4..5f3a3db 100644
--- a/modules/pam_unix/pam_unix_passwd.c
+++ b/modules/pam_unix/pam_unix_passwd.c
@@ -204,7 +204,7 @@ static int _unix_run_update_binary(pam_handle_t *pamh, unsigned int ctrl, const
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 @@ static int _unix_run_update_binary(pam_handle_t *pamh, unsigned int ctrl, const
}
/* 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"));
diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c
index 19d72e6..3a849c8 100644
--- a/modules/pam_unix/support.c
+++ b/modules/pam_unix/support.c
@@ -567,7 +567,7 @@ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd,
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 @@ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd,
}
/* 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 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name
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 --git a/modules/pam_userdb/pam_userdb.c b/modules/pam_userdb/pam_userdb.c
index ff040e6..ba36ebf 100644
--- a/modules/pam_userdb/pam_userdb.c
+++ b/modules/pam_userdb/pam_userdb.c
@@ -184,7 +184,7 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode,
else
key.dsize = strlen(key.dptr);
} else {
- key.dptr = x_strdup(user);
+ key.dptr = strdup(user);
key.dsize = strlen(user);
}
diff --git a/modules/pam_userdb/pam_userdb.h b/modules/pam_userdb/pam_userdb.h
index 3cd8fee..86e9b47 100644
--- a/modules/pam_userdb/pam_userdb.h
+++ b/modules/pam_userdb/pam_userdb.h
@@ -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 --git a/modules/pam_xauth/pam_xauth.c b/modules/pam_xauth/pam_xauth.c
index e1c0064..7075547 100644
--- a/modules/pam_xauth/pam_xauth.c
+++ b/modules/pam_xauth/pam_xauth.c
@@ -127,8 +127,7 @@ run_coprocess(pam_handle_t *pamh, const char *input, char **output,
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)
@@ -166,16 +165,15 @@ run_coprocess(pam_handle_t *pamh, const char *input, char **output,
}
/* 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);
}
10 years, 3 months
[linux-pam] pam_userdb: fix password hash comparison
by Dmitry V. Levin
commit 57a1e2b274d0a6376d92ada9926e5c5741e7da20
Author: Dmitry V. Levin <ldv(a)altlinux.org>
Date: Fri Jan 24 22:18:32 2014 +0000
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
modules/pam_userdb/pam_userdb.c | 9 ++++++---
1 files changed, 6 insertions(+), 3 deletions(-)
---
diff --git a/modules/pam_userdb/pam_userdb.c b/modules/pam_userdb/pam_userdb.c
index de8b5b1..ff040e6 100644
--- a/modules/pam_userdb/pam_userdb.c
+++ b/modules/pam_userdb/pam_userdb.c
@@ -222,12 +222,15 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode,
} 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");
}
};
10 years, 3 months
[linux-pam] pam_xauth: log fatal errors preventing xauth process execution
by Dmitry V. Levin
commit 91c66ca82063aaab5db9de0bf76f4456b2b11527
Author: Dmitry V. Levin <ldv(a)altlinux.org>
Date: Fri Jan 24 15:30:01 2014 +0000
pam_xauth: log fatal errors preventing xauth process execution
* modules/pam_xauth/pam_xauth.c (run_coprocess): Log errors from pipe()
and fork() calls.
modules/pam_xauth/pam_xauth.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
---
diff --git a/modules/pam_xauth/pam_xauth.c b/modules/pam_xauth/pam_xauth.c
index 88624b1..e1c0064 100644
--- a/modules/pam_xauth/pam_xauth.c
+++ b/modules/pam_xauth/pam_xauth.c
@@ -103,9 +103,11 @@ run_coprocess(pam_handle_t *pamh, const char *input, char **output,
/* 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 @@ run_coprocess(pam_handle_t *pamh, const char *input, char **output,
/* 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]);
10 years, 3 months
[linux-pam] pam_loginuid: cleanup loginuid buffer initialization
by Dmitry V. Levin
commit c15791289bbf1a4cef0898dc09a12fde16e53d67
Author: Dmitry V. Levin <ldv(a)altlinux.org>
Date: Sun Jan 19 14:02:53 2014 +0000
pam_loginuid: cleanup loginuid buffer initialization
* modules/pam_loginuid/pam_loginuid.c (set_loginuid): Move loginuid
buffer initialization closer to its first use.
modules/pam_loginuid/pam_loginuid.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
---
diff --git a/modules/pam_loginuid/pam_loginuid.c b/modules/pam_loginuid/pam_loginuid.c
index d258422..c476f7b 100644
--- a/modules/pam_loginuid/pam_loginuid.c
+++ b/modules/pam_loginuid/pam_loginuid.c
@@ -69,7 +69,6 @@ static int set_loginuid(pam_handle_t *pamh, uid_t uid)
close(fd);
}
- count = snprintf(loginuid, sizeof(loginuid), "%lu", (unsigned long)uid);
fd = open("/proc/self/loginuid", O_NOFOLLOW|O_RDWR);
if (fd < 0) {
if (errno == ENOENT) {
@@ -82,6 +81,7 @@ static int set_loginuid(pam_handle_t *pamh, uid_t uid)
return rc;
}
+ 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;
10 years, 3 months
[linux-pam] libpam_misc: fix an inconsistency in handling memory allocation errors
by Dmitry V. Levin
commit f760a6dc5853869d21051c7ed6015117941c1155
Author: Dmitry V. Levin <ldv(a)altlinux.org>
Date: Wed Jan 22 02:34:03 2014 +0000
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.
libpam_misc/misc_conv.c | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)
---
diff --git a/libpam_misc/misc_conv.c b/libpam_misc/misc_conv.c
index 3f74eea..be53f34 100644
--- a/libpam_misc/misc_conv.c
+++ b/libpam_misc/misc_conv.c
@@ -210,8 +210,12 @@ static int read_string(int echo, const char *prompt, char **retstr)
}
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 */
10 years, 3 months
[linux-pam] pam_limits: fix utmp->ut_user handling
by Dmitry V. Levin
commit 6b7558c8f88851ab954174e62d3b1e46cd2664b1
Author: Dmitry V. Levin <ldv(a)altlinux.org>
Date: Mon Jan 20 16:24:18 2014 +0000
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.
modules/pam_limits/pam_limits.c | 11 ++++++++---
1 files changed, 8 insertions(+), 3 deletions(-)
---
diff --git a/modules/pam_limits/pam_limits.c b/modules/pam_limits/pam_limits.c
index e2bc8e1..eabc856 100644
--- a/modules/pam_limits/pam_limits.c
+++ b/modules/pam_limits/pam_limits.c
@@ -270,20 +270,25 @@ check_logins (pam_handle_t *pamh, const char *name, int limit, int ctrl,
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, name);
+ "Stale utmp entry (pid %d) for '%s' ignored",
+ ut->ut_pid, user);
continue;
}
}
10 years, 3 months