Race: data race between shmem_getpage() and mapping_set_gfp_mask()

[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 can be a harmful bug.

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

 /tmp/tmp.B7zb7od2zE-5.3.11/extract/linux-5.3.11/include/linux/pagemap.h:118
         98  }
         99
        100  static inline gfp_t mapping_gfp_mask(struct address_space * mapping)
        101  {
        102      return mapping->gfp_mask;
        103  }
        104
        105  /* Restricts the given gfp_mask to what the mapping allows. */
        106  static inline gfp_t mapping_gfp_constraint(struct address_space *mapping,
        107          gfp_t gfp_mask)
        108  {
        109      return mapping_gfp_mask(mapping) & gfp_mask;
        110  }
        111
        112  /*
        113   * This is non-atomic.  Only to be used before the mapping is activated.
        114   * Probably needs a barrier...
        115   */
        116  static inline void mapping_set_gfp_mask(struct address_space *m, gfp_t mask)
        117  {
 ==>    118      m->gfp_mask = mask;
        119  }

------------------------------------------
Reader site

/tmp/tmp.B7zb7od2zE-5.3.11/extract/linux-5.3.11/mm/shmem.c:139
        119
        120      return min(nr_pages - totalhigh_pages(), nr_pages / 2);
        121  }
        122  #endif
        123
        124  static bool shmem_should_replace_page(struct page *page, gfp_t gfp);
        125  static int shmem_replace_page(struct page **pagep, gfp_t gfp,
        126                  struct shmem_inode_info *info, pgoff_t index);
        127  static int shmem_swapin_page(struct inode *inode, pgoff_t index,
        128                   struct page **pagep, enum sgp_type sgp,
        129                   gfp_t gfp, struct vm_area_struct *vma,
        130                   vm_fault_t *fault_type);
        131  static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
        132          struct page **pagep, enum sgp_type sgp,
        133          gfp_t gfp, struct vm_area_struct *vma,
        134          struct vm_fault *vmf, vm_fault_t *fault_type);
        135
        136  int shmem_getpage(struct inode *inode, pgoff_t index,
        137          struct page **pagep, enum sgp_type sgp)
        138  {
 ==>    139      return shmem_getpage_gfp(inode, index, pagep, sgp,
        140          mapping_gfp_mask(inode->i_mapping), NULL, NULL, NULL);
        141  }
        

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

- ksys_ioctl
-- do_vfs_ioctl
--- vfs_ioctl
---- blkdev_ioctl
----- __blkdev_driver_ioctl
------ loop_set_fd

------------------------------------------
Reader calling trace

- ksys_read
-- vfs_read
--- __vfs_read
---- shmem_getpage



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