From d6b00d6c16c9f525693e8be653f1e721d779a68d Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Mon, 28 Oct 2019 11:36:02 +0800 Subject: [PATCH] arm64: vdso: move vdso_fix into struct vdso_data hulk inclusion category: bugfix bugzilla: 16082 CVE: NA ------------------------------------------------- Using static key type may cause segmentation fault in bionic, change type of vdso_fix to bool and move it int struct vdso_data. On Hi1620, without this patch, gettimeofday costs 0.02775: ./gettimeofday -E -C 200 -L -S -W -N "gettimeofday" Running: gettimeofday# ./gettimeofday -E -C 200 -L -S -W -N gettimeofday prc thr usecs/call samples errors cnt/samp gettimeofday 1 1 0.02775 174 0 20000 with this patch, gettimeofday costs 0.02701: ./gettimeofday -E -C 200 -L -S -W -N "gettimeofday" Running: gettimeofday# ./gettimeofday -E -C 200 -L -S -W -N gettimeofday prc thr usecs/call samples errors cnt/samp gettimeofday 1 1 0.02701 170 0 20000 On Hi1616, without this patch, gettimeofday costs 0.03396: ./gettimeofday -E -C 200 -L -S -W -N "gettimeofday" Running: gettimeofday# ./gettimeofday -E -C 200 -L -S -W -N gettimeofday prc thr usecs/call samples errors cnt/samp gettimeofday 1 1 0.03396 194 0 20000 with this patch, gettimeofday costs 0.03660: ./gettimeofday -E -C 200 -L -S -W -N "gettimeofday" Running: gettimeofday# ./gettimeofday -E -C 200 -L -S -W -N gettimeofday prc thr usecs/call samples errors cnt/samp gettimeofday 1 1 0.03660 200 0 20000 Signed-off-by: Yang Yingliang Reviewed-by: Xuefeng Wang Signed-off-by: Yang Yingliang --- arch/arm64/include/asm/clocksource.h | 1 + arch/arm64/include/asm/vdso_datapage.h | 1 + arch/arm64/kernel/asm-offsets.c | 1 + arch/arm64/kernel/vdso.c | 1 + arch/arm64/kernel/vdso/gettimeofday.c | 3 +-- drivers/clocksource/arm_arch_timer.c | 8 ++++---- 6 files changed, 9 insertions(+), 6 deletions(-) diff --git a/arch/arm64/include/asm/clocksource.h b/arch/arm64/include/asm/clocksource.h index 0ece64a26c8c..734428342ebf 100644 --- a/arch/arm64/include/asm/clocksource.h +++ b/arch/arm64/include/asm/clocksource.h @@ -4,6 +4,7 @@ struct arch_clocksource_data { bool vdso_direct; /* Usable for direct VDSO access? */ + bool vdso_fix; /* Need avoid the clock bug in VDSO? */ }; #endif diff --git a/arch/arm64/include/asm/vdso_datapage.h b/arch/arm64/include/asm/vdso_datapage.h index f89263c8e11a..6c466a041d75 100644 --- a/arch/arm64/include/asm/vdso_datapage.h +++ b/arch/arm64/include/asm/vdso_datapage.h @@ -39,6 +39,7 @@ struct vdso_data { __u32 tz_dsttime; __u32 use_syscall; __u32 hrtimer_res; + __u32 vdso_fix; /* Avoid the clock bug in VDSO */ }; #endif /* !__ASSEMBLY__ */ diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c index 7106417842d6..5ee9f3985977 100644 --- a/arch/arm64/kernel/asm-offsets.c +++ b/arch/arm64/kernel/asm-offsets.c @@ -122,6 +122,7 @@ int main(void) DEFINE(VDSO_TZ_MINWEST, offsetof(struct vdso_data, tz_minuteswest)); DEFINE(VDSO_TZ_DSTTIME, offsetof(struct vdso_data, tz_dsttime)); DEFINE(VDSO_USE_SYSCALL, offsetof(struct vdso_data, use_syscall)); + DEFINE(VDSO_FIX, offsetof(struct vdso_data, vdso_fix)); BLANK(); DEFINE(TVAL_TV_SEC, offsetof(struct timeval, tv_sec)); DEFINE(TVAL_TV_USEC, offsetof(struct timeval, tv_usec)); diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c index 42b7082029e1..fc72138b5c25 100644 --- a/arch/arm64/kernel/vdso.c +++ b/arch/arm64/kernel/vdso.c @@ -224,6 +224,7 @@ void update_vsyscall(struct timekeeper *tk) smp_wmb(); vdso_data->use_syscall = use_syscall; + vdso_data->vdso_fix = tk->tkr_mono.clock->archdata.vdso_fix; vdso_data->xtime_coarse_sec = tk->xtime_sec; vdso_data->xtime_coarse_nsec = tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift; diff --git a/arch/arm64/kernel/vdso/gettimeofday.c b/arch/arm64/kernel/vdso/gettimeofday.c index 382c76d3109b..2e28ff5bb1e2 100644 --- a/arch/arm64/kernel/vdso/gettimeofday.c +++ b/arch/arm64/kernel/vdso/gettimeofday.c @@ -29,7 +29,6 @@ #include extern struct vdso_data _vdso_data; -DECLARE_STATIC_KEY_FALSE(vdso_fix); static notrace int gettimeofday_fallback(struct timeval *_tv, struct timezone *_tz) @@ -120,7 +119,7 @@ static notrace u64 get_clock_shifted_nsec(u64 cycle_last, u64 mult) /* Read the virtual counter. */ isb(); asm volatile("mrs %0, cntvct_el0" : "=r" (res) :: "memory"); - if (static_branch_unlikely(&vdso_fix)) { + if (_vdso_data.vdso_fix) { u64 new; int retries = 50; diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index eeea2bd27c1e..486e51605e68 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -76,7 +76,7 @@ static bool arch_timer_c3stop; static bool arch_timer_mem_use_virtual; static bool arch_counter_suspend_stop; static bool vdso_default = true; -DEFINE_STATIC_KEY_FALSE(vdso_fix); +static bool vdso_fix; static cpumask_t evtstrm_available = CPU_MASK_NONE; static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM); @@ -553,7 +553,7 @@ void arch_timer_enable_workaround(const struct arch_timer_erratum_workaround *wa if (wa->read_cntvct_el0) { clocksource_counter.archdata.vdso_direct = true; vdso_default = true; - static_branch_enable(&vdso_fix); + vdso_fix = true; } } @@ -857,8 +857,7 @@ static void arch_counter_set_user_access(void) * need to be workaround. The vdso may have been already * disabled though. */ - if (arch_timer_this_cpu_has_cntvct_wa() && - !static_branch_unlikely(&vdso_fix)) + if (arch_timer_this_cpu_has_cntvct_wa() && !vdso_fix) pr_info("CPU%d: Trapping CNTVCT access\n", smp_processor_id()); else cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN; @@ -993,6 +992,7 @@ static void __init arch_counter_register(unsigned type) arch_timer_read_counter = arch_counter_get_cntpct; clocksource_counter.archdata.vdso_direct = vdso_default; + clocksource_counter.archdata.vdso_fix = vdso_fix; } else { arch_timer_read_counter = arch_counter_get_cntvct_mem; } -- GitLab