From: Karel Zak Date: Wed, 18 Mar 2026 11:01:11 +0000 (+0100) Subject: findmnt: fix SIGSEGV when parsing empty file X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ee5f5935e1e51c63e98f7cc06dcf6b3740150957;p=thirdparty%2Futil-linux.git findmnt: fix SIGSEGV when parsing empty file Set mnt_table_set_userdata() right after mnt_new_table() in all functions that create a libmount table, so that parser_errcb() can always safely access the findmnt userdata. Previously, userdata was set only in main() after parse_tabfiles() returned, meaning the error callback would dereference a NULL pointer when encountering parse errors (e.g., an empty file passed via -F). Also add a NULL guard in parser_errcb() as a safety net, and a test for the empty file case. Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=2448233 Signed-off-by: Karel Zak --- diff --git a/misc-utils/findmnt.c b/misc-utils/findmnt.c index afc40ebeb..c892bf299 100644 --- a/misc-utils/findmnt.c +++ b/misc-utils/findmnt.c @@ -1019,7 +1019,8 @@ static int parser_errcb(struct libmnt_table *tb, { struct findmnt *findmnt = mnt_table_get_userdata(tb); warnx(_("%s: parse error at line %d -- ignored"), filename, line); - findmnt->parse_nerrors++; + if (findmnt) + findmnt->parse_nerrors++; return 1; } @@ -1039,7 +1040,8 @@ static char **append_pid_tabfile(char **files, int *nfiles, pid_t pid) } /* calls libmount fstab/mtab/mountinfo parser */ -static struct libmnt_table *parse_tabfiles(char **files, +static struct libmnt_table *parse_tabfiles(struct findmnt *findmnt, + char **files, int nfiles, int tabtype) { @@ -1051,6 +1053,7 @@ static struct libmnt_table *parse_tabfiles(char **files, warn(_("failed to initialize libmount table")); return NULL; } + mnt_table_set_userdata(tb, findmnt); mnt_table_set_parser_errcb(tb, parser_errcb); do { @@ -1086,7 +1089,7 @@ static struct libmnt_table *parse_tabfiles(char **files, return tb; } -static struct libmnt_table *fetch_listmount(void) +static struct libmnt_table *fetch_listmount(struct findmnt *findmnt) { struct libmnt_table *tb = NULL; struct libmnt_statmnt *sm = NULL; @@ -1102,6 +1105,7 @@ static struct libmnt_table *fetch_listmount(void) warn(_("failed to initialize libmount table")); goto failed; } + mnt_table_set_userdata(tb, findmnt); mnt_table_refer_statmnt(tb, sm); @@ -1121,7 +1125,7 @@ failed: * Parses mountinfo and calls mnt_cache_set_targets(cache, mtab). Only * necessary if @tb in main() was read from a non-kernel source. */ -static void cache_set_targets(struct libmnt_cache *tmp) +static void cache_set_targets(struct findmnt *findmnt, struct libmnt_cache *tmp) { struct libmnt_table *tb; const char *path; @@ -1129,6 +1133,8 @@ static void cache_set_targets(struct libmnt_cache *tmp) tb = mnt_new_table(); if (!tb) return; + mnt_table_set_userdata(tb, findmnt); + mnt_table_set_parser_errcb(tb, parser_errcb); path = access(_PATH_PROC_MOUNTINFO, R_OK) == 0 ? _PATH_PROC_MOUNTINFO : @@ -1402,6 +1408,7 @@ static int poll_table(struct libmnt_table *tb, const char *tabfile, goto done; } + mnt_table_set_userdata(tb_new, findmnt); mnt_table_set_parser_errcb(tb_new, parser_errcb); fds[0].fd = fileno(f); @@ -2142,12 +2149,11 @@ int main(int argc, char *argv[]) mnt_init_debug(0); if (tabtype == TABTYPE_KERNEL_LISTMOUNT) - tb = fetch_listmount(); + tb = fetch_listmount(&findmnt); else - tb = parse_tabfiles(tabfiles, ntabfiles, tabtype); + tb = parse_tabfiles(&findmnt, tabfiles, ntabfiles, tabtype); if (!tb) goto leave; - mnt_table_set_userdata(tb, &findmnt); if (tabtype == TABTYPE_MTAB && tab_is_kernel(tb)) tabtype = TABTYPE_KERNEL_MOUNTINFO; @@ -2168,7 +2174,7 @@ int main(int argc, char *argv[]) mnt_table_set_cache(tb, findmnt.cache); if (tabtype == TABTYPE_FSTAB || tabtype == TABTYPE_MTAB) - cache_set_targets(findmnt.cache); + cache_set_targets(&findmnt, findmnt.cache); } if (findmnt.flags & FL_UNIQ) diff --git a/tests/expected/findmnt/outputs-empty-file b/tests/expected/findmnt/outputs-empty-file new file mode 100644 index 000000000..321433716 --- /dev/null +++ b/tests/expected/findmnt/outputs-empty-file @@ -0,0 +1 @@ +rc=1 diff --git a/tests/ts/findmnt/outputs b/tests/ts/findmnt/outputs index 83c9134f9..198cbea98 100755 --- a/tests/ts/findmnt/outputs +++ b/tests/ts/findmnt/outputs @@ -46,4 +46,10 @@ $TS_CMD_FINDMNT --tab-file "$TS_SELF/files/mountinfo-messy" &> $TS_OUTPUT echo rc=$? >> $TS_OUTPUT ts_finalize_subtest +ts_init_subtest "empty-file" +touch "$TS_OUTDIR/empty" +$TS_CMD_FINDMNT --tab-file "$TS_OUTDIR/empty" &> $TS_OUTPUT +echo rc=$? >> $TS_OUTPUT +ts_finalize_subtest + ts_finalize