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

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