From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.9 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,NICE_REPLY_A,SPF_HELO_NONE, SPF_PASS,USER_AGENT_SANE_1 autolearn=no autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BE919C432BE for ; Fri, 6 Aug 2021 09:59:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A6C7860ED6 for ; Fri, 6 Aug 2021 09:59:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244788AbhHFJ7u (ORCPT ); Fri, 6 Aug 2021 05:59:50 -0400 Received: from mout.gmx.net ([212.227.15.18]:53887 "EHLO mout.gmx.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244717AbhHFJ7t (ORCPT ); Fri, 6 Aug 2021 05:59:49 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gmx.net; s=badeba3b8450; t=1628243957; bh=+KEi0FRZFBN7XAaW7PZ7XTiqUsYOzmGpUX8S/pEkTC8=; h=X-UI-Sender-Class:Subject:To:Cc:References:From:Date:In-Reply-To; b=EHVGFVrzMjxAnDCVYRsPt11ICA9PjrKSsjkC2+RUB+jlW2Hn4d5nJAYxBKM+sT7XZ z1+5UlzHi8jtbBiUpPUMaN7W9L/xQ6XbGQAq8q6s9hOFsSURfCAoPoTAVLomFYh2hI 0FO5Mwht3I7AmmPnnJDkcNaskTnw4+YF0eWLWtxQ= X-UI-Sender-Class: 01bb95c1-4bf8-414a-932a-4f6e2808ef9c Received: from [0.0.0.0] ([149.28.201.231]) by mail.gmx.net (mrgmx005 [212.227.17.184]) with ESMTPSA (Nemesis) id 1N6KUd-1nDjJt2tD7-016h8c; Fri, 06 Aug 2021 11:59:17 +0200 Subject: Re: A null-ptr-dereference bug in btrfs_rm_device in fs/btrfs/volumes.c To: butt3rflyh4ck , clm@fb.com, Josef Bacik , dsterba@suse.com Cc: linux-btrfs@vger.kernel.org References: From: Qu Wenruo Message-ID: <30a749de-8228-05ad-13bc-15d6ac010e40@gmx.com> Date: Fri, 6 Aug 2021 17:59:12 +0800 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.12.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: quoted-printable X-Provags-ID: V03:K1:v69Ghrt3wKDUY5I+6SnGBDMWXi4vLhzb/FkyJD8LebbSXW6dMT8 ZtI0JGLed7uMjgKQO7LdfI1ruQEjUr+H6tWQCLSngZYXlcLO3K9vwONd7SlhcNw4POXCNvA 7FBofjNCa5W5cPKhu6hbBcr87KDvPPrYX5yl5Vv1S2VRxpRM9eJSwFIZHkgrVlcuFHuzTDJ CtNzDPZEKKt2YPWAqkpVA== X-UI-Out-Filterresults: notjunk:1;V03:K0:3cx4nIES19c=:qCQHA26V0uY4S46zRLLruv SWb2Bg92MERaJI0nlayPBHeklEGtCAu8ssLea0MvdRrYKJd5QTejSJm8Ea0ot6KDT7w29nUku GHGFGUwFk2uUWS6RrSztkgJ4HxjTgKFwhlCkCpUazWTxrcAXx9EhY0nLkoUHMsclXBBL5qiwd Idc5F+XQAWDgXxEfqTeMjNwFirLiHOEaYwf/0mrZhoa8E1Cpo1Cbh74IW+KN3cu5YPyBbpy4v AXIr4Ggl9ZbNYSXSTexo3a1OF6Hqm/CjPtQlcfrIR7syLZGUJzQqq4mFBJspEWPuvrxdJ+5Tp nlJEcBD2umUGRm23ELwtikf3rwVDjWqtXgWdP1So3/4JIciY9S2jjaa2lDXgDmTFz9gPmAtKG T17+sF48D6sYIcUdMURhV8rV9kLZepCPRmSRH7kHWZWQI1EJU34a6EtUCu8dfotleQ2Oc1IEt NbogAfHvtSJrTJ1wdR18+sB8yFK68JRR3lwLtqUKGjlOz50icdOLc4wDzoh3W+7JO1Co1hFtD coBbxIA1paT9XhgFS3+IoKV21q/CABiuuAa9VOeSEsznEoS+uj1bDXR7+asg1Wik6w/frluc7 C5uIueA1sQ69sXHFAPN5wYInotjsGkSweMQT0LXNBY7iG+D/kShpCJh7aNCcmajxMbY/w7f0E zsDWrZQz6ClZlCr6KBMqPZNGJg27ELAjahkt3NTN10V5wBuz7f59c3ms3KmhXUL4lRmLgDKbd ZghM07SqEp8NDMN4MYYZxzzRHz/MDAPgxdnJNJGFKI6VBQ9YPWWFhzdcrT2oitNKM5f0c/1N4 g7EFrjm2cVHS21mrgd5aB2Sqlei9rCKmtrZOGr0PiTwb6DrYKdx2KDZd6UOtqTqoDUochQOGu KRQPhv0SW6ZamKEhA2WMCG6T8UiXLQeDmj4DrLKDet47SF9Q+jyVEfMJ58Hs3CYHDyDZHdpm6 k1FetG+2VAmcZ+PzBh7AVBvDgPS5WCLtxA5sZlB0Y/xFOqyBfnTi6MIYZRQEX4wZALlaPkZva kwCFURLGZcHpCLxunup//qgm7A6YLRLc8Dzrb2KTDrtrLy5WO8OWVSgUp2G7AKm+SIJvwQRnI 8IyyKHZX4Ukzux5R82etSrhzeE1ldhZEJ5w6ooZRoHVU1ahN8N4ds412A== Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org On 2021/8/6 =E4=B8=8B=E5=8D=885:52, butt3rflyh4ck wrote: > Hello, there is a null pointer dereference bug in the btrfs_rm_device > function in fs/btrfs/volumes.c. > When a user invokes a BTRFS_IOC_RM_DEV_V2 ioctl to remove a volume devic= e, > it would call btrfs_ioctl_rm_dev_v2 function to implement. And > btrfs_ioctl_rm_dev_v2 would call btrfs_rm_device, > if the id of the volume device is illegal, it would trigger a > null-ptr-deref bug to cause DoS. > Fortunately, invoking this function requires =E2=80=98CAP_SYS_ADMIN=E2= =80=99 advanced > permissions. > > Ok, let us see the code as follows: > btrfs_ioctl_rm_dev_v2 > `````` > static long btrfs_ioctl_rm_dev_v2(struct file *file, void __user *arg) > { > struct inode *inode =3D file_inode(file); > struct btrfs_fs_info *fs_info =3D btrfs_sb(inode->i_sb); > struct btrfs_ioctl_vol_args_v2 *vol_args; > int ret; > bool cancel =3D false; > > if (!capable(CAP_SYS_ADMIN)) ///------------> =E2=80=98CAP_S= YS_ADMIN=E2=80=99 need > return -EPERM; > > ... > > vol_args =3D memdup_user(arg, sizeof(*vol_args)); // > -------------> copy a user data from 'arg' to vol_args. > if (IS_ERR(vol_args)) { > ret =3D PTR_ERR(vol_args); > goto err_drop; > } > > ... > > if (vol_args->flags & BTRFS_DEVICE_SPEC_BY_ID) > //---------------> here would judge vol_args->flags > ret =3D btrfs_rm_device(fs_info, NULL, vol_args->devid)= ; > // ------------->call btrfs_rm_device > else > ret =3D btrfs_rm_device(fs_info, vol_args->name, 0); > > ```` > if the vol_args->flags is BTRFS_DEVICE_SPEC_BY_ID, it would also > call btrfs_rm_device function, > the second arg type is a pointer,but the second arg is NULL, the third > arg is a id of volome device. > > Let us see the code as follows: > btrfs_rm_device > ```` > int btrfs_rm_device(struct btrfs_fs_info *fs_info, const char *device_pa= th, > u64 devid) > { > struct btrfs_device *device; > struct btrfs_fs_devices *cur_devices; > struct btrfs_fs_devices *fs_devices =3D fs_info->fs_devices; > u64 num_devices; > int ret =3D 0; > > mutex_lock(&uuid_mutex); > > num_devices =3D btrfs_num_devices(fs_info); > > ret =3D btrfs_check_raid_min_devices(fs_info, num_devices - 1); > if (ret) > goto out; > > device =3D btrfs_find_device_by_devspec(fs_info, devid, > device_path); // ------------> this function would get a volume > device by devid. > > if (IS_ERR(device)) { > if (PTR_ERR(device) =3D=3D -ENOENT && > strcmp(device_path, "missing") =3D=3D 0) > //-----------------> use device_path pointer, but device_patch is > NULL. > ret =3D BTRFS_ERROR_DEV_MISSING_NOT_FOUND; > else > ret =3D PTR_ERR(device); > goto out; > } > ```` > btrfs_find_device_by_devspec would lookup a volume device by devid, > ``` > * Lookup a device given by device id, or the path if the id is 0. > */ > struct btrfs_device *btrfs_find_device_by_devspec( > struct btrfs_fs_info *fs_info, u64 devid, > const char *device_path) > { > struct btrfs_device *device; > > if (devid) { > device =3D btrfs_find_device(fs_info->fs_devices, devid= , NULL, > NULL); > if (!device) > return ERR_PTR(-ENOENT); // -----> if not > lookup a device, it return -ENOENT error. > return device; > } > > .... > > ``` > After returning an -ENOENT error, it would call strcmp to compare > device_path with 'missing'. > As our previous analysis, device_path is NULL, it would trigger a > null-ptr-deref bug. > > crash log: > root@syzkaller:/home/user# ./btrfs_rm_device > [ 46.204657][ T8385] loop0: detected capacity change from 0 to 32768 > [ 46.218173][ T8385] BTRFS: device fsid > 195aeaee-03bd-442f-8f6e-93f8f339d194 devid 1 transid 7 /dev/loop0 > scanned by btrfs_rm_device (8385) > [ 46.238597][ T8385] BTRFS info (device loop0): disabling tree log > [ 46.239838][ T8385] BTRFS info (device loop0): disk space caching is = enabled > [ 46.241198][ T8385] BTRFS info (device loop0): has skinny extents > [ 46.253597][ T8385] BTRFS info (device loop0): enabling ssd optimizat= ions > [ 46.286692][ T8385] BUG: kernel NULL pointer dereference, address: > 0000000000000000 > [ 46.288135][ T8385] #PF: supervisor read access in kernel mode > [ 46.289222][ T8385] #PF: error_code(0x0000) - not-present page > [ 46.290308][ T8385] PGD 4618d067 P4D 4618d067 PUD 4616b067 PMD 0 > [ 46.291469][ T8385] Oops: 0000 [#1] PREEMPT SMP > [ 46.292247][ T8385] CPU: 0 PID: 8385 Comm: btrfs_rm_device Not > tainted 5.14.0-rc4+ #4 > [ 46.293485][ T8385] Hardware name: QEMU Standard PC (i440FX + PIIX, > 1996), BIOS 1.13.0-1ubuntu1 04/01/2014 > [ 46.295205][ T8385] RIP: 0010:btrfs_rm_device+0x487/0x6d0 > [ 46.296136][ T8385] Code: fe 74 18 45 89 f4 e9 91 fd ff ff 48 89 df > 45 89 ec e8 bd e3 f9 ff e9 2f ff ff ff 48 c7 c7 6a d1 a2 84 b9 08 00 > 00 00 4c 89 ee b > [ 46.299535][ T8385] RSP: 0018:ffffc9000560bd90 EFLAGS: 00010246 > [ 46.300588][ T8385] RAX: fffffffffffffffe RBX: 0000000000000000 > RCX: 0000000000000008 > [ 46.301961][ T8385] RDX: fffffffffffffffe RSI: 0000000000000000 > RDI: ffffffff84a2d16a > [ 46.303374][ T8385] RBP: ffff88804939c000 R08: ffff888013010600 > R09: 0000000000000001 > [ 46.304793][ T8385] R10: 0000000000000001 R11: 00000000001357f7 > R12: 0000000000000008 > [ 46.306238][ T8385] R13: 0000000000000000 R14: fffffffffffffffe > R15: ffffffff83d8c123 > [ 46.307614][ T8385] FS: 000000000214a880(0000) > GS:ffff88803ec00000(0000) knlGS:0000000000000000 > [ 46.308999][ T8385] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 > [ 46.310141][ T8385] CR2: 0000000000000000 CR3: 0000000046200000 > CR4: 00000000000006f0 > [ 46.311604][ T8385] Call Trace: > [ 46.312123][ T8385] btrfs_ioctl+0xba8/0x31b0 > [ 46.312821][ T8385] ? __x64_sys_ioctl+0x7b/0xb0 > [ 46.313655][ T8385] __x64_sys_ioctl+0x7b/0xb0 > [ 46.314460][ T8385] do_syscall_64+0x35/0xb0 > [ 46.315454][ T8385] entry_SYSCALL_64_after_hwframe+0x44/0xae > [ 46.316501][ T8385] RIP: 0033:0x44f51d > [ 46.317178][ T8385] Code: 02 b8 ff ff ff ff c3 66 0f 1f 44 00 00 f3 > 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b > 4c 24 08 0f 05 <48>8 > [ 46.320656][ T8385] RSP: 002b:00007ffc361763e8 EFLAGS: 00000283 > ORIG_RAX: 0000000000000010 > [ 46.321991][ T8385] RAX: ffffffffffffffda RBX: 0000000000400530 > RCX: 000000000044f51d > [ 46.323410][ T8385] RDX: 0000000020001d80 RSI: 000000005000943a > RDI: 0000000000000005 > [ 46.324773][ T8385] RBP: 00007ffc36176400 R08: 0000000020001db0 > R09: 0000000000000000 > [ 46.326029][ T8385] R10: 0000000000000000 R11: 0000000000000283 > R12: 00000000004042a0 > [ 46.327388][ T8385] R13: 0000000000000000 R14: 00000000004ca018 > R15: 0000000000000000 > [ 46.328775][ T8385] Modules linked in: > [ 46.329458][ T8385] CR2: 0000000000000000 > [ 46.330389][ T8385] ---[ end trace 1cb21b999dbc3d91 ]--- > [ 46.331249][ T8385] RIP: 0010:btrfs_rm_device+0x487/0x6d0 > [ 46.332180][ T8385] Code: fe 74 18 45 89 f4 e9 91 fd ff ff 48 89 df > 45 89 ec e8 bd e3 f9 ff e9 2f ff ff ff 48 c7 c7 6a d1 a2 84 b9 08 00 > 00 00 4c 89 ee b > [ 46.335928][ T8385] RSP: 0018:ffffc9000560bd90 EFLAGS: 00010246 > [ 46.337120][ T8385] RAX: fffffffffffffffe RBX: 0000000000000000 > RCX: 0000000000000008 > [ 46.338710][ T8385] RDX: fffffffffffffffe RSI: 0000000000000000 > RDI: ffffffff84a2d16a > [ 46.340164][ T8385] RBP: ffff88804939c000 R08: ffff888013010600 > R09: 0000000000000001 > [ 46.341611][ T8385] R10: 0000000000000001 R11: 00000000001357f7 > R12: 0000000000000008 > [ 46.343055][ T8385] R13: 0000000000000000 R14: fffffffffffffffe > R15: ffffffff83d8c123 > [ 46.344521][ T8385] FS: 000000000214a880(0000) > GS:ffff88803ec00000(0000) knlGS:0000000000000000 > [ 46.346265][ T8385] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 > [ 46.347470][ T8385] CR2: 0000000000000000 CR3: 0000000046200000 > CR4: 00000000000006f0 > [ 46.348918][ T8385] Kernel panic - not syncing: Fatal exception > [ 46.350160][ T8385] Kernel Offset: disabled > [ 46.350978][ T8385] Rebooting in 86400 seconds.. > > the attachment is reproduce. Awesome analyse and reproducer. > > Regards, > butt3rflyh4ck. > BTW, would you like us to use "butt3rflyh4ck" as reported-by user name? Normally we use real names for reported-by, not sure if "butt3rflyh4ck" would work here. (Awesome hacky ID though) Thanks, Qu