Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 68807 Details for
Bug 98403
patch to util-linux that makes mount write to /etc/mtab symlinks, as long as they don't point to /proc
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
New version of the patch to apply against -r3
util-linux-2.12q-r3-symlinkmtab.patch (text/plain), 16.40 KB, created by
Patrick McLean
on 2005-09-19 07:20:38 UTC
(
hide
)
Description:
New version of the patch to apply against -r3
Filename:
MIME Type:
Creator:
Patrick McLean
Created:
2005-09-19 07:20:38 UTC
Size:
16.40 KB
patch
obsolete
>diff -ur util-linux-2.12q/mount/fstab.c util-linux-2.12q-new/mount/fstab.c >--- util-linux-2.12q/mount/fstab.c 2005-09-19 10:10:36.000000000 -0400 >+++ util-linux-2.12q-new/mount/fstab.c 2005-09-19 10:12:48.000000000 -0400 >@@ -1,7 +1,10 @@ >-/* 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL> >+/* >+ * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL> > * - added Native Language Support >- * Sun Mar 21 1999 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> >+ * 1999-03-21 Arnaldo Carvalho de Melo <acme@conectiva.com.br> > * - fixed strerr(errno) in gettext calls >+ * 2003-08-08 Thomas Hood <jdthood@yahoo.co.uk> with help from Patrick McLean >+ * - Write through a symlink at /etc/mtab if it doesn't point into /proc/ > */ > > #include <unistd.h> >@@ -11,67 +14,127 @@ > #include <sys/stat.h> > #include "mntent.h" > #include "fstab.h" >+#include "realpath.h" > #include "sundries.h" > #include "xmalloc.h" > #include "mount_blkid.h" > #include "paths.h" > #include "nls.h" > >-#define streq(s, t) (strcmp ((s), (t)) == 0) >- >-#define PROC_MOUNTS "/proc/mounts" >- >- > /* Information about mtab. ------------------------------------*/ >-static int have_mtab_info = 0; >-static int var_mtab_does_not_exist = 0; >-static int var_mtab_is_a_symlink = 0; >+/* A 64 bit number can be displayed in 20 decimal digits */ >+#define LEN_LARGEST_PID 20 >+#define MTAB_PATH_MAX (PATH_MAX - (sizeof(MTAB_LOCK_SUFFIX) - 1) - LEN_LARGEST_PID) >+static char mtab_path[MTAB_PATH_MAX]; >+static char mtab_lock_path[PATH_MAX]; >+static char mtab_lock_targ[PATH_MAX]; >+static char mtab_temp_path[PATH_MAX]; > >-static void >+/* >+ * Set mtab_path to the real path of the mtab file >+ * or to the null string if that path is inaccessible >+ * >+ * Run this early >+ */ >+void > get_mtab_info(void) { > struct stat mtab_stat; > >- if (!have_mtab_info) { >- if (lstat(MOUNTED, &mtab_stat)) >- var_mtab_does_not_exist = 1; >- else if (S_ISLNK(mtab_stat.st_mode)) >- var_mtab_is_a_symlink = 1; >- have_mtab_info = 1; >+ if (lstat(MOUNTED, &mtab_stat)) { >+ /* Assume that the lstat error means that the file does not exist */ >+ /* (Maybe we should check errno here) */ >+ strcpy(mtab_path, MOUNTED); >+ } else if (S_ISLNK(mtab_stat.st_mode)) { >+ /* Is a symlink */ >+ int len; >+ char *r = myrealpath(MOUNTED, mtab_path, MTAB_PATH_MAX); >+ mtab_path[MTAB_PATH_MAX - 1] = 0; /* Just to be sure */ >+ len = strlen(mtab_path); >+ if ( >+ r == NULL >+ || len == 0 >+ || len >= (MTAB_PATH_MAX - 1) >+ || streqn(mtab_path, PATH_PROC, sizeof(PATH_PROC) - 1) >+ ) { >+ /* Real path invalid or inaccessible */ >+ mtab_path[0] = '\0'; >+ return; >+ } >+ /* mtab_path now contains mtab's real path */ >+ } else { >+ /* Exists and is not a symlink */ >+ strcpy(mtab_path, MOUNTED); > } >+ >+ sprintf(mtab_lock_path, "%s%s", mtab_path, MTAB_LOCK_SUFFIX); >+ sprintf(mtab_lock_targ, "%s%s%d", mtab_path, MTAB_LOCK_SUFFIX, getpid()); >+ sprintf(mtab_temp_path, "%s%s", mtab_path, MTAB_TEMP_SUFFIX); >+ >+ return; > } > >-int >-mtab_does_not_exist(void) { >- get_mtab_info(); >- return var_mtab_does_not_exist; >+/* >+ * Tell whether or not the mtab real path is accessible >+ * >+ * get_mtab_info() must have been run >+ */ >+static int >+mtab_is_accessible(void) { >+ return (mtab_path[0] != '\0'); > } > >+/* >+ * Tell whether or not the mtab file currently exists >+ * >+ * Note that the answer here is independent of whether or >+ * not the file is writable, so if you are planning to create >+ * the mtab file then check mtab_is_writable() too. >+ * >+ * get_mtab_info() must have been run >+ */ > int >-mtab_is_a_symlink(void) { >- get_mtab_info(); >- return var_mtab_is_a_symlink; >+mtab_does_not_exist(void) { >+ struct stat mtab_stat; >+ >+ if (!mtab_is_accessible()) >+ return 1; >+ >+ if (lstat(mtab_path, &mtab_stat)) >+ return 1; >+ >+ return 0; > } > >+/* >+ * Tell whether or not mtab is writable (whether or not it currently exists) >+ * >+ * This depends on whether or not the real path is accessible and, >+ * if so, whether or not the file can be opened. This function >+ * has the side effect of creating the file if it is writable. >+ * >+ * get_mtab_info() must have been run >+ */ > int > mtab_is_writable() { >- static int ret = -1; >+ static int is_writable = -1; >+ int fd; >+ >+ if (is_writable != -1) >+ return is_writable; > >- /* Should we write to /etc/mtab upon an update? >- Probably not if it is a symlink to /proc/mounts, since that >- would create a file /proc/mounts in case the proc filesystem >- is not mounted. */ >- if (mtab_is_a_symlink()) >- return 0; >- >- if (ret == -1) { >- int fd = open(MOUNTED, O_RDWR | O_CREAT, 0644); >- if (fd >= 0) { >- close(fd); >- ret = 1; >- } else >- ret = 0; >+ if (!mtab_is_accessible()) { >+ is_writable = 0; >+ return is_writable; > } >- return ret; >+ >+ fd = open(mtab_path, O_RDWR | O_CREAT, 0644); >+ if (fd >= 0) { >+ close(fd); >+ is_writable = 1; >+ } else { >+ is_writable = 0; >+ } >+ return is_writable; > } > > /* Contents of mtab and fstab ---------------------------------*/ >@@ -154,21 +217,21 @@ > got_mtab = 1; > mc->nxt = mc->prev = NULL; > >- fnam = MOUNTED; >+ fnam = mtab_path; > mfp = my_setmntent (fnam, "r"); > if (mfp == NULL || mfp->mntent_fp == NULL) { > int errsv = errno; >- fnam = PROC_MOUNTS; >+ fnam = PATH_PROC_MOUNTS; > mfp = my_setmntent (fnam, "r"); > if (mfp == NULL || mfp->mntent_fp == NULL) { > error(_("warning: can't open %s: %s"), >- MOUNTED, strerror (errsv)); >+ mtab_path, strerror (errsv)); > return; > } > if (verbose) > printf (_("mount: could not open %s - " > "using %s instead\n"), >- MOUNTED, PROC_MOUNTS); >+ mtab_path, PATH_PROC_MOUNTS); > } > read_mntentchn(mfp, fnam, mc); > } >@@ -396,9 +459,6 @@ > /* Flag for already existing lock file. */ > static int we_created_lockfile = 0; > >-/* Flag to indicate that signals have been set up. */ >-static int signals_have_been_setup = 0; >- > /* Ensure that the lock is released if we are interrupted. */ > extern char *strsignal(int sig); /* not always in <string.h> */ > >@@ -416,35 +476,33 @@ > void > unlock_mtab (void) { > if (we_created_lockfile) { >- unlink (MOUNTED_LOCK); >+ unlink (mtab_lock_path); > we_created_lockfile = 0; > } > } > >-/* Create the lock file. >- The lock file will be removed if we catch a signal or when we exit. */ >+/* >+ * Create the lock file >+ * >+ * The lock file will be removed if we catch a signal or when we exit >+ */ > /* The old code here used flock on a lock file /etc/mtab~ and deleted >- this lock file afterwards. However, as rgooch remarks, that has a >- race: a second mount may be waiting on the lock and proceed as >- soon as the lock file is deleted by the first mount, and immediately >- afterwards a third mount comes, creates a new /etc/mtab~, applies >- flock to that, and also proceeds, so that the second and third mount >- now both are scribbling in /etc/mtab. >+ this lock file afterwards. However, as rgooch remarks, that races: >+ a second mount may be waiting on the lock which will proceed as >+ soon as the lock file is deleted by the first mount; immediately >+ afterwards a third mount can come, create a new /etc/mtab~, apply >+ flock to that, and also proceed, so that the second and third mount >+ now both scribble in /etc/mtab. > The new code uses a link() instead of a creat(), where we proceed >- only if it was us that created the lock, and hence we always have >+ only if it was we that created the lock, and hence we always have > to delete the lock afterwards. Now the use of flock() is in principle >- superfluous, but avoids an arbitrary sleep(). */ >- >-/* Where does the link point to? Obvious choices are mtab and mtab~~. >- HJLu points out that the latter leads to races. Right now we use >- mtab~.<pid> instead. Use 20 as upper bound for the length of %d. */ >-#define MOUNTLOCK_LINKTARGET MOUNTED_LOCK "%d" >-#define MOUNTLOCK_LINKTARGET_LTH (sizeof(MOUNTED_LOCK)+20) >+ superfluous, but using it allows us to avoid an arbitrary sleep(). */ > > void > lock_mtab (void) { > int tries = 3; >- char linktargetfile[MOUNTLOCK_LINKTARGET_LTH]; >+ /* Flag to indicate that signals have been set up. */ >+ static int signals_have_been_setup = 0; > > at_die = unlock_mtab; > >@@ -467,30 +525,28 @@ > signals_have_been_setup = 1; > } > >- sprintf(linktargetfile, MOUNTLOCK_LINKTARGET, getpid ()); >- > /* Repeat until it was us who made the link */ > while (!we_created_lockfile) { > struct flock flock; > int errsv, fd, i, j; > >- i = open (linktargetfile, O_WRONLY|O_CREAT, 0); >+ i = open (mtab_lock_targ, O_WRONLY|O_CREAT, 0); > if (i < 0) { > int errsv = errno; >- /* linktargetfile does not exist (as a file) >+ /* mtab_lock_targ does not exist (as a file) > and we cannot create it. Read-only filesystem? > Too many files open in the system? > Filesystem full? */ > die (EX_FILEIO, _("can't create lock file %s: %s " > "(use -n flag to override)"), >- linktargetfile, strerror (errsv)); >+ mtab_lock_targ, strerror (errsv)); > } > close(i); > >- j = link(linktargetfile, MOUNTED_LOCK); >+ j = link(mtab_lock_targ, mtab_lock_path); > errsv = errno; > >- (void) unlink(linktargetfile); >+ (void) unlink(mtab_lock_targ); > > if (j == 0) > we_created_lockfile = 1; >@@ -498,10 +554,10 @@ > if (j < 0 && errsv != EEXIST) { > die (EX_FILEIO, _("can't link lock file %s: %s " > "(use -n flag to override)"), >- MOUNTED_LOCK, strerror (errsv)); >+ mtab_lock_path, strerror (errsv)); > } > >- fd = open (MOUNTED_LOCK, O_WRONLY); >+ fd = open (mtab_lock_path, O_WRONLY); > > if (fd < 0) { > int errsv = errno; >@@ -510,7 +566,7 @@ > continue; > die (EX_FILEIO, _("can't open lock file %s: %s " > "(use -n flag to override)"), >- MOUNTED_LOCK, strerror (errsv)); >+ mtab_lock_path, strerror (errsv)); > } > > flock.l_type = F_WRLCK; >@@ -524,7 +580,7 @@ > if (verbose) { > int errsv = errno; > printf(_("Can't lock lock file %s: %s\n"), >- MOUNTED_LOCK, strerror (errsv)); >+ mtab_lock_path, strerror (errsv)); > } > /* proceed anyway */ > } >@@ -536,17 +592,17 @@ > if (fcntl (fd, F_SETLKW, &flock) == -1) { > int errsv = errno; > die (EX_FILEIO, _("can't lock lock file %s: %s"), >- MOUNTED_LOCK, (errno == EINTR) ? >+ mtab_lock_path, (errno == EINTR) ? > _("timed out") : strerror (errsv)); > } > alarm(0); > /* Limit the number of iterations - maybe there >- still is some old /etc/mtab~ */ >+ still is some old lock */ > if (tries++ > 3) { > if (tries > 5) > die (EX_FILEIO, _("Cannot create link %s\n" > "Perhaps there is a stale lock file?\n"), >- MOUNTED_LOCK); >+ mtab_lock_path); > sleep(1); > } > } >@@ -568,16 +624,16 @@ > void > update_mtab (const char *dir, struct my_mntent *instead) { > mntFILE *mfp, *mftmp; >- const char *fnam = MOUNTED; >+ const char *fnam = mtab_path; > struct mntentchn mtabhead; /* dummy */ > struct mntentchn *mc, *mc0, *absent = NULL; > >- if (mtab_does_not_exist() || mtab_is_a_symlink()) >+ if (mtab_does_not_exist()) > return; > > lock_mtab(); > >- /* having locked mtab, read it again */ >+ /* Having got the lock, we read mtab again */ > mc0 = mc = &mtabhead; > mc->nxt = mc->prev = NULL; > >@@ -636,11 +692,11 @@ > } > > /* write chain to mtemp */ >- mftmp = my_setmntent (MOUNTED_TEMP, "w"); >+ mftmp = my_setmntent (mtab_temp_path, "w"); > if (mftmp == NULL || mftmp->mntent_fp == NULL) { > int errsv = errno; > error (_("cannot open %s (%s) - mtab not updated"), >- MOUNTED_TEMP, strerror (errsv)); >+ mtab_temp_path, strerror (errsv)); > /* Do not leak memory */ > discard_mntentchn(mc0); > goto leave; >@@ -650,7 +706,7 @@ > if (my_addmntent(mftmp, &(mc->m)) == 1) { > int errsv = errno; > die (EX_FILEIO, _("error writing %s: %s"), >- MOUNTED_TEMP, strerror (errsv)); >+ mtab_temp_path, strerror (errsv)); > } > } > >@@ -660,25 +716,25 @@ > S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) { > int errsv = errno; > fprintf(stderr, _("error changing mode of %s: %s\n"), >- MOUNTED_TEMP, strerror (errsv)); >+ mtab_temp_path, strerror (errsv)); > } > my_endmntent (mftmp); > > { /* > * If mount is setuid and some non-root user mounts sth, >- * then mtab.tmp might get the group of this user. Copy uid/gid >- * from the present mtab before renaming. >+ * then the temp file might get the group of this user. >+ * Copy uid/gid from the present mtab before renaming. > */ > struct stat sbuf; >- if (stat (MOUNTED, &sbuf) == 0) >- chown (MOUNTED_TEMP, sbuf.st_uid, sbuf.st_gid); >+ if (stat (mtab_path, &sbuf) == 0) >+ chown (mtab_temp_path, sbuf.st_uid, sbuf.st_gid); > } > > /* rename mtemp to mtab */ >- if (rename (MOUNTED_TEMP, MOUNTED) < 0) { >+ if (rename (mtab_temp_path, mtab_path) < 0) { > int errsv = errno; > fprintf(stderr, _("can't rename %s to %s: %s\n"), >- MOUNTED_TEMP, MOUNTED, strerror(errsv)); >+ mtab_temp_path, mtab_path, strerror(errsv)); > } > > leave: >diff -ur util-linux-2.12q/mount/fstab.h util-linux-2.12q-new/mount/fstab.h >--- util-linux-2.12q/mount/fstab.h 2004-09-19 14:45:53.000000000 -0400 >+++ util-linux-2.12q-new/mount/fstab.h 2005-09-19 10:10:47.000000000 -0400 >@@ -22,6 +22,10 @@ > struct mntentchn *getfsuuidspec (const char *uuid); > struct mntentchn *getfsvolspec (const char *label); > >+void get_mtab_info (void); >+int mtab_is_writable(void); >+int mtab_does_not_exist(void); >+int is_mounted_once(const char *name); > void lock_mtab (void); > void unlock_mtab (void); >-void update_mtab (const char *special, struct my_mntent *with); >+void update_mtab (const char *dir, struct my_mntent *instead); >diff -ur util-linux-2.12q/mount/mount.c util-linux-2.12q-new/mount/mount.c >--- util-linux-2.12q/mount/mount.c 2005-09-19 10:10:38.000000000 -0400 >+++ util-linux-2.12q-new/mount/mount.c 2005-09-19 10:10:47.000000000 -0400 >@@ -398,7 +398,11 @@ > return ret; > } > >-/* Create mtab with a root entry. */ >+/* >+ * Create mtab with a root entry. >+ * >+ * Caller should check that mtab is writable first >+ */ > static void > create_mtab (void) { > struct mntentchn *fstab; >@@ -1529,6 +1533,9 @@ > initproctitle(argc, argv); > #endif > >+ get_mtab_info(); >+ /* Keep in mind that /etc/mtab may be a symlink */ >+ > while ((c = getopt_long (argc, argv, "afFhilL:no:O:p:rsU:vVwt:", > longopts, NULL)) != -1) { > switch (c) { >@@ -1653,7 +1660,7 @@ > die (EX_USAGE, _("mount: only root can do that")); > } > >- if (!nomtab && mtab_does_not_exist()) { >+ if (!nomtab && mtab_does_not_exist() && mtab_is_writable()) { > if (verbose > 1) > printf(_("mount: no %s found - creating it..\n"), > MOUNTED); >diff -ur util-linux-2.12q/mount/paths.h util-linux-2.12q-new/mount/paths.h >--- util-linux-2.12q/mount/paths.h 2004-09-19 14:45:38.000000000 -0400 >+++ util-linux-2.12q-new/mount/paths.h 2005-09-19 10:10:47.000000000 -0400 >@@ -1,10 +1,14 @@ > #include <mntent.h> >-#define _PATH_FSTAB "/etc/fstab" >+#define _PATH_FSTAB "/etc/fstab" >+#define PATH_PROC "/proc/" >+#define PATH_PROC_MOUNTS PATH_PROC "mounts" >+#define MTAB_LOCK_SUFFIX "~" >+#define MTAB_TEMP_SUFFIX ".tmp" > #ifdef _PATH_MOUNTED >-#define MOUNTED_LOCK _PATH_MOUNTED "~" >-#define MOUNTED_TEMP _PATH_MOUNTED ".tmp" >+#define MOUNTED_LOCK _PATH_MOUNTED "~" >+#define MOUNTED_TEMP _PATH_MOUNTED ".tmp" > #else >-#define MOUNTED_LOCK "/etc/mtab~" >-#define MOUNTED_TEMP "/etc/mtab.tmp" >+#define MOUNTED_LOCK "/etc/mtab~" >+#define MOUNTED_TEMP "/etc/mtab.tmp" > #endif >-#define LOCK_TIMEOUT 10 >+#define LOCK_TIMEOUT 10 >diff -ur util-linux-2.12q/mount/sundries.h util-linux-2.12q-new/mount/sundries.h >--- util-linux-2.12q/mount/sundries.h 2005-09-19 10:10:37.000000000 -0400 >+++ util-linux-2.12q-new/mount/sundries.h 2005-09-19 10:10:47.000000000 -0400 >@@ -17,7 +17,8 @@ > extern int verbose; > extern int sloppy; > >-#define streq(s, t) (strcmp ((s), (t)) == 0) >+#define streq(s, t) (strcmp ((s), (t)) == 0) >+#define streqn(s, t, n) (strncmp((s), (t), (n)) == 0) > > /* Functions in sundries.c that are used in mount.c and umount.c */ > void block_signals (int how); >diff -ur util-linux-2.12q/mount/umount.c util-linux-2.12q-new/mount/umount.c >--- util-linux-2.12q/mount/umount.c 2005-09-19 10:10:35.000000000 -0400 >+++ util-linux-2.12q-new/mount/umount.c 2005-09-19 10:10:47.000000000 -0400 >@@ -264,8 +264,11 @@ > } > } > >-/* Umount a single device. Return a status code, so don't exit >- on a non-fatal error. We lock/unlock around each umount. */ >+/* >+ * Umount a single device >+ * >+ * Returns a status code; doesn't exit on a non-fatal error >+ */ > static int > umount_one (const char *spec, const char *node, const char *type, > const char *opts, struct mntentchn *mc) { >@@ -666,6 +669,8 @@ > > umask(022); > >+ get_mtab_info(); >+ > while ((c = getopt_long (argc, argv, "adfhlnrit:O:vV", > longopts, NULL)) != -1) > switch (c) {
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 98403
:
62963
|
62964
|
63637
|
63980
| 68807 |
162291