static inline void arch_unmap(struct mm_struct *mm,
                              unsigned long start, unsigned long end)
 {
-       unsigned long vdso_base = (unsigned long)mm->context.vdso;
-
-       if (start <= vdso_base && vdso_base < end)
-               mm->context.vdso = NULL;
 }
 
 #ifdef CONFIG_PPC_MEM_KEYS
 
        return vdso_mremap(sm, new_vma, &vdso64_end - &vdso64_start);
 }
 
+static void vdso_close(const struct vm_special_mapping *sm, struct vm_area_struct *vma)
+{
+       struct mm_struct *mm = vma->vm_mm;
+
+       /*
+        * close() is called for munmap() but also for mremap(). In the mremap()
+        * case the vdso pointer has already been updated by the mremap() hook
+        * above, so it must not be set to NULL here.
+        */
+       if (vma->vm_start != (unsigned long)mm->context.vdso)
+               return;
+
+       mm->context.vdso = NULL;
+}
+
 static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
                             struct vm_area_struct *vma, struct vm_fault *vmf);
 
 static struct vm_special_mapping vdso32_spec __ro_after_init = {
        .name = "[vdso]",
        .mremap = vdso32_mremap,
+       .close = vdso_close,
 };
 
 static struct vm_special_mapping vdso64_spec __ro_after_init = {
        .name = "[vdso]",
        .mremap = vdso64_mremap,
+       .close = vdso_close,
 };
 
 #ifdef CONFIG_TIME_NS