From nobody Sun Feb 8 20:58:09 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1648455851; cv=none; d=zohomail.com; s=zohoarc; b=B2BJkLq/NFQUXNUAvtRwxu9wRJ96y/15DUj3STDO9uRWl5sBd3g3TAc+UbEaCM/45OWyLkgvc9MtS3JiDRuboFGLxWZZRwBhycy2K5RHCo/tX9VWo2oVZANTBP2Le3IY8lFzzLABAT7vMIUueC9bj/ggL1Q3IEQb9CUTmAXdOAE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1648455851; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Sender:Subject:To; bh=1A+bkRpPOIxZemodG+d/wB/y34+LbR+LvOXldKOSbNk=; b=eJJr8j7ir/35BTvudNKUcu53jXRR+EXMSLyxORJp4hzMZkwBk/M9SZynt7HWQMgZfCQzslY51cpX4zuAQJksvk1mLje1ITAtNlEh57x5f06sNes3/18zhfUJUnMLxHch7ePcLq1fmSOrGZfFhUZu1FTp+7lPvTArG5qS0em9ep4= ARC-Authentication-Results: i=1; mx.zohomail.com; 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=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1648455851287838.7172236663837; Mon, 28 Mar 2022 01:24:11 -0700 (PDT) Received: from localhost ([::1]:46284 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nYkfZ-0006dd-Hj for importer@patchew.org; Mon, 28 Mar 2022 04:24:09 -0400 Received: from eggs.gnu.org ([209.51.188.92]:52204) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nYke2-0005xC-0o for qemu-devel@nongnu.org; Mon, 28 Mar 2022 04:22:34 -0400 Received: from szxga08-in.huawei.com ([45.249.212.255]:3861) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nYkdx-0007xv-T4 for qemu-devel@nongnu.org; Mon, 28 Mar 2022 04:22:33 -0400 Received: from kwepemi500022.china.huawei.com (unknown [172.30.72.53]) by szxga08-in.huawei.com (SkyGuard) with ESMTP id 4KRlzS3W4Xz1GDGr; Mon, 28 Mar 2022 16:21:56 +0800 (CST) Received: from kwepemm600015.china.huawei.com (7.193.23.52) by kwepemi500022.china.huawei.com (7.221.188.64) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.24; Mon, 28 Mar 2022 16:22:11 +0800 Received: from localhost (10.174.149.172) by kwepemm600015.china.huawei.com (7.193.23.52) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.21; Mon, 28 Mar 2022 16:22:10 +0800 To: , , , CC: , , Subject: [PATCH] chardev: avoid use-after-free when client disconnect Date: Mon, 28 Mar 2022 16:22:07 +0800 Message-ID: <20220328082207.2525-1-hogan.wang@huawei.com> X-Mailer: git-send-email 2.33.0 MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Originating-IP: [10.174.149.172] X-ClientProxiedBy: dggems703-chm.china.huawei.com (10.3.19.180) To kwepemm600015.china.huawei.com (7.193.23.52) X-CFilter-Loop: Reflected 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=45.249.212.255; envelope-from=hogan.wang@huawei.com; helo=szxga08-in.huawei.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 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" Reply-to: Hogan Wang From: Hogan Wang via X-ZM-MESSAGEID: 1648455852945100001 Content-Type: text/plain; charset="utf-8" IOWatchPoll object did not hold the @ioc and @src objects reference, then io_watch_poll_prepare execute in IO thread, if IOWatchPoll removed by mian thread, io_watch_poll_prepare may execute at last chance and access the freed @ioc or @src object. In IO thread monitor scene, the IO thread used to accept client, receive qmp request and handle hung-up event. Main thread used to handle qmp request and send response, it will remove IOWatchPoll and free @ioc when send response fail, then cause use-after-free like this: (gdb) bt 0 0x00007f4d121c8edf in g_source_remove_child_source (source=3D0x7f4c58003= 560, child_source=3D0x7f4c58009b10) 1 0x00007f4d11e0705c in io_watch_poll_prepare (source=3D0x7f4c58003560, ti= meout=3Dtimeout@entry=3D0x7f4c7fffed94 2 0x00007f4d121ca419 in g_main_context_prepare (context=3Dcontext@entry=3D= 0x55a1463f8260, priority=3Dpriority@entry=3D0x7f4c7fffee20) 3 0x00007f4d121cadeb in g_main_context_iterate (context=3D0x55a1463f8260, = block=3Dblock@entry=3D1, dispatch=3Ddispatch@entry=3D1, self=3Dself@entry= =3D0x7f4c94002260) 4 0x00007f4d121cb21d in g_main_loop_run (loop=3D0x55a146c90920) 5 0x00007f4d11de3ea1 in iothread_run (opaque=3D0x55a146411820) 6 0x00007f4d11d77470 in qemu_thread_start (args=3D0x55a146b1f3c0) 7 0x00007f4d11f2ef3b in ?? () from /usr/lib64/libpthread.so.0 8 0x00007f4d120ba550 in clone () from /usr/lib64/libc.so.6 (gdb) p iwp $1 =3D (IOWatchPoll *) 0x7f4c58003560 (gdb) p *iwp $2 =3D {parent =3D {callback_data =3D 0x0, callback_funcs =3D 0x0, source_funcs =3D 0x7f4d11f10760 , ref_count =3D 1, context =3D 0x55a1463f8260, priority =3D 0, flags =3D 0, source_id =3D 544, poll_fds =3D 0x0, prev =3D 0x55a147a47a30, next =3D 0x55a14712fb80, name =3D 0x7f4c580036d0 "chardev-iowatch-charmonitor", priv =3D 0x7f4c58003060}, ioc =3D 0x7f4c580033f0, src =3D 0x7f4c58009b10, fd_can_read =3D 0x7f4d11e0a5d0 , fd_read =3D 0x7f4d11e0a380 , opaque =3D 0x55a1463aeea0 } (gdb) p iwp->ioc $3 =3D (QIOChannel *) 0x7f4c580033f0 (gdb) p *iwp->ioc $4 =3D {parent =3D {class =3D 0x55a14707f400, free =3D 0x55a146313010, properties =3D 0x55a147b37b60, ref =3D 0, parent =3D 0x0}, features =3D 3, name =3D 0x7f4c580085f0 "\240F", ctx =3D 0x0, read_coroutine =3D 0x0, write_coroutine =3D 0x0} Solution: IOWatchPoll object hold the @ioc and @src objects reference and release the reference in GSource finalize callback function. Signed-off-by: Hogan Wang --- chardev/char-io.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/chardev/char-io.c b/chardev/char-io.c index 8ced184160..3af388eeaa 100644 --- a/chardev/char-io.c +++ b/chardev/char-io.c @@ -55,9 +55,9 @@ static gboolean io_watch_poll_prepare(GSource *source, iwp->ioc, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL); g_source_set_callback(iwp->src, iwp->fd_read, iwp->opaque, NULL); g_source_add_child_source(source, iwp->src); - g_source_unref(iwp->src); } else { g_source_remove_child_source(source, iwp->src); + g_source_unref(iwp->src); iwp->src =3D NULL; } return FALSE; @@ -69,9 +69,23 @@ static gboolean io_watch_poll_dispatch(GSource *source, = GSourceFunc callback, return G_SOURCE_CONTINUE; } =20 +static void io_watch_poll_finalize(GSource *source) +{ + IOWatchPoll *iwp =3D io_watch_poll_from_source(source); + if (iwp->src) { + g_source_unref(iwp->src); + iwp->src =3D NULL; + } + if (iwp->ioc) { + object_unref(OBJECT(iwp->ioc)); + iwp->ioc =3D NULL; + } +} + static GSourceFuncs io_watch_poll_funcs =3D { .prepare =3D io_watch_poll_prepare, .dispatch =3D io_watch_poll_dispatch, + .finalize =3D io_watch_poll_finalize, }; =20 GSource *io_add_watch_poll(Chardev *chr, @@ -88,6 +102,7 @@ GSource *io_add_watch_poll(Chardev *chr, sizeof(IOWatchPoll)); iwp->fd_can_read =3D fd_can_read; iwp->opaque =3D user_data; + object_ref(OBJECT(ioc)); iwp->ioc =3D ioc; iwp->fd_read =3D (GSourceFunc) fd_read; iwp->src =3D NULL; --=20 2.33.0