[linux-pam] pam_mkhomedir: check and create home directory for the same user (ticket #22)
by Dmitry V. Levin
commit f9db4aae8b0292d1273c7acda1cc20ff87fabd5c
Author: Dmitry V. Levin <ldv(a)altlinux.org>
Date: Mon Jan 20 02:29:41 2014 +0000
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.
modules/pam_mkhomedir/pam_mkhomedir.c | 10 +++++-----
1 files changed, 5 insertions(+), 5 deletions(-)
---
diff --git a/modules/pam_mkhomedir/pam_mkhomedir.c b/modules/pam_mkhomedir/pam_mkhomedir.c
index 5ac8a0f..0b5fc75 100644
--- a/modules/pam_mkhomedir/pam_mkhomedir.c
+++ b/modules/pam_mkhomedir/pam_mkhomedir.c
@@ -103,14 +103,14 @@ _pam_parse (const pam_handle_t *pamh, int flags, int argc, const char **argv,
/* 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."));
@@ -146,7 +146,7 @@ create_homedir (pam_handle_t *pamh, options_t *opt,
/* exec the mkhomedir helper */
args[0] = x_strdup(MKHOMEDIR_HELPER);
- args[1] = pwd->pw_name;
+ args[1] = (char *) user;
args[2] = x_strdup(opt->umask);
args[3] = x_strdup(opt->skeldir);
@@ -181,7 +181,7 @@ create_homedir (pam_handle_t *pamh, options_t *opt,
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 @@ pam_sm_open_session (pam_handle_t *pamh, int flags, int argc,
return PAM_SUCCESS;
}
- return create_homedir(pamh, &opt, pwd);
+ return create_homedir(pamh, &opt, user, pwd->pw_dir);
}
/* Ignore */
10 years, 3 months
[linux-pam] pam_limits: detect and ignore stale utmp entries
by Tomáš Mráz
commit 4eb04f3974b9245e31a59b0910c7b81ac5bc0496
Author: Tomas Mraz <tmraz(a)fedoraproject.org>
Date: Mon Jan 20 17:12:53 2014 +0100
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.
modules/pam_limits/pam_limits.c | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
---
diff --git a/modules/pam_limits/pam_limits.c b/modules/pam_limits/pam_limits.c
index 8bf3b9b..e2bc8e1 100644
--- a/modules/pam_limits/pam_limits.c
+++ b/modules/pam_limits/pam_limits.c
@@ -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>
@@ -279,6 +280,12 @@ check_logins (pam_handle_t *pamh, const char *name, int limit, int ctrl,
&& !pam_modutil_user_in_group_nam_nam(pamh, ut->UT_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);
+ continue;
+ }
}
if (++count > limit) {
break;
10 years, 3 months
[linux-pam] pam_loginuid: Always return PAM_IGNORE in userns
by vorlon
commit 2e62d5aea3f5ac267cfa54f0ea1f8c07ac85a95a
Author: Stéphane Graber <stgraber(a)ubuntu.com>
Date: Fri Jan 17 18:24:16 2014 -0500
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.
Signed-off-by: Stéphane Graber <stgraber(a)ubuntu.com>
Signed-off-by: Steve Langasek <vorlon(a)debian.org>
Signed-off-by: Dmitry V. Levin <ldv(a)altlinux.org>
modules/pam_loginuid/pam_loginuid.c | 21 +++++++++++----------
1 files changed, 11 insertions(+), 10 deletions(-)
---
diff --git a/modules/pam_loginuid/pam_loginuid.c b/modules/pam_loginuid/pam_loginuid.c
index 54ae6f0..d258422 100644
--- a/modules/pam_loginuid/pam_loginuid.c
+++ b/modules/pam_loginuid/pam_loginuid.c
@@ -58,21 +58,22 @@ static int set_loginuid(pam_handle_t *pamh, uid_t uid)
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_RDWR);
if (fd < 0) {
if (errno == ENOENT) {
rc = PAM_IGNORE;
- } else if (errno == EACCES) {
- 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);
- }
- if (rc != PAM_IGNORE)
- errno = EACCES;
}
if (rc != PAM_IGNORE) {
pam_syslog(pamh, LOG_ERR,
10 years, 3 months
[linux-pam] pam_namespace: don't use bashisms in default namespace.init script
by vorlon
commit fbc65c39d6853af268c9a093923afc876d0b138e
Author: Steve Langasek <vorlon(a)debian.org>
Date: Tue Jan 14 19:48:51 2014 -0800
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.
Signed-off-by: Steve Langasek <vorlon(a)debian.org>
Bug-Debian: http://bugs.debian.org/624842
Bug-Ubuntu: https://bugs.launchpad.net/bugs/1081323
modules/pam_namespace/namespace.init | 2 +-
modules/pam_namespace/pam_namespace.c | 5 +++++
2 files changed, 6 insertions(+), 1 deletions(-)
---
diff --git a/modules/pam_namespace/namespace.init b/modules/pam_namespace/namespace.init
index 9ab5806..67d4aa2 100755
--- a/modules/pam_namespace/namespace.init
+++ b/modules/pam_namespace/namespace.init
@@ -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 --git a/modules/pam_namespace/pam_namespace.c b/modules/pam_namespace/pam_namespace.c
index e0d5e30..92883f5 100644
--- a/modules/pam_namespace/pam_namespace.c
+++ b/modules/pam_namespace/pam_namespace.c
@@ -1205,6 +1205,11 @@ static int inst_init(const struct polydir_s *polyptr, const char *ipath,
_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);
10 years, 3 months
[linux-pam] pam_loginuid: Ignore failure in user namespaces
by vorlon
commit 24f3a88e7de52fbfcb7b8a1ebdae0cdbef420edf
Author: Stéphane Graber <stgraber(a)ubuntu.com>
Date: Tue Jan 7 16:12:03 2014 -0800
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).
Signed-off-by: Steve Langasek <vorlon(a)debian.org>
Signed-off-by: Dmitry V. Levin <ldv(a)altlinux.org>
modules/pam_loginuid/pam_loginuid.c | 15 ++++++++++++++-
1 files changed, 14 insertions(+), 1 deletions(-)
---
diff --git a/modules/pam_loginuid/pam_loginuid.c b/modules/pam_loginuid/pam_loginuid.c
index 96f8ffa..54ae6f0 100644
--- a/modules/pam_loginuid/pam_loginuid.c
+++ b/modules/pam_loginuid/pam_loginuid.c
@@ -55,13 +55,26 @@ static int set_loginuid(pam_handle_t *pamh, uid_t uid)
{
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)];
count = snprintf(loginuid, sizeof(loginuid), "%lu", (unsigned long)uid);
fd = open("/proc/self/loginuid", O_NOFOLLOW|O_RDWR);
if (fd < 0) {
if (errno == ENOENT) {
rc = PAM_IGNORE;
- } else {
+ } else if (errno == EACCES) {
+ 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);
+ }
+ if (rc != PAM_IGNORE)
+ errno = EACCES;
+ }
+ if (rc != PAM_IGNORE) {
pam_syslog(pamh, LOG_ERR,
"Cannot open /proc/self/loginuid: %m");
}
10 years, 3 months
[linux-pam] pam_loginuid: return PAM_IGNORE when /proc/self/loginuid does not exist
by vorlon
commit 5825450540e6620ac331c64345b42fdcbb1d6e87
Author: Dmitry V. Levin <ldv(a)altlinux.org>
Date: Wed Jan 8 15:53:30 2014 -0800
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.
modules/pam_loginuid/pam_loginuid.c | 43 ++++++++++++++++++++++------------
1 files changed, 28 insertions(+), 15 deletions(-)
---
diff --git a/modules/pam_loginuid/pam_loginuid.c b/modules/pam_loginuid/pam_loginuid.c
index a903845..96f8ffa 100644
--- a/modules/pam_loginuid/pam_loginuid.c
+++ b/modules/pam_loginuid/pam_loginuid.c
@@ -47,29 +47,35 @@
/*
* 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;
+ int fd, count, rc = PAM_SESSION_ERR;
char loginuid[24], buf[24];
count = snprintf(loginuid, sizeof(loginuid), "%lu", (unsigned long)uid);
fd = open("/proc/self/loginuid", O_NOFOLLOW|O_RDWR);
if (fd < 0) {
- if (errno != ENOENT) {
- rc = 1;
+ if (errno == ENOENT) {
+ rc = PAM_IGNORE;
+ } else {
pam_syslog(pamh, LOG_ERR,
"Cannot open /proc/self/loginuid: %m");
}
return rc;
}
+
if (pam_modutil_read(fd, buf, sizeof(buf)) == count &&
- memcmp(buf, loginuid, count) == 0)
+ memcmp(buf, loginuid, count) == 0) {
+ rc = PAM_SUCCESS;
goto done; /* already correct */
- if (lseek(fd, 0, SEEK_SET) == -1 || (ftruncate(fd, 0) == -1 ||
- pam_modutil_write(fd, loginuid, count) != count))
- rc = 1;
+ }
+ 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;
@@ -170,6 +176,7 @@ _pam_loginuid(pam_handle_t *pamh, int flags UNUSED,
{
const char *user = NULL;
struct passwd *pwd;
+ int ret;
#ifdef HAVE_LIBAUDIT
int require_auditd = 0;
#endif
@@ -188,9 +195,14 @@ _pam_loginuid(pam_handle_t *pamh, int flags UNUSED,
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
@@ -200,11 +212,12 @@ _pam_loginuid(pam_handle_t *pamh, int flags UNUSED,
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;
}
/*
10 years, 3 months
[linux-pam] pam_access: fix debug level logging (ticket #19)
by Dmitry V. Levin
commit 2a5d231074efd71281a8d722519b69fda0748a7e
Author: Dmitry V. Levin <ldv(a)altlinux.org>
Date: Wed Nov 20 15:55:40 2013 +0000
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.
modules/pam_access/pam_access.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
---
diff --git a/modules/pam_access/pam_access.c b/modules/pam_access/pam_access.c
index a9cce51..87626e7 100644
--- a/modules/pam_access/pam_access.c
+++ b/modules/pam_access/pam_access.c
@@ -573,7 +573,7 @@ group_match (pam_handle_t *pamh, const char *tok, const char* usr,
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;
10 years, 3 months