summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Pitt <martin.pitt@ubuntu.com>2014-03-05 14:07:44 +0100
committerMartin Pitt <martin.pitt@ubuntu.com>2014-03-10 09:58:52 +0100
commitebf61ed8471a45cf8bce7231de00cb1bbc140708 (patch)
tree373a29cd87271ab62aec25148f2e2ba5bee29686
parent7dcaa0ca3bf48a618e1482700baf727bfd88365d (diff)
Fix buffer overflow in mount path parsing
In the mount monitor we parse mount points from /proc/self/mountinfo. Ensure that we don't overflow the buffers on platforms where mount paths could be longer than PATH_MAX (unknown if that can actually happen), as at least the mount paths for hotpluggable devices are somewhat user-controlled. Thanks to Florian Weimer for discovering this bug, and to David Zeuthen for his initial patch! CVE-2014-0004
-rw-r--r--src/mount-monitor.c21
1 files changed, 15 insertions, 6 deletions
diff --git a/src/mount-monitor.c b/src/mount-monitor.c
index d541deb..573a69c 100644
--- a/src/mount-monitor.c
+++ b/src/mount-monitor.c
@@ -39,6 +39,11 @@
#include "mount.h"
#include "private.h"
+/* build a %Ns format string macro with N == PATH_MAX */
+#define xstr(s) str(s)
+#define str(s) #s
+#define PATH_MAX_FMT "%" xstr(PATH_MAX) "s"
+
/*--------------------------------------------------------------------------------------------------------------*/
enum
@@ -320,8 +325,8 @@ mount_monitor_ensure (MountMonitor *monitor)
guint mount_id;
guint parent_id;
guint major, minor;
- gchar encoded_root[PATH_MAX];
- gchar encoded_mount_point[PATH_MAX];
+ gchar encoded_root[PATH_MAX + 1];
+ gchar encoded_mount_point[PATH_MAX + 1];
gchar *mount_point;
dev_t dev;
@@ -329,7 +334,7 @@ mount_monitor_ensure (MountMonitor *monitor)
continue;
if (sscanf (lines[n],
- "%d %d %d:%d %s %s",
+ "%d %d %d:%d " PATH_MAX_FMT " " PATH_MAX_FMT,
&mount_id,
&parent_id,
&major,
@@ -340,6 +345,8 @@ mount_monitor_ensure (MountMonitor *monitor)
g_warning ("Error parsing line '%s'", lines[n]);
continue;
}
+ encoded_root[sizeof encoded_root - 1] = '\0';
+ encoded_mount_point[sizeof encoded_mount_point - 1] = '\0';
/* ignore mounts where only a subtree of a filesystem is mounted */
if (g_strcmp0 (encoded_root, "/") != 0)
@@ -358,15 +365,17 @@ mount_monitor_ensure (MountMonitor *monitor)
sep = strstr (lines[n], " - ");
if (sep != NULL)
{
- gchar fstype[PATH_MAX];
- gchar mount_source[PATH_MAX];
+ gchar fstype[PATH_MAX + 1];
+ gchar mount_source[PATH_MAX + 1];
struct stat statbuf;
- if (sscanf (sep + 3, "%s %s", fstype, mount_source) != 2)
+ if (sscanf (sep + 3, PATH_MAX_FMT " " PATH_MAX_FMT, fstype, mount_source) != 2)
{
g_warning ("Error parsing things past - for '%s'", lines[n]);
continue;
}
+ fstype[sizeof fstype - 1] = '\0';
+ mount_source[sizeof mount_source - 1] = '\0';
if (g_strcmp0 (fstype, "btrfs") != 0)
continue;