diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c index 000861c1..333db4c9 100644 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -2117,6 +2117,38 @@ libwebsocket_ensure_user_space(struct libwebsocket *wsi) return wsi->user_space; } +/** + * lws_confirm_legit_wsi: returns nonzero if the wsi looks bad + * + * @wsi: struct libwebsocket to assess + * + * Performs consistecy checks on what the wsi claims and what the + * polling arrays hold. This'll catch a closed wsi still in use. + * Don't try to use on the listen (nonconnection) wsi as it will + * fail it. Otherwise 0 return == wsi seems consistent. + */ + +int lws_confirm_legit_wsi(struct libwebsocket *wsi) +{ + struct libwebsocket_context *context; + + if (!(wsi && wsi->protocol && wsi->protocol->owning_server)) + return 1; + + context = wsi->protocol->owning_server; + + if (!context) + return 2; + + if (!wsi->position_in_fds_table) + return 3; /* position in fds table looks bad */ + if (context->fds[wsi->position_in_fds_table].fd != wsi->sock) + return 4; /* pollfd entry does not wait on our socket descriptor */ + if (context->lws_lookup[wsi->sock] != wsi) + return 5; /* lookup table does not agree with wsi */ + + return 0; +} static void lwsl_emit_stderr(const char *line) { diff --git a/lib/output.c b/lib/output.c index 68fd312d..eff467c9 100644 --- a/lib/output.c +++ b/lib/output.c @@ -295,6 +295,10 @@ int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf, struct lws_tokens eff_buf; int m; + if (lws_confirm_legit_wsi(wsi)) { + lwsl_err("libwebsocket_write on illegitimate wsi\n"); + return -1; + } if (len == 0 && protocol != LWS_WRITE_CLOSE) { lwsl_warn("zero length libwebsocket_write attempt\n"); return 0; diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index 4f6400df..a3047f77 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -491,6 +491,9 @@ lws_issue_raw_ext_access(struct libwebsocket *wsi, extern int _libwebsocket_rx_flow_control(struct libwebsocket *wsi); +extern int +lws_confirm_legit_wsi(struct libwebsocket *wsi); + extern int user_callback_handle_rxflow(callback_function, struct libwebsocket_context * context, struct libwebsocket *wsi, diff --git a/libwebsockets-api-doc.html b/libwebsockets-api-doc.html index 73aefe8f..6acd4f39 100644 --- a/libwebsockets-api-doc.html +++ b/libwebsockets-api-doc.html @@ -350,6 +350,23 @@ having to take any care about data visibility between the processes, it'll "just work".
+Performs consistecy checks on what the wsi claims and what the +polling arrays hold. This'll catch a closed wsi still in use. +Don't try to use on the listen (nonconnection) wsi as it will +fail it. Otherwise 0 return == wsi seems consistent. ++