From 0b1055f64657dc0bf175f75c23470b2be7630451 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Sun, 3 Oct 2010 21:00:53 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix Commit summary: --------------- 2010-10-04 Dmitry V. Levin * libpam/pam_modutil_priv.c: New file. * libpam/Makefile.am (libpam_la_SOURCES): Add it. * libpam/include/security/pam_modutil.h (struct pam_modutil_privs, PAM_MODUTIL_DEF_PRIVS, pam_modutil_drop_priv, pam_modutil_regain_priv): New declarations. * libpam/libpam.map (LIBPAM_MODUTIL_1.1.3): New interface. * modules/pam_env/pam_env.c (handle_env): Use new pam_modutil interface. * modules/pam_mail/pam_mail.c (_do_mail): Likewise. * modules/pam_xauth/pam_xauth.c (check_acl, pam_sm_open_session, pam_sm_close_session): Likewise. (pam_sm_open_session): Remove redundant fchown call. Fixes CVE-2010-3430, CVE-2010-3431. --- modules/pam_env/pam_env.c | 13 ++++++--- modules/pam_mail/pam_mail.c | 16 +++++++++--- modules/pam_xauth/pam_xauth.c | 61 ++++++++++++++++++++++--------------------- 3 files changed, 52 insertions(+), 38 deletions(-) (limited to 'modules') diff --git a/modules/pam_env/pam_env.c b/modules/pam_env/pam_env.c index 3a9eebea..8ac8ed33 100644 --- a/modules/pam_env/pam_env.c +++ b/modules/pam_env/pam_env.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -791,9 +790,15 @@ handle_env (pam_handle_t *pamh, int argc, const char **argv) return PAM_BUF_ERR; } if (stat(envpath, &statbuf) == 0) { - uid_t fsuid = setfsuid(user_entry->pw_uid); - retval = _parse_config_file(pamh, envpath); - setfsuid(fsuid); + PAM_MODUTIL_DEF_PRIVS(privs); + + if (pam_modutil_drop_priv(pamh, &privs, user_entry)) { + retval = PAM_SESSION_ERR; + } else { + retval = _parse_config_file(pamh, envpath); + if (pam_modutil_regain_priv(pamh, &privs)) + retval = PAM_SESSION_ERR; + } if (retval == PAM_IGNORE) retval = PAM_SUCCESS; } diff --git a/modules/pam_mail/pam_mail.c b/modules/pam_mail/pam_mail.c index c19cbbe3..f5ba1733 100644 --- a/modules/pam_mail/pam_mail.c +++ b/modules/pam_mail/pam_mail.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -444,9 +443,18 @@ static int _do_mail(pam_handle_t *pamh, int flags, int argc, if ((est && !(ctrl & PAM_NO_LOGIN)) || (!est && (ctrl & PAM_LOGOUT_TOO))) { - uid_t fsuid = setfsuid(pwd->pw_uid); - type = get_mail_status(pamh, ctrl, folder); - setfsuid(fsuid); + PAM_MODUTIL_DEF_PRIVS(privs); + + if (pam_modutil_drop_priv(pamh, &privs, pwd)) { + retval = PAM_SESSION_ERR; + goto do_mail_cleanup; + } else { + type = get_mail_status(pamh, ctrl, folder); + if (pam_modutil_regain_priv(pamh, &privs)) { + retval = PAM_SESSION_ERR; + goto do_mail_cleanup; + } + } if (type != 0) { retval = report_mail(pamh, ctrl, type, folder); diff --git a/modules/pam_xauth/pam_xauth.c b/modules/pam_xauth/pam_xauth.c index be2a2c7c..a64ae89f 100644 --- a/modules/pam_xauth/pam_xauth.c +++ b/modules/pam_xauth/pam_xauth.c @@ -35,7 +35,6 @@ #include "config.h" #include -#include #include #include #include @@ -237,8 +236,9 @@ check_acl(pam_handle_t *pamh, struct passwd *pwd; FILE *fp = NULL; int i, fd = -1, save_errno; - uid_t fsuid; struct stat st; + PAM_MODUTIL_DEF_PRIVS(privs); + /* Check this user's file. */ pwd = pam_modutil_getpwnam(pamh, this_user); if (pwd == NULL) { @@ -254,7 +254,8 @@ check_acl(pam_handle_t *pamh, "name of user's home directory is too long"); return PAM_SESSION_ERR; } - fsuid = setfsuid(pwd->pw_uid); + if (pam_modutil_drop_priv(pamh, &privs, pwd)) + return PAM_SESSION_ERR; if (!stat(path, &st)) { if (!S_ISREG(st.st_mode)) errno = EINVAL; @@ -262,7 +263,11 @@ check_acl(pam_handle_t *pamh, fd = open(path, O_RDONLY | O_NOCTTY); } save_errno = errno; - setfsuid(fsuid); + if (pam_modutil_regain_priv(pamh, &privs)) { + if (fd >= 0) + close(fd); + return PAM_SESSION_ERR; + } if (fd >= 0) { if (!fstat(fd, &st)) { if (!S_ISREG(st.st_mode)) @@ -344,7 +349,7 @@ pam_sm_open_session (pam_handle_t *pamh, int flags UNUSED, struct passwd *tpwd, *rpwd; int fd, i, debug = 0; int retval = PAM_SUCCESS; - uid_t systemuser = 499, targetuser = 0, fsuid; + uid_t systemuser = 499, targetuser = 0; /* Parse arguments. We don't understand many, so no sense in breaking * this into a separate function. */ @@ -506,10 +511,11 @@ pam_sm_open_session (pam_handle_t *pamh, int flags UNUSED, getuid(), getgid(), xauth, "-f", cookiefile, "nlist", display, NULL) == 0) { - int save_errno; #ifdef WITH_SELINUX security_context_t context = NULL; #endif + PAM_MODUTIL_DEF_PRIVS(privs); + /* Check that we got a cookie. If not, we get creative. */ if (((cookie == NULL) || (strlen(cookie) == 0)) && ((strncmp(display, "localhost:", 10) == 0) || @@ -592,8 +598,10 @@ pam_sm_open_session (pam_handle_t *pamh, int flags UNUSED, } /* Generate a new file to hold the data. */ - fsuid = setfsuid(tpwd->pw_uid); - + if (pam_modutil_drop_priv(pamh, &privs, tpwd)) { + retval = PAM_SESSION_ERR; + goto cleanup; + } #ifdef WITH_SELINUX if (is_selinux_enabled() > 0) { struct selabel_handle *ctx = selabel_open(SELABEL_CTX_FILE, NULL, 0); @@ -611,33 +619,24 @@ pam_sm_open_session (pam_handle_t *pamh, int flags UNUSED, } } } +#endif /* WITH_SELINUX */ fd = mkstemp(xauthority + sizeof(XAUTHENV)); - save_errno = errno; + if (fd < 0) + pam_syslog(pamh, LOG_ERR, + "error creating temporary file `%s': %m", + xauthority + sizeof(XAUTHENV)); +#ifdef WITH_SELINUX if (context != NULL) { free(context); setfscreatecon(NULL); } -#else - fd = mkstemp(xauthority + sizeof(XAUTHENV)); - save_errno = errno; -#endif - - setfsuid(fsuid); - if (fd == -1) { - errno = save_errno; - pam_syslog(pamh, LOG_ERR, - "error creating temporary file `%s': %m", - xauthority + sizeof(XAUTHENV)); +#endif /* WITH_SELINUX */ + if (fd >= 0) + close(fd); + if (pam_modutil_regain_priv(pamh, &privs) || fd < 0) { retval = PAM_SESSION_ERR; goto cleanup; } - /* Set permissions on the new file and dispose of the - * descriptor. */ - setfsuid(tpwd->pw_uid); - if (fchown(fd, tpwd->pw_uid, tpwd->pw_gid) < 0) - pam_syslog (pamh, LOG_ERR, "fchown: %m"); - setfsuid(fsuid); - close(fd); /* Get a copy of the filename to save as a data item for * removal at session-close time. */ @@ -736,7 +735,7 @@ pam_sm_close_session (pam_handle_t *pamh, int flags UNUSED, const void *data; const char *cookiefile; struct passwd *tpwd; - uid_t fsuid; + PAM_MODUTIL_DEF_PRIVS(privs); /* Try to retrieve the name of a file we created when * the session was opened. */ @@ -774,10 +773,12 @@ pam_sm_close_session (pam_handle_t *pamh, int flags UNUSED, if (debug) pam_syslog(pamh, LOG_DEBUG, "removing `%s'", cookiefile); - fsuid = setfsuid(tpwd->pw_uid); + if (pam_modutil_drop_priv(pamh, &privs, tpwd)) + return PAM_SESSION_ERR; if (unlink(cookiefile) == -1 && errno != ENOENT) pam_syslog(pamh, LOG_WARNING, "Couldn't remove `%s': %m", cookiefile); - setfsuid(fsuid); + if (pam_modutil_regain_priv(pamh, &privs)) + return PAM_SESSION_ERR; return PAM_SUCCESS; } -- cgit v1.2.3