Bugzilla – Attachment 2875 Details for
Bug 2615
LoginGraceTime bypass (DoS)
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
watchdog process backing-up login_grace_time alarm
login_grace_time_watchdog.patch.txt (text/plain), 4.78 KB, created by
Tomas Kuthan
on 2016-09-15 22:56:57 AEST
(
hide
)
Description:
watchdog process backing-up login_grace_time alarm
Filename:
MIME Type:
Creator:
Tomas Kuthan
Created:
2016-09-15 22:56:57 AEST
Size:
4.78 KB
patch
obsolete
>From 3f21f2687b185b316170a9841fe0aff7e2d4a483 Mon Sep 17 00:00:00 2001 >From: Tomas Kuthan <tkuthan@gmail.com> >Date: Mon, 12 Sep 2016 13:19:02 +0200 >Subject: [PATCH] Implements watchdog process, which backs up login_grace_time > alarm. > >If the main process is hung in a syscall, SIGALRM is queued but not >delivered and the connection stays unauthenticated for too long. > >Function start_grace_watchdog forks of a watchdog process, that sends the >main process a SIGTERM, if it does neither authenticate nor exit before >(login_grace_time + GRACE_WATCHDOG_TRESHOLD). > >If the main process does not react to SIGTERM, SIGKILL is sent >after additional GRACE_WATCHDOG_TRESHOLD seconds. >--- > sshd.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 96 insertions(+), 1 deletion(-) > >diff --git a/sshd.c b/sshd.c >index 6d18223..7a78673 100644 >--- a/sshd.c >+++ b/sshd.c >@@ -241,10 +241,15 @@ Buffer loginmsg; > /* Unprivileged user */ > struct passwd *privsep_pw = NULL; > >+/* Pid of process backing up login_grace_time alarm. */ >+pid_t grace_watchdog_pid = -1; >+#define GRACE_WATCHDOG_TRESHOLD 10 >+ > /* Prototypes for various functions defined later in this file. */ > void destroy_sensitive_data(void); > void demote_sensitive_data(void); > static void do_ssh2_kex(void); >+static void stop_grace_watchdog(); > > /* > * Close all listening sockets >@@ -354,12 +359,98 @@ grace_alarm_handler(int sig) > signal(SIGTERM, SIG_IGN); > kill(0, SIGTERM); > } >+ stop_grace_watchdog(); > > /* Log error and exit. */ > sigdie("Timeout before authentication for %s port %d", > ssh_remote_ipaddr(active_state), ssh_remote_port(active_state)); > } > >+static inline void >+sleep_reliably(unsigned int seconds) >+{ >+ while (seconds > 0) >+ seconds = sleep(seconds); >+} >+ >+/* >+ * Implements watchdog process, which backs up login_grace_time alarm. >+ * >+ * If the main process is hung in a syscall, SIGALRM is queued but not >+ * delivered and the connection stays unauthenticated for too long. >+ * >+ * This function forks of a watchdog process, that sends the main process >+ * a SIGTERM, if it does neither authenticate nor exit before >+ * (login_grace_time + GRACE_WATCHDOG_TRESHOLD). >+ * If the main process does not react to SIGTERM, SIGKILL is sent after >+ * additional GRACE_WATCHDOG_TRESHOLD seconds. >+ */ >+static void >+start_grace_watchdog(int login_grace_time) >+{ >+ pid_t ppid; >+ >+ if (login_grace_time == 0) >+ return; >+ >+ if (grace_watchdog_pid != -1) { >+ error("login_grace_time watchdog process already running"); >+ return; >+ } >+ >+ grace_watchdog_pid = fork(); >+ if (grace_watchdog_pid == -1) >+ fatal("fork of login_grace_time watchdog process failed"); >+ else if (grace_watchdog_pid > 0) >+ return; >+ >+ /* child */ >+ ppid = getppid(); >+ >+ /* close open fds, including client socket and startup_pipe */ >+ closefrom(3); >+ >+ /* kill the monitor with SIGTERM after timeout + treshold */ >+ sleep_reliably(login_grace_time + GRACE_WATCHDOG_TRESHOLD); >+ if (getppid() != ppid) { >+ debug("login_grace_time watchdog still active, " >+ "but watched process %d already exited.", (int)ppid); >+ exit(0); >+ } >+ error("Timeout before authentication for %s. Killing process %d " >+ "with SIGTERM.", ssh_remote_ipaddr(active_state), (int)ppid); >+ kill(ppid, SIGTERM); >+ >+ /* if neccessary, kill it with SIGKILL */ >+ sleep_reliably(GRACE_WATCHDOG_TRESHOLD); >+ if (getppid() != ppid) >+ exit(0); >+ error("Watched process %d did not respond to SIGTERM. " >+ "Killing it with SIGKILL.", (int)ppid); >+ kill(ppid, SIGKILL); >+ >+ /* give up */ >+ sleep_reliably(GRACE_WATCHDOG_TRESHOLD); >+ if (getppid() == ppid) { >+ error("login_grace_time watchdog failed to kill %d", (int)ppid); >+ exit(255); >+ } >+ exit(0); >+} >+ >+/* kill grace watchdog process */ >+static void >+stop_grace_watchdog() >+{ >+ if (grace_watchdog_pid == -1) { >+ debug3("login_grace_time watchdog process not running"); >+ return; >+ } >+ >+ kill(grace_watchdog_pid, SIGTERM); >+ grace_watchdog_pid = -1; >+} >+ > static void > sshd_exchange_identification(struct ssh *ssh, int sock_in, int sock_out) > { >@@ -608,6 +699,7 @@ privsep_preauth(Authctxt *authctxt) > /* child */ > close(pmonitor->m_sendfd); > close(pmonitor->m_log_recvfd); >+ grace_watchdog_pid = -1; > > /* Arrange for logging to be sent to the monitor */ > set_log_handler(mm_log_handler, pmonitor); >@@ -1989,8 +2081,10 @@ main(int ac, char **av) > * are about to discover the bug. > */ > signal(SIGALRM, grace_alarm_handler); >- if (!debug_flag) >+ if (!debug_flag) { > alarm(options.login_grace_time); >+ start_grace_watchdog(options.login_grace_time); >+ } > > sshd_exchange_identification(ssh, sock_in, sock_out); > packet_set_nonblocking(); >@@ -2038,6 +2132,7 @@ main(int ac, char **av) > */ > alarm(0); > signal(SIGALRM, SIG_DFL); >+ stop_grace_watchdog(); > authctxt->authenticated = 1; > if (startup_pipe != -1) { > close(startup_pipe); >-- >2.7.4 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 2615
: 2875