summaryrefslogtreecommitdiffstats
path: root/sys-apps/util-linux/files/util-linux-2.12q-update_mtab-fixes.patch
blob: 7e1c9db6bf86509072f8cf40b3116415e5ba783f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
This fixes a few issues with update_mtab():
- If it is a remount, and only mnt_opts needs updating, mc->m.mnt_opts is set
  to point to instead->mnt_opts, rather than allocating a new string, which
  would cause a double free if the caller actually freed the passed mnt_opts,
  as we free mc->m.mnt_opts before returning to the caller.
- Mostly the same issue as above.  If mtab does not contain the new entry, then
  absent->m is set to point to instead, which would have cause a double free
  if absent was inserted properly into the linked list, since we free all
  elements of absent before returning to the caller.
- If mtab does not contain the new entry, then only mc0->prev is updated to
  point to absent, but not the old mc0->prev's nxt pointer.  Because we then
  use the nxt pointers to write the new mtab, absent is not added to the new
  mtab.
- If mtab is empty, absent->prev should be set to mc0, and not mc0->prev, as
  it will be NULL.
- Memory leak if we have to abort before mc0 and co are freed.

Patch by Martin Schlemmer <azarah@gentoo.org>


--- util-linux-2.12q/mount/fstab.c	2005-09-14 15:30:10.000000000 +0200
+++ util-linux-2.12q.az/mount/fstab.c	2005-09-14 15:31:48.000000000 +0200
@@ -604,15 +604,32 @@ update_mtab (const char *dir, struct my_
 				free(mc);
 			}
 		} else {
-			/* A remount */
-			mc->m.mnt_opts = instead->mnt_opts;
+			/* A remount. */
+			my_free(mc->m.mnt_opts);
+			/* Need to alloc memory, else we might
+			 * run into issues if both we and the caller frees
+			 * mnt_opts ... */
+			mc->m.mnt_opts = xstrdup(instead->mnt_opts);
 		}
 	} else if (instead) {
 		/* not found, add a new entry */
 		absent = xmalloc(sizeof(*absent));
-		absent->m = *instead;
+		/* Cannot just set absent->m to instead, as we free absent
+		 * below, and the caller might free instead */
+		absent->m.mnt_fsname = xstrdup(instead->mnt_fsname);
+		absent->m.mnt_dir = xstrdup(instead->mnt_dir);
+		absent->m.mnt_type = xstrdup(instead->mnt_type);
+		absent->m.mnt_opts = xstrdup(instead->mnt_opts);
+		absent->m.mnt_freq = instead->mnt_freq;
+		absent->m.mnt_passno = instead->mnt_passno;
+
 		absent->nxt = mc0;
-		absent->prev = mc0->prev;
+		if (mc0->prev != NULL) {
+			absent->prev = mc0->prev;
+			mc0->prev->nxt = absent;
+		} else {
+			absent->prev = mc0;
+		}
 		mc0->prev = absent;
 		if (mc0->nxt == NULL)
 			mc0->nxt = absent;
@@ -624,6 +641,8 @@ update_mtab (const char *dir, struct my_
 		int errsv = errno;
 		error (_("cannot open %s (%s) - mtab not updated"),
 		       MOUNTED_TEMP, strerror (errsv));
+		/* Do not leak memory */
+		discard_mntentchn(mc0);
 		goto leave;
 	}