]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
login: fix signal race
authorTobias Stoeckmann <tobias@stoeckmann.org>
Mon, 25 Sep 2017 19:54:11 +0000 (21:54 +0200)
committerKarel Zak <kzak@redhat.com>
Tue, 26 Sep 2017 10:03:24 +0000 (12:03 +0200)
The functions warnx(3) and gettext(3) are not safe to use within signal
handlers and should be avoided. Preparing the message beforehand and
calling write(2) as well as calling _exit(2) solves the problem.

[kzak@redhat.com: - use program_invocation_short_name rather than argv[0],
                  - use ignore_result() to keep compiler happy]

Signed-off-by: Karel Zak <kzak@redhat.com>
login-utils/login.c

index 7f311536efa1774bd47cf1233774591fd5fd3ead..ae0d66d0a78502af39e6e286269a1e2172ee899d 100644 (file)
@@ -139,6 +139,7 @@ struct login_context {
 static unsigned int timeout = LOGIN_TIMEOUT;
 static int child_pid = 0;
 static volatile int got_sig = 0;
+static char timeout_msg[128];
 
 #ifdef LOGIN_CHOWN_VCS
 /* true if the filedescriptor fd is a console tty, very Linux specific */
@@ -174,15 +175,14 @@ timedout2(int sig __attribute__ ((__unused__)))
        tcgetattr(0, &ti);
        ti.c_lflag |= ECHO;
        tcsetattr(0, TCSANOW, &ti);
-       exit(EXIT_SUCCESS);     /* %% */
+       _exit(EXIT_SUCCESS);    /* %% */
 }
 
 static void timedout(int sig __attribute__ ((__unused__)))
 {
        signal(SIGALRM, timedout2);
        alarm(10);
-       /* TRANSLATORS: The standard value for %u is 60. */
-       warnx(_("timed out after %u seconds"), timeout);
+       ignore_result( write(STDERR_FILENO, timeout_msg, strlen(timeout_msg)) );
        signal(SIGALRM, SIG_IGN);
        alarm(0);
        timedout2(0);
@@ -1134,6 +1134,15 @@ int main(int argc, char **argv)
 
        timeout = (unsigned int)getlogindefs_num("LOGIN_TIMEOUT", LOGIN_TIMEOUT);
 
+       setlocale(LC_ALL, "");
+       bindtextdomain(PACKAGE, LOCALEDIR);
+       textdomain(PACKAGE);
+
+       /* TRANSLATORS: The standard value for %u is 60. */
+       snprintf(timeout_msg, sizeof(timeout_msg),
+           _("%s: timed out after %u seconds"),
+           program_invocation_short_name, timeout);
+
        signal(SIGALRM, timedout);
        (void) sigaction(SIGALRM, NULL, &act);
        act.sa_flags &= ~SA_RESTART;
@@ -1142,10 +1151,6 @@ int main(int argc, char **argv)
        signal(SIGQUIT, SIG_IGN);
        signal(SIGINT, SIG_IGN);
 
-       setlocale(LC_ALL, "");
-       bindtextdomain(PACKAGE, LOCALEDIR);
-       textdomain(PACKAGE);
-
        setpriority(PRIO_PROCESS, 0, 0);
        initproctitle(argc, argv);