bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bash randomly logs out on VT / serial console


From: rmk
Subject: bash randomly logs out on VT / serial console
Date: Sun, 01 Jan 2017 21:01:29 +0000

Configuration Information [Automatically generated, do not change]:
Machine: aarch64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='aarch64' 
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='aarch64-unknown-linux-gnu' 
-DCONF_VENDOR='unknown' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' 
-DSHELL -DHAVE_CONFIG_H   -I.  -I../. -I.././include -I.././lib  
-D_FORTIFY_SOURCE=2 -g -O2 -fstack-protector-strong -Wformat 
-Werror=format-security -Wall
uname output: Linux mcbin 4.9.0+ #249 SMP PREEMPT Sun Jan 1 17:28:33 GMT 2017 
aarch64 aarch64 aarch64 GNU/Linux
Machine Type: aarch64-unknown-linux-gnu

Bash Version: 4.3
Patch Level: 30
Release Status: release

Description:
        Running:
                while :; do s=$(sleep .005 | cat); echo $s; done | uniq
        in a login shell on a virtual terminal or serial console results
        in the shell randomly logging out after ^C.

        Debugging reveals that:
        (a) the top-level shell sets the terminal PGRP and current process
         group to the shell's process ID (shell_pgrp as bash calls it).
         However, when bash gets around to reading input, it receives an
         EIO error - kernel debugging shows that this is because the TTY
         PGRP does not match the processes PGRP at this point.
        (b) the sub-shell running the "while" does not wait for the $(...)
         to finish before sending itself a SIGINT.
        (c) the sub-sub-shell for the $(...) waits for the "sleep" command
         to terminate, and then sets the PGRP and current process group to
         original_pgrp, which is the login process ID.

        stracing the shell (strace -tt -ff -o str.bash -p <shell-pid>)
        and grepping the resulting log files for SPGRP shows:

str.bash.10928:17:38:38.745323 ioctl(255, TIOCGPGRP, [14119]) = 0
str.bash.10928:17:38:39.478119 ioctl(255, TIOCSPGRP, [10928]) = 0
str.bash.10928:17:38:39.480458 ioctl(255, TIOCSPGRP, [10928]) = 0
str.bash.10928:17:38:39.902027 ioctl(255, TIOCSPGRP, [10875]) = 0
str.bash.14119:17:38:38.719282 ioctl(255, TIOCSPGRP, [14119]) = 0
str.bash.14119:17:38:39.476968 ioctl(255, TIOCSPGRP, [10875]) = 0
str.bash.14120:17:38:38.718508 ioctl(255, TIOCSPGRP, [14119]) = 0
str.bash.14241:17:38:39.485459 ioctl(255, TIOCSPGRP, [10875]) = 0
str.bash.14243:17:38:39.477927 ioctl(255, TIOCSPGRP, [10875]) = 0

        and stracing the login shell for terminal IO:
str.bash.10928:17:38:39.482909 write(2, "address@hidden:~# ", 14) = 14
str.bash.10928:17:38:39.483027 read(0, "\33", 1)       = 1
str.bash.10928:17:38:39.870424 read(0, 0x7fc81f8737, 1) = -1 EIO (Input/output 
error)
str.bash.10928:17:38:39.884115 write(2, "\7", 1)       = 1
str.bash.10928:17:38:39.884212 read(0, 0x7fc81f87a7, 1) = -1 EIO (Input/output 
error)
str.bash.10928:17:38:39.899960 write(2, "logout\n", 7) = 7

        From the timestamps, you can see that PID 14241 changed the TTY
        PGRP between the write-out of the prompt, reading the first
        character of input, and attempting to read the subsequent
        characters - resulting in the shell logging itself out.

        Here, pid 10875 was the login process.

        Adding debug into give_terminal_to() changes the timing enough
        that it becomes very difficult to trigger.  Remove the debug and
        it seems to be soo easy that bash is painful to use on such a
        terminal.

        (My command which discovered this was slightly more complex and
         useful than the above, but the above is a simpler test case
         which reproduces the problem.)

Repeat-By:
        Login on a serial console.  Probably logging in on a Linux
        virtual terminal will also be good enough.  Not a SSH connection,
        there needs to be a login(8) process as bash's parent.

        Run:
          while :; do s=$(sleep .005 | cat); echo $s; done | uniq

        Hit ^c.  Repeat a few times.  Tested on a quad-core ARM64 machine
        and a dual-core 32-bit ARM machine.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]