Blame SOURCES/0020-Fix-162-sadc-crashes-on-a-mtab-file-with-really-long.patch

9a8d55
From 01efeb144322c61e53cc4e21783ce0a69ec28922 Mon Sep 17 00:00:00 2001
9a8d55
From: Sebastien GODARD <sysstat@users.noreply.github.com>
9a8d55
Date: Sat, 26 Aug 2017 14:42:28 +0200
9a8d55
Subject: [PATCH] Fix #162: sadc crashes on a mtab file with really long lines
9a8d55
9a8d55
A segmentation fault may happen with "sadc -S DISK..." or
9a8d55
"sadc -S XDISK..." when lines longer than 512 bytes are read from
9a8d55
/etc/mtab.
9a8d55
9a8d55
Such lines are possible for instance when overlay2 filesystem
9a8d55
with docker is used. In such a case a single mtab entry can look
9a8d55
like this (note that new line characters were added for readability,
9a8d55
the original entry contained only one '\n' at the end):
9a8d55
9a8d55
overlay /var/lib/docker/overlay2/f23d2377a67b9ab1b49555ecd09b2ccdc03
9a8d55
7e0ee5d9e54f87e59f07f4398e71f/merged overlay rw,relatime,lowerdir=/v
9a8d55
ar/lib/docker/overlay2/l/L6VKIYXWBQSJ5R7V35SS43R6Y6:/var/lib/docker/
9a8d55
overlay2/l/UCCHKGXUJPWCMLHR36IZJNNIQP:/var/lib/docker/overlay2/l/RKV
9a8d55
YEXD2FH65FTMK76RDWPLESX:/var/lib/docker/overlay2/l/DX4JZRKTFP2GOO4V6
9a8d55
OWQ6CPJFY:/var/lib/docker/overlay2/l/6CYNWDKADUPPDZJ5IHOH2R7Y5S:/var
9a8d55
/lib/docker/overlay2/l/JTPINUZIATXADL6XWFHG2OYGSF:/var/lib/docker/ov
9a8d55
erlay2/l/OTSTIV5TTRHF4IUD7BODQ2FUON:/var/lib/docker/overlay2/l/QFNH3
9a8d55
EFS5EZGRTC4DPHU3PJ4TU:/var/lib/docker/overlay2/l/ZOOUKT2E5U4CSLP57Z7
9a8d55
MXYX5CD:/var/lib/docker/overlay2/l/3LUU6IDR2HWPTVBARC5K6XSMRC:/var/l
9a8d55
ib/docker/overlay2/l/XOHYBP4RWXQKQZ43I7JKG24KE4:/var/lib/docker/over
9a8d55
lay2/l/MN5M5B7AY5LPXQQC6V2MBJWWBF:/var/lib/docker/overlay2/l/3DRMKQ3
9a8d55
4AIZD2AROU3TVK3OCUT:/var/lib/docker/overlay2/l/73ZXDHBV6C53Q3SPXA57E
9a8d55
OLGHU:/var/lib/docker/overlay2/l/C2IZBQ55EUTGEAAORSLE73ZPNM:/var/lib
9a8d55
/docker/overlay2/l/ITHARNV7RPWN5S3BCZ2QDMZIMJ:/var/lib/docker/overla
9a8d55
y2/l/TQKUV4LEG4AFUUCMFHHRLDBHAH:/var/lib/docker/overlay2/l/N75JZWPPD
9a8d55
EKJ4DTN4GMEGTDIZL:/var/lib/docker/overlay2/l/QGUUYAETPMK643DG3AKWJAI
9a8d55
IZA,upperdir=/var/lib/docker/overlay2/f23d2377a67b9ab1b49555ecd09b2c
9a8d55
cdc037e0ee5d9e54f87e59f07f4398e71f/diff,workdir=/var/lib/docker/over
9a8d55
lay2/f23d2377a67b9ab1b49555ecd09b2ccdc037e0ee5d9e54f87e59f07f4398e71
9a8d55
f/work 0 0
9a8d55
9a8d55
The crash occurs in the get_filesystem_nr() and read_filesystem()
9a8d55
functions which call strchr(line, ' ') but fail to check if the result
9a8d55
is not NULL.
9a8d55
9a8d55
This patch adds this check, and when a single mtab entry requires more
9a8d55
that one call to fgets() (i.e. the entry is longer than 512 bytes), it
9a8d55
ignores outcome of the second and following calls.
9a8d55
9a8d55
Bugs-Debian: https://bugs.debian.org/872926
9a8d55
Signed-off-by: Robert Luberda <robert@debian.org>
9a8d55
Signed-off-by: Sebastien GODARD <sysstat@users.noreply.github.com>
9a8d55
(cherry picked from commit d40c8ecc530303d7e802617f21a9ac85dbcd68bd)
9a8d55
---
9a8d55
 rd_stats.c | 41 ++++++++++++++++++++++++++++++++++++-----
9a8d55
 1 file changed, 36 insertions(+), 5 deletions(-)
9a8d55
9a8d55
diff --git a/rd_stats.c b/rd_stats.c
9a8d55
index 01276b6..c054b58 100644
9a8d55
--- a/rd_stats.c
9a8d55
+++ b/rd_stats.c
9a8d55
@@ -1916,15 +1916,30 @@ void read_filesystem(struct stats_filesystem *st_filesystem, int nbr)
9a8d55
 {
9a8d55
 	FILE *fp;
9a8d55
 	char line[512], fs_name[128], mountp[256];
9a8d55
-	int fs = 0;
9a8d55
+	int fs = 0, skip = 0, skip_next = 0;
9a8d55
+	char *pos = 0;
9a8d55
 	struct stats_filesystem *st_filesystem_i;
9a8d55
 	struct statvfs buf;
9a8d55
 
9a8d55
 	if ((fp = fopen(MTAB, "r")) == NULL)
9a8d55
 		return;
9a8d55
 
9a8d55
-	while ((fgets(line, 256, fp) != NULL) && (fs < nbr)) {
9a8d55
+	while ((fgets(line, sizeof(line), fp) != NULL) && (fs < nbr)) {
9a8d55
+		/*
9a8d55
+		 * Ignore line if the preceding line did not contain '\n'.
9a8d55
+		 * (Some very long lines may be found for instance when
9a8d55
+		 * overlay2 filesystem with docker is used).
9a8d55
+		 */
9a8d55
+		skip = skip_next;
9a8d55
+		skip_next = (strchr(line, '\n') == NULL);
9a8d55
+		if (skip)
9a8d55
+			continue;
9a8d55
+
9a8d55
 		if (line[0] == '/') {
9a8d55
+			/* Find field separator position */
9a8d55
+			pos = strchr(line, ' ');
9a8d55
+			if (pos == NULL)
9a8d55
+				continue;
9a8d55
 
9a8d55
 			/* Read current filesystem name */
9a8d55
 			sscanf(line, "%127s", fs_name);
9a8d55
@@ -1937,7 +1952,7 @@ void read_filesystem(struct stats_filesystem *st_filesystem, int nbr)
9a8d55
 			 * from the fs name. This will result in a bogus name
9a8d55
 			 * and following statvfs() function will always fail.
9a8d55
 			 */
9a8d55
-			sscanf(strchr(line, ' ') + 1, "%255s", mountp);
9a8d55
+			sscanf(pos + 1, "%255s", mountp);
9a8d55
 
9a8d55
 			/* Replace octal codes */
9a8d55
 			oct2chr(mountp);
9a8d55
@@ -2397,7 +2412,9 @@ int get_filesystem_nr(void)
9a8d55
 {
9a8d55
 	FILE *fp;
9a8d55
 	char line[512], fs_name[MAX_FS_LEN], mountp[256];
9a8d55
-	int fs = 0;
9a8d55
+        int fs = 0, skip = 0, skip_next = 0;
9a8d55
+        char *pos = 0;
9a8d55
+
9a8d55
 	struct statvfs buf;
9a8d55
 
9a8d55
 	if ((fp = fopen(MTAB, "r")) == NULL)
9a8d55
@@ -2406,11 +2423,25 @@ int get_filesystem_nr(void)
9a8d55
 
9a8d55
 	/* Get current filesystem */
9a8d55
 	while (fgets(line, 256, fp) != NULL) {
9a8d55
+                /*
9a8d55
+		 * Ignore line if the preceding line did not contain '\n'.
9a8d55
+		 * (Some very long lines may be found for instance when
9a8d55
+		 * overlay2 filesystem with docker is used).
9a8d55
+		 */
9a8d55
+		skip = skip_next;
9a8d55
+		skip_next = (strchr(line, '\n') == NULL);
9a8d55
+		if (skip)
9a8d55
+			continue;
9a8d55
+
9a8d55
 		if (line[0] == '/') {
9a8d55
+			/* Find field separator position */
9a8d55
+			pos = strchr(line, ' ');
9a8d55
+			if (pos == NULL)
9a8d55
+				continue;
9a8d55
 			
9a8d55
 			/* Read filesystem name and mount point */
9a8d55
                        sscanf(line, "%127s", fs_name);
9a8d55
-                       sscanf(strchr(line, ' ') + 1, "%255s", mountp);
9a8d55
+                       sscanf(pos + 1, "%255s", mountp);
9a8d55
 
9a8d55
                         /* Replace octal codes */
9a8d55
 			oct2chr(mountp);
9a8d55
-- 
9a8d55
2.14.3
9a8d55