From nobody Sun Apr 28 23:02:27 2024 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=1658301239; cv=none; d=zohomail.com; s=zohoarc; b=TBd8t0goIv7JQ/ThaO2JvGlTZAmkfxy5s4AYYhtmm6DK2RYDbQAYSyvv1BKtXzpP+zJteHkb1ZtD26FiMFI+6u3THg1lEp8109E7eQU2FCnB1FFsPpTQ8MH1VbzxpgHefAwivYbQgC4vluTqtYmHGHNEkUjksYGbce/6OhzVIUQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1658301239; 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=SQHHVmyk/V1c31wPX4TZfcnMbwPd+bdz8zGeNhYNnEM=; b=XGh8Gi0avju6qjsaM8c9qS0wH0Oa29zcs4/7wr+Ky6+AVlkYBKCoj/fS3K6ScUdrvtbXlEgxNBaFlNikPtlkaUV5RTl8htMGAzYqCTk4I9Ap9UKyv/HHODzZUS9/7vN8KCM5ElhF/AZvhk5f8uR223/J+K0cCfQ332FVRj8YbCU= 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 1658301239026505.76126643258453; Wed, 20 Jul 2022 00:13:59 -0700 (PDT) Received: from localhost ([::1]:59528 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oE3uA-0007gE-07 for importer@patchew.org; Wed, 20 Jul 2022 03:13:58 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35398) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oE3s1-0004yE-IX for qemu-devel@nongnu.org; Wed, 20 Jul 2022 03:11:46 -0400 Received: from szxga01-in.huawei.com ([45.249.212.187]:4514) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oE3ry-00083n-HW for qemu-devel@nongnu.org; Wed, 20 Jul 2022 03:11:45 -0400 Received: from dggemv704-chm.china.huawei.com (unknown [172.30.72.53]) by szxga01-in.huawei.com (SkyGuard) with ESMTP id 4LnmyJ6MY6zjXLk; Wed, 20 Jul 2022 15:08:40 +0800 (CST) Received: from kwepemm600015.china.huawei.com (7.193.23.52) by dggemv704-chm.china.huawei.com (10.3.19.47) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.24; Wed, 20 Jul 2022 15:11:02 +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.2375.24; Wed, 20 Jul 2022 15:11:02 +0800 To: , , CC: , , , Subject: [PATCH v2] chardev: avoid use-after-free when client disconnect Date: Wed, 20 Jul 2022 15:10:57 +0800 Message-ID: <20220720071057.1745-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: dggems706-chm.china.huawei.com (10.3.19.183) 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.187; envelope-from=hogan.wang@huawei.com; helo=szxga01-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, 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: 1658301242436100001 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, then io_watch_poll_prepare access @ioc or @src concurrently lead to coredump. 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 | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/chardev/char-io.c b/chardev/char-io.c index 4451128cba..6b10217a70 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,17 @@ 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); + g_clear_pointer(&iwp->src, g_source_unref); + g_clear_pointer(&iwp->ioc, object_unref); +} + 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,7 +96,7 @@ GSource *io_add_watch_poll(Chardev *chr, sizeof(IOWatchPoll)); iwp->fd_can_read =3D fd_can_read; iwp->opaque =3D user_data; - iwp->ioc =3D ioc; + iwp->ioc =3D object_ref(ioc); iwp->fd_read =3D (GSourceFunc) fd_read; iwp->src =3D NULL; =20 --=20 2.33.0