Skip to content

de10nano: /bin/sh and root's login shell are bash, as on stock - #145

Merged
mcfbytes merged 5 commits into
masterfrom
fix/bin-sh-bash-parity
Sep 4, 2026
Merged

de10nano: /bin/sh and root's login shell are bash, as on stock#145
mcfbytes merged 5 commits into
masterfrom
fix/bin-sh-bash-parity

Conversation

@mcfbytes

@mcfbytes mcfbytes commented Sep 3, 2026

Copy link
Copy Markdown
Owner

Fixes #144. Companion to #143 (WinSCP resize fix) but independent: separate root cause, separate branch off master.

What

BR2_SYSTEM_BIN_SH_BASH=y in configs/fragments/de10nano-image.fragment, plus the de10nano golden hash, docs, and CI assertions.

Why

Stock (release_20250402) Ours before Ours after
root's shell in /etc/passwd /bin/bash /bin/sh /bin/bash
/bin/sh -> bash BusyBox ash -> bash

No fragment ever set BR2_SYSTEM_BIN_SH, so Buildroot's BusyBox default applied and nothing in docs/init-parity.md recorded it. User scripts with #!/bin/sh + bash syntax work on stock and could fail here; interactive root got ash.

One symbol does both halves: Buildroot's SKELETON_INIT_COMMON_SET_BIN_SH finalize hook runs ln -sf bash /bin/sh and sed '/^root:/s,[^/]*$,bash,' /etc/passwd. No overlay or post-build change. BusyBox ash stays built and in /etc/shells, as on stock.

Changes

  • de10nano-image.fragment: the symbol, with a WARNING that it silently depends on BUSYBOX_SHOW_OTHERS.
  • golden.sha256: de10nano line regenerated via check-config-fragments.sh --update-golden (only stack affected; de10nano-kernel/de25nano/rt unchanged).
  • docs/buildroot-config.md §5.19: rationale. docs/init-parity.md: new row for /etc/passwd (root's shell) + /bin/sh.
  • scripts/ci-tests.sh: asserts ./usr/bin/sh -> bash and root's passwd shell from rootfs.tar (P3.4 section), and runs the dhcpcd timezone hook under the target's own bash --posix (what /bin/sh is on the box now) in addition to BusyBox ash.

Verification

  • make de10nano-defconfig: resolved .config has BR2_SYSTEM_BIN_SH_BASH=y, BR2_SYSTEM_BIN_SH="bash".
  • check-config-fragments.sh: OK, 4 stacks regenerate cleanly.
  • make all (incremental): output/target/bin/sh -> bash, root:x:0:0:root:/root:/bin/bash, same in rootfs.tar; check-linux-img.sh all assertions passed.
  • scripts/ci-tests.sh: the four new/changed checks PASS. The only failures are the three known exFAT cases of the local QEMU initramfs harness (harness kernel issue, pre-existing, unrelated).

Not tested on hardware yet; no runtime behaviour changes beyond which interpreter sh resolves to.

Follow-ups folded in (per review)

  • Copilot nits (37ac6be): full Kconfig symbol names in the fragment WARNING and the ci-tests comment; grep -m1 for root's passwd line.
  • Audit of everything that now runs under bash-as-sh (e90b85d): every #!/bin/sh file, udev RUN+= line, inittab entry, sourced dhcpcd hook and profile.d snippet on the target was checked. All parse under bash --posix -n; none uses a construct that differs between BusyBox ash (BASH_COMPAT) and bash in POSIX mode. Eight of them are stock files vendored byte-identical, for which bash is the original interpreter. The initramfs and installer images are separate defconfigs and stay on ash. Five doc/comment statements that still called ash "the shell on the box" were updated (stock-reconciliation timidity row, README, test-timezone.sh header, ADR 0025 dated addendum).
  • Local QEMU harness fix (78a3b04), found while running ci-tests for this PR: scripts/test-initramfs.sh invoked the kernel's merge_config.sh from the repo root, and that script ends with a bare make alldefconfig in the cwd, which hit our wrapper Makefile and failed, so CONFIG_EXFAT_FS / CONFIG_FAT_DEFAULT_UTF8 were silently dropped from the test kernel and the three exFAT cases failed with "No such device". Now runs from the kernel tree, dies on failure, and asserts every fragment =y survived (with the stale-cache remedy in the message). Unrelated to the shell change but it is what made "the only failures are the known exFAT cases" true.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Vq3yLoYntjiJ1wUaAdruLU

Stock ships /bin/sh -> bash and root:x:0:0:root:/root:/bin/bash. We shipped
Buildroot's defaults -- BusyBox ash as /bin/sh, root on /bin/sh -- because no
fragment ever set BR2_SYSTEM_BIN_SH, and nothing recorded the difference.
Bash was already in the image for wifi.sh.

Consequences of the gap: a user script in /media/fat/Scripts with a
#!/bin/sh shebang and bash syntax runs on stock and may not here, and an
interactive root session gets ash instead of bash (WinSCP's error text in
#142 literally says "BASH is recommended").

One symbol, BR2_SYSTEM_BIN_SH_BASH=y, gives stock's exact layout: Buildroot's
SKELETON_INIT_COMMON_SET_BIN_SH finalize hook both re-links /bin/sh and
rewrites root's passwd shell. No overlay or post-build edit needed. It
depends on BUSYBOX_SHOW_OTHERS (already on); the fragment carries a WARNING
because kconfig would drop it silently otherwise.

- de10nano golden.sha256 line regenerated (the only stack that changes)
- docs/buildroot-config.md §5.19 rationale; docs/init-parity.md new row
- ci-tests.sh asserts ./usr/bin/sh -> bash and root's passwd shell from
  rootfs.tar, and runs the dhcpcd timezone hook under the target's own
  bash --posix (what /bin/sh now is on the box) as well as BusyBox ash

Verified: make all -> output/target/bin/sh -> bash, root:/bin/bash, both
in rootfs.tar; ci-tests new checks PASS; check-linux-img.sh all assertions
passed; check-config-fragments OK.

Fixes #144

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vq3yLoYntjiJ1wUaAdruLU
Copilot AI lite review requested due to automatic review settings September 3, 2026 16:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The functional changes are straightforward and well-documented with CI coverage; remaining feedback is limited to minor maintainability nits in comments/test robustness.

Pull request overview

This PR aligns the DE10-Nano image with stock MiSTer behavior by making /bin/sh resolve to bash and setting root’s login shell to /bin/bash, and then documents and asserts that parity in CI.

Changes:

  • Enable BR2_SYSTEM_BIN_SH_BASH=y for the DE10-Nano image fragment to make /bin/sh -> bash and root’s passwd shell /bin/bash.
  • Update documentation to record the parity decision and rationale.
  • Update CI assertions to verify /bin/sh and root’s login shell, and execute the timezone hook tests under the target’s bash (POSIX mode) in addition to BusyBox ash.
File summaries
File Description
configs/fragments/de10nano-image.fragment Enables BR2_SYSTEM_BIN_SH_BASH and adds an explanatory warning comment.
configs/fragments/golden.sha256 Updates the DE10-Nano golden hash to match the new fragment output.
docs/buildroot-config.md Documents the rationale/behavior of BR2_SYSTEM_BIN_SH_BASH in this project.
docs/init-parity.md Records /bin/sh + root shell parity with stock.
scripts/ci-tests.sh Adds CI assertions for /bin/sh and root’s shell, and expands timezone-hook testing under target bash --posix.
Review details
  • Files reviewed: 5/5 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread scripts/ci-tests.sh Outdated
Comment thread configs/fragments/de10nano-image.fragment Outdated
Comment thread scripts/ci-tests.sh Outdated
mcfbytes and others added 4 commits September 3, 2026 11:27
…ot grep

Copilot review nits: spell out BR2_SYSTEM_BIN_SH_BASH /
BR2_PACKAGE_BUSYBOX_SHOW_OTHERS in the fragment WARNING and the ci-tests
comment so they grep; take only the first root: line from passwd so a
malformed file fails the check legibly instead of confusing the case.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vq3yLoYntjiJ1wUaAdruLU
Follow-up to BR2_SYSTEM_BIN_SH_BASH (#144): an audit of every #!/bin/sh
file, udev RUN+= line, inittab entry, sourced dhcpcd hook and profile.d
snippet on the target found nothing that behaves differently under bash
in POSIX mode (all parse under `bash --posix -n`; the one bashism in the
tree, usr/bin/timidity's `function`, is a stock file written for bash).
It did find five statements that still call BusyBox ash the shell that
runs things on the box:

- docs/stock-reconciliation.md timidity row: the ash BASH_COMPAT note was
  the accommodation, not the design
- README.md, scripts/test-timezone.sh header/comments, ADR 0025 (dated
  addendum): the timezone hook test now runs three times -- host shell,
  target bash --posix (what /bin/sh is on the box), target BusyBox ash

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vq3yLoYntjiJ1wUaAdruLU
…fragment survived

The three exFAT cases (exfat, fsck-request, symlink) have been failing
locally with "mount: mounting /dev/vdb1 on /mnt/fat failed: No such
device": the QEMU test kernel had `# CONFIG_EXFAT_FS is not set` even
though scripts/test-initramfs/qemu-test-kernel.config says =y.

Cause: the kernel's merge_config.sh ends with a BARE `make ... alldefconfig`
in the current directory (no -C). Invoked from this repo's root, that make
hits the wrapper Makefile, which forwards `alldefconfig` to Buildroot,
which dies with "Can't read seed configuration", and merge_config.sh exits
before writing the merged config. Symbols multi_v7_defconfig already had
looked merged; the two it lacked (CONFIG_EXFAT_FS, CONFIG_FAT_DEFAULT_UTF8)
were silently dropped. Reproduced with a fresh defconfig + merge from the
repo root (dropped) and from inside the kernel tree (kept).

Fix: cd into $KERNEL_SRC for the merge, pass ARCH/CROSS_COMPILE, and die
if it fails. Backstop: after olddefconfig, assert every `CONFIG_X=y` in
the fragment is in the resolved .config, with a message that names the
stale-cache remedy (rm -rf work/test-initramfs-kbuild) -- a cache built
by a failed merge keeps its broken .config forever because the merge only
runs on bootstrap.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vq3yLoYntjiJ1wUaAdruLU
@mcfbytes
mcfbytes merged commit 161e6da into master Sep 4, 2026
2 checks passed
@mcfbytes
mcfbytes deleted the fix/bin-sh-bash-parity branch September 4, 2026 01:04
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.

root login shell and /bin/sh differ from stock (ash vs bash), undocumented

2 participants