Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Evergreen:11.4
ecryptfs-utils.import4986
CVE-2011-1831,1832,1834.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File CVE-2011-1831,1832,1834.patch of Package ecryptfs-utils.import4986
Description: fix privilege escalation via mountpoint race conditions Author: Dan Rosenberg Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/ecryptfs-utils/+bug/732628 Index: ecryptfs-utils-83/src/utils/mount.ecryptfs_private.c =================================================================== --- ecryptfs-utils-83.orig/src/utils/mount.ecryptfs_private.c +++ ecryptfs-utils-83/src/utils/mount.ecryptfs_private.c @@ -152,6 +152,47 @@ char *fetch_sig(char *pw_dir, int entry) return sig; } +int check_ownership_mnt(int uid, char **mnt) { +/* Check ownership of mount point, chdir into it, and + * canonicalize the path for use in mtab updating. + * Return 0 if everything is in order, 1 on error. + */ + struct stat s; + char *cwd; + + /* From here on, we'll refer to "." as our mountpoint, to avoid + * races. + */ + if (chdir(*mnt) != 0) { + fputs("Cannot chdir into mountpoint.\n", stderr); + return 1; + } + if (stat(".", &s) != 0) { + fputs("Cannot examine mountpoint.\n", stderr); + return 1; + } + if (!S_ISDIR(s.st_mode)) { + fputs("Mountpoint is not a directory.\n", stderr); + return 1; + } + if (s.st_uid != uid) { + fputs("You do not own that mountpoint.\n", stderr); + return 1; + } + + /* Canonicalize our pathname based on the current directory to + * avoid races. + */ + cwd = getcwd(NULL, 0); + if (!cwd) { + fputs("Failed to get current directory\n", stderr); + return 1; + } + *mnt = cwd; + return 0; +} + + int check_ownerships(int uid, char *path) { /* Check ownership of device and mount point. * Return 0 if everything is in order, 1 on error. @@ -177,31 +218,77 @@ int update_mtab(char *dev, char *mnt, ch /* Update /etc/mtab with new mount entry. * Return 0 on success, 1 on failure. */ - FILE *fh; - struct mntent m; - fh = setmntent("/etc/mtab", "a"); - if (fh == NULL) { + int fd; + FILE *old_mtab, *new_mtab; + struct mntent *old_ent, new_ent; + + /* Make an attempt to play nice with other mount helpers + * by creating an /etc/mtab~ lock file. Of course this + * only works if those other helpers actually check for + * this. + */ + fd = open("/etc/mtab~", O_RDONLY | O_CREAT | O_EXCL, 0644); + if (fd < 0) { + perror("open"); + return 1; + } + close(fd); + + old_mtab = setmntent("/etc/mtab", "r"); + if (old_mtab == NULL) { perror("setmntent"); - /* Unmount if mtab cannot be updated */ - umount(mnt); return 1; } - m.mnt_fsname = dev; - m.mnt_dir = mnt; - m.mnt_type = FSTYPE; - m.mnt_opts = opt; - m.mnt_freq = 0; - m.mnt_passno = 0; - flockfile(fh); - if (addmntent(fh, &m) != 0) { + + new_mtab = setmntent("/etc/mtab.tmp", "w"); + if (new_mtab == NULL) { + perror("setmntent"); + goto fail_early; + } + + while (old_ent = getmntent(old_mtab)) { + if (addmntent(new_mtab, old_ent) != 0) { + perror("addmntent"); + goto fail; + } + } + endmntent(old_mtab); + + new_ent.mnt_fsname = dev; + new_ent.mnt_dir = mnt; + new_ent.mnt_type = FSTYPE; + new_ent.mnt_opts = opt; + new_ent.mnt_freq = 0; + new_ent.mnt_passno = 0; + + if (addmntent(new_mtab, &new_ent) != 0) { perror("addmntent"); - endmntent(fh); - /* Unmount if mtab cannot be updated */ - umount(mnt); - return 1; + goto fail; + } + + if (fchmod(fileno(new_mtab), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) { + perror("fchmod"); + goto fail; + } + endmntent(new_mtab); + + if (rename("/etc/mtab.tmp", "/etc/mtab") < 0) { + perror("rename"); + goto fail_late; } - endmntent(fh); + + unlink("/etc/mtab~"); + return 0; + +fail: + endmntent(new_mtab); +fail_late: + unlink("/etc/mtab.tmp"); +fail_early: + endmntent(old_mtab); + unlink("/etc/mtab~"); + return 1; } FILE *lock_counter(char *u, int uid) { @@ -431,8 +518,9 @@ int main(int argc, char *argv[]) { } } - /* Check ownership of mnt */ - if (check_ownerships(uid, mnt) != 0) { + /* Check ownership of the mountpoint. From here on, dest refers + * to a canonicalized path, and the mountpoint is the cwd. */ + if (check_ownership_mnt(uid, &mnt) != 0) { goto fail; } @@ -462,7 +550,7 @@ int main(int argc, char *argv[]) { */ setreuid(-1, 0); /* Perform mount */ - if (mount(dev, mnt, FSTYPE, 0, opt) == 0) { + if (mount(dev, ".", FSTYPE, 0, opt) == 0) { if (update_mtab(dev, mnt, opt) != 0) { goto fail; } @@ -492,7 +580,7 @@ int main(int argc, char *argv[]) { * Do not use the umount.ecryptfs helper (-i). */ setresuid(0,0,0); - execl("/bin/umount", "umount", "-i", "-l", mnt, NULL); + execl("/bin/umount", "umount", "-i", "-l", ".", NULL); perror("execl unmount failed"); goto fail; }
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor