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 <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg
2022-05-01 21:43:13 +02:00
parent 1015124530
commit d6c55282ef
3 changed files with 9 additions and 4 deletions
+1 -1
View File
@@ -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
+5 -2
View File
@@ -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
+3 -1
View File
@@ -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))