linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: butt3rflyh4ck <butterflyhuangxx@gmail.com>
To: Qu Wenruo <quwenruo.btrfs@gmx.com>
Cc: clm@fb.com, Josef Bacik <josef@toxicpanda.com>,
	dsterba@suse.com, linux-btrfs@vger.kernel.org
Subject: Re: A null-ptr-dereference bug in btrfs_rm_device in fs/btrfs/volumes.c
Date: Sat, 7 Aug 2021 14:00:17 +0800	[thread overview]
Message-ID: <CAFcO6XO5TC5sEo-C9JGC75JkNAzkOSSLA3a=bwQqXFFbRTZ7Gw@mail.gmail.com> (raw)
In-Reply-To: <30a749de-8228-05ad-13bc-15d6ac010e40@gmx.com>

Yes, please do.

Regards,
 butt3rflyh4ck.

On Fri, Aug 6, 2021 at 5:59 PM Qu Wenruo <quwenruo.btrfs@gmx.com> wrote:
>
>
>
> On 2021/8/6 下午5: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 device,
> > 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 ‘CAP_SYS_ADMIN’ 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 = file_inode(file);
> >          struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
> >          struct btrfs_ioctl_vol_args_v2 *vol_args;
> >          int ret;
> >          bool cancel = false;
> >
> >          if (!capable(CAP_SYS_ADMIN))   ///------------>  ‘CAP_SYS_ADMIN’  need
> >                  return -EPERM;
> >
> >           ...
> >
> >          vol_args = memdup_user(arg, sizeof(*vol_args));  //
> > -------------> copy a user data from 'arg' to vol_args.
> >          if (IS_ERR(vol_args)) {
> >                  ret = PTR_ERR(vol_args);
> >                  goto err_drop;
> >          }
> >
> >         ...
> >
> >                 if (vol_args->flags & BTRFS_DEVICE_SPEC_BY_ID)
> > //---------------> here would judge vol_args->flags
> >                  ret = btrfs_rm_device(fs_info, NULL, vol_args->devid);
> >   // ------------->call btrfs_rm_device
> >          else
> >                  ret = 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_path,
> >                      u64 devid)
> > {
> >          struct btrfs_device *device;
> >          struct btrfs_fs_devices *cur_devices;
> >          struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
> >          u64 num_devices;
> >          int ret = 0;
> >
> >          mutex_lock(&uuid_mutex);
> >
> >          num_devices = btrfs_num_devices(fs_info);
> >
> >          ret = btrfs_check_raid_min_devices(fs_info, num_devices - 1);
> >          if (ret)
> >                  goto out;
> >
> >          device = 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) == -ENOENT &&
> >                      strcmp(device_path, "missing") == 0)
> > //-----------------> use device_path pointer,  but device_patch is
> > NULL.
> >                          ret = BTRFS_ERROR_DEV_MISSING_NOT_FOUND;
> >                  else
> >                          ret = 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 = 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 optimizations
> > [   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 <f3>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 <f3>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



-- 
Active Defense Lab of Venustech

      reply	other threads:[~2021-08-07  6:00 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-06  9:52 butt3rflyh4ck
2021-08-06  9:59 ` Qu Wenruo
2021-08-07  6:00   ` butt3rflyh4ck [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAFcO6XO5TC5sEo-C9JGC75JkNAzkOSSLA3a=bwQqXFFbRTZ7Gw@mail.gmail.com' \
    --to=butterflyhuangxx@gmail.com \
    --cc=clm@fb.com \
    --cc=dsterba@suse.com \
    --cc=josef@toxicpanda.com \
    --cc=linux-btrfs@vger.kernel.org \
    --cc=quwenruo.btrfs@gmx.com \
    --subject='Re: A null-ptr-dereference bug in btrfs_rm_device in fs/btrfs/volumes.c' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).