|
|
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 |
|