Le 01/09/2022 à 19:35, Suren Baghdasaryan a écrit : > Assert there are no holders of VMA lock for reading when it is about to be > destroyed. > > Signed-off-by: Suren Baghdasaryan <surenb@xxxxxxxxxx> > --- > include/linux/mm.h | 8 ++++++++ > kernel/fork.c | 2 ++ > 2 files changed, 10 insertions(+) > > diff --git a/include/linux/mm.h b/include/linux/mm.h > index dc72be923e5b..0d9c1563c354 100644 > --- a/include/linux/mm.h > +++ b/include/linux/mm.h > @@ -676,6 +676,13 @@ static inline void vma_assert_write_locked(struct vm_area_struct *vma, int pos) > VM_BUG_ON_VMA(vma->vm_lock_seq != READ_ONCE(vma->vm_mm->mm_lock_seq), vma); > } > > +static inline void vma_assert_no_reader(struct vm_area_struct *vma) > +{ > + VM_BUG_ON_VMA(rwsem_is_locked(&vma->lock) && > + vma->vm_lock_seq != READ_ONCE(vma->vm_mm->mm_lock_seq), > + vma); > +} > + > #else /* CONFIG_PER_VMA_LOCK */ > > static inline void vma_init_lock(struct vm_area_struct *vma) {} > @@ -685,6 +692,7 @@ static inline bool vma_read_trylock(struct vm_area_struct *vma) > static inline void vma_read_unlock(struct vm_area_struct *vma) {} > static inline void vma_assert_locked(struct vm_area_struct *vma) {} > static inline void vma_assert_write_locked(struct vm_area_struct *vma, int pos) {} > +static inline void vma_assert_no_reader(struct vm_area_struct *vma) {} > > #endif /* CONFIG_PER_VMA_LOCK */ > > diff --git a/kernel/fork.c b/kernel/fork.c > index 1872ad549fed..b443ba3a247a 100644 > --- a/kernel/fork.c > +++ b/kernel/fork.c > @@ -487,6 +487,8 @@ static void __vm_area_free(struct rcu_head *head) > { > struct vm_area_struct *vma = container_of(head, struct vm_area_struct, > vm_rcu); > + /* The vma should either have no lock holders or be write-locked. */ > + vma_assert_no_reader(vma); I'm wondering if this can be hit in the case the thread freeing a VMA is preempted before incrementing the mm ref count, like this: VMA is about to be freed write lock VMA free vma -> call_rcu .. <--- thread preempted rcu handler runs rcu calls __vm_area_free() <<<<<< unlock mmap_lock and increase the mm seq count > kmem_cache_free(vm_area_cachep, vma); > } > #endif