From 2cdb64897d4fe33a11af13c6356dcd338c561e77 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Mon, 28 Apr 2008 16:29:12 +1000 Subject: [PATCH] Fix for segfault when reading /proc/mdstat Some kernel versions don't put a space between 'active' and '(auto-read-only)' in /proc/mdstat. This causes a parsing problem leaving 'level' set to NULL which causes a crash. So synthesise a space there if it is missing, and check for 'level' to be NULL and don't de-ref if it is. --- ChangeLog | 4 ++++ Incremental.c | 1 + Monitor.c | 1 + config.c | 13 +++++++++++++ 4 files changed, 19 insertions(+) diff --git a/ChangeLog b/ChangeLog index fa4fed45..fdf720d2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Changes Prior to this release + - Avoid segfault when parsing /proc/mdstat with auto-read-only + arrays. + Changes Prior to 2.6.4 release - Make "--create --auto=mdp" work for non-standard device names. - Fix restarting of a 'reshape' if it was stopped in the middle. diff --git a/Incremental.c b/Incremental.c index ab37ef0c..4c6a2a79 100644 --- a/Incremental.c +++ b/Incremental.c @@ -332,6 +332,7 @@ int Incremental(char *devname, int verbose, int runstop, struct supertype *st2; sra = sysfs_read(mdfd, devnum, (GET_VERSION | GET_DEVS | GET_STATE)); + if (sra->array.major_version != st->ss->major || sra->array.minor_version != st->minor_version) { if (verbose >= 0) diff --git a/Monitor.c b/Monitor.c index 6b0c760b..54193f5c 100644 --- a/Monitor.c +++ b/Monitor.c @@ -403,6 +403,7 @@ int Monitor(mddev_dev_t devlist, struct mdstat_ent *mse; for (mse=mdstat; mse; mse=mse->next) if (mse->devnum != INT_MAX && + mse->level && (strcmp(mse->level, "raid0")!=0 && strcmp(mse->level, "linear")!=0) ) { diff --git a/config.c b/config.c index 29eadc59..121b3373 100644 --- a/config.c +++ b/config.c @@ -161,11 +161,24 @@ char *conf_word(FILE *file, int allow_key) word[len++] = c; } c = getc(file); + /* Hack for broken kernels (2.6.14-.24) that put + * "active(auto-read-only)" + * in /proc/mdstat instead of + * "active (auto-read-only)" + */ + if (c == '(' && len >= 6 + && strncmp(word+len-6, "active", 6) == 0) + c = ' '; } } if (c != EOF) ungetc(c, file); } word[len] = 0; + + /* Further HACK for broken kernels.. 2.6.14-2.6.24 */ + if (strcmp(word, "auto-read-only)") == 0) + strcpy(word, "(auto-read-only)"); + /* printf("word is <%s>\n", word); */ if (!wordfound) { free(word); -- 2.39.2