From d6c55282ef8da54ce63facfb3233506340c35b51 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sun, 1 May 2022 21:43:13 +0200 Subject: [PATCH] Fix #253: use reentrant getmntent_r() API When iterating over the system fstab file to call fsck, Finit calls the helper function ismnt(), which opens /proc/mounts to make sure mounted file systems are not fsck'ed. Both the main function and ismnt() used the same non-reentrant getmntent() API which caused ismnt() to set the fstab pointer for the first out of whack. This change replaces getmntent() in the two critical functions with the getmntent_r() API instead. Signed-off-by: Joachim Wiberg --- configure.ac | 2 +- src/finit.c | 7 +++++-- src/util.c | 4 +++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index e04365d5..967a712a 100644 --- a/configure.ac +++ b/configure.ac @@ -34,7 +34,7 @@ AC_PROG_MKDIR_P # Configuration. AC_HEADER_STDC AC_CHECK_HEADERS([termios.h sys/ioctl.h mntent.h sys/sysmacros.h]) -AC_CHECK_FUNCS([strstr getopt getmntent]) +AC_CHECK_FUNCS([strstr getopt getmntent getmntent_r]) # Check for uint[8,16,32]_t AC_TYPE_UINT8_T diff --git a/src/finit.c b/src/finit.c index 57a3045c..4d3afb99 100644 --- a/src/finit.c +++ b/src/finit.c @@ -190,8 +190,10 @@ char *fs_root_dev(char *real, size_t len) */ static int fsck(int pass) { + struct mntent mount; struct mntent *mnt; char real[192]; + char buf[256]; int rc = 0; FILE *fp; @@ -201,7 +203,7 @@ static int fsck(int pass) sulogin(1); } _d("Opened %s, pass %d", fstab, pass); - while ((mnt = getmntent(fp))) { + while ((mnt = getmntent_r(fp, &mount, buf, sizeof(buf)))) { int fsck_rc = 0; struct stat st; char cmd[256]; @@ -211,7 +213,7 @@ static int fsck(int pass) mnt->mnt_fsname, mnt->mnt_dir, mnt->mnt_type, mnt->mnt_opts, mnt->mnt_freq, mnt->mnt_passno); - if (mnt->mnt_passno != pass) + if (mnt->mnt_passno == 0 || mnt->mnt_passno != pass) continue; /* Device to maybe fsck, */ @@ -252,6 +254,7 @@ static int fsck(int pass) #else snprintf(cmd, sizeof(cmd), "fsck -a %s", dev); #endif + _d("Running pass %d fsck command %s", pass, cmd); fsck_rc = run_interactive(cmd, "Checking filesystem %.13s", dev); /* * "failure" is defined as exiting with a return code of diff --git a/src/util.c b/src/util.c index 76cc03aa..37a085a3 100644 --- a/src/util.c +++ b/src/util.c @@ -488,7 +488,9 @@ static int hasopt(char *opts, char *opt) int ismnt(char *file, char *dir, char *mode) { + struct mntent mount; struct mntent *mnt; + char buf[256]; int found = 0; FILE *fp; @@ -496,7 +498,7 @@ int ismnt(char *file, char *dir, char *mode) if (!fp) return 0; /* Dunno, maybe not */ - while ((mnt = getmntent(fp))) { + while ((mnt = getmntent_r(fp, &mount, buf, sizeof(buf)))) { if (!strcmp(mnt->mnt_dir, dir)) { if (mode) { if (hasopt(mnt->mnt_opts, mode))