We've long known (see
https://www.halfdog.net/Security/2012/TtyPushbackPrivilegeEscalation/
and https://jdebp.uk/FGA/dont-abuse-su-for-dropping-privileges.html)
that su should be used to gain but not drop privilege. Much more
recently, linux added the ability to prevent TIOCSTI through a
configurable /proc/sys/dev/tty/legacy_tiocsti setting.
If /proc/sys/dev/tty/legacy_tiocsti is set to 0, then we are protected
from the callee injecting commands on caller's tty through TIOCSTI.
If it's 1, or doesn't exist, then we are not. That can be dangerous
if caller is root. We currently give up the controlling terminal
for non-interactive uses of su (-c). Let's do that for interactive
calls as well, only in the dangerous case.
#ifdef USE_PAM
#include "pam_defs.h"
#endif /* USE_PAM */
+#include "io/fgets/fgets.h"
#include "pwauth.h"
#include "prototypes.h"
#include "shadowlog.h"
}
+// See linux.git 83efeeeb3d04 (2022-10-22; "tty: Allow TIOCSTI to be disabled")
+static bool legacy_tiocsti_is_disabled(void)
+{
+ char buf[3];
+ FILE *fp;
+ void *ret;
+
+ fp = fopen("/proc/sys/dev/tty/legacy_tiocsti", "r");
+ if (NULL == fp)
+ return false;
+ ret = fgets_a(buf, fp);
+ fclose(fp);
+ if (ret == NULL)
+ return false;
+
+ return streq(buf, "0\n");
+}
+
/*
* su - switch user id
*
{
const char *cp;
struct passwd *pw = NULL;
+ bool need_pty_prot;
#ifdef USE_PAM
int ret;
save_caller_context();
+ need_pty_prot = caller_is_root && !legacy_tiocsti_is_disabled();
+
OPENLOG (Prog);
process_flags (argc, argv);
set_environment (pw);
- if (!doshell) {
+ if (!doshell || need_pty_prot) {
/* There is no need for a controlling terminal.
* This avoids the callee to inject commands on
* the caller's tty. */