Skip to content

shadow-rs: replace println!/eprintln! with non-panicking writes (#141)#142

Merged
pierre-warnier merged 2 commits into
mainfrom
fix/141-remove-println-panic
Apr 17, 2026
Merged

shadow-rs: replace println!/eprintln! with non-panicking writes (#141)#142
pierre-warnier merged 2 commits into
mainfrom
fix/141-remove-println-panic

Conversation

@pierre-warnier

Copy link
Copy Markdown
Collaborator

Summary

Replace all println!/eprintln! in production code with non-panicking write alternatives. These macros panic when stdout/stderr is full or closed (e.g., command >/dev/full), which is unacceptable for setuid-root tools that must fail gracefully.

Fixes #141. Raised by @oech3.

Changes (10 files)

  • show_error!/show_warning! macros rewritten to use let _ = writeln!(stderr()) instead of eprintln!
  • Normal output uses let _ = writeln!(stdout) with locked handles
  • PAM display_message uses let _ = writeln!(stderr())
  • Also fixes a pre-existing clippy::map_unwrap_or lint in atomic.rs

Test code intentionally left unchanged — panicking on write failure in tests is acceptable.

Test plan

  • cargo fmt --all --check — clean
  • cargo clippy --workspace --all-targets -- -D warnings — zero warnings
  • Pre-push hook: full test suite on debian/alpine/fedora — all pass

println!() and eprintln!() panic when stdout/stderr is full or closed
(e.g., `command >/dev/full`). Replace all production-code occurrences
with non-panicking alternatives:

- show_error!/show_warning! macros rewritten to use
  `let _ = writeln!(stderr())` instead of eprintln!
- Normal output uses `let _ = writeln!(stdout)` with locked handles
- PAM display_message uses `let _ = writeln!(stderr())`

Also fixes a pre-existing clippy::map_unwrap_or lint in atomic.rs.

Test code is intentionally left unchanged — panicking on write failure
in tests is acceptable and desirable for fast failure.

Fixes #141.
Copilot AI review requested due to automatic review settings April 17, 2026 08: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.

Pull request overview

This PR hardens shadow-rs production binaries against panics caused by println!/eprintln! when stdout/stderr is closed or full (e.g., redirected to /dev/full), which is particularly important for setuid-root utilities.

Changes:

  • Replaces println!/eprintln! in multiple utilities and binaries with best-effort write!/writeln! (typically using locked stdout/stderr handles and ignoring write errors).
  • Updates PAM message display and shared error/warning macros to use non-panicking writes.
  • Fixes a pre-existing clippy lint in atomic.rs by replacing map(...).unwrap_or(...) with map_or(...).

Reviewed changes

Copilot reviewed 8 out of 10 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/uu/useradd/src/useradd.rs Uses locked stdout + writeln! for useradd -D defaults output without panicking on write failure.
src/uu/pwck/src/pwck.rs Replaces stderr output paths with non-panicking alternatives (including switching one message to uucore::show_error!).
src/uu/passwd/src/passwd.rs Uses locked stdout for status output; replaces critical stderr log in Drop with best-effort writeln!.
src/uu/chsh/src/chsh.rs Uses locked stdout + writeln! for --list-shells output.
src/uu/chage/src/chage.rs Uses locked stdout + writeln! for chage -l aging info output.
src/shadow-core/src/pam.rs Makes PAM display_message best-effort via writeln!(stderr, ...) to avoid panic on write failure.
src/shadow-core/src/error.rs Rewrites show_error! / show_warning! macros to lock stderr and perform non-panicking writes.
src/shadow-core/src/atomic.rs Refactors metadata permission selection to map_or(...) (clippy lint fix).
src/bin/shadow-rs.rs Converts dispatcher usage/help/error output to best-effort writeln! (stdout/stderr).
src/bin/completions.rs Converts stderr reporting to best-effort writeln! to avoid panics on write failure.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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.

Pull request overview

Copilot reviewed 8 out of 10 changed files in this pull request and generated 6 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/shadow-core/src/error.rs Outdated
Comment thread src/shadow-core/src/error.rs Outdated
Comment thread src/shadow-core/src/pam.rs
Comment thread src/uu/passwd/src/passwd.rs Outdated
Comment thread src/uu/pwck/src/pwck.rs
Comment thread src/uu/pwck/src/pwck.rs
- show_error!/show_warning!: combine prefix + message into a single
  writeln! call (was two writes: write! then writeln!)
- pam display_message: lock stderr before writing
- passwd PrivDrop::Drop: lock stderr before writing
- pwck check_passwd_entries: hoist stderr lock above the loop so
  per-entry diagnostics reuse one locked handle instead of
  reconstructing it on each iteration

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.

Pull request overview

Copilot reviewed 8 out of 10 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@pierre-warnier pierre-warnier merged commit 512c63e into main Apr 17, 2026
10 checks passed
@pierre-warnier pierre-warnier deleted the fix/141-remove-println-panic branch April 17, 2026 09:07
@oech3

oech3 commented Apr 17, 2026

Copy link
Copy Markdown
Contributor

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.

Remove (e)print(ln)! to avoid panic with >/dev/full or 2>/dev/full at production code

3 participants