diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c index a6bfcc8243cd..9a953e7c76db 100644 --- a/arch/x86/entry/vdso/vma.c +++ b/arch/x86/entry/vdso/vma.c @@ -6,6 +6,7 @@ */ #include #include +#include #include #include #include @@ -73,6 +74,31 @@ static void vdso_fix_landing(const struct vdso_image *image, regs->ip = new_vma->vm_start + ipoffset; } +#ifdef CONFIG_FUTEX_ROBUST_UNLOCK +static void vdso_futex_robust_unlock_update_ips(void) +{ + const struct vdso_image *image = current->mm->context.vdso_image; + unsigned long vdso = (unsigned long) current->mm->context.vdso; + struct futex_mm_data *fd = ¤t->mm->futex; + unsigned int idx = 0; + + futex_reset_cs_ranges(fd); + +#ifdef CONFIG_X86_64 + futex_set_vdso_cs_range(fd, idx, vdso + image->sym___futex_list64_try_unlock_cs_start, + vdso + image->sym___futex_list64_try_unlock_cs_end, false); + idx++; +#endif /* CONFIG_X86_64 */ + +#if defined(CONFIG_X86_32) || defined(CONFIG_COMPAT) + futex_set_vdso_cs_range(fd, idx, vdso + image->sym___futex_list32_try_unlock_cs_start, + vdso + image->sym___futex_list32_try_unlock_cs_end, true); +#endif /* CONFIG_X86_32 || CONFIG_COMPAT */ +} +#else +static inline void vdso_futex_robust_unlock_update_ips(void) { } +#endif + static int vdso_mremap(const struct vm_special_mapping *sm, struct vm_area_struct *new_vma) { @@ -80,6 +106,7 @@ static int vdso_mremap(const struct vm_special_mapping *sm, vdso_fix_landing(image, new_vma); current->mm->context.vdso = (void __user *)new_vma->vm_start; + vdso_futex_robust_unlock_update_ips(); return 0; } @@ -185,6 +212,8 @@ static int map_vdso(const struct vdso_image *image, unsigned long addr) current->mm->context.vdso = (void __user *)text_start; current->mm->context.vdso_image = image; + vdso_futex_robust_unlock_update_ips(); + up_fail: mmap_write_unlock(mm); return ret; diff --git a/arch/x86/include/asm/vdso.h b/arch/x86/include/asm/vdso.h index f2d49212ae90..4e735158c1b2 100644 --- a/arch/x86/include/asm/vdso.h +++ b/arch/x86/include/asm/vdso.h @@ -24,6 +24,10 @@ struct vdso_image { long sym_int80_landing_pad; long sym_vdso32_sigreturn_landing_pad; long sym_vdso32_rt_sigreturn_landing_pad; + long sym___futex_list64_try_unlock_cs_start; + long sym___futex_list64_try_unlock_cs_end; + long sym___futex_list32_try_unlock_cs_start; + long sym___futex_list32_try_unlock_cs_end; }; extern const struct vdso_image vdso64_image; diff --git a/arch/x86/tools/vdso2c.c b/arch/x86/tools/vdso2c.c index b8a555763f43..64a636b9fc37 100644 --- a/arch/x86/tools/vdso2c.c +++ b/arch/x86/tools/vdso2c.c @@ -75,12 +75,16 @@ struct vdso_sym { }; struct vdso_sym required_syms[] = { - {"__kernel_vsyscall", true}, - {"__kernel_sigreturn", true}, - {"__kernel_rt_sigreturn", true}, - {"int80_landing_pad", true}, - {"vdso32_rt_sigreturn_landing_pad", true}, - {"vdso32_sigreturn_landing_pad", true}, + {"__kernel_vsyscall", true}, + {"__kernel_sigreturn", true}, + {"__kernel_rt_sigreturn", true}, + {"int80_landing_pad", true}, + {"vdso32_rt_sigreturn_landing_pad", true}, + {"vdso32_sigreturn_landing_pad", true}, + {"__futex_list64_try_unlock_cs_start", true}, + {"__futex_list64_try_unlock_cs_end", true}, + {"__futex_list32_try_unlock_cs_start", true}, + {"__futex_list32_try_unlock_cs_end", true}, }; __attribute__((format(printf, 1, 2))) __attribute__((noreturn))