From 24496747b648d1a7bd0d6da1ef3759f035ba1cd6 Mon Sep 17 00:00:00 2001 From: Martin Pitt Date: Wed, 5 Mar 2014 13:47:15 +0100 Subject: Fix buffer overflow in mount path parsing In the mount monitor we parse mount points from /proc/self/mountinfo and /proc/swaps. 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 --- src/udisksmountmonitor.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/udisksmountmonitor.c b/src/udisksmountmonitor.c index 8af1028..e7097fa 100644 --- a/src/udisksmountmonitor.c +++ b/src/udisksmountmonitor.c @@ -38,6 +38,11 @@ #include "udisksmount.h" #include "udisksprivate.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" + /** * SECTION:udisksmountmonitor * @title: UDisksMountMonitor @@ -416,8 +421,8 @@ udisks_mount_monitor_get_mountinfo (UDisksMountMonitor *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; @@ -425,7 +430,7 @@ udisks_mount_monitor_get_mountinfo (UDisksMountMonitor *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, @@ -436,6 +441,8 @@ udisks_mount_monitor_get_mountinfo (UDisksMountMonitor *monitor, udisks_warning ("Error parsing line '%s'", lines[n]); continue; } + encoded_root[sizeof encoded_root - 1] = '\0'; + encoded_mount_point[sizeof encoded_mount_point - 1] = '\0'; /* Temporary work-around for btrfs, see * @@ -450,15 +457,17 @@ udisks_mount_monitor_get_mountinfo (UDisksMountMonitor *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) { udisks_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; @@ -546,7 +555,7 @@ udisks_mount_monitor_get_swaps (UDisksMountMonitor *monitor, lines = g_strsplit (contents, "\n", 0); for (n = 0; lines[n] != NULL; n++) { - gchar filename[PATH_MAX]; + gchar filename[PATH_MAX + 1]; struct stat statbuf; dev_t dev; @@ -557,11 +566,12 @@ udisks_mount_monitor_get_swaps (UDisksMountMonitor *monitor, if (strlen (lines[n]) == 0) continue; - if (sscanf (lines[n], "%s", filename) != 1) + if (sscanf (lines[n], PATH_MAX_FMT, filename) != 1) { udisks_warning ("Error parsing line '%s'", lines[n]); continue; } + filename[sizeof filename - 1] = '\0'; if (stat (filename, &statbuf) != 0) { -- cgit v1.2.3