diff -Naurp samba-3.5.10/client/mount.cifs.c samba-3.5.10.oden/client/mount.cifs.c --- samba-3.5.10/client/mount.cifs.c 2011-07-24 20:04:44.000000000 +0000 +++ samba-3.5.10.oden/client/mount.cifs.c 2011-10-11 07:31:50.000000000 +0000 @@ -41,6 +41,7 @@ #include <limits.h> #include <fstab.h> #include "mount.h" +#include <signal.h> #define MOUNT_CIFS_VERSION_MAJOR "1" #define MOUNT_CIFS_VERSION_MINOR "14" @@ -338,9 +339,9 @@ static void mount_cifs_usage(FILE *strea } /* caller frees username if necessary */ -static char * getusername(void) { +static char * getusername(uid_t uid) { char *username = NULL; - struct passwd *password = getpwuid(getuid()); + struct passwd *password = getpwuid(uid); if (password) { username = password->pw_name; @@ -1243,6 +1244,7 @@ int main(int argc, char ** argv) char * resolved_path = NULL; char * temp; char * dev_name; + char * mount_user = NULL; int rc = 0; int rsize = 0; int wsize = 0; @@ -1251,6 +1253,7 @@ int main(int argc, char ** argv) int gid = 0; int optlen = 0; int orgoptlen = 0; + int fd, tmprc; size_t options_size = 0; size_t current_len; int retry = 0; /* set when we have to retry mount with uppercase */ @@ -1259,7 +1262,9 @@ int main(int argc, char ** argv) struct mntent mountent; struct sockaddr_in *addr4; struct sockaddr_in6 *addr6; + struct stat statbuf; FILE * pmntfile; + sigset_t mask, oldmask; if (check_setuid()) return EX_USAGE; @@ -1539,7 +1544,7 @@ int main(int argc, char ** argv) if (getenv("USER")) user_name = strdup(getenv("USER")); if (user_name == NULL) - user_name = getusername(); + user_name = getusername(getuid()); got_user = 1; } @@ -1712,6 +1717,38 @@ mount_retry: if (nomtab) goto mount_exit; + + uid = getuid(); + if (uid != 0) + mount_user = getusername(uid); + + /* + * Set the real uid to the effective uid. This prevents unprivileged + * users from sending signals to this process, though ^c on controlling + * terminal should still work. + */ + rc = setreuid(geteuid(), -1); + if (rc != 0) { + fprintf(stderr, "Unable to set real uid to effective uid: %s\n", + strerror(errno)); + rc = EX_FILEIO; + goto mount_exit; + } + + rc = sigfillset(&mask); + if (rc) { + fprintf(stderr, "Unable to set filled signal mask\n"); + rc = EX_FILEIO; + goto mount_exit; + } + + rc = sigprocmask(SIG_SETMASK, &mask, &oldmask); + if (rc) { + fprintf(stderr, "Unable to make process ignore signals\n"); + rc = EX_FILEIO; + goto mount_exit; + } + atexit(unlock_mtab); rc = lock_mtab(); if (rc) { @@ -1725,12 +1762,27 @@ mount_retry: rc = EX_FILEIO; goto mount_exit; } + fd = fileno(pmntfile); + if (fd < 0) { + fprintf(stderr, "mntent does not appear to be valid\n"); + unlock_mtab(); + rc = EX_FILEIO; + goto mount_exit; + } + rc = fstat(fd, &statbuf); + if (rc != 0) { + fprintf(stderr, "unable to fstat open mtab\n"); + endmntent(pmntfile); + unlock_mtab(); + rc = EX_FILEIO; + goto mount_exit; + } + mountent.mnt_fsname = dev_name; mountent.mnt_dir = mountpoint; mountent.mnt_type = CONST_DISCARD(char *,"cifs"); mountent.mnt_opts = (char *)malloc(220); if(mountent.mnt_opts) { - char * mount_user = getusername(); memset(mountent.mnt_opts,0,200); if(flags & MS_RDONLY) strlcat(mountent.mnt_opts,"ro",220); @@ -1757,12 +1809,21 @@ mount_retry: } mountent.mnt_freq = 0; mountent.mnt_passno = 0; - rc = addmntent(pmntfile,&mountent); - endmntent(pmntfile); + rc = addmntent(pmntfile, &mountent); + if (rc) { + fprintf(stderr, "unable to add mount entry to mtab\n"); + ftruncate(fd, statbuf.st_size); + } + tmprc = my_endmntent(pmntfile, statbuf.st_size); + if (tmprc) { + fprintf(stderr, "error %d detected on close of mtab\n", tmprc); + rc = EX_FILEIO; + } unlock_mtab(); SAFE_FREE(mountent.mnt_opts); if (rc) rc = EX_FILEIO; + sigprocmask(SIG_SETMASK, &oldmask, NULL); mount_exit: if(mountpassword) { int len = strlen(mountpassword); diff -Naurp samba-3.5.10/client/mount.h samba-3.5.10.oden/client/mount.h --- samba-3.5.10/client/mount.h 2011-07-24 20:04:44.000000000 +0000 +++ samba-3.5.10.oden/client/mount.h 2011-10-11 07:31:50.000000000 +0000 @@ -34,5 +34,6 @@ extern int lock_mtab(void); extern void unlock_mtab(void); +extern int my_endmntent(FILE *stream, off_t size); #endif /* ! _MOUNT_H_ */ diff -Naurp samba-3.5.10/client/mtab.c samba-3.5.10.oden/client/mtab.c --- samba-3.5.10/client/mtab.c 2011-07-24 20:04:44.000000000 +0000 +++ samba-3.5.10.oden/client/mtab.c 2011-10-11 07:31:50.000000000 +0000 @@ -218,3 +218,30 @@ lock_mtab (void) { return 0; } +/* + * Call fflush and fsync on the mtab, and then endmntent. If either fflush + * or fsync fails, then truncate the file back to "size". endmntent is called + * unconditionally, and the errno (if any) from fflush and fsync are returned. + */ +int +my_endmntent(FILE *stream, off_t size) +{ + int rc, fd; + + fd = fileno(stream); + if (fd < 0) + return -EBADF; + + rc = fflush(stream); + if (!rc) + rc = fsync(fd); + + /* truncate file back to "size" -- best effort here */ + if (rc) { + rc = errno; + ftruncate(fd, size); + } + + endmntent(stream); + return rc; +}