Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion src/su.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
#ifdef USE_PAM
#include "pam_defs.h"
#endif /* USE_PAM */
#include "io/fgets/fgets.h"
#include "pwauth.h"
#include "prototypes.h"
#include "shadowlog.h"
Expand Down Expand Up @@ -996,6 +997,29 @@ static void set_environment (struct passwd *pw)

}

/*
* See the following kernel commit:
* commit 83efeeeb3d04b22aaed1df99bc70a48fe9d22c4d
* Author: Kees Cook <kees@kernel.org>
* Date: Sat Oct 22 11:29:49 2022 -0700
* Subject: tty: Allow TIOCSTI to be disabled
*/
Comment on lines +1000 to +1006

@alejandro-colomar alejandro-colomar Jun 28, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about compacting that?:

// See linux.git 83efeeeb3d04 (2022-10-22; "tty: Allow TIOCSTI to be disabled")

static bool legacy_tiocsti_is_disabled(void) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move the brace to a new line (and optionally the type, but at least the brace).

char buf[3];
Comment thread
alejandro-colomar marked this conversation as resolved.
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 buf[0] == '0';

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to avoid all direct operations on bytes of strings. The good thing about str*() functions is that you can fortify them with _FORTIFY_SOURCE, and other niceties. They're also easier to grep(1).

I suggest using one of the following alternatives:

return streq(buf, "0\n");

return !!strspn(buf, "0");

@alejandro-colomar alejandro-colomar Jun 28, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer the former, because it also implicitly validates the rest of the string.

Maybe it would be interesting to validate and remove the newline explicitly separately:

if (stpspn(buf, "\n") == NULL)
	return false;

return streq(buf, "0");

This makes the streq() call more readable, while still validating the entire line.

}

/*
* su - switch user id
*
Expand All @@ -1010,6 +1034,7 @@ int main (int argc, char **argv)
{
const char *cp;
struct passwd *pw = NULL;
bool need_pty_prot;

#ifdef USE_PAM
int ret;
Expand All @@ -1023,6 +1048,8 @@ int main (int argc, char **argv)

save_caller_context();

need_pty_prot = caller_is_root && !legacy_tiocsti_is_disabled();

OPENLOG (Prog);

process_flags (argc, argv);
Expand Down Expand Up @@ -1152,7 +1179,7 @@ int main (int argc, char **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. */
Expand Down
Loading