MINOR: ssl/show_fd: report some FDs as suspicious when possible

If a subscriber's tasklet was called more than one million times, if
the ssl_ctx's connection doesn't match the current one, or if the
connection appears closed in one direction while the SSL stack is
still subscribed, the FD is reported as suspicious. The close cases
may occasionally trigger a false positive during very short and rare
windows. Similarly the 1M calls will trigger after 16GB are transferred
over a given connection. These are rare enough events to be reported as
suspicious.

(cherry picked from commit 4bd5d630ace94ee6b4cbb7375ec75f50a927a826)
Signed-off-by: Willy Tarreau <w@1wt.eu>
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index 8f3159f..eb8f052 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -6247,17 +6247,20 @@
 #endif
 
 /* "show fd" helper to dump ssl internals. Warning: the output buffer is often
- * the common trash!
+ * the common trash! It returns non-zero if the connection entry looks suspicious.
  */
 static int ssl_sock_show_fd(struct buffer *buf, const struct connection *conn, const void *ctx)
 {
 	const struct ssl_sock_ctx *sctx = ctx;
+	int ret = 0;
 
 	if (!sctx)
-		return 0;
+		return ret;
 
-	if (sctx->conn != conn)
-		chunk_appendf(&trash, " xctx.conn=%p(BOGUS!)", sctx->conn);
+	if (sctx->conn != conn) {
+		chunk_appendf(&trash, " xctx.conn=%p(BOGUS)", sctx->conn);
+		ret = 1;
+	}
 	chunk_appendf(&trash, " xctx.st=%d", sctx->xprt_st);
 
 	if (sctx->xprt) {
@@ -6267,9 +6270,21 @@
 	}
 
 	chunk_appendf(&trash, " .wait.ev=%d", sctx->wait_event.events);
+
+	/* as soon as a shutdown is reported the lower layer unregisters its
+	 * subscriber, so the situations below are transient and rare enough to
+	 * be reported as suspicious. In any case they shouldn't last.
+	 */
+	if ((sctx->wait_event.events & 1) && (conn->flags & (CO_FL_SOCK_RD_SH|CO_FL_ERROR)))
+		ret = 1;
+	if ((sctx->wait_event.events & 2) && (conn->flags & (CO_FL_SOCK_WR_SH|CO_FL_ERROR)))
+		ret = 1;
+
 	chunk_appendf(&trash, " .subs=%p", sctx->subs);
 	if (sctx->subs) {
 		chunk_appendf(&trash, "(ev=%d tl=%p", sctx->subs->events, sctx->subs->tasklet);
+		if (sctx->subs->tasklet->calls >= 1000000)
+			ret = 1;
 		chunk_appendf(&trash, " tl.calls=%d tl.ctx=%p tl.fct=",
 			      sctx->subs->tasklet->calls,
 			      sctx->subs->tasklet->context);
@@ -6278,7 +6293,7 @@
 	}
 	chunk_appendf(&trash, " .sent_early=%d", sctx->sent_early_data);
 	chunk_appendf(&trash, " .early_in=%d", (int)sctx->early_buf.data);
-	return 0;
+	return ret;
 }
 
 /* This function is used with TLS ticket keys management. It permits to browse