From nobody Fri Nov 14 23:28:01 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1759230626; cv=none; d=zohomail.com; s=zohoarc; b=B2bisGpaD2oobZZ6i16A0muYK2ei6KwyB/NFfPQ4EtILX5xyFHTysvibtFfi/gqHFVEn3w2jG5/vm2sFy4cYoNFKyCnaN1kveO4XZqZkjC/18woMI7eGcxTPHF35Fg4IViQngdKl9WlIEd75NaWovUYDAs2v4WPhrzHm9+gC1Uk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1759230626; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=j1mCGF6Bwwkfd0T50pC6dG4iBUjt9f5lKksnanTgIdQ=; b=bMsnDmBBBFZvDU/EhP7m65mAanYNeMx2JvFpPmNmsm2hbCJccbTFWWyjjUpzRAIc/lXqB0U7m28H3tIJ6hz0pYamzKYrhYY2IybZ4QnKkT26aPWLmfUw++DyVgHJnlBwzCTJwmsh5X2X1Xo+29lQ3lmgUvbxYFenzFIPKPh2Fl0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1759230626173606.3726694976215; Tue, 30 Sep 2025 04:10:26 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v3YEN-0005y7-Nr; Tue, 30 Sep 2025 07:09:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1v3YEK-0005xr-S1 for qemu-devel@nongnu.org; Tue, 30 Sep 2025 07:09:12 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1v3YE0-0007ge-3A for qemu-devel@nongnu.org; Tue, 30 Sep 2025 07:09:12 -0400 Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-48-77byysIONG-1zpWHvPZL0w-1; Tue, 30 Sep 2025 07:08:40 -0400 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id D3164180048E; Tue, 30 Sep 2025 11:08:39 +0000 (UTC) Received: from toolbx.redhat.com (unknown [10.42.28.102]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 69BF819560B4; Tue, 30 Sep 2025 11:08:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1759230524; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=j1mCGF6Bwwkfd0T50pC6dG4iBUjt9f5lKksnanTgIdQ=; b=AUG38IRQk3CAnyf/pdiINPYQ5KW5PJ0fOJm5xXjqys+IZga3Q6kpl5TFH9hYs2vJMlK6F0 ZPAfY6sOB4yw6XUdoezBSRWLiqJdA1GylI4Uv0fT656Mc7621dZshSUtOw4vzbSF0L8qid rY/hKIKoBW8PprExDjAfJsc8EYisknU= X-MC-Unique: 77byysIONG-1zpWHvPZL0w-1 X-Mimecast-MFC-AGG-ID: 77byysIONG-1zpWHvPZL0w_1759230520 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , Grant Millar | Cylo , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Subject: [PATCH 1/2] io: move websock resource release to close method Date: Tue, 30 Sep 2025 12:08:33 +0100 Message-ID: <20250930110834.2551757-2-berrange@redhat.com> In-Reply-To: <20250930110834.2551757-1-berrange@redhat.com> References: <20250930110834.2551757-1-berrange@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=berrange@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -24 X-Spam_score: -2.5 X-Spam_bar: -- X-Spam_report: (-2.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.445, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1759230627606116601 The QIOChannelWebsock object releases all its resources in the finalize callback. This is too late, as callers expect to be able to call qio_channel_close() to fully close a channel and release resources related to I/O. Only releasing the underlying QIOChannel transport can be delayed until finalize. Furthermore the close callback must be robust against being called multiple times. Thus when moving the code we now clear the GSource ID using g_clear_handle_id. Signed-off-by: Daniel P. Berrang=C3=A9 --- io/channel-websock.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/io/channel-websock.c b/io/channel-websock.c index 0a8c5c4712..56d53355d5 100644 --- a/io/channel-websock.c +++ b/io/channel-websock.c @@ -919,16 +919,7 @@ static void qio_channel_websock_finalize(Object *obj) { QIOChannelWebsock *ioc =3D QIO_CHANNEL_WEBSOCK(obj); =20 - buffer_free(&ioc->encinput); - buffer_free(&ioc->encoutput); - buffer_free(&ioc->rawinput); object_unref(OBJECT(ioc->master)); - if (ioc->io_tag) { - g_source_remove(ioc->io_tag); - } - if (ioc->io_err) { - error_free(ioc->io_err); - } } =20 =20 @@ -1218,6 +1209,15 @@ static int qio_channel_websock_close(QIOChannel *ioc, QIOChannelWebsock *wioc =3D QIO_CHANNEL_WEBSOCK(ioc); =20 trace_qio_channel_websock_close(ioc); + buffer_free(&wioc->encinput); + buffer_free(&wioc->encoutput); + buffer_free(&wioc->rawinput); + if (wioc->io_tag) { + g_clear_handle_id(&wioc->io_tag, g_source_remove); + } + if (wioc->io_err) { + g_clear_pointer(&wioc->io_err, error_free); + } return qio_channel_close(wioc->master, errp); } =20 --=20 2.50.1 From nobody Fri Nov 14 23:28:01 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1759230627; cv=none; d=zohomail.com; s=zohoarc; b=Gx3ssrEdSzp7CF1fzf7aE5fFD5swbX7e1NGalX0BF9CphtqRp/W0ykpgEHn7baY3WH1I54ndn6HS7B3xkydZjkCzbqfjkWbeQkSTL9sWdwRGXKxz80n4gIGW0eEG2D3Si5kMphLZDKScqQpelowoUnHSQLkjKMTtSczdSwmM+Ds= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1759230627; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=WJ004NYdXAyPlxQNdz1jcbvRzHTnf1+4agR11jcuXJ8=; b=ERtOQlKdI0++xFHoYCJe1rAEt4hmQhI9MRGL4l+wAeBMigBPO3sLHZEadqCpZg1DWxBvW/c1x+6swOalkiZ9OMPDhwjxUzpToUtclrTOEdxdk/3BW3AMd8i4sgG+S09nmdVhApLvvbcaSJQ0m+OIEtrh8iqZHIC9uM2cFavNTss= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1759230627900999.8825123130837; Tue, 30 Sep 2025 04:10:27 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1v3YEN-0005yb-N3; Tue, 30 Sep 2025 07:09:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1v3YEK-0005xn-TF for qemu-devel@nongnu.org; Tue, 30 Sep 2025 07:09:13 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1v3YEA-0007hD-SG for qemu-devel@nongnu.org; Tue, 30 Sep 2025 07:09:11 -0400 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-190-4ezfv-RbO2OD8yjd8vHCIg-1; Tue, 30 Sep 2025 07:08:43 -0400 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 305E91800289; Tue, 30 Sep 2025 11:08:42 +0000 (UTC) Received: from toolbx.redhat.com (unknown [10.42.28.102]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 6CC4219560B4; Tue, 30 Sep 2025 11:08:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1759230528; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WJ004NYdXAyPlxQNdz1jcbvRzHTnf1+4agR11jcuXJ8=; b=NplDPOyrI5NpRk0N5vlcuHEXBD8uJtgzeXNbdN+wbFJDHEzF8JobURyayVBEFB+ayLCO2e ht4s87WLmJ3Og1r+hnR0LxW7NeFOELpuOIt387SB9H4twyb5gf06HTbsjdJ6yShEm3kBbg VgUbDO15/Bmqiu9EVtF5irvXVYaazgU= X-MC-Unique: 4ezfv-RbO2OD8yjd8vHCIg-1 X-Mimecast-MFC-AGG-ID: 4ezfv-RbO2OD8yjd8vHCIg_1759230522 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , Grant Millar | Cylo , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Subject: [PATCH 2/2] io: fix use after free in websocket handshake code Date: Tue, 30 Sep 2025 12:08:34 +0100 Message-ID: <20250930110834.2551757-3-berrange@redhat.com> In-Reply-To: <20250930110834.2551757-1-berrange@redhat.com> References: <20250930110834.2551757-1-berrange@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=berrange@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -24 X-Spam_score: -2.5 X-Spam_bar: -- X-Spam_report: (-2.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.445, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1759230629964116600 If the QIOChannelWebsock object is freed while it is waiting to complete a handshake, a GSource is leaked. This can lead to the callback firing later on and triggering a use-after-free in the use of the channel. This was observed in the VNC server with the following trace from valgrind: =3D=3D2523108=3D=3D Invalid read of size 4 =3D=3D2523108=3D=3D at 0x4054A24: vnc_disconnect_start (vnc.c:1296) =3D=3D2523108=3D=3D by 0x4054A24: vnc_client_error (vnc.c:1392) =3D=3D2523108=3D=3D by 0x4068A09: vncws_handshake_done (vnc-ws.c:105) =3D=3D2523108=3D=3D by 0x44863B4: qio_task_complete (task.c:197) =3D=3D2523108=3D=3D by 0x448343D: qio_channel_websock_handshake_io (chan= nel-websock.c:588) =3D=3D2523108=3D=3D by 0x6EDB862: UnknownInlinedFun (gmain.c:3398) =3D=3D2523108=3D=3D by 0x6EDB862: g_main_context_dispatch_unlocked.lto_p= riv.0 (gmain.c:4249) =3D=3D2523108=3D=3D by 0x6EDBAE4: g_main_context_dispatch (gmain.c:4237) =3D=3D2523108=3D=3D by 0x45EC79F: glib_pollfds_poll (main-loop.c:287) =3D=3D2523108=3D=3D by 0x45EC79F: os_host_main_loop_wait (main-loop.c:31= 0) =3D=3D2523108=3D=3D by 0x45EC79F: main_loop_wait (main-loop.c:589) =3D=3D2523108=3D=3D by 0x423A56D: qemu_main_loop (runstate.c:835) =3D=3D2523108=3D=3D by 0x454F300: qemu_default_main (main.c:37) =3D=3D2523108=3D=3D by 0x73D6574: (below main) (libc_start_call_main.h:5= 8) =3D=3D2523108=3D=3D Address 0x57a6e0dc is 28 bytes inside a block of size = 103,608 free'd =3D=3D2523108=3D=3D at 0x5F2FE43: free (vg_replace_malloc.c:989) =3D=3D2523108=3D=3D by 0x6EDC444: g_free (gmem.c:208) =3D=3D2523108=3D=3D by 0x4053F23: vnc_update_client (vnc.c:1153) =3D=3D2523108=3D=3D by 0x4053F23: vnc_refresh (vnc.c:3225) =3D=3D2523108=3D=3D by 0x4042881: dpy_refresh (console.c:880) =3D=3D2523108=3D=3D by 0x4042881: gui_update (console.c:90) =3D=3D2523108=3D=3D by 0x45EFA1B: timerlist_run_timers.part.0 (qemu-time= r.c:562) =3D=3D2523108=3D=3D by 0x45EFC8F: timerlist_run_timers (qemu-timer.c:495) =3D=3D2523108=3D=3D by 0x45EFC8F: qemu_clock_run_timers (qemu-timer.c:57= 6) =3D=3D2523108=3D=3D by 0x45EFC8F: qemu_clock_run_all_timers (qemu-timer.= c:663) =3D=3D2523108=3D=3D by 0x45EC765: main_loop_wait (main-loop.c:600) =3D=3D2523108=3D=3D by 0x423A56D: qemu_main_loop (runstate.c:835) =3D=3D2523108=3D=3D by 0x454F300: qemu_default_main (main.c:37) =3D=3D2523108=3D=3D by 0x73D6574: (below main) (libc_start_call_main.h:5= 8) =3D=3D2523108=3D=3D Block was alloc'd at =3D=3D2523108=3D=3D at 0x5F343F3: calloc (vg_replace_malloc.c:1675) =3D=3D2523108=3D=3D by 0x6EE2F81: g_malloc0 (gmem.c:133) =3D=3D2523108=3D=3D by 0x4057DA3: vnc_connect (vnc.c:3245) =3D=3D2523108=3D=3D by 0x448591B: qio_net_listener_channel_func (net-lis= tener.c:54) =3D=3D2523108=3D=3D by 0x6EDB862: UnknownInlinedFun (gmain.c:3398) =3D=3D2523108=3D=3D by 0x6EDB862: g_main_context_dispatch_unlocked.lto_p= riv.0 (gmain.c:4249) =3D=3D2523108=3D=3D by 0x6EDBAE4: g_main_context_dispatch (gmain.c:4237) =3D=3D2523108=3D=3D by 0x45EC79F: glib_pollfds_poll (main-loop.c:287) =3D=3D2523108=3D=3D by 0x45EC79F: os_host_main_loop_wait (main-loop.c:31= 0) =3D=3D2523108=3D=3D by 0x45EC79F: main_loop_wait (main-loop.c:589) =3D=3D2523108=3D=3D by 0x423A56D: qemu_main_loop (runstate.c:835) =3D=3D2523108=3D=3D by 0x454F300: qemu_default_main (main.c:37) =3D=3D2523108=3D=3D by 0x73D6574: (below main) (libc_start_call_main.h:5= 8) =3D=3D2523108=3D=3D The above can be reproduced by launching QEMU with $ qemu-system-x86_64 -vnc localhost:0,websocket=3D5700 and then repeatedly running: for i in {1..100}; do (echo -n "GET / HTTP/1.1" && sleep 0.05) | nc -w 1 localhost 5700 & done Reported-by: Grant Millar | Cylo Signed-off-by: Daniel P. Berrang=C3=A9 --- include/io/channel-websock.h | 1 + io/channel-websock.c | 16 ++++++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/include/io/channel-websock.h b/include/io/channel-websock.h index e180827c57..d1e760e449 100644 --- a/include/io/channel-websock.h +++ b/include/io/channel-websock.h @@ -61,6 +61,7 @@ struct QIOChannelWebsock { size_t payload_remain; size_t pong_remain; QIOChannelWebsockMask mask; + guint hs_io_tag; guint io_tag; Error *io_err; gboolean io_eof; diff --git a/io/channel-websock.c b/io/channel-websock.c index 56d53355d5..588c313dfb 100644 --- a/io/channel-websock.c +++ b/io/channel-websock.c @@ -597,7 +597,7 @@ static gboolean qio_channel_websock_handshake_io(QIOCha= nnel *ioc, error_propagate(&wioc->io_err, err); =20 trace_qio_channel_websock_handshake_reply(ioc); - qio_channel_add_watch( + wioc->hs_io_tag =3D qio_channel_add_watch( wioc->master, G_IO_OUT, qio_channel_websock_handshake_send, @@ -907,11 +907,12 @@ void qio_channel_websock_handshake(QIOChannelWebsock = *ioc, =20 trace_qio_channel_websock_handshake_start(ioc); trace_qio_channel_websock_handshake_pending(ioc, G_IO_IN); - qio_channel_add_watch(ioc->master, - G_IO_IN, - qio_channel_websock_handshake_io, - task, - NULL); + ioc->hs_io_tag =3D qio_channel_add_watch( + ioc->master, + G_IO_IN, + qio_channel_websock_handshake_io, + task, + NULL); } =20 =20 @@ -1212,6 +1213,9 @@ static int qio_channel_websock_close(QIOChannel *ioc, buffer_free(&wioc->encinput); buffer_free(&wioc->encoutput); buffer_free(&wioc->rawinput); + if (wioc->hs_io_tag) { + g_clear_handle_id(&wioc->hs_io_tag, g_source_remove); + } if (wioc->io_tag) { g_clear_handle_id(&wioc->io_tag, g_source_remove); } --=20 2.50.1