diff -ruN ecryptfs-utils-96//src/pam_ecryptfs/pam_ecryptfs.c ecryptfs-utils-96//src/pam_ecryptfs/pam_ecryptfs.c --- ecryptfs-utils-96//src/pam_ecryptfs/pam_ecryptfs.c 2011-12-14 00:01:38.000000000 +0100 +++ ecryptfs-utils-96//src/pam_ecryptfs/pam_ecryptfs.c 2012-06-20 14:18:22.124559899 +0200 @@ -119,7 +119,8 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) { - uid_t uid = 0; + uid_t uid = 0, oeuid = 0; + gid_t gid = 0, oegid = 0; char *homedir = NULL; uid_t saved_uid = 0; const char *username; @@ -139,12 +140,24 @@ pwd = getpwnam(username); if (pwd) { uid = pwd->pw_uid; + gid = pwd->pw_gid; homedir = pwd->pw_dir; } } else { syslog(LOG_ERR, "pam_ecryptfs: Error getting passwd info for user [%s]; rc = [%ld]\n", username, rc); goto out; } + + if ((oeuid = geteuid()) < 0 || (oegid = getegid()) < 0) { + syslog(LOG_ERR, "pam_ecryptfs: geteuid error"); + goto outnouid; + } + + if (setfsgid(gid) != gid || setfsuid(uid) != uid) { + syslog(LOG_ERR, "pam_ecryptfs: setfsuid error"); + goto outnouid; + } + if (!file_exists_dotecryptfs(homedir, "auto-mount")) goto out; private_mnt = ecryptfs_fetch_private_mnt(homedir); @@ -158,13 +171,10 @@ load ecryptfs module if not loaded already */ if (ecryptfs_get_version(&version) != 0) syslog(LOG_WARNING, "pam_ecryptfs: Can't check if kernel supports ecryptfs\n"); - saved_uid = geteuid(); - seteuid(uid); if(file_exists_dotecryptfs(homedir, "wrapping-independent") == 1) rc = pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, &passphrase, "Encryption passphrase: "); else rc = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&passphrase); - seteuid(saved_uid); if (rc != PAM_SUCCESS) { syslog(LOG_ERR, "pam_ecryptfs: Error retrieving passphrase; rc = [%ld]\n", rc); @@ -182,7 +192,11 @@ } else from_hex(salt, salt_hex, ECRYPTFS_SALT_SIZE); if ((child_pid = fork()) == 0) { - setuid(uid); + if (setgroups(1, &gid) < 0 || setgid(gid) < 0 || setuid(uid) < 0) { + syslog(LOG_ERR, "pam_ecryptfs: setting uid/gid failed"); + rc = -errno; + goto out_child; + } if (passphrase == NULL) { syslog(LOG_ERR, "pam_ecryptfs: NULL passphrase; aborting\n"); rc = -EINVAL; @@ -240,6 +254,11 @@ if (tmp_pid == -1) syslog(LOG_WARNING, "pam_ecryptfs: waitpid() returned with error condition\n"); out: + + setfsuid(oeuid); + setfsgid(oegid); + +outnouid: if (private_mnt != NULL) free(private_mnt); return PAM_SUCCESS; @@ -338,8 +357,12 @@ syslog(LOG_DEBUG, "pam_ecryptfs: Skipping automatic eCryptfs mount"); return 0; } + clearenv(); /* run mount.ecryptfs_private as the user */ - setresuid(pwd->pw_uid, pwd->pw_uid, pwd->pw_uid); + if (setresuid(pwd->pw_uid, pwd->pw_uid, pwd->pw_uid) < 0) + return -1; + if (setgroups(1, &pwd->pw_gid) < 0 || setgid(pwd->pw_gid) < 0) + return -1; execl("/sbin/mount.ecryptfs_private", "mount.ecryptfs_private", NULL); } else { @@ -348,8 +371,12 @@ syslog(LOG_DEBUG, "pam_ecryptfs: Skipping automatic eCryptfs unmount"); return 0; } + clearenv(); /* run umount.ecryptfs_private as the user */ - setresuid(pwd->pw_uid, pwd->pw_uid, pwd->pw_uid); + if (setresuid(pwd->pw_uid, pwd->pw_uid, pwd->pw_uid) < 0) + return -1; + if (setgroups(1, &pwd->pw_gid) < 0 || setgid(pwd->pw_gid) < 0) + return -1; execl("/sbin/umount.ecryptfs_private", "umount.ecryptfs_private", NULL); } @@ -391,7 +418,8 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, int argc, const char **argv) { - uid_t uid = 0; + uid_t uid = 0, oeuid = 0; + gid_t gid = 0, oegid = 0; char *homedir = NULL; uid_t saved_uid = 0; const char *username; @@ -411,6 +439,7 @@ pwd = getpwnam(username); if (pwd) { uid = pwd->pw_uid; + gid = pwd->pw_gid; homedir = pwd->pw_dir; name = pwd->pw_name; } @@ -418,13 +447,21 @@ syslog(LOG_ERR, "pam_ecryptfs: Error getting passwd info for user [%s]; rc = [%ld]\n", username, rc); goto out; } - saved_uid = geteuid(); - seteuid(uid); + + if ((oeuid = geteuid()) < 0 || (oegid = getegid()) < 0) { + syslog(LOG_ERR, "pam_ecryptfs: geteuid error"); + goto outnouid; + } + + if (setfsgid(gid) != gid || setfsuid(uid) != uid) { + syslog(LOG_ERR, "pam_ecryptfs: setfsuid error"); + goto outnouid; + } + if ((rc = pam_get_item(pamh, PAM_OLDAUTHTOK, (const void **)&old_passphrase)) != PAM_SUCCESS) { syslog(LOG_ERR, "pam_ecryptfs: Error retrieving old passphrase; rc = [%d]\n", rc); - seteuid(saved_uid); goto out; } /* On the first pass, do nothing except check that we have a password */ @@ -434,14 +471,12 @@ syslog(LOG_WARNING, "pam_ecryptfs: PAM passphrase change module retrieved a NULL passphrase; nothing to do\n"); rc = PAM_AUTHTOK_RECOVER_ERR; } - seteuid(saved_uid); goto out; } if ((rc = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&new_passphrase)) != PAM_SUCCESS) { syslog(LOG_ERR, "pam_ecryptfs: Error retrieving new passphrase; rc = [%d]\n", rc); - seteuid(saved_uid); goto out; } if ((rc = asprintf(&wrapped_pw_filename, "%s/.ecryptfs/%s", homedir, @@ -462,7 +497,6 @@ goto out; } - seteuid(saved_uid); if (!old_passphrase || !new_passphrase || *new_passphrase == '\0') { syslog(LOG_WARNING, "pam_ecryptfs: PAM passphrase change module retrieved at least one NULL passphrase; nothing to do\n"); rc = PAM_AUTHTOK_RECOVER_ERR; @@ -472,7 +506,10 @@ if ((child_pid = fork()) == 0) { char passphrase[ECRYPTFS_MAX_PASSWORD_LENGTH + 1]; - setuid(uid); + if (setuid(uid) < 0 || setgid(gid) < 0 || setgroups(1, &gid) < 0) { + syslog(LOG_ERR, "pam_ecryptfs: Error setting uid/gid"); + goto out_child; + } if ((rc = ecryptfs_unwrap_passphrase(passphrase, wrapped_pw_filename, old_passphrase, salt))) { @@ -492,5 +529,10 @@ syslog(LOG_WARNING, "pam_ecryptfs: waitpid() returned with error condition\n"); free(wrapped_pw_filename); out: + + setfsuid(oeuid); + setfsgid(oegid); + +outnouid: return rc; } diff -ruN ecryptfs-utils-96//src/utils/mount.ecryptfs_private.c ecryptfs-utils-96//src/utils/mount.ecryptfs_private.c --- ecryptfs-utils-96//src/utils/mount.ecryptfs_private.c 2011-12-14 19:59:24.000000000 +0100 +++ ecryptfs-utils-96//src/utils/mount.ecryptfs_private.c 2012-06-20 14:34:54.694561382 +0200 @@ -535,6 +535,11 @@ exit(1); } + if (strstr(alias, "..")) { + fputs("Invalid alias", stderr); + exit(1); + } + /* Lock the counter through the rest of the program */ fh_counter = lock_counter(pwd->pw_name, uid, alias); if (fh_counter == NULL) { @@ -627,7 +632,7 @@ goto fail; } /* Perform mount */ - if (mount(src, ".", FSTYPE, 0, opt) == 0) { + if (mount(src, ".", FSTYPE, MS_NOSUID, opt) == 0) { if (update_mtab(src, dest, opt) != 0) { goto fail; } @@ -676,6 +681,7 @@ */ setresuid(0,0,0); setresgid(0,0,0); + clearenv(); /* Since we're doing a lazy unmount anyway, just unmount the current * directory. This avoids a lot of complexity in dealing with race