Skip to content

findmnt: skip shadowed entries when matching by --target#4451

Open
dengbo11 wants to merge 1 commit into
util-linux:masterfrom
dengbo11:fix-target
Open

findmnt: skip shadowed entries when matching by --target#4451
dengbo11 wants to merge 1 commit into
util-linux:masterfrom
dengbo11:fix-target

Conversation

@dengbo11

Copy link
Copy Markdown

When a bind mount overlays the same mountpoint (e.g. mount -B /boot /boot), findmnt --target produces duplicate results because both the original and bind entries match via mnt_fs_match_target().

Filter out over-mounted entries using mnt_table_over_fs() when the target match is active. This ensures --target returns only the visible (topmost) filesystem for the given path.

[misc-utils/findmnt.c: match_func()]

Fixes #4424

When a bind mount overlays the same mountpoint (e.g. mount -B /boot /boot),
findmnt --target <path> produces duplicate results because both the
original and bind entries match via mnt_fs_match_target().

Filter out over-mounted entries using mnt_table_over_fs() when the target
match is active. This ensures --target returns only the visible (topmost)
filesystem for the given path.

[misc-utils/findmnt.c: match_func()]

Fixes util-linux#4424
@karelzak

Copy link
Copy Markdown
Collaborator

Thanks for looking into this. The fix addresses a real problem, but the approach in match_func() is fragile because is_defined_match(COL_TARGET) is not a reliable indicator that --target was used. set_match(COL_TARGET, ...) is also called from:

  • get_next_fs() — source/target swap fallback when source-only match fails
  • poll_match() — same swap logic for --poll
  • positional args: findmnt <source> <target> (without FL_NOSWAPMATCH)

The swap cases would cause false shadowed-entry filtering on what was originally a source spec.

The good news is that this is already solved by existing infrastructure — we just need to enable it for --target. The mount table is read from /proc/self/mountinfo where later mounts appear later in the file. With MNT_ITER_BACKWARD, add_matching_lines() iterates from the end, so the last-mounted (topmost/visible) entry is seen first. Combined with FL_FIRSTONLY, it stops after that first match — returning exactly the visible filesystem. No changes to match_func() needed.

The fix would be something like:

case 'M':
    findmnt.flags |= FL_STRICTTARGET;
    FALLTHROUGH;
case 'T':
    set_match(COL_TARGET, optarg);
    force_target = 1;
    break;

where force_target is a local int in main(), and then after the getopt loop:

if (force_target) {
    direction = MNT_ITER_BACKWARD;
    findmnt.flags |= FL_NOSWAPMATCH | FL_FIRSTONLY;
}

— assisted by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

findmnt --target can produce duplicate result

2 participants