File util-linux-sulogin4bsc1175514.patch of Package util-linux.12160
From: Werner Fink <werner@suse.de>
Date: Fri, 30 Oct 2020 14:54:59 +0100
Subject: [PATCH] sulogin: ignore not existing console devices
and also not functional console devices. Redirect the error
messages to the appropiate console device.
---
login-utils/sulogin-consoles.h | 1 +
login-utils/sulogin.c | 97 +++++++++++++++++++++++++++++++++++-------
2 files changed, 82 insertions(+), 16 deletions(-)
Index: util-linux-2.28/login-utils/sulogin-consoles.h
===================================================================
--- util-linux-2.28.orig/login-utils/sulogin-consoles.h
+++ util-linux-2.28/login-utils/sulogin-consoles.h
@@ -40,6 +40,7 @@ struct console {
int fd, id;
#define CON_SERIAL 0x0001
#define CON_NOTTY 0x0002
+#define CON_EIO 0x0004
pid_t pid;
struct chardata cp;
struct termios tio;
Index: util-linux-2.28/login-utils/sulogin.c
===================================================================
--- util-linux-2.28.orig/login-utils/sulogin.c
+++ util-linux-2.28/login-utils/sulogin.c
@@ -52,6 +52,7 @@
#ifdef __linux__
# include <sys/kd.h>
# include <sys/param.h>
+# include <linux/serial.h>
#endif
#include "c.h"
@@ -137,6 +138,9 @@ static void tcinit(struct console *con)
struct termios *tio = &con->tio;
struct termios lock;
int fd = con->fd;
+#if defined(TIOCGSERIAL)
+ struct serial_struct serinfo;
+#endif
#ifdef TIOCGLCKTRMIOS
int i = (plymouth_command("--ping")) ? 20 : 0;
@@ -156,28 +160,72 @@ static void tcinit(struct console *con)
}
memset(&lock, 0, sizeof(struct termios));
ioctl(fd, TIOCSLCKTRMIOS, &lock);
+ errno = 0;
#endif
+#if defined(TIOCGSERIAL)
+ if (ioctl(fd, TIOCGSERIAL, &serinfo) >= 0)
+ con->flags |= CON_SERIAL;
+ errno = 0;
+#else
+# if defined(KDGKBMODE)
+ if (ioctl(fd, KDGKBMODE, &mode) < 0)
+ con->flags |= CON_SERIAL;
errno = 0;
+# endif
+#endif
if (tcgetattr(fd, tio) < 0) {
- warn(_("tcgetattr failed"));
- con->flags |= CON_NOTTY;
- return;
+ int saveno = errno;
+#if defined(KDGKBMODE) || defined(TIOCGSERIAL)
+ if (con->flags & CON_SERIAL) { /* Try to recover this */
+
+# if defined(TIOCGSERIAL)
+ serinfo.flags |= ASYNC_SKIP_TEST; /* Skip test of UART */
+
+ if (ioctl(fd, TIOCSSERIAL, &serinfo) < 0)
+ goto tcgeterr;
+ if (ioctl(fd, TIOCSERCONFIG) < 0) /* Try to autoconfigure */
+ goto tcgeterr;
+ if (ioctl(fd, TIOCGSERIAL, &serinfo) < 0)
+ goto tcgeterr; /* Ouch */
+# endif
+ if (tcgetattr(fd, tio) < 0) /* Retry to get tty attributes */
+ saveno = errno;
+ }
+# if defined(TIOCGSERIAL)
+ tcgeterr:
+# endif
+ if (saveno)
+#endif
+ {
+ FILE *fcerr = fdopen(fd, "w");
+ if (fcerr) {
+ fprintf(fcerr, _("tcgetattr failed"));
+ fclose(fcerr);
+ }
+ warn(_("tcgetattr failed"));
+
+ con->flags &= ~CON_SERIAL;
+ if (saveno != EIO)
+ con->flags |= CON_NOTTY;
+ else
+ con->flags |= CON_EIO;
+
+ errno = 0;
+ return;
+ }
}
/* Handle lines other than virtual consoles here */
-#if defined(KDGKBMODE)
- if (ioctl(fd, KDGKBMODE, &mode) < 0)
+#if defined(KDGKBMODE) || defined(TIOCGSERIAL)
+ if (con->flags & CON_SERIAL)
#endif
{
speed_t ispeed, ospeed;
struct winsize ws;
errno = 0;
- /* this is a modem line */
- con->flags |= CON_SERIAL;
-
/* Flush input and output queues on modem lines */
tcflush(fd, TCIOFLUSH);
@@ -253,6 +301,8 @@ static void tcfinal(struct console *con)
struct termios *tio;
int fd;
+ if (con->flags & CON_EIO)
+ return;
if ((con->flags & CON_SERIAL) == 0) {
setenv("TERM", "linux", 1);
return;
@@ -594,8 +644,6 @@ static void setup(struct console *con)
pid_t pid, pgrp, ppgrp, ttypgrp;
int fd;
- if (con->flags & CON_NOTTY)
- return;
fd = con->fd;
/*
@@ -605,6 +653,10 @@ static void setup(struct console *con)
pid = getpid();
pgrp = getpgid(0);
ppgrp = getpgid(getppid());
+ if (con->flags & CON_NOTTY)
+ goto notty;
+ if (con->flags & CON_EIO)
+ return;
ttypgrp = tcgetpgrp(fd);
if (pgrp != ttypgrp && ppgrp != ttypgrp) {
@@ -625,6 +677,7 @@ static void setup(struct console *con)
ioctl(fd, TIOCSCTTY, (char *)1);
tcsetpgrp(fd, ppgrp);
}
+notty:
dup2(fd, STDIN_FILENO);
dup2(fd, STDOUT_FILENO);
dup2(fd, STDERR_FILENO);
@@ -648,21 +701,26 @@ static char *getpasswd(struct console *c
struct termios tty;
static char pass[128], *ptr;
struct chardata *cp;
- char *ret = pass;
+ char *ret = NULL;
unsigned char tc;
char c, ascval;
int eightbit;
int fd;
- if (con->flags & CON_NOTTY)
+ if (con->flags & CON_EIO)
goto out;
+
fd = con->fd;
cp = &con->cp;
tty = con->tio;
+ tc = 0;
+ ret = pass;
tty.c_iflag &= ~(IUCLC|IXON|IXOFF|IXANY);
tty.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|TOSTOP|ISIG);
- tc = (tcsetattr(fd, TCSAFLUSH, &tty) == 0);
+
+ if ((con->flags & CON_NOTTY) == 0)
+ tc = (tcsetattr(fd, TCSAFLUSH, &tty) == 0);
sigemptyset(&sa.sa_mask);
sa.sa_handler = alrm_handler;
@@ -684,11 +742,12 @@ static char *getpasswd(struct console *c
}
ret = (char*)0;
switch (errno) {
- case 0:
case EIO:
+ con->flags |= CON_EIO;
case ESRCH:
case EINVAL:
case ENOENT:
+ case 0:
break;
default:
warn(_("cannot read %s"), con->tty);
@@ -811,7 +870,7 @@ static void sushell(struct passwd *pwd)
#ifdef HAVE_LIBSELINUX
if (is_selinux_enabled() > 0) {
- security_context_t scon=NULL;
+ char *scon=NULL;
char *seuser=NULL;
char *level=NULL;
if (getseuserbyname("root", &seuser, &level) == 0) {
@@ -981,6 +1040,8 @@ int main(int argc, char **argv)
con = list_entry(ptr, struct console, entry);
if (con->id >= CONMAX)
break;
+ if (con->flags & CON_EIO)
+ goto next;
if (con->fd >= 0) {
openfd |= (1 << con->fd);
tcinit(con);
@@ -1008,6 +1069,7 @@ int main(int argc, char **argv)
switch ((con->pid = fork())) {
case 0:
mask_signal(SIGCHLD, SIG_DFL, NULL);
+ dup2(con->fd, STDERR_FILENO);
/* fall through */
nofork:
setup(con);
@@ -1065,7 +1127,7 @@ int main(int argc, char **argv)
default:
break;
}
-
+ next:
ptr = ptr->next;
} while (ptr != &consoles);