]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
login: prevent undefined ioctl and tcsetattr calls
authorTobias Stoeckmann <tobias@stoeckmann.org>
Thu, 21 Sep 2023 18:25:55 +0000 (20:25 +0200)
committerTobias Stoeckmann <tobias@stoeckmann.org>
Thu, 21 Sep 2023 20:36:54 +0000 (22:36 +0200)
Do not call tcsetattr if tcgetattr fails, because the content of
tt and ttt is undefined in that case.

Also do not just warn if ioctl fails, but also avoid calling it again
after tty has been re-opened.

I've solved this by setting struct variables to values which cannot be
valid at this point. If they do have these exact values, then the
calls will be prevented.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
login-utils/login.c

index 31a7adb07bc404a912a4c3f4fade4e08b52bc3c4..544eab5aaa5d4224f211c3536765d091af4c8b0b 100644 (file)
@@ -177,9 +177,10 @@ static void __attribute__((__noreturn__))
        struct termios ti;
 
        /* reset echo */
-       tcgetattr(0, &ti);
-       ti.c_lflag |= ECHO;
-       tcsetattr(0, TCSANOW, &ti);
+       if (tcgetattr(0, &ti) >= 0) {
+               ti.c_lflag |= ECHO;
+               tcsetattr(0, TCSANOW, &ti);
+       }
        _exit(EXIT_SUCCESS);    /* %% */
 }
 
@@ -513,8 +514,8 @@ static void chown_tty(struct login_context *cxt)
 static void init_tty(struct login_context *cxt)
 {
        struct stat st;
-       struct termios tt, ttt;
-       struct winsize ws;
+       struct termios tt, ttt = { 0 };
+       struct winsize ws = { 0 };
        int fd;
 
        cxt->tty_mode = (mode_t) getlogindefs_num("TTYPERM", TTY_MODE);
@@ -549,13 +550,18 @@ 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(fd, TIOCGWINSZ, &ws) < 0)
+       if (ioctl(fd, TIOCGWINSZ, &ws) < 0) {
                syslog(LOG_WARNING, _("TIOCGWINSZ ioctl failed: %m"));
+               ws.ws_row = 0;
+               ws.ws_col = 0;
+       }
 
-       tcgetattr(fd, &tt);
-       ttt = tt;
-       ttt.c_cflag &= ~HUPCL;
+       if (tcgetattr(fd, &tt) >= 0) {
+               ttt = tt;
+               ttt.c_cflag &= ~HUPCL;
+       } else {
+               ttt.c_cflag = HUPCL;
+       }
 
        if ((fchown(fd, 0, 0) || fchmod(fd, cxt->tty_mode)) && errno != EROFS) {
 
@@ -565,7 +571,8 @@ static void init_tty(struct login_context *cxt)
        }
 
        /* Kill processes left on this tty */
-       tcsetattr(fd, TCSANOW, &ttt);
+       if ((ttt.c_cflag & HUPCL) == 0)
+               tcsetattr(fd, TCSANOW, &ttt);
 
        /*
         * Let's close file descriptors before vhangup
@@ -583,7 +590,8 @@ static void init_tty(struct login_context *cxt)
        open_tty(cxt->tty_path);
 
        /* restore tty modes */
-       tcsetattr(STDIN_FILENO, TCSAFLUSH, &tt);
+       if ((ttt.c_cflag & HUPCL) == 0)
+               tcsetattr(STDIN_FILENO, TCSAFLUSH, &tt);
 
        /* Restore tty size */
        if ((ws.ws_row > 0 || ws.ws_col > 0)