--- Linux-PAM-0.99.7.0/modules/pam_namespace/pam_namespace.c.unmnt-override 2007-01-22 14:06:31.000000000 +0100 +++ Linux-PAM-0.99.7.0/modules/pam_namespace/pam_namespace.c 2007-01-23 16:41:57.000000000 +0100 @@ -417,17 +417,18 @@ * uids for the polyinstantiated directory, polyinstantiation is not * performed for that user for that directory. */ -static int ns_override(struct polydir_s *polyptr, struct instance_data *idata) +static int ns_override(struct polydir_s *polyptr, struct instance_data *idata, + uid_t uid) { unsigned int i; if (idata->flags & PAMNS_DEBUG) pam_syslog(idata->pamh, LOG_DEBUG, "Checking for ns override in dir %s for uid %d", - polyptr->dir, idata->uid); + polyptr->dir, uid); for (i = 0; i < polyptr->num_uids; i++) { - if (idata->uid == polyptr->uid[i]) { + if (uid == polyptr->uid[i]) { return 1; } } @@ -1013,21 +1014,46 @@ int retval = 0, need_poly = 0, changing_dir = 0; char *cptr, *fptr, poly_parent[PATH_MAX]; struct polydir_s *pptr; + uid_t req_uid; + const void *ruser_name; + struct passwd *pwd; if (idata->flags & PAMNS_DEBUG) pam_syslog(idata->pamh, LOG_DEBUG, "Set up namespace for pid %d", getpid()); + retval = pam_get_item(idata->pamh, PAM_RUSER, &ruser_name); + if (ruser_name == NULL || retval != PAM_SUCCESS) { + retval = PAM_SUCCESS; + req_uid = getuid(); + } else { + pwd = pam_modutil_getpwnam(idata->pamh, ruser_name); + if (pwd != NULL) { + req_uid = pwd->pw_uid; + } else { + req_uid = getuid(); + } + } + /* * Cycle through all polyinstantiated directory entries to see if * polyinstantiation is needed at all. */ for (pptr = idata->polydirs_ptr; pptr; pptr = pptr->next) { - if (ns_override(pptr, idata)) { - if (idata->flags & PAMNS_DEBUG) - pam_syslog(idata->pamh, LOG_DEBUG, + if (ns_override(pptr, idata, idata->uid)) { + if (unmnt == NO_UNMNT || ns_override(pptr, idata, req_uid)) { + if (idata->flags & PAMNS_DEBUG) + pam_syslog(idata->pamh, LOG_DEBUG, "Overriding poly for user %d for dir %s", idata->uid, pptr->dir); + } else { + if (idata->flags & PAMNS_DEBUG) + pam_syslog(idata->pamh, LOG_DEBUG, + "Need unmount ns for user %d for dir %s", + idata->uid, pptr->dir); + need_poly = 1; + break; + } continue; } else { if (idata->flags & PAMNS_DEBUG) @@ -1057,15 +1083,20 @@ * call ns_setup to setup polyinstantiation for a particular entry. */ for (pptr = idata->polydirs_ptr; pptr; pptr = pptr->next) { - if (ns_override(pptr, idata)) - continue; - else { - if (idata->flags & PAMNS_DEBUG) + enum unmnt_op dir_unmnt = unmnt; + if (ns_override(pptr, idata, idata->uid)) { + if (unmnt == NO_UNMNT || ns_override(pptr, idata, req_uid)) { + continue; + } else { + dir_unmnt = UNMNT_ONLY; + } + } + if (idata->flags & PAMNS_DEBUG) pam_syslog(idata->pamh, LOG_DEBUG, "Setting poly ns for user %d for dir %s", idata->uid, pptr->dir); - if ((unmnt == UNMNT_REMNT) || (unmnt == UNMNT_ONLY)) { + if ((dir_unmnt == UNMNT_REMNT) || (dir_unmnt == UNMNT_ONLY)) { /* * Check to see if process current directory is in the * bind mounted instance_parent directory that we are trying to @@ -1105,13 +1136,12 @@ } else if (idata->flags & PAMNS_DEBUG) pam_syslog(idata->pamh, LOG_DEBUG, "Umount succeeded %s", pptr->dir); - } + } - if (unmnt != UNMNT_ONLY) { + if (dir_unmnt != UNMNT_ONLY) { retval = ns_setup(pptr, idata); if (retval != PAM_SUCCESS) break; - } } } @@ -1138,7 +1168,7 @@ * appropriate polyinstantiated instance directories. */ for (pptr = idata->polydirs_ptr; pptr; pptr = pptr->next) { - if (ns_override(pptr, idata)) + if (ns_override(pptr, idata, idata->uid)) continue; else { if (idata->flags & PAMNS_DEBUG)