From: finefoot <33361833+finefoot@users.noreply.github.com> Date: Sun, 21 Sep 2025 20:40:07 +0000 (+0200) Subject: runuser|su: elaborate man page regarding TIOCSTI/TIOCLINUX ioctl command injection X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2863ed62d77bb2bae5aecc2297236d440ad21c4d;p=thirdparty%2Futil-linux.git runuser|su: elaborate man page regarding TIOCSTI/TIOCLINUX ioctl command injection --- diff --git a/login-utils/runuser.1.adoc b/login-utils/runuser.1.adoc index 8402bfeac..392d4a8c4 100644 --- a/login-utils/runuser.1.adoc +++ b/login-utils/runuser.1.adoc @@ -34,6 +34,7 @@ Since version 2.38 *runuser* resets process resource limits RLIMIT_NICE, RLIMIT_ *-c*, *--command*=_command_:: Pass _command_ to the shell with the *-c* option. +Creates a new session via *setsid*(2). Refer to *--session-command* to keep the same session. *-f*, *--fast*:: Pass *-f* to the shell, which may or may not be useful, depending on the shell. @@ -56,7 +57,10 @@ Start the shell as a login shell with an environment similar to a real login: Preserve the entire environment, i.e., do not set *HOME*, *SHELL*, *USER* or *LOGNAME*. The option is ignored if the option *--login* is specified. *-P*, *--pty*:: -Create a pseudo-terminal for the session. The independent terminal provides better security as the user does not share a terminal with the original session. This can be used to avoid TIOCSTI ioctl terminal injection and other security attacks against terminal file descriptors. The entire session can also be moved to the background (e.g., *runuser --pty* *-u* _user_ *--* _command_ *&*). If the pseudo-terminal is enabled, then *runuser* works as a proxy between the sessions (sync stdin and stdout). +Create a pseudo-terminal for the session. The independent terminal provides better security as the user does not share a terminal with the original session. +Please note security advice about TIOCSTI vulnerability below. ++ +The entire session can also be moved to the background (e.g., *runuser --pty* *-u* _user_ *--* _command_ *&*). If the pseudo-terminal is enabled, then *runuser* works as a proxy between the sessions (sync stdin and stdout). + This feature is mostly designed for interactive sessions. If the standard input is not a terminal, but for example a pipe (e.g., *echo "date" | runuser --pty -u* _user_), then the *ECHO* flag for the pseudo-terminal is disabled to avoid messy output. @@ -72,10 +76,11 @@ If the target user has a restricted shell (i.e., not listed in _/etc/shells_), t **--session-command=**__command__:: Same as *-c*, but do not create a new session. (Discouraged.) +Please note security advice about TIOCSTI vulnerability below. *-T*, *--no-pty*:: Do not create a pseudo-terminal, opposite of *--pty* and *-P*. -Note that running without a pseudo-terminal opens the security risk of privilege escalation through TIOCSTI/TIOCLINUX ioctl command injection. +Please note security advice about TIOCSTI vulnerability below. *-u*, *--user*=_user_:: Run _command_ with the effective user ID and group ID of the user name _user_. @@ -129,6 +134,10 @@ runuser specific logindef config file _/etc/login.defs_:: global logindef config file +== SECURITY NOTES + +If *runuser* shares a terminal with the original session, it is potentially vulnerable to privilege escalation through TIOCSTI/TIOCLINUX ioctl command injection. There are two built-in ways to prevent this: Either you can use *runuser* with the *-c* option, which starts a new session via *setsid*(2) without a controlling terminal. Or, if your use case requires a controlling terminal, for example an interactive session, you can instruct *runuser* to use a pseudo terminal with the *--pty* or *-P* option. + == HISTORY This *runuser* command was derived from coreutils' *su*, which was based on an implementation by David MacKenzie, and the Fedora *runuser* command by Dan Walsh. diff --git a/login-utils/su.1.adoc b/login-utils/su.1.adoc index 22f0f1f56..8772bfe1f 100644 --- a/login-utils/su.1.adoc +++ b/login-utils/su.1.adoc @@ -35,6 +35,7 @@ Since version 2.38 *su* resets process resource limits RLIMIT_NICE, RLIMIT_RTPRI *-c*, *--command* __command__:: Pass _command_ to the shell with the *-c* option. +Creates a new session via *setsid*(2). Refer to *--session-command* to keep the same session. *-f*, *--fast*:: Pass *-f* to the shell, which may or may not be useful, depending on the shell. @@ -64,7 +65,10 @@ PAM) from this point of view. You need to use tools like *systemd-run*(1) or Preserve the entire environment, i.e., do not set *HOME*, *SHELL*, *USER* or *LOGNAME*. This option is ignored if the option *--login* is specified. *-P*, *--pty*:: -Create a pseudo-terminal for the session. The independent terminal provides better security as the user does not share a terminal with the original session. This can be used to avoid *TIOCSTI* ioctl terminal injection and other security attacks against terminal file descriptors. The entire session can also be moved to the background (e.g., *su --pty* **-** __user__ *-c* _application_ *&*). If the pseudo-terminal is enabled, then *su* works as a proxy between the sessions (sync stdin and stdout). +Create a pseudo-terminal for the session. The independent terminal provides better security as the user does not share a terminal with the original session. +Please note security advice about TIOCSTI vulnerability below. ++ +The entire session can also be moved to the background (e.g., *su --pty* **-** __user__ *-c* _application_ *&*). If the pseudo-terminal is enabled, then *su* works as a proxy between the sessions (sync stdin and stdout). + This feature is mostly designed for interactive sessions. If the standard input is not a terminal, but for example a pipe (e.g., *echo "date" | su --pty*), then the *ECHO* flag for the pseudo-terminal is disabled to avoid messy output. @@ -80,10 +84,11 @@ The shell to run is selected according to the following rules, in order: **--session-command=**__command__:: Same as *-c*, but do not create a new session. (Discouraged.) +Please note security advice about TIOCSTI vulnerability below. *-T*, *--no-pty*:: Do not create a pseudo-terminal, opposite of *--pty* and *-P*. -Note that running without a pseudo-terminal opens the security risk of privilege escalation through TIOCSTI/TIOCLINUX ioctl command injection. +Please note security advice about TIOCSTI vulnerability below. *-w*, *--whitelist-environment* __list__:: Don't reset the environment variables specified in the comma-separated _list_ when clearing the environment for *--login*. The whitelist is ignored for the environment variables *HOME*, *SHELL*, *USER*, *LOGNAME*, and *PATH*. @@ -141,7 +146,9 @@ command specific logindef config file _/etc/login.defs_:: global logindef config file -== NOTES +== SECURITY NOTES + +If *su* shares a terminal with the original session, it is potentially vulnerable to privilege escalation through TIOCSTI/TIOCLINUX ioctl command injection. There are two built-in ways to prevent this: Either you can use *su* with the *-c* option, which starts a new session via *setsid*(2) without a controlling terminal. Or, if your use case requires a controlling terminal, for example an interactive session, you can instruct *su* to use a pseudo terminal with the *--pty* or *-P* option. For security reasons, *su* always logs failed log-in attempts to the _btmp_ file, but it does not write to the _lastlog_ file at all. This solution can be used to control *su* behavior by PAM configuration. If you want to use the *pam_lastlog*(8) module to print warning message about failed log-in attempts then *pam_lastlog*(8) has to be configured to update the _lastlog_ file as well. For example by: