mtd: fix use-after-free in find_ubi_for_mtd (segfault on musl arm64)#171
Merged
Conversation
POSIX leaves struct dirent invalid after closedir(); glibc happens to keep the buffer alive across the close, musl invalidates it immediately. find_ubi_for_mtd() did: closedir(d); int ubi_num; sscanf(de->d_name, "ubi%d", &ubi_num); /* <-- read freed memory */ return ubi_num; That's a segfault on the Bootlin-musl-built aarch64 release binary (reproducible in `ipctool` -> "rom" step -> cb_mtd_info -> mtd4 ubifs volume), while the same source builds clean and runs through to full YAML on glibc. Restructure to parse de->d_name BEFORE closedir(), with a single local `ubi_num` initialised to -1 that's returned at the end. Also flatten the `if (f)` block to early-`continue` on fopen() failure to keep the control flow obvious. Same fix would be the right thing for the equivalent dirent-after- closedir pattern elsewhere in the tree if it surfaces. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Found while validating the arm64 release binary on a Hi3519DV500 board: the published
ipctool-arm64(Bootlin musl static) segfaults withexit 139immediately after detection, but only onipctool(full YAML); subcommands like-c,-s,clocksall work.The bug
find_ubi_for_mtd()readsde->d_nameafterclosedir(d):POSIX explicitly leaves
struct direntinvalid afterclosedir(). glibc happens to keep the buffer alive across the close (so the bug never surfaced on the old arm32/mips32 release artifacts or on the local glibc dev build); musl invalidates it immediately, which is what the published Bootlin-musl arm64 binary hits.Reproduction
Bisected
build_yaml()→get_mtd_info→cb_mtd_info→find_ubi_for_mtd(4):num=4matchesmtd_num=4(the rootfs ubifs volume), so the function enters the "match" branch where it closes the dir and then derefsde. Local repro with/opt/aarch64--musl--stable-2025.08-1/bin/aarch64-buildroot-linux-musl-gccconfirms the same crash; glibc-built binary doesn't.Fix
Restructure to parse
de->d_namebeforeclosedir()with a single localubi_numinitialised to -1 returned at the end. Same control-flow shape (earlycontinueon fopen failure) so the diff stays small.Test plan
Impact
The currently published
ipctool-arm64atlatestis broken on bare invocation. Merging this and letting the release workflow re-publish closes the regression. The pre-merge state ofmaster(after #168, #169, #170) does not exhibit the bug on the glibc dev build we used to validate V5 earlier — only the musl-built release artifact.🤖 Generated with Claude Code