[Race] data race between blkdev_ioctl() and generic_fadvise()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

We found a data race in linux kernel 5.3.11 that we are able to reproduce in x86 under specific interleavings. Currently, we are not sure about the consequence of this race so we would like to confirm with the community if this is a harmful bug.

------------------------------------------
Writer site

 /tmp/tmp.B7zb7od2zE-5.3.11/extract/linux-5.3.11/block/ioctl.c:573
        553      case BLKPBSZGET: /* get block device physical block size */
        554          return put_uint(arg, bdev_physical_block_size(bdev));
        555      case BLKIOMIN:
        556          return put_uint(arg, bdev_io_min(bdev));
        557      case BLKIOOPT:
        558          return put_uint(arg, bdev_io_opt(bdev));
        559      case BLKALIGNOFF:
        560          return put_int(arg, bdev_alignment_offset(bdev));
        561      case BLKDISCARDZEROES:
        562          return put_uint(arg, 0);
        563      case BLKSECTGET:
        564          max_sectors = min_t(unsigned int, USHRT_MAX,
        565                      queue_max_sectors(bdev_get_queue(bdev)));
        566          return put_ushort(arg, max_sectors);
        567      case BLKROTATIONAL:
        568          return put_ushort(arg, !blk_queue_nonrot(bdev_get_queue(bdev)));
        569      case BLKRASET:
        570      case BLKFRASET:
        571          if(!capable(CAP_SYS_ADMIN))
        572              return -EACCES;
 ==>    573          bdev->bd_bdi->ra_pages = (arg * 512) / PAGE_SIZE;
        574          return 0;
        575      case BLKBSZSET:
        576          return blkdev_bszset(bdev, mode, argp);
        577      case BLKPG:
        578          return blkpg_ioctl(bdev, argp);
        579      case BLKRRPART:
        580          return blkdev_reread_part(bdev);
        581      case BLKGETSIZE:
        582          size = i_size_read(bdev->bd_inode);
        583          if ((size >> 9) > ~0UL)
        584              return -EFBIG;
        585          return put_ulong(arg, size >> 9);
        586      case BLKGETSIZE64:
        587          return put_u64(arg, i_size_read(bdev->bd_inode));
        588      case BLKTRACESTART:
        589      case BLKTRACESTOP:
        590      case BLKTRACESETUP:
        591      case BLKTRACETEARDOWN:
        592          return blk_trace_ioctl(bdev, cmd, argp);
        593      case IOC_PR_REGISTER:

------------------------------------------
Reader site
/tmp/tmp.B7zb7od2zE-5.3.11/extract/linux-5.3.11/mm/fadvise.c:79
         66      /*
         67       * Careful about overflows. Len == 0 means "as much as possible".  Use
         68       * unsigned math because signed overflows are undefined and UBSan
         69       * complains.
         70       */
         71      endbyte = (u64)offset + (u64)len;
         72      if (!len || endbyte < len)
         73          endbyte = -1;
         74      else
         75          endbyte--;      /* inclusive */
         76
         77      switch (advice) {
         78      case POSIX_FADV_NORMAL:
 ==>     79          file->f_ra.ra_pages = bdi->ra_pages;
         80          spin_lock(&file->f_lock);
         81          file->f_mode &= ~FMODE_RANDOM;
         82          spin_unlock(&file->f_lock);
         83          break;
         84      case POSIX_FADV_RANDOM:
         85          spin_lock(&file->f_lock);
         86          file->f_mode |= FMODE_RANDOM;
         87          spin_unlock(&file->f_lock);
         88          break;
         89      case POSIX_FADV_SEQUENTIAL:
         90          file->f_ra.ra_pages = bdi->ra_pages * 2;
         91          spin_lock(&file->f_lock);
         92          file->f_mode &= ~FMODE_RANDOM;
         93          spin_unlock(&file->f_lock);
         94          break;
         95      case POSIX_FADV_WILLNEED:
         96          /* First and last PARTIAL page! */
         97          start_index = offset >> PAGE_SHIFT;
         98          end_index = endbyte >> PAGE_SHIFT;



------------------------------------------
Writer calling trace

- ksys_ioctl
-- do_vfs_ioctl
--- vfs_ioctl
---- blkdev_ioctl

------------------------------------------
Reader calling trace
- ksys_fadvise64_64
-- vfs_fadvise
--- generic_fadvise



Thanks,
Sishuai






[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux