From 21c386860f1973344872eec4e4dd68644b1b48aa Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Fri, 10 Mar 2023 11:15:19 +0000 Subject: [PATCH] ktls: Do not return GNUTLS_E_INTERRUPTED/AGAIN from short writes If sendmsg returns a short write, we end up going around the loop with data_to_send being smaller. However if sendmsg then returns -EAGAIN or -EINTR then we return an error. But we have "forgotten" that we already sent some data. This causes the caller to retry gnutls_record_send with the full buffer (ie. with a buffer that has already been partially sent), causing desynchronization. Instead check if we sent some data in this case and return the number of bytes sent. Fixes: https://gitlab.com/gnutls/gnutls/-/issues/1470 Thanks: Dan Berrange for suggesting a fix Signed-off-by: Richard W.M. Jones --- lib/system/ktls.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/system/ktls.c b/lib/system/ktls.c index fd57a9c30..bb59fab7c 100644 --- a/lib/system/ktls.c +++ b/lib/system/ktls.c @@ -604,9 +604,17 @@ int _gnutls_ktls_send_control_msg(gnutls_session_t session, if (ret == -1) { switch (errno) { case EINTR: - return GNUTLS_E_INTERRUPTED; + if (data_to_send < data_size) { + return data_size - data_to_send; + } else { + return GNUTLS_E_INTERRUPTED; + } case EAGAIN: - return GNUTLS_E_AGAIN; + if (data_to_send < data_size) { + return data_size - data_to_send; + } else { + return GNUTLS_E_AGAIN; + } default: return GNUTLS_E_PUSH_ERROR; } -- 2.39.2