sudo-project/sudo

sudo consumes stdin even when not prompting for password

printfn opened this issue · 1 comments

Create the following shell script:

sleep 1
sudo true

Run it, and immediately type some input in the terminal while the script is sleeping for one second. Make sure sudo is configured to not prompt for a password, or run the script as root. I expected the script to ignore what I typed, causing it to appear on the prompt after the script finished executing, but instead the sudo true command consumed stdin.

On recent versions of sudo (checked on 1.9.9 and 1.9.14 on Ubuntu 22.04 and 23.10), the sudo command will swallow standard input, whereas on version 1.8.31 (Ubuntu 20.04) it ignores the input like I expected. Changing the second line to echo | sudo true works around the issue, but adding -S or -n or changing the use_pty setting had no effect.

This is a side-effect of running a command in a pseudo-terminal. There is no way for sudo to tell whether or not the command actually wants the input, it can only tell that the pty's buffer can accept input. There are two possible workarounds.

  1. Explicitly disable the use_pty option. E.g.

    Defaults !use_pty

    This will prevent sudo from setting /dev/tty to raw mode and reading from it. Note that simply removing or commenting out the existing Defaults use_pty line is not sufficient, you need to explicitly disable it. Also, this will have no effect if log_input or log_output is enabled but it doesn't sound like that is the case here.

  2. Enable the execbg option. E.g.

    Defaults exec_background

    This will execute commands in the background instead of the foreground. If a background process needs to read from the terminal, it will receive SIGTTIN, which sudo will notice, grant the command access to the terminal and start reading from the user's /dev/tty. Not all programs behave properly when run in the background, though.

I just verified that both of those fix the issue on Ubuntu 22.04 with sudo 1.9.9 and 1.9.15p5.