summaryrefslogtreecommitdiff
path: root/modules/pam_loginuid/pam_loginuid.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/pam_loginuid/pam_loginuid.c')
-rw-r--r--modules/pam_loginuid/pam_loginuid.c95
1 files changed, 61 insertions, 34 deletions
diff --git a/modules/pam_loginuid/pam_loginuid.c b/modules/pam_loginuid/pam_loginuid.c
index 06479973..96bfd98e 100644
--- a/modules/pam_loginuid/pam_loginuid.c
+++ b/modules/pam_loginuid/pam_loginuid.c
@@ -47,25 +47,56 @@
/*
* 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)];
- count = snprintf(loginuid, sizeof(loginuid), "%lu", (unsigned long)uid);
- fd = open("/proc/self/loginuid", O_NOFOLLOW|O_WRONLY|O_TRUNC);
+ /* 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);
+ }
+
+ fd = open("/proc/self/loginuid", O_NOFOLLOW|O_RDWR);
if (fd < 0) {
- if (errno != ENOENT) {
- rc = 1;
- pam_syslog(pamh, LOG_ERR,
- "Cannot open /proc/self/loginuid: %m");
+ if (errno == ENOENT) {
+ rc = PAM_IGNORE;
+ }
+ if (rc != PAM_IGNORE) {
+ pam_syslog(pamh, LOG_ERR, "Cannot open %s: %m",
+ "/proc/self/loginuid");
}
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;
+ } else {
+ if (rc != PAM_IGNORE) {
+ pam_syslog(pamh, LOG_ERR, "Error writing %s: %m",
+ "/proc/self/loginuid");
+ }
+ }
+ done:
close(fd);
return rc;
}
@@ -165,6 +196,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
@@ -183,9 +215,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
@@ -195,11 +232,14 @@ _pam_loginuid(pam_handle_t *pamh, int flags UNUSED,
argv++;
}
- if (require_auditd)
- return check_auditd();
- else
+ if (require_auditd) {
+ int rc = check_auditd();
+ if (rc != PAM_SUCCESS)
+ pam_syslog(pamh, LOG_ERR, "required running auditd not detected");
+ return rc != PAM_SUCCESS ? rc : ret;
+ } else
#endif
- return PAM_SUCCESS;
+ return ret;
}
/*
@@ -207,34 +247,21 @@ _pam_loginuid(pam_handle_t *pamh, int flags UNUSED,
*
* This is here for vsftpd which doesn't seem to run the session stack
*/
-PAM_EXTERN int
+int
pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
return _pam_loginuid(pamh, flags, argc, argv);
}
-PAM_EXTERN int
+int
pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
return _pam_loginuid(pamh, flags, argc, argv);
}
-PAM_EXTERN int
+int
pam_sm_close_session(pam_handle_t *pamh UNUSED, int flags UNUSED,
int argc UNUSED, const char **argv UNUSED)
{
return PAM_SUCCESS;
}
-
-/* static module data */
-#ifdef PAM_STATIC
-struct pam_module _pam_loginuid_modstruct = {
- "pam_loginuid",
- NULL,
- NULL,
- pam_sm_acct_mgmt,
- pam_sm_open_session,
- pam_sm_close_session,
- NULL
-};
-#endif