Bug 1597 - During ssh login, the motd may not appear
Summary: During ssh login, the motd may not appear
Status: CLOSED FIXED
Alias: None
Product: Portable OpenSSH
Classification: Unclassified
Component: sshd (show other bugs)
Version: 5.2p1
Hardware: ix86 Linux
: P2 normal
Assignee: Assigned to nobody
URL:
Keywords:
Depends on:
Blocks: V_5_4
  Show dependency treegraph
 
Reported: 2009-05-14 05:58 AEST by John Ata
Modified: 2010-03-26 10:51 AEDT (History)
2 users (show)

See Also:


Attachments
Flushed pending output such as motd before execv of shell (298 bytes, patch)
2009-05-14 05:58 AEST, John Ata
no flags Details | Diff
Flushed pending output so motd is not lost (818 bytes, application/octet-stream)
2009-05-16 09:12 AEST, John Ata
no flags Details
Flushed pending output so motd is not lost (560 bytes, patch)
2009-05-16 09:16 AEST, John Ata
no flags Details | Diff
flush just before exec() (480 bytes, patch)
2009-09-09 10:54 AEST, Damien Miller
dtucker: ok+
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description John Ata 2009-05-14 05:58:11 AEST
Created attachment 1637 [details]
Flushed pending output  such as motd before execv of shell

In do_login (session.c), the routine do_motd() is called that writes to the stdout stream.  Apparently, it may have been assumed that stdout was line buffered because it was a pseudo terminal.  Even though stdio is indeed a terminal, this may not be the correct assumption.  The following sequence of events can occur:

1) Forked child "rexecs" sshd in main() with stdout pointing to a non-tty device (accepted socket).
2) Because the stdout stream is not a terminal, the libc startup code run immediately in the execed process will cause the stdout stream to be fully buffered.
3) After some processing, do_exec_pty (session.c) is called which dup2 the the psedudo tty to fd 1.  The stdio buffering mode for the stdout stream is not affected and is still fully buffered even though it is now a terminal.
4) Process calls do_motd and calls fputs to the stdout stream for the motd.  The data is now buffered but is not displayed even though it is a terminal.
5) Process execs the shell.  Since the stdout stream is now a terminal, the startup code in libc will cause the stdout stream to be line buffered.  From this point forward, everything is ok.  However, the buffered data from the motd will will lost.

Suggest a fflush(NULL) be called before the execv of the shell or alternatively after do_motd writes to stdout.  Attached patch does the former.
Comment 1 John Ata 2009-05-15 11:03:58 AEST
Additional info: I am using uClibc rather than glibc.  Apparently glibc forces the stream to line buffer mode on the first I/O if it is a terminal so when the loginmsg or motd is printed in step 4, even though it is fully buffered before the I/O, it is switched over during the stdio call such as printf or fputs causing the output to be flushed.  However, uClibc does not do this which explains the problem reported.
Comment 2 John Ata 2009-05-16 09:12:38 AEST
Created attachment 1638 [details]
Flushed pending output so motd is not lost
Comment 3 John Ata 2009-05-16 09:16:09 AEST
Created attachment 1639 [details]
Flushed pending output so motd is not lost
Comment 4 Damien Miller 2009-09-09 10:54:40 AEST
Created attachment 1694 [details]
flush just before exec()

Does this work? It delays the flush until just before we perform an exec
Comment 5 John Ata 2009-09-10 01:52:36 AEST
(In reply to comment #4)
> Does this work? It delays the flush until just before we perform an
> exec

Works fine, thanks!
Comment 6 Damien Miller 2009-10-06 15:47:10 AEDT
fix committed, will be in openssh-5.4
Comment 7 Darren Tucker 2010-03-26 10:51:51 AEDT
With the release of 5.4p1, this bug is now considered closed.