All of lore.kernel.org
 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 A null-ptr-dereference bug in btrfs_rm_device in fs/btrfs/volumes.c 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 \
    /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
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.