105 lines
3.2 KiB
Diff
105 lines
3.2 KiB
Diff
From f7feb6530b5e350c9aa635d7f39110177e34fb83 Mon Sep 17 00:00:00 2001
|
|
From: Tobias Stoeckmann <tobias@stoeckmann.org>
|
|
Date: Thu, 21 Sep 2023 20:15:46 +0200
|
|
Subject: [PATCH] login: use correct terminal fd during setup
|
|
|
|
The function get_terminal_name iterates through standard file
|
|
descriptors until it finds a terminal. This means that it's not
|
|
guaranteed that STDIN_FILENO (i.e. 0) is actually a terminal.
|
|
|
|
Do not modify permissions on possible files. Instead, retrieve
|
|
the file descriptor which was used by get_terminal_name as well.
|
|
|
|
Proof of Concept (as root):
|
|
|
|
1. Create a temporary file with a mode different than TTYPERM.
|
|
```
|
|
install -m 700 /dev/null /tmp/test
|
|
ls -l /tmp/test
|
|
-rwx------ 1 root root 0 Sep 21 20:15 /tmp/test
|
|
```
|
|
|
|
2. Run login within a terminal with adjusted stdin.
|
|
```
|
|
login < /tmp/test
|
|
host login:
|
|
Hangup
|
|
```
|
|
|
|
3. Check permissions of input file.
|
|
```
|
|
ls -l /tmp/test
|
|
-rw------- 1 root root 0 Sep 21 20:15 /tmp/test
|
|
```
|
|
|
|
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
|
|
---
|
|
login-utils/login.c | 14 ++++++++------
|
|
1 file changed, 8 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/login-utils/login.c b/login-utils/login.c
|
|
index 2a4e8cb..d6c6af7 100644
|
|
--- a/login-utils/login.c
|
|
+++ b/login-utils/login.c
|
|
@@ -514,10 +514,12 @@ static void init_tty(struct login_context *cxt)
|
|
struct stat st;
|
|
struct termios tt, ttt;
|
|
struct winsize ws;
|
|
+ int fd;
|
|
|
|
cxt->tty_mode = (mode_t) getlogindefs_num("TTYPERM", TTY_MODE);
|
|
|
|
get_terminal_name(&cxt->tty_path, &cxt->tty_name, &cxt->tty_number);
|
|
+ fd = get_terminal_stdfd();
|
|
|
|
/*
|
|
* In case login is suid it was possible to use a hardlink as stdin
|
|
@@ -530,7 +532,7 @@ static void init_tty(struct login_context *cxt)
|
|
if (!cxt->tty_path || !*cxt->tty_path ||
|
|
lstat(cxt->tty_path, &st) != 0 || !S_ISCHR(st.st_mode) ||
|
|
(st.st_nlink > 1 && strncmp(cxt->tty_path, "/dev/", 5) != 0) ||
|
|
- access(cxt->tty_path, R_OK | W_OK) != 0) {
|
|
+ access(cxt->tty_path, R_OK | W_OK) != 0 || fd == -EINVAL) {
|
|
|
|
syslog(LOG_ERR, _("FATAL: bad tty"));
|
|
sleepexit(EXIT_FAILURE);
|
|
@@ -547,14 +549,14 @@ static void init_tty(struct login_context *cxt)
|
|
/* The TTY size might be reset to 0x0 by the kernel when we close the stdin/stdout/stderr file
|
|
* descriptors so let's save the size now so we can reapply it later */
|
|
memset(&ws, 0, sizeof(struct winsize));
|
|
- if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) < 0)
|
|
+ if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
|
|
syslog(LOG_WARNING, _("TIOCGWINSZ ioctl failed: %m"));
|
|
|
|
- tcgetattr(0, &tt);
|
|
+ tcgetattr(fd, &tt);
|
|
ttt = tt;
|
|
ttt.c_cflag &= ~HUPCL;
|
|
|
|
- if ((fchown(0, 0, 0) || fchmod(0, cxt->tty_mode)) && errno != EROFS) {
|
|
+ if ((fchown(fd, 0, 0) || fchmod(fd, cxt->tty_mode)) && errno != EROFS) {
|
|
|
|
syslog(LOG_ERR, _("FATAL: %s: change permissions failed: %m"),
|
|
cxt->tty_path);
|
|
@@ -562,7 +564,7 @@ static void init_tty(struct login_context *cxt)
|
|
}
|
|
|
|
/* Kill processes left on this tty */
|
|
- tcsetattr(0, TCSANOW, &ttt);
|
|
+ tcsetattr(fd, TCSANOW, &ttt);
|
|
|
|
/*
|
|
* Let's close file descriptors before vhangup
|
|
@@ -580,7 +582,7 @@ static void init_tty(struct login_context *cxt)
|
|
open_tty(cxt->tty_path);
|
|
|
|
/* restore tty modes */
|
|
- tcsetattr(0, TCSAFLUSH, &tt);
|
|
+ tcsetattr(STDIN_FILENO, TCSAFLUSH, &tt);
|
|
|
|
/* Restore tty size */
|
|
if (ws.ws_row > 0 || ws.ws_col > 0)
|
|
--
|
|
2.33.0
|
|
|