-
Notifications
You must be signed in to change notification settings - Fork 121
wolfsshd: keep the shell loop past a stderr EOF #1263
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
ejohnstown
wants to merge
6
commits into
wolfSSL:master
Choose a base branch
from
ejohnstown:shell-eof-errno
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+174
−14
Open
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
3523286
wolfsshd: keep the shell loop past a stderr EOF
ejohnstown 421fd06
wolfsshd: test a stderr EOF with output queued
ejohnstown cbad0b7
wolfsshd: bound the wait on a drained child
ejohnstown 97cad3b
wolfsshd: match the stdout and pty read arms
ejohnstown ce72017
wolfsshd: bound and guard the stderr EOF test
ejohnstown c97a768
wolfsshd: give the stderr EOF test a temp dir
ejohnstown File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,133 @@ | ||
| #!/bin/bash | ||
|
|
||
| # The child's stderr reaching end of file must not end the shell loop while | ||
| # its stdout still has bytes queued for the peer. | ||
| # | ||
| # read() returns 0 at EOF and leaves errno alone, so an errno tested there | ||
| # reports whatever the last call left. A shell loop holding a backlog stops | ||
| # reading the child's pipes, so stdout backs up and the stderr EOF arrives | ||
| # behind it; if that EOF is read as an error the loop ends and everything | ||
| # still queued is dropped. The peer sees a short transfer and no error. | ||
| # | ||
| # Whether the stale errno happens to be fatal is a race, so one transfer | ||
| # proves nothing and this repeats. A short transfer is never correct, so a | ||
| # failure here is always real; a regression can only hide by passing every | ||
| # iteration. | ||
|
|
||
| if [ -z "$1" ] || [ -z "$2" ]; then | ||
| echo "expecting host and port as arguments" | ||
| echo "./sshd_stderr_eof_test.sh 127.0.0.1 22222" | ||
| exit 1 | ||
| fi | ||
|
|
||
| PWD=`pwd` | ||
|
|
||
| if [ ! -z "$3" ]; then | ||
| USER="$3" | ||
| else | ||
| USER=`whoami` | ||
| fi | ||
| TEST_HOST="$1" | ||
| TEST_PORT="$2" | ||
|
|
||
| # Enough data to outrun the send window, a reader that stalls long enough for | ||
| # the child to finish and exit while the backlog is held, and enough passes to | ||
| # make the race show. | ||
| TEST_SIZE=16777216 | ||
| TEST_STALL=4 | ||
| TEST_ITERS=12 | ||
|
|
||
| # A byte count cannot tell a short transfer from one that never finished, and | ||
| # the runner invokes this test synchronously: a regression that leaves the | ||
| # session open would stall the whole suite here. One pass takes about four | ||
| # seconds, so this is only a deadline, not a budget. Degraded rather than | ||
| # skipped where "timeout" is missing, matching run_all_sshd_tests.sh. | ||
| TEST_TIMEOUT=120 | ||
| TIMEOUT="" | ||
| if command -v timeout >/dev/null 2>&1; then | ||
| TIMEOUT="timeout $TEST_TIMEOUT" | ||
| fi | ||
|
|
||
| source ./start_sshd.sh | ||
|
|
||
| # The runner leases a port block per run so two runs can share a host, and | ||
| # fixed names in the checkout are the other half of that: a second run | ||
| # overwrites this one's config and payload, and whichever finishes first | ||
| # removes them from under the other, which then reports a short transfer that | ||
| # never happened. Everything this test writes goes in a directory of its own. | ||
| TEST_TMP=`mktemp -d 2>/dev/null` || TEST_TMP=`mktemp -d -t stderreof` | ||
| if [ -z "$TEST_TMP" ] || [ ! -d "$TEST_TMP" ]; then | ||
| echo "Failed to create a temp dir" | ||
| exit 1 | ||
| fi | ||
| TEST_CONFIG="$TEST_TMP/sshd_config_test_stderr_eof" | ||
| TEST_FILE="$TEST_TMP/stderr-eof-test.txt" | ||
| TEST_RESULT_FILE="$TEST_TMP/stderr-eof-test-result.txt" | ||
|
|
||
| # The payload is 16 MB and the daemon is shared with the rest of the run, so | ||
| # neither may be left behind by an interrupted pass. Installed before the | ||
| # daemon starts so a failure in between is covered too; stop_wolfsshd is | ||
| # idempotent, so the explicit call at the end still stands. | ||
| trap 'rm -rf "$TEST_TMP"; stop_wolfsshd' EXIT | ||
|
|
||
| cat <<CONF > "$TEST_CONFIG" | ||
| Port $TEST_PORT | ||
| Protocol 2 | ||
| LoginGraceTime 600 | ||
| PermitRootLogin yes | ||
| PasswordAuthentication yes | ||
| PermitEmptyPasswords no | ||
| UsePrivilegeSeparation no | ||
| UseDNS no | ||
| HostKey $PWD/../../../keys/server-key.pem | ||
| AuthorizedKeysFile $PWD/authorized_keys_test | ||
| CONF | ||
|
|
||
| start_wolfsshd "$TEST_CONFIG" | ||
| if [ -z "$PID" ]; then | ||
| echo "Failed to start wolfsshd" | ||
| exit 1 | ||
| fi | ||
| cd ../../.. | ||
|
|
||
| TEST_CLIENT="./examples/client/client" | ||
| PRIVATE_KEY="./keys/hansel-key-ecc.der" | ||
| PUBLIC_KEY="./keys/hansel-key-ecc.pub" | ||
| PWD=`pwd` | ||
|
|
||
| head -c $TEST_SIZE /dev/urandom > "$TEST_FILE" | ||
| EXPECTED=`wc -c < "$TEST_FILE"` | ||
|
|
||
| RESULT=0 | ||
| for i in `seq 1 $TEST_ITERS`; do | ||
| # The inner client cats the file through the outer session, so the shell | ||
| # loop is the one relaying it. Stalling the outer client's reader fills | ||
| # the window and leaves the loop holding a backlog. | ||
| $TIMEOUT $TEST_CLIENT -q -c "cd $PWD; $TEST_CLIENT -q -c \"cat $TEST_FILE\" -u $USER -i $PRIVATE_KEY -j $PUBLIC_KEY -h $TEST_HOST -p $TEST_PORT" \ | ||
| -u $USER -i $PRIVATE_KEY -j $PUBLIC_KEY -h $TEST_HOST -p $TEST_PORT 2>/dev/null \ | ||
| | { sleep $TEST_STALL; cat; } > "$TEST_RESULT_FILE" | ||
| # The client's own status, not the reader's. 124 is the deadline above, | ||
| # which a byte count would go on to report as a short transfer. | ||
| CLIENT_RESULT=${PIPESTATUS[0]} | ||
|
|
||
| if [ "$CLIENT_RESULT" = 124 ]; then | ||
| echo "pass $i of $TEST_ITERS never finished" | ||
| echo "the client was still running after $TEST_TIMEOUT seconds" | ||
| RESULT=1 | ||
| break | ||
| fi | ||
|
|
||
| GOT=`wc -c < "$TEST_RESULT_FILE"` | ||
| if [ "$GOT" != "$EXPECTED" ]; then | ||
| echo "pass $i of $TEST_ITERS truncated the shell output" | ||
| echo "expected $EXPECTED bytes, got $GOT, short by $((EXPECTED-GOT))" | ||
| RESULT=1 | ||
| break | ||
| fi | ||
| done | ||
|
|
||
| rm -rf "$TEST_TMP" | ||
| cd apps/wolfsshd/test | ||
| stop_wolfsshd | ||
|
|
||
| exit $RESULT |
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
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.