sudo-project / sudo

Utility to execute a command as another user
https://www.sudo.ws
Other
1.14k stars 209 forks source link

Malformed stderr output when stdout is not piped #349

Open bboozzoo opened 5 months ago

bboozzoo commented 5 months ago

The change https://www.sudo.ws/repos/sudo/rev/faa06b1e8913 (https://github.com/sudo-project/sudo/commit/78b712101e17883b6d916495ef2b9bb0e34d3ca1) fixed the problem with 'staircase' output when stdout is piped. However when invoking applications under program like strace (which poduces its output mainly to stderr), it is possible that only stderr is piped, while stdin/stdout remain as they were. In this case, the autodetection of a piped output will fail to identify the scenario correctly and the output of stderr will be badly formatted.

A possible workaround is to pipe the stdout as well, but that has unwanted side effects if the application is interactive like eg. bash.

millert commented 5 months ago

This is a non-trivial problem for interactive commands. I don't know what command you are using but for, e.g.

sudo strace bash 2> >(tee /tmp/foo)

The user's terminal needs to be in raw mode so input can be passed to the interactive bash process running in a pseudo-terminal. The tee in this case is also writing to the user's terminal (not the pty being used by bash), which won't automatically convert newlines to newline + carriage return pairs (because it is in raw mode).

I'm not sure why you wouldn't just use strace's -o flag in this type of situation. You could work around the problem by only running commands in a pty is the target user is something other than root. E.g.

Defaults>root !use_pty
bboozzoo commented 5 months ago

Thanks for the reply, appreciated. I suspected the problem may indeed be non-trivial and I'm not sure it can be addressed in sudo without falling back to changing the system wide configuration.

For context, there is a command snap run --strace <app>, which will invoke strace on a app for the caller, but since a setuid binary (snap-confine) is included in the command chain, it's really calling sudo strace -u <target-user> .. under the hood. The output from strace is going directly to stderr in this case, unless the user explicitly passed -o to strace (eg. snap run --strace='-o myfile' <app>). Even after I identified that adding sudo would make the stderr output go weird, there was some head scratching involved when trying to guess why it's correct on Debian, Ubuntu (with sudo 1.9.13), but wrong on Fedora, Arch (with sudo 1.9.15). I obviously wanted to preserve the default behavior, and our own controlled --output was one of the options I considered, but that obviously came with more questions depending on whether the destination would be a file/fifo, cleanup, reading etc. Then piping stdout triggers the behavior I wanted.