summaryrefslogtreecommitdiffstats
path: root/term-utils
diff options
context:
space:
mode:
authorSteven Smith2017-11-17 17:44:33 +0100
committerKarel Zak2017-11-21 10:54:39 +0100
commitd23597a88cdbdbc7f2a1c84cd6fe0b2ad9f7e87b (patch)
treecc2b29d1d0d0f0b8aeb1940efee0877917a2bef8 /term-utils
parentlibblkid: Mark char* params to blkid_dev_set_search as const (diff)
downloadkernel-qcow2-util-linux-d23597a88cdbdbc7f2a1c84cd6fe0b2ad9f7e87b.tar.gz
kernel-qcow2-util-linux-d23597a88cdbdbc7f2a1c84cd6fe0b2ad9f7e87b.tar.xz
kernel-qcow2-util-linux-d23597a88cdbdbc7f2a1c84cd6fe0b2ad9f7e87b.zip
agetty: Fix a use of uninitialised memory in an agetty error path.
get_logname() assumes that when it calls read() it initializes c and errno, which isn't always true if we hit a whitelisted error or end of file. This occasionally shows up as agetty going into an infinite loop. Fix it by just delaying ten seconds and exiting when things go wrong, similarly to the behavior after a non-whitelisted error. [kzak@redhat.com: - interpret readres == 0 as c = 0 - ignore speed configurations for VCONSOLE] Signed-off-by: Steven Smith <sos22@srcf.ucam.org> Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'term-utils')
-rw-r--r--term-utils/agetty.c25
1 files changed, 19 insertions, 6 deletions
diff --git a/term-utils/agetty.c b/term-utils/agetty.c
index 9763fcd30..844220401 100644
--- a/term-utils/agetty.c
+++ b/term-utils/agetty.c
@@ -317,6 +317,7 @@ static void termio_final(struct options *op,
static int caps_lock(char *s);
static speed_t bcode(char *s);
static void usage(void) __attribute__((__noreturn__));
+static void exit_slowly(int code) __attribute__((__noreturn__));
static void log_err(const char *, ...) __attribute__((__noreturn__))
__attribute__((__format__(printf, 1, 2)));
static void log_warn (const char *, ...)
@@ -1983,9 +1984,11 @@ static char *get_logname(struct options *op, struct termios *tp, struct chardata
while (cp->eol == '\0') {
char key;
+ ssize_t readres;
debug("read from FD\n");
- if (read(STDIN_FILENO, &c, 1) < 1) {
+ readres = read(STDIN_FILENO, &c, 1);
+ if (readres < 0) {
debug("read failed\n");
/* The terminal could be open with O_NONBLOCK when
@@ -2000,12 +2003,15 @@ static char *get_logname(struct options *op, struct termios *tp, struct chardata
case ESRCH:
case EINVAL:
case ENOENT:
- break;
+ exit_slowly(EXIT_SUCCESS);
default:
log_err(_("%s: read: %m"), op->tty);
}
}
+ if (readres == 0)
+ c = 0;
+
/* Do parity bit handling. */
if (eightbit)
ascval = c;
@@ -2030,8 +2036,10 @@ static char *get_logname(struct options *op, struct termios *tp, struct chardata
switch (key) {
case 0:
*bp = 0;
- if (op->numspeed > 1)
+ if (op->numspeed > 1 && !(op->flags & F_VCONSOLE))
return NULL;
+ if (readres == 0)
+ exit_slowly(EXIT_SUCCESS);
break;
case CR:
case NL:
@@ -2317,6 +2325,13 @@ static void dolog(int priority, const char *fmt, va_list ap)
#endif /* USE_SYSLOG */
}
+static void exit_slowly(int code)
+{
+ /* Be kind to init(8). */
+ sleep(10);
+ exit(code);
+}
+
static void log_err(const char *fmt, ...)
{
va_list ap;
@@ -2325,9 +2340,7 @@ static void log_err(const char *fmt, ...)
dolog(LOG_ERR, fmt, ap);
va_end(ap);
- /* Be kind to init(8). */
- sleep(10);
- exit(EXIT_FAILURE);
+ exit_slowly(EXIT_FAILURE);
}
static void log_warn(const char *fmt, ...)