Message ID | 20221027124528.2487025-1-zengheng4@huawei.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp210534wru; Thu, 27 Oct 2022 05:49:42 -0700 (PDT) X-Google-Smtp-Source: AMsMyM4fNIdGVnmJOTLaOBxBrnwb02zSneAUv8fiz3lVPwll+z14m7Y9Cg5AMe59/xEVZ1OZMpSz X-Received: by 2002:a17:907:7610:b0:78d:b374:898e with SMTP id jx16-20020a170907761000b0078db374898emr44480704ejc.28.1666874982700; Thu, 27 Oct 2022 05:49:42 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1666874982; cv=none; d=google.com; s=arc-20160816; b=I6dNbD5c9YG6BjFqpYafW0Zk1NNDH8gCGAE/U764Sm/xfBosoenkCojyuEtKUtS3EE eir3Lrfp1vKKcX8SNAPO3+00t1qK5wMZnL17z53+b3sc9x5uQI34uGE03q2zD1GcIHdp HFs88WSM33koDBceNmuwc3unttMNw5lgfAszZD8x9I9YlTPjOYxpNhBZ+p8E85+Td1hA T634VjJfBkfwkPp3FiveczKPXvO9WHXEJw9Fra773o/plrCeKfZLsZkkDcx6Eaeb8qmh h8OKdYyxGzXnaepM4wbX4o8dkjaDsJuBTRbE5vDvaGLEwHLq9mypsfwLKBztLDnWNOu6 b/Ag== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from; bh=DpWw8OERUGUt8nqzWQjzuFU4hJGXU6cmi1BAsjYyGE8=; b=PxP6QLqU3sySdhnMmA9/JTEoz0UbBT1PcALzcOxVHQmPgiZdkpsp6Zyu6tJBAEtS5X 5VTxNBcDEH5A8NnPfyEJIZuI2r8RXTlPPPh3sJ4ByP9EgUynttMGRxjZ3p3MTMVy+si5 paELt8rQwAoYeYfPbVtkv2VXcxNk3NClB6Gi7DzhOzDa3KFN/71bioyw4sOb0+nDwra1 UaEDLDCb0wnRrVMrErEL4wY9Jst1asVt/Ec/Q3XOTK6E+QhsJcvyfFCeR8Vtc+y9tP8Q rxgUS/KD9wiUhlLk3PdQotbURSlFsvpNAcdS1m5F/eZ+OkmJt9TiXUKs/qXMRoGFwAYC uK1w== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=huawei.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id b17-20020a056402279100b00462a20f860bsi1401207ede.539.2022.10.27.05.49.15; Thu, 27 Oct 2022 05:49:42 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=huawei.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235743AbiJ0Mqb (ORCPT <rfc822;chrisfriedt@gmail.com> + 99 others); Thu, 27 Oct 2022 08:46:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33404 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235020AbiJ0Mqa (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Thu, 27 Oct 2022 08:46:30 -0400 Received: from szxga08-in.huawei.com (szxga08-in.huawei.com [45.249.212.255]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C364561B1F; Thu, 27 Oct 2022 05:46:28 -0700 (PDT) Received: from kwepemi500024.china.huawei.com (unknown [172.30.72.57]) by szxga08-in.huawei.com (SkyGuard) with ESMTP id 4Mylfg6cXWz15MCN; Thu, 27 Oct 2022 20:41:31 +0800 (CST) Received: from huawei.com (10.175.103.91) by kwepemi500024.china.huawei.com (7.221.188.100) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.31; Thu, 27 Oct 2022 20:46:25 +0800 From: Zeng Heng <zengheng4@huawei.com> To: <sfrench@samba.org>, <tom@talpey.com>, <sprasad@microsoft.com>, <pc@cjr.nz>, <lsahlber@redhat.com> CC: <linux-cifs@vger.kernel.org>, <samba-technical@lists.samba.org>, <linux-kernel@vger.kernel.org>, <liwei391@huawei.com> Subject: [PATCH v4] cifs: fix use-after-free caused by invalid pointer `hostname` Date: Thu, 27 Oct 2022 20:45:28 +0800 Message-ID: <20221027124528.2487025-1-zengheng4@huawei.com> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 Content-Transfer-Encoding: 7BIT Content-Type: text/plain; charset=US-ASCII X-Originating-IP: [10.175.103.91] X-ClientProxiedBy: dggems702-chm.china.huawei.com (10.3.19.179) To kwepemi500024.china.huawei.com (7.221.188.100) X-CFilter-Loop: Reflected X-Spam-Status: No, score=-3.2 required=5.0 tests=BAYES_00,HEXHASH_WORD, RCVD_IN_DNSWL_MED,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1747845101611692053?= X-GMAIL-MSGID: =?utf-8?q?1747845101611692053?= |
Series |
[v4] cifs: fix use-after-free caused by invalid pointer `hostname`
|
|
Commit Message
Zeng Heng
Oct. 27, 2022, 12:45 p.m. UTC
`hostname` needs to be set as null-pointer after free in `cifs_put_tcp_session` function, or when `cifsd` thread attempts to resolve hostname and reconnect the host, the thread would deref the invalid pointer. Here is one of practical backtrace examples as reference: Task 477 --------------------------- do_mount path_mount do_new_mount vfs_get_tree smb3_get_tree smb3_get_tree_common cifs_smb3_do_mount cifs_mount mount_put_conns cifs_put_tcp_session --> kfree(server->hostname) cifsd --------------------------- kthread cifs_demultiplex_thread cifs_reconnect reconn_set_ipaddr_from_hostname --> if (!server->hostname) --> if (server->hostname[0] == '\0') // !! UAF fault here CIFS: VFS: cifs_mount failed w/return code = -112 mount error(112): Host is down BUG: KASAN: use-after-free in reconn_set_ipaddr_from_hostname+0x2ba/0x310 Read of size 1 at addr ffff888108f35380 by task cifsd/480 CPU: 2 PID: 480 Comm: cifsd Not tainted 6.1.0-rc2-00106-gf705792f89dd-dirty #25 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014 Call Trace: <TASK> dump_stack_lvl+0x68/0x85 print_report+0x16c/0x4a3 kasan_report+0x95/0x190 reconn_set_ipaddr_from_hostname+0x2ba/0x310 __cifs_reconnect.part.0+0x241/0x800 cifs_reconnect+0x65f/0xb60 cifs_demultiplex_thread+0x1570/0x2570 kthread+0x2c5/0x380 ret_from_fork+0x22/0x30 </TASK> Allocated by task 477: kasan_save_stack+0x1e/0x40 kasan_set_track+0x21/0x30 __kasan_kmalloc+0x7e/0x90 __kmalloc_node_track_caller+0x52/0x1b0 kstrdup+0x3b/0x70 cifs_get_tcp_session+0xbc/0x19b0 mount_get_conns+0xa9/0x10c0 cifs_mount+0xdf/0x1970 cifs_smb3_do_mount+0x295/0x1660 smb3_get_tree+0x352/0x5e0 vfs_get_tree+0x8e/0x2e0 path_mount+0xf8c/0x1990 do_mount+0xee/0x110 __x64_sys_mount+0x14b/0x1f0 do_syscall_64+0x3b/0x90 entry_SYSCALL_64_after_hwframe+0x63/0xcd Freed by task 477: kasan_save_stack+0x1e/0x40 kasan_set_track+0x21/0x30 kasan_save_free_info+0x2a/0x50 __kasan_slab_free+0x10a/0x190 __kmem_cache_free+0xca/0x3f0 cifs_put_tcp_session+0x30c/0x450 cifs_mount+0xf95/0x1970 cifs_smb3_do_mount+0x295/0x1660 smb3_get_tree+0x352/0x5e0 vfs_get_tree+0x8e/0x2e0 path_mount+0xf8c/0x1990 do_mount+0xee/0x110 __x64_sys_mount+0x14b/0x1f0 do_syscall_64+0x3b/0x90 entry_SYSCALL_64_after_hwframe+0x63/0xcd The buggy address belongs to the object at ffff888108f35380 which belongs to the cache kmalloc-16 of size 16 The buggy address is located 0 bytes inside of 16-byte region [ffff888108f35380, ffff888108f35390) The buggy address belongs to the physical page: page:00000000333f8e58 refcount:1 mapcount:0 mapping:0000000000000000 index:0xffff888108f350e0 pfn:0x108f35 flags: 0x200000000000200(slab|node=0|zone=2) raw: 0200000000000200 0000000000000000 dead000000000122 ffff8881000423c0 raw: ffff888108f350e0 000000008080007a 00000001ffffffff 0000000000000000 page dumped because: kasan: bad access detected Memory state around the buggy address: ffff888108f35280: fa fb fc fc fa fb fc fc fa fb fc fc fa fb fc fc ffff888108f35300: fa fb fc fc fa fb fc fc fa fb fc fc fa fb fc fc >ffff888108f35380: fa fb fc fc fa fb fc fc fa fb fc fc fa fb fc fc ^ ffff888108f35400: fa fb fc fc fc fc fc fc fc fc fc fc fc fc fc fc ffff888108f35480: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc Fixes: 7be3248f3139 ("cifs: To match file servers, make sure the server hostname matches") Signed-off-by: Zeng Heng <zengheng4@huawei.com> Reviewed-by: Paulo Alcantara (SUSE) <pc@cjr.nz> --- changes in v4: - correct fix tag - add reviewed-by --- fs/cifs/connect.c | 1 + 1 file changed, 1 insertion(+)
Comments
merged into cifs-2.6 for-next thx On Thu, Oct 27, 2022 at 7:49 AM Zeng Heng <zengheng4@huawei.com> wrote: > > `hostname` needs to be set as null-pointer after free in > `cifs_put_tcp_session` function, or when `cifsd` thread attempts > to resolve hostname and reconnect the host, the thread would deref > the invalid pointer. > > Here is one of practical backtrace examples as reference: > > Task 477 > --------------------------- > do_mount > path_mount > do_new_mount > vfs_get_tree > smb3_get_tree > smb3_get_tree_common > cifs_smb3_do_mount > cifs_mount > mount_put_conns > cifs_put_tcp_session > --> kfree(server->hostname) > > cifsd > --------------------------- > kthread > cifs_demultiplex_thread > cifs_reconnect > reconn_set_ipaddr_from_hostname > --> if (!server->hostname) > --> if (server->hostname[0] == '\0') // !! UAF fault here > > CIFS: VFS: cifs_mount failed w/return code = -112 > mount error(112): Host is down > BUG: KASAN: use-after-free in reconn_set_ipaddr_from_hostname+0x2ba/0x310 > Read of size 1 at addr ffff888108f35380 by task cifsd/480 > CPU: 2 PID: 480 Comm: cifsd Not tainted 6.1.0-rc2-00106-gf705792f89dd-dirty #25 > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014 > Call Trace: > <TASK> > dump_stack_lvl+0x68/0x85 > print_report+0x16c/0x4a3 > kasan_report+0x95/0x190 > reconn_set_ipaddr_from_hostname+0x2ba/0x310 > __cifs_reconnect.part.0+0x241/0x800 > cifs_reconnect+0x65f/0xb60 > cifs_demultiplex_thread+0x1570/0x2570 > kthread+0x2c5/0x380 > ret_from_fork+0x22/0x30 > </TASK> > Allocated by task 477: > kasan_save_stack+0x1e/0x40 > kasan_set_track+0x21/0x30 > __kasan_kmalloc+0x7e/0x90 > __kmalloc_node_track_caller+0x52/0x1b0 > kstrdup+0x3b/0x70 > cifs_get_tcp_session+0xbc/0x19b0 > mount_get_conns+0xa9/0x10c0 > cifs_mount+0xdf/0x1970 > cifs_smb3_do_mount+0x295/0x1660 > smb3_get_tree+0x352/0x5e0 > vfs_get_tree+0x8e/0x2e0 > path_mount+0xf8c/0x1990 > do_mount+0xee/0x110 > __x64_sys_mount+0x14b/0x1f0 > do_syscall_64+0x3b/0x90 > entry_SYSCALL_64_after_hwframe+0x63/0xcd > Freed by task 477: > kasan_save_stack+0x1e/0x40 > kasan_set_track+0x21/0x30 > kasan_save_free_info+0x2a/0x50 > __kasan_slab_free+0x10a/0x190 > __kmem_cache_free+0xca/0x3f0 > cifs_put_tcp_session+0x30c/0x450 > cifs_mount+0xf95/0x1970 > cifs_smb3_do_mount+0x295/0x1660 > smb3_get_tree+0x352/0x5e0 > vfs_get_tree+0x8e/0x2e0 > path_mount+0xf8c/0x1990 > do_mount+0xee/0x110 > __x64_sys_mount+0x14b/0x1f0 > do_syscall_64+0x3b/0x90 > entry_SYSCALL_64_after_hwframe+0x63/0xcd > The buggy address belongs to the object at ffff888108f35380 > which belongs to the cache kmalloc-16 of size 16 > The buggy address is located 0 bytes inside of > 16-byte region [ffff888108f35380, ffff888108f35390) > The buggy address belongs to the physical page: > page:00000000333f8e58 refcount:1 mapcount:0 mapping:0000000000000000 index:0xffff888108f350e0 pfn:0x108f35 > flags: 0x200000000000200(slab|node=0|zone=2) > raw: 0200000000000200 0000000000000000 dead000000000122 ffff8881000423c0 > raw: ffff888108f350e0 000000008080007a 00000001ffffffff 0000000000000000 > page dumped because: kasan: bad access detected > Memory state around the buggy address: > ffff888108f35280: fa fb fc fc fa fb fc fc fa fb fc fc fa fb fc fc > ffff888108f35300: fa fb fc fc fa fb fc fc fa fb fc fc fa fb fc fc > >ffff888108f35380: fa fb fc fc fa fb fc fc fa fb fc fc fa fb fc fc > ^ > ffff888108f35400: fa fb fc fc fc fc fc fc fc fc fc fc fc fc fc fc > ffff888108f35480: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc > > Fixes: 7be3248f3139 ("cifs: To match file servers, make sure the server hostname matches") > Signed-off-by: Zeng Heng <zengheng4@huawei.com> > Reviewed-by: Paulo Alcantara (SUSE) <pc@cjr.nz> > --- > changes in v4: > - correct fix tag > - add reviewed-by > --- > fs/cifs/connect.c | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c > index ffb291579bb9..1cc47dd3b4d6 100644 > --- a/fs/cifs/connect.c > +++ b/fs/cifs/connect.c > @@ -1584,6 +1584,7 @@ cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect) > server->session_key.response = NULL; > server->session_key.len = 0; > kfree(server->hostname); > + server->hostname = NULL; > > task = xchg(&server->tsk, NULL); > if (task) > -- > 2.25.1 >
On Thu, Oct 27, 2022 at 6:19 PM Zeng Heng <zengheng4@huawei.com> wrote: > > `hostname` needs to be set as null-pointer after free in > `cifs_put_tcp_session` function, or when `cifsd` thread attempts > to resolve hostname and reconnect the host, the thread would deref > the invalid pointer. > > Here is one of practical backtrace examples as reference: > > Task 477 > --------------------------- > do_mount > path_mount > do_new_mount > vfs_get_tree > smb3_get_tree > smb3_get_tree_common > cifs_smb3_do_mount > cifs_mount > mount_put_conns > cifs_put_tcp_session > --> kfree(server->hostname) > > cifsd > --------------------------- > kthread > cifs_demultiplex_thread > cifs_reconnect > reconn_set_ipaddr_from_hostname > --> if (!server->hostname) > --> if (server->hostname[0] == '\0') // !! UAF fault here > > CIFS: VFS: cifs_mount failed w/return code = -112 > mount error(112): Host is down > BUG: KASAN: use-after-free in reconn_set_ipaddr_from_hostname+0x2ba/0x310 > Read of size 1 at addr ffff888108f35380 by task cifsd/480 > CPU: 2 PID: 480 Comm: cifsd Not tainted 6.1.0-rc2-00106-gf705792f89dd-dirty #25 > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014 > Call Trace: > <TASK> > dump_stack_lvl+0x68/0x85 > print_report+0x16c/0x4a3 > kasan_report+0x95/0x190 > reconn_set_ipaddr_from_hostname+0x2ba/0x310 > __cifs_reconnect.part.0+0x241/0x800 > cifs_reconnect+0x65f/0xb60 > cifs_demultiplex_thread+0x1570/0x2570 > kthread+0x2c5/0x380 > ret_from_fork+0x22/0x30 > </TASK> > Allocated by task 477: > kasan_save_stack+0x1e/0x40 > kasan_set_track+0x21/0x30 > __kasan_kmalloc+0x7e/0x90 > __kmalloc_node_track_caller+0x52/0x1b0 > kstrdup+0x3b/0x70 > cifs_get_tcp_session+0xbc/0x19b0 > mount_get_conns+0xa9/0x10c0 > cifs_mount+0xdf/0x1970 > cifs_smb3_do_mount+0x295/0x1660 > smb3_get_tree+0x352/0x5e0 > vfs_get_tree+0x8e/0x2e0 > path_mount+0xf8c/0x1990 > do_mount+0xee/0x110 > __x64_sys_mount+0x14b/0x1f0 > do_syscall_64+0x3b/0x90 > entry_SYSCALL_64_after_hwframe+0x63/0xcd > Freed by task 477: > kasan_save_stack+0x1e/0x40 > kasan_set_track+0x21/0x30 > kasan_save_free_info+0x2a/0x50 > __kasan_slab_free+0x10a/0x190 > __kmem_cache_free+0xca/0x3f0 > cifs_put_tcp_session+0x30c/0x450 > cifs_mount+0xf95/0x1970 > cifs_smb3_do_mount+0x295/0x1660 > smb3_get_tree+0x352/0x5e0 > vfs_get_tree+0x8e/0x2e0 > path_mount+0xf8c/0x1990 > do_mount+0xee/0x110 > __x64_sys_mount+0x14b/0x1f0 > do_syscall_64+0x3b/0x90 > entry_SYSCALL_64_after_hwframe+0x63/0xcd > The buggy address belongs to the object at ffff888108f35380 > which belongs to the cache kmalloc-16 of size 16 > The buggy address is located 0 bytes inside of > 16-byte region [ffff888108f35380, ffff888108f35390) > The buggy address belongs to the physical page: > page:00000000333f8e58 refcount:1 mapcount:0 mapping:0000000000000000 index:0xffff888108f350e0 pfn:0x108f35 > flags: 0x200000000000200(slab|node=0|zone=2) > raw: 0200000000000200 0000000000000000 dead000000000122 ffff8881000423c0 > raw: ffff888108f350e0 000000008080007a 00000001ffffffff 0000000000000000 > page dumped because: kasan: bad access detected > Memory state around the buggy address: > ffff888108f35280: fa fb fc fc fa fb fc fc fa fb fc fc fa fb fc fc > ffff888108f35300: fa fb fc fc fa fb fc fc fa fb fc fc fa fb fc fc > >ffff888108f35380: fa fb fc fc fa fb fc fc fa fb fc fc fa fb fc fc > ^ > ffff888108f35400: fa fb fc fc fc fc fc fc fc fc fc fc fc fc fc fc > ffff888108f35480: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc > > Fixes: 7be3248f3139 ("cifs: To match file servers, make sure the server hostname matches") > Signed-off-by: Zeng Heng <zengheng4@huawei.com> > Reviewed-by: Paulo Alcantara (SUSE) <pc@cjr.nz> > --- > changes in v4: > - correct fix tag > - add reviewed-by > --- > fs/cifs/connect.c | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c > index ffb291579bb9..1cc47dd3b4d6 100644 > --- a/fs/cifs/connect.c > +++ b/fs/cifs/connect.c > @@ -1584,6 +1584,7 @@ cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect) > server->session_key.response = NULL; > server->session_key.len = 0; > kfree(server->hostname); > + server->hostname = NULL; > > task = xchg(&server->tsk, NULL); > if (task) > -- > 2.25.1 > Good catch. But I think there can be a better fix. How about moving the lines that follow i.e. cifsd thread kill to before setting tcpStatus? That way, we don't leave scope for things to race.
On Fri, Oct 28, 2022 at 11:29 AM Steve French <smfrench@gmail.com> wrote: > > merged into cifs-2.6 for-next > > thx > > On Thu, Oct 27, 2022 at 7:49 AM Zeng Heng <zengheng4@huawei.com> wrote: > > > > `hostname` needs to be set as null-pointer after free in > > `cifs_put_tcp_session` function, or when `cifsd` thread attempts > > to resolve hostname and reconnect the host, the thread would deref > > the invalid pointer. > > > > Here is one of practical backtrace examples as reference: > > > > Task 477 > > --------------------------- > > do_mount > > path_mount > > do_new_mount > > vfs_get_tree > > smb3_get_tree > > smb3_get_tree_common > > cifs_smb3_do_mount > > cifs_mount > > mount_put_conns > > cifs_put_tcp_session > > --> kfree(server->hostname) > > > > cifsd > > --------------------------- > > kthread > > cifs_demultiplex_thread > > cifs_reconnect > > reconn_set_ipaddr_from_hostname > > --> if (!server->hostname) > > --> if (server->hostname[0] == '\0') // !! UAF fault here > > > > CIFS: VFS: cifs_mount failed w/return code = -112 > > mount error(112): Host is down > > BUG: KASAN: use-after-free in reconn_set_ipaddr_from_hostname+0x2ba/0x310 > > Read of size 1 at addr ffff888108f35380 by task cifsd/480 > > CPU: 2 PID: 480 Comm: cifsd Not tainted 6.1.0-rc2-00106-gf705792f89dd-dirty #25 > > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014 > > Call Trace: > > <TASK> > > dump_stack_lvl+0x68/0x85 > > print_report+0x16c/0x4a3 > > kasan_report+0x95/0x190 > > reconn_set_ipaddr_from_hostname+0x2ba/0x310 > > __cifs_reconnect.part.0+0x241/0x800 > > cifs_reconnect+0x65f/0xb60 > > cifs_demultiplex_thread+0x1570/0x2570 > > kthread+0x2c5/0x380 > > ret_from_fork+0x22/0x30 > > </TASK> > > Allocated by task 477: > > kasan_save_stack+0x1e/0x40 > > kasan_set_track+0x21/0x30 > > __kasan_kmalloc+0x7e/0x90 > > __kmalloc_node_track_caller+0x52/0x1b0 > > kstrdup+0x3b/0x70 > > cifs_get_tcp_session+0xbc/0x19b0 > > mount_get_conns+0xa9/0x10c0 > > cifs_mount+0xdf/0x1970 > > cifs_smb3_do_mount+0x295/0x1660 > > smb3_get_tree+0x352/0x5e0 > > vfs_get_tree+0x8e/0x2e0 > > path_mount+0xf8c/0x1990 > > do_mount+0xee/0x110 > > __x64_sys_mount+0x14b/0x1f0 > > do_syscall_64+0x3b/0x90 > > entry_SYSCALL_64_after_hwframe+0x63/0xcd > > Freed by task 477: > > kasan_save_stack+0x1e/0x40 > > kasan_set_track+0x21/0x30 > > kasan_save_free_info+0x2a/0x50 > > __kasan_slab_free+0x10a/0x190 > > __kmem_cache_free+0xca/0x3f0 > > cifs_put_tcp_session+0x30c/0x450 > > cifs_mount+0xf95/0x1970 > > cifs_smb3_do_mount+0x295/0x1660 > > smb3_get_tree+0x352/0x5e0 > > vfs_get_tree+0x8e/0x2e0 > > path_mount+0xf8c/0x1990 > > do_mount+0xee/0x110 > > __x64_sys_mount+0x14b/0x1f0 > > do_syscall_64+0x3b/0x90 > > entry_SYSCALL_64_after_hwframe+0x63/0xcd > > The buggy address belongs to the object at ffff888108f35380 > > which belongs to the cache kmalloc-16 of size 16 > > The buggy address is located 0 bytes inside of > > 16-byte region [ffff888108f35380, ffff888108f35390) > > The buggy address belongs to the physical page: > > page:00000000333f8e58 refcount:1 mapcount:0 mapping:0000000000000000 index:0xffff888108f350e0 pfn:0x108f35 > > flags: 0x200000000000200(slab|node=0|zone=2) > > raw: 0200000000000200 0000000000000000 dead000000000122 ffff8881000423c0 > > raw: ffff888108f350e0 000000008080007a 00000001ffffffff 0000000000000000 > > page dumped because: kasan: bad access detected > > Memory state around the buggy address: > > ffff888108f35280: fa fb fc fc fa fb fc fc fa fb fc fc fa fb fc fc > > ffff888108f35300: fa fb fc fc fa fb fc fc fa fb fc fc fa fb fc fc > > >ffff888108f35380: fa fb fc fc fa fb fc fc fa fb fc fc fa fb fc fc > > ^ > > ffff888108f35400: fa fb fc fc fc fc fc fc fc fc fc fc fc fc fc fc > > ffff888108f35480: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc > > > > Fixes: 7be3248f3139 ("cifs: To match file servers, make sure the server hostname matches") > > Signed-off-by: Zeng Heng <zengheng4@huawei.com> > > Reviewed-by: Paulo Alcantara (SUSE) <pc@cjr.nz> > > --- > > changes in v4: > > - correct fix tag > > - add reviewed-by > > --- > > fs/cifs/connect.c | 1 + > > 1 file changed, 1 insertion(+) > > > > diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c > > index ffb291579bb9..1cc47dd3b4d6 100644 > > --- a/fs/cifs/connect.c > > +++ b/fs/cifs/connect.c > > @@ -1584,6 +1584,7 @@ cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect) > > server->session_key.response = NULL; > > server->session_key.len = 0; > > kfree(server->hostname); > > + server->hostname = NULL; > > > > task = xchg(&server->tsk, NULL); > > if (task) > > -- > > 2.25.1 > > > > > -- > Thanks, > > Steve What I mean is something like this: https://github.com/sprasad-microsoft/smb3-kernel-client/commit/07abfbeb01d3cb8d55d76c1937bd4cde46063e5d.patch
On Sat, Oct 29, 2022 at 8:25 AM Zeng Heng <zengheng4@huawei.com> wrote: > > Make sure `cifsd` terminated to avoid race condition, it has to call > function like kthread_stop. > > Then the whole `server` struct would be released by `cifsd` and another > UAF appears. > > > On 2022/10/28 13:41, Shyam Prasad N wrote: > > On Thu, Oct 27, 2022 at 6:19 PM Zeng Heng <zengheng4@huawei.com> wrote: > >> `hostname` needs to be set as null-pointer after free in > >> `cifs_put_tcp_session` function, or when `cifsd` thread attempts > >> to resolve hostname and reconnect the host, the thread would deref > >> the invalid pointer. > >> > >> Here is one of practical backtrace examples as reference: > >> > >> Task 477 > >> --------------------------- > >> do_mount > >> path_mount > >> do_new_mount > >> vfs_get_tree > >> smb3_get_tree > >> smb3_get_tree_common > >> cifs_smb3_do_mount > >> cifs_mount > >> mount_put_conns > >> cifs_put_tcp_session > >> --> kfree(server->hostname) > >> > >> cifsd > >> --------------------------- > >> kthread > >> cifs_demultiplex_thread > >> cifs_reconnect > >> reconn_set_ipaddr_from_hostname > >> --> if (!server->hostname) > >> --> if (server->hostname[0] == '\0') // !! UAF fault here > >> > >> CIFS: VFS: cifs_mount failed w/return code = -112 > >> mount error(112): Host is down > >> BUG: KASAN: use-after-free in reconn_set_ipaddr_from_hostname+0x2ba/0x310 > >> Read of size 1 at addr ffff888108f35380 by task cifsd/480 > >> CPU: 2 PID: 480 Comm: cifsd Not tainted 6.1.0-rc2-00106-gf705792f89dd-dirty #25 > >> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014 > >> Call Trace: > >> <TASK> > >> dump_stack_lvl+0x68/0x85 > >> print_report+0x16c/0x4a3 > >> kasan_report+0x95/0x190 > >> reconn_set_ipaddr_from_hostname+0x2ba/0x310 > >> __cifs_reconnect.part.0+0x241/0x800 > >> cifs_reconnect+0x65f/0xb60 > >> cifs_demultiplex_thread+0x1570/0x2570 > >> kthread+0x2c5/0x380 > >> ret_from_fork+0x22/0x30 > >> </TASK> > >> Allocated by task 477: > >> kasan_save_stack+0x1e/0x40 > >> kasan_set_track+0x21/0x30 > >> __kasan_kmalloc+0x7e/0x90 > >> __kmalloc_node_track_caller+0x52/0x1b0 > >> kstrdup+0x3b/0x70 > >> cifs_get_tcp_session+0xbc/0x19b0 > >> mount_get_conns+0xa9/0x10c0 > >> cifs_mount+0xdf/0x1970 > >> cifs_smb3_do_mount+0x295/0x1660 > >> smb3_get_tree+0x352/0x5e0 > >> vfs_get_tree+0x8e/0x2e0 > >> path_mount+0xf8c/0x1990 > >> do_mount+0xee/0x110 > >> __x64_sys_mount+0x14b/0x1f0 > >> do_syscall_64+0x3b/0x90 > >> entry_SYSCALL_64_after_hwframe+0x63/0xcd > >> Freed by task 477: > >> kasan_save_stack+0x1e/0x40 > >> kasan_set_track+0x21/0x30 > >> kasan_save_free_info+0x2a/0x50 > >> __kasan_slab_free+0x10a/0x190 > >> __kmem_cache_free+0xca/0x3f0 > >> cifs_put_tcp_session+0x30c/0x450 > >> cifs_mount+0xf95/0x1970 > >> cifs_smb3_do_mount+0x295/0x1660 > >> smb3_get_tree+0x352/0x5e0 > >> vfs_get_tree+0x8e/0x2e0 > >> path_mount+0xf8c/0x1990 > >> do_mount+0xee/0x110 > >> __x64_sys_mount+0x14b/0x1f0 > >> do_syscall_64+0x3b/0x90 > >> entry_SYSCALL_64_after_hwframe+0x63/0xcd > >> The buggy address belongs to the object at ffff888108f35380 > >> which belongs to the cache kmalloc-16 of size 16 > >> The buggy address is located 0 bytes inside of > >> 16-byte region [ffff888108f35380, ffff888108f35390) > >> The buggy address belongs to the physical page: > >> page:00000000333f8e58 refcount:1 mapcount:0 mapping:0000000000000000 index:0xffff888108f350e0 pfn:0x108f35 > >> flags: 0x200000000000200(slab|node=0|zone=2) > >> raw: 0200000000000200 0000000000000000 dead000000000122 ffff8881000423c0 > >> raw: ffff888108f350e0 000000008080007a 00000001ffffffff 0000000000000000 > >> page dumped because: kasan: bad access detected > >> Memory state around the buggy address: > >> ffff888108f35280: fa fb fc fc fa fb fc fc fa fb fc fc fa fb fc fc > >> ffff888108f35300: fa fb fc fc fa fb fc fc fa fb fc fc fa fb fc fc > >>> ffff888108f35380: fa fb fc fc fa fb fc fc fa fb fc fc fa fb fc fc > >> ^ > >> ffff888108f35400: fa fb fc fc fc fc fc fc fc fc fc fc fc fc fc fc > >> ffff888108f35480: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc > >> > >> Fixes: 7be3248f3139 ("cifs: To match file servers, make sure the server hostname matches") > >> Signed-off-by: Zeng Heng <zengheng4@huawei.com> > >> Reviewed-by: Paulo Alcantara (SUSE) <pc@cjr.nz> > >> --- > >> changes in v4: > >> - correct fix tag > >> - add reviewed-by > >> --- > >> fs/cifs/connect.c | 1 + > >> 1 file changed, 1 insertion(+) > >> > >> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c > >> index ffb291579bb9..1cc47dd3b4d6 100644 > >> --- a/fs/cifs/connect.c > >> +++ b/fs/cifs/connect.c > >> @@ -1584,6 +1584,7 @@ cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect) > >> server->session_key.response = NULL; > >> server->session_key.len = 0; > >> kfree(server->hostname); > >> + server->hostname = NULL; > >> > >> task = xchg(&server->tsk, NULL); > >> if (task) > >> -- > >> 2.25.1 > >> > > Good catch. But I think there can be a better fix. > > How about moving the lines that follow i.e. cifsd thread kill to > > before setting tcpStatus? That way, we don't leave scope for things to > > race. > > Good point. We need to ensure that.
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index ffb291579bb9..1cc47dd3b4d6 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1584,6 +1584,7 @@ cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect) server->session_key.response = NULL; server->session_key.len = 0; kfree(server->hostname); + server->hostname = NULL; task = xchg(&server->tsk, NULL); if (task)