linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch 0/5] lib/vdso, x86/vdso: Fix fallout from generic VDSO conversion
@ 2019-07-28 13:12 Thomas Gleixner
  2019-07-28 13:12 ` [patch 1/5] lib/vdso/32: Remove inconsistent NULL pointer checks Thomas Gleixner
                   ` (4 more replies)
  0 siblings, 5 replies; 28+ messages in thread
From: Thomas Gleixner @ 2019-07-28 13:12 UTC (permalink / raw)
  To: LKML
  Cc: x86, Andy Lutomirski, Vincenzo Frascino, Sean Christopherson,
	Kees Cook, Paul Bolle, Will Deacon

Several reporters noticed a regression with the new VDSO. 32bit user space
applications are tripping over seccomp filters with 5.3-rc. The reason is
that the 32bit VDSO syscall fallback uses clock_gettime64()/getres64() for
simplicity reasons. Existing seccomp filters do not enable the new 64bit
syscalls and prevent the applications from working correctly.

The following series addresses this by using the legacy 32bit syscall as
fallback in 32bit VDSOs.

Note, using the legacy syscall fallback is opt-in for now because otherwise
architectures which have their conversion queued in -next would break.

Once all are converted over, the conditional and the 64bit fallback
implementation can be removed.

Thanks,

	tglx

8<--------------
 arch/arm64/include/asm/vdso/compat_gettimeofday.h |   40 +++++++
 arch/x86/include/asm/vdso/gettimeofday.h          |   36 +++++++
 lib/vdso/gettimeofday.c                           |  111 +++++++++++++++-------
 3 files changed, 156 insertions(+), 31 deletions(-)





^ permalink raw reply	[flat|nested] 28+ messages in thread

* [patch 1/5] lib/vdso/32: Remove inconsistent NULL pointer checks
  2019-07-28 13:12 [patch 0/5] lib/vdso, x86/vdso: Fix fallout from generic VDSO conversion Thomas Gleixner
@ 2019-07-28 13:12 ` Thomas Gleixner
  2019-07-28 14:33   ` Andy Lutomirski
                     ` (3 more replies)
  2019-07-28 13:12 ` [patch 2/5] lib/vdso: Move fallback invocation to the callers Thomas Gleixner
                   ` (3 subsequent siblings)
  4 siblings, 4 replies; 28+ messages in thread
From: Thomas Gleixner @ 2019-07-28 13:12 UTC (permalink / raw)
  To: LKML
  Cc: x86, Andy Lutomirski, Vincenzo Frascino, Sean Christopherson,
	Kees Cook, Paul Bolle, Will Deacon

The 32bit variants of vdso_clock_gettime()/getres() have a NULL pointer
check for the timespec pointer. That's inconsistent vs. 64bit.

But the vdso implementation will never be consistent versus the syscall
because the only case which it can handle is NULL. Any other invalid
pointer will cause a segfault. So special casing NULL is not really useful.

Remove it along with the superflouos syscall fallback invocation as that
will return -EFAULT anyway. That also gets rid of the dubious typecast
which only works because the pointer is NULL.

Fixes: 00b26474c2f1 ("lib/vdso: Provide generic VDSO implementation")
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 lib/vdso/gettimeofday.c |   18 ++----------------
 1 file changed, 2 insertions(+), 16 deletions(-)

--- a/lib/vdso/gettimeofday.c
+++ b/lib/vdso/gettimeofday.c
@@ -115,9 +115,6 @@ static __maybe_unused int
 	struct __kernel_timespec ts;
 	int ret;
 
-	if (res == NULL)
-		goto fallback;
-
 	ret = __cvdso_clock_gettime(clock, &ts);
 
 	if (ret == 0) {
@@ -126,9 +123,6 @@ static __maybe_unused int
 	}
 
 	return ret;
-
-fallback:
-	return clock_gettime_fallback(clock, (struct __kernel_timespec *)res);
 }
 
 static __maybe_unused int
@@ -204,10 +198,8 @@ int __cvdso_clock_getres(clockid_t clock
 		goto fallback;
 	}
 
-	if (res) {
-		res->tv_sec = 0;
-		res->tv_nsec = ns;
-	}
+	res->tv_sec = 0;
+	res->tv_nsec = ns;
 
 	return 0;
 
@@ -221,9 +213,6 @@ static __maybe_unused int
 	struct __kernel_timespec ts;
 	int ret;
 
-	if (res == NULL)
-		goto fallback;
-
 	ret = __cvdso_clock_getres(clock, &ts);
 
 	if (ret == 0) {
@@ -232,8 +221,5 @@ static __maybe_unused int
 	}
 
 	return ret;
-
-fallback:
-	return clock_getres_fallback(clock, (struct __kernel_timespec *)res);
 }
 #endif /* VDSO_HAS_CLOCK_GETRES */



^ permalink raw reply	[flat|nested] 28+ messages in thread

* [patch 2/5] lib/vdso: Move fallback invocation to the callers
  2019-07-28 13:12 [patch 0/5] lib/vdso, x86/vdso: Fix fallout from generic VDSO conversion Thomas Gleixner
  2019-07-28 13:12 ` [patch 1/5] lib/vdso/32: Remove inconsistent NULL pointer checks Thomas Gleixner
@ 2019-07-28 13:12 ` Thomas Gleixner
  2019-07-28 14:37   ` Andy Lutomirski
                     ` (2 more replies)
  2019-07-28 13:12 ` [patch 3/5] lib/vdso/32: Provide legacy syscall fallbacks Thomas Gleixner
                   ` (2 subsequent siblings)
  4 siblings, 3 replies; 28+ messages in thread
From: Thomas Gleixner @ 2019-07-28 13:12 UTC (permalink / raw)
  To: LKML
  Cc: x86, Andy Lutomirski, Vincenzo Frascino, Sean Christopherson,
	Kees Cook, Paul Bolle, Will Deacon

To allow syscall fallbacks using the legacy 32bit syscall for 32bit VDSO
builds, move the fallback invocation out into the callers.

Split the common code out of __cvdso_clock_gettime/getres() and invoke the
syscall fallback in the 64bit and 32bit variants.

Preparatory work for using legacy syscalls in 32bit VDSO. No functional
change.

Fixes: 00b26474c2f1 ("lib/vdso: Provide generic VDSO implementation")
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 lib/vdso/gettimeofday.c |   53 ++++++++++++++++++++++++++++++++----------------
 1 file changed, 36 insertions(+), 17 deletions(-)

--- a/lib/vdso/gettimeofday.c
+++ b/lib/vdso/gettimeofday.c
@@ -51,7 +51,7 @@ static int do_hres(const struct vdso_dat
 		ns = vdso_ts->nsec;
 		last = vd->cycle_last;
 		if (unlikely((s64)cycles < 0))
-			return clock_gettime_fallback(clk, ts);
+			return -1;
 
 		ns += vdso_calc_delta(cycles, last, vd->mask, vd->mult);
 		ns >>= vd->shift;
@@ -82,14 +82,14 @@ static void do_coarse(const struct vdso_
 }
 
 static __maybe_unused int
-__cvdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts)
+__cvdso_clock_gettime_common(clockid_t clock, struct __kernel_timespec *ts)
 {
 	const struct vdso_data *vd = __arch_get_vdso_data();
 	u32 msk;
 
 	/* Check for negative values or invalid clocks */
 	if (unlikely((u32) clock >= MAX_CLOCKS))
-		goto fallback;
+		return -1;
 
 	/*
 	 * Convert the clockid to a bitmask and use it to check which
@@ -104,9 +104,17 @@ static __maybe_unused int
 	} else if (msk & VDSO_RAW) {
 		return do_hres(&vd[CS_RAW], clock, ts);
 	}
+	return -1;
+}
 
-fallback:
-	return clock_gettime_fallback(clock, ts);
+static __maybe_unused int
+__cvdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts)
+{
+	int ret = __cvdso_clock_gettime_common(clock, ts);
+
+	if (unlikely(ret))
+		return clock_gettime_fallback(clock, ts);
+	return 0;
 }
 
 static __maybe_unused int
@@ -115,9 +123,12 @@ static __maybe_unused int
 	struct __kernel_timespec ts;
 	int ret;
 
-	ret = __cvdso_clock_gettime(clock, &ts);
+	ret = __cvdso_clock_gettime_common(clock, &ts);
 
-	if (ret == 0) {
+	if (unlikely(ret))
+		ret = clock_gettime_fallback(clock, &ts);
+
+	if (likely(!ret)) {
 		res->tv_sec = ts.tv_sec;
 		res->tv_nsec = ts.tv_nsec;
 	}
@@ -163,17 +174,18 @@ static __maybe_unused time_t __cvdso_tim
 
 #ifdef VDSO_HAS_CLOCK_GETRES
 static __maybe_unused
-int __cvdso_clock_getres(clockid_t clock, struct __kernel_timespec *res)
+int __cvdso_clock_getres_common(clockid_t clock, struct __kernel_timespec *res)
 {
 	const struct vdso_data *vd = __arch_get_vdso_data();
-	u64 ns;
+	u64 hrtimer_res;
 	u32 msk;
-	u64 hrtimer_res = READ_ONCE(vd[CS_HRES_COARSE].hrtimer_res);
+	u64 ns;
 
 	/* Check for negative values or invalid clocks */
 	if (unlikely((u32) clock >= MAX_CLOCKS))
-		goto fallback;
+		return -1;
 
+	hrtimer_res = READ_ONCE(vd[CS_HRES_COARSE].hrtimer_res);
 	/*
 	 * Convert the clockid to a bitmask and use it to check which
 	 * clocks are handled in the VDSO directly.
@@ -195,16 +207,22 @@ int __cvdso_clock_getres(clockid_t clock
 		 */
 		ns = hrtimer_res;
 	} else {
-		goto fallback;
+		return -1;
 	}
 
 	res->tv_sec = 0;
 	res->tv_nsec = ns;
 
 	return 0;
+}
+
+int __cvdso_clock_getres(clockid_t clock, struct __kernel_timespec *res)
+{
+	int ret = __cvdso_clock_getres_common(clock, res);
 
-fallback:
-	return clock_getres_fallback(clock, res);
+	if (unlikely(ret))
+		return clock_getres_fallback(clock, res);
+	return 0;
 }
 
 static __maybe_unused int
@@ -213,13 +231,14 @@ static __maybe_unused int
 	struct __kernel_timespec ts;
 	int ret;
 
-	ret = __cvdso_clock_getres(clock, &ts);
+	ret = __cvdso_clock_getres_common(clock, &ts);
+	if (unlikely(ret))
+		ret = clock_getres_fallback(clock, &ts);
 
-	if (ret == 0) {
+	if (likely(!ret)) {
 		res->tv_sec = ts.tv_sec;
 		res->tv_nsec = ts.tv_nsec;
 	}
-
 	return ret;
 }
 #endif /* VDSO_HAS_CLOCK_GETRES */



^ permalink raw reply	[flat|nested] 28+ messages in thread

* [patch 3/5] lib/vdso/32: Provide legacy syscall fallbacks
  2019-07-28 13:12 [patch 0/5] lib/vdso, x86/vdso: Fix fallout from generic VDSO conversion Thomas Gleixner
  2019-07-28 13:12 ` [patch 1/5] lib/vdso/32: Remove inconsistent NULL pointer checks Thomas Gleixner
  2019-07-28 13:12 ` [patch 2/5] lib/vdso: Move fallback invocation to the callers Thomas Gleixner
@ 2019-07-28 13:12 ` Thomas Gleixner
  2019-07-28 14:39   ` Andy Lutomirski
                     ` (2 more replies)
  2019-07-28 13:12 ` [patch 4/5] x86/vdso/32: Use 32bit syscall fallback Thomas Gleixner
  2019-07-28 13:12 ` [patch 5/5] arm64: compat: vdso: Use legacy syscalls as fallback Thomas Gleixner
  4 siblings, 3 replies; 28+ messages in thread
From: Thomas Gleixner @ 2019-07-28 13:12 UTC (permalink / raw)
  To: LKML
  Cc: x86, Andy Lutomirski, Vincenzo Frascino, Sean Christopherson,
	Kees Cook, Paul Bolle, Will Deacon

To address the regression which causes seccomp to deny applications the
access to clock_gettime64() and clock_getres64() syscalls because they
are not enabled in the existing filters.

That trips over the fact that 32bit VDSOs use the new clock_gettime64() and
clock_getres64() syscalls in the fallback path.

Implement a __cvdso_clock_get*time32() variants which invokes the legacy
32bit syscalls when the architecture requests it.

The conditional can go away once all architectures are converted.

Fixes: 00b26474c2f1 ("lib/vdso: Provide generic VDSO implementation")
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 lib/vdso/gettimeofday.c |   46 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 45 insertions(+), 1 deletion(-)

--- a/lib/vdso/gettimeofday.c
+++ b/lib/vdso/gettimeofday.c
@@ -117,6 +117,8 @@ static __maybe_unused int
 	return 0;
 }
 
+#ifndef VDSO_HAS_32BIT_FALLBACK
+
 static __maybe_unused int
 __cvdso_clock_gettime32(clockid_t clock, struct old_timespec32 *res)
 {
@@ -132,10 +134,29 @@ static __maybe_unused int
 		res->tv_sec = ts.tv_sec;
 		res->tv_nsec = ts.tv_nsec;
 	}
-
 	return ret;
 }
 
+#else
+
+static __maybe_unused int
+__cvdso_clock_gettime32(clockid_t clock, struct old_timespec32 *res)
+{
+	struct __kernel_timespec ts;
+	int ret;
+
+	ret = __cvdso_clock_gettime_common(clock, &ts);
+
+	if (likely(!ret)) {
+		res->tv_sec = ts.tv_sec;
+		res->tv_nsec = ts.tv_nsec;
+		return 0;
+	}
+	return clock_gettime32_fallback(clock, res);
+}
+
+#endif
+
 static __maybe_unused int
 __cvdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz)
 {
@@ -225,6 +246,8 @@ int __cvdso_clock_getres(clockid_t clock
 	return 0;
 }
 
+#ifndef VDSO_HAS_32BIT_FALLBACK
+
 static __maybe_unused int
 __cvdso_clock_getres_time32(clockid_t clock, struct old_timespec32 *res)
 {
@@ -241,4 +264,25 @@ static __maybe_unused int
 	}
 	return ret;
 }
+
+#else
+
+static __maybe_unused int
+__cvdso_clock_getres_time32(clockid_t clock, struct old_timespec32 *res)
+{
+	struct __kernel_timespec ts;
+	int ret;
+
+	ret = __cvdso_clock_getres_common(clock, &ts);
+
+	if (likely(!ret)) {
+		res->tv_sec = ts.tv_sec;
+		res->tv_nsec = ts.tv_nsec;
+		return 0;
+	}
+
+	return clock_getres32_fallback(clock, res);
+}
+#endif
+
 #endif /* VDSO_HAS_CLOCK_GETRES */



^ permalink raw reply	[flat|nested] 28+ messages in thread

* [patch 4/5] x86/vdso/32: Use 32bit syscall fallback
  2019-07-28 13:12 [patch 0/5] lib/vdso, x86/vdso: Fix fallout from generic VDSO conversion Thomas Gleixner
                   ` (2 preceding siblings ...)
  2019-07-28 13:12 ` [patch 3/5] lib/vdso/32: Provide legacy syscall fallbacks Thomas Gleixner
@ 2019-07-28 13:12 ` Thomas Gleixner
  2019-07-28 14:50   ` Andy Lutomirski
                     ` (3 more replies)
  2019-07-28 13:12 ` [patch 5/5] arm64: compat: vdso: Use legacy syscalls as fallback Thomas Gleixner
  4 siblings, 4 replies; 28+ messages in thread
From: Thomas Gleixner @ 2019-07-28 13:12 UTC (permalink / raw)
  To: LKML
  Cc: x86, Andy Lutomirski, Vincenzo Frascino, Sean Christopherson,
	Kees Cook, Paul Bolle, Will Deacon

The generic VDSO implementation uses the Y2038 safe clock_gettime64() and
clock_getres_time64() syscalls as fallback for 32bit VDSO. This breaks
seccomp setups because these syscalls might be not (yet) allowed.

Implement the 32bit variants which use the legacy syscalls and select the
variant in the core library.

The 64bit time variants are not removed because they are required for the
time64 based vdso accessors.

Reported-by: Sean Christopherson <sean.j.christopherson@intel.com>
Reported-by: Paul Bolle <pebolle@tiscali.nl>
Suggested-by: Andy Lutomirski <luto@kernel.org>
Fixes: 7ac870747988 ("x86/vdso: Switch to generic vDSO implementation")
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/include/asm/vdso/gettimeofday.h |   36 +++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

--- a/arch/x86/include/asm/vdso/gettimeofday.h
+++ b/arch/x86/include/asm/vdso/gettimeofday.h
@@ -96,6 +96,8 @@ long clock_getres_fallback(clockid_t _cl
 
 #else
 
+#define VDSO_HAS_32BIT_FALLBACK	1
+
 static __always_inline
 long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
 {
@@ -114,6 +116,23 @@ long clock_gettime_fallback(clockid_t _c
 }
 
 static __always_inline
+long clock_gettime32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
+{
+	long ret;
+
+	asm (
+		"mov %%ebx, %%edx \n"
+		"mov %[clock], %%ebx \n"
+		"call __kernel_vsyscall \n"
+		"mov %%edx, %%ebx \n"
+		: "=a" (ret), "=m" (*_ts)
+		: "0" (__NR_clock_gettime), [clock] "g" (_clkid), "c" (_ts)
+		: "edx");
+
+	return ret;
+}
+
+static __always_inline
 long gettimeofday_fallback(struct __kernel_old_timeval *_tv,
 			   struct timezone *_tz)
 {
@@ -146,6 +165,23 @@ clock_getres_fallback(clockid_t _clkid,
 		: "edx");
 
 	return ret;
+}
+
+static __always_inline
+long clock_getres32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
+{
+	long ret;
+
+	asm (
+		"mov %%ebx, %%edx \n"
+		"mov %[clock], %%ebx \n"
+		"call __kernel_vsyscall \n"
+		"mov %%edx, %%ebx \n"
+		: "=a" (ret), "=m" (*_ts)
+		: "0" (__NR_clock_getres), [clock] "g" (_clkid), "c" (_ts)
+		: "edx");
+
+	return ret;
 }
 
 #endif



^ permalink raw reply	[flat|nested] 28+ messages in thread

* [patch 5/5] arm64: compat: vdso: Use legacy syscalls as fallback
  2019-07-28 13:12 [patch 0/5] lib/vdso, x86/vdso: Fix fallout from generic VDSO conversion Thomas Gleixner
                   ` (3 preceding siblings ...)
  2019-07-28 13:12 ` [patch 4/5] x86/vdso/32: Use 32bit syscall fallback Thomas Gleixner
@ 2019-07-28 13:12 ` Thomas Gleixner
  2019-07-28 15:35   ` Vincenzo Frascino
  2019-07-30 22:22   ` [tip:timers/urgent] " tip-bot for Thomas Gleixner
  4 siblings, 2 replies; 28+ messages in thread
From: Thomas Gleixner @ 2019-07-28 13:12 UTC (permalink / raw)
  To: LKML
  Cc: x86, Andy Lutomirski, Vincenzo Frascino, Sean Christopherson,
	Kees Cook, Paul Bolle, Will Deacon

The generic VDSO implementation uses the Y2038 safe clock_gettime64() and
clock_getres_time64() syscalls as fallback for 32bit VDSO. This breaks
seccomp setups because these syscalls might be not (yet) allowed.

Implement the 32bit variants which use the legacy syscalls and select the
variant in the core library.

The 64bit time variants are not removed because they are required for the
time64 based vdso accessors.

Reported-by: Sean Christopherson <sean.j.christopherson@intel.com>
Reported-by: Paul Bolle <pebolle@tiscali.nl>
Suggested-by: Andy Lutomirski <luto@kernel.org>
Fixes: 00b26474c2f1 ("lib/vdso: Provide generic VDSO implementation")
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
Note:

The NULL pointer check in the getres/getres32() fallbacks is just wrong.
The proper return code for a NULL pointer is -EFAULT. How did this ever
pass any posix test? Also it just should go away because any other invalid
pointer will be caught in the syscall anyway. The clockid check is also
part of the syscall so no point in having it here again. Handling calls
with invalid arguments is not really a performance critical operation.

---
 arch/arm64/include/asm/vdso/compat_gettimeofday.h |   40 ++++++++++++++++++++++
 1 file changed, 40 insertions(+)

--- a/arch/arm64/include/asm/vdso/compat_gettimeofday.h
+++ b/arch/arm64/include/asm/vdso/compat_gettimeofday.h
@@ -16,6 +16,8 @@
 
 #define VDSO_HAS_CLOCK_GETRES		1
 
+#define VDSO_HAS_32BIT_FALLBACK		1
+
 static __always_inline
 int gettimeofday_fallback(struct __kernel_old_timeval *_tv,
 			  struct timezone *_tz)
@@ -52,6 +54,23 @@ long clock_gettime_fallback(clockid_t _c
 }
 
 static __always_inline
+long clock_gettime32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
+{
+	register struct old_timespec32 *ts asm("r1") = _ts;
+	register clockid_t clkid asm("r0") = _clkid;
+	register long ret asm ("r0");
+	register long nr asm("r7") = __NR_compat_clock_gettime;
+
+	asm volatile(
+	"	swi #0\n"
+	: "=r" (ret)
+	: "r" (clkid), "r" (ts), "r" (nr)
+	: "memory");
+
+	return ret;
+}
+
+static __always_inline
 int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
 {
 	register struct __kernel_timespec *ts asm("r1") = _ts;
@@ -61,6 +80,27 @@ int clock_getres_fallback(clockid_t _clk
 
 	/* The checks below are required for ABI consistency with arm */
 	if ((_clkid >= MAX_CLOCKS) && (_ts == NULL))
+		return -EINVAL;
+
+	asm volatile(
+	"       swi #0\n"
+	: "=r" (ret)
+	: "r" (clkid), "r" (ts), "r" (nr)
+	: "memory");
+
+	return ret;
+}
+
+static __always_inline
+int clock_getres32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
+{
+	register struct old_timespec32 *ts asm("r1") = _ts;
+	register clockid_t clkid asm("r0") = _clkid;
+	register long ret asm ("r0");
+	register long nr asm("r7") = __NR_compat_clock_getres;
+
+	/* The checks below are required for ABI consistency with arm */
+	if ((_clkid >= MAX_CLOCKS) && (_ts == NULL))
 		return -EINVAL;
 
 	asm volatile(



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch 1/5] lib/vdso/32: Remove inconsistent NULL pointer checks
  2019-07-28 13:12 ` [patch 1/5] lib/vdso/32: Remove inconsistent NULL pointer checks Thomas Gleixner
@ 2019-07-28 14:33   ` Andy Lutomirski
  2019-07-28 14:42     ` Thomas Gleixner
  2019-07-28 15:30   ` Vincenzo Frascino
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 28+ messages in thread
From: Andy Lutomirski @ 2019-07-28 14:33 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, X86 ML, Andy Lutomirski, Vincenzo Frascino,
	Sean Christopherson, Kees Cook, Paul Bolle, Will Deacon

On Sun, Jul 28, 2019 at 6:20 AM Thomas Gleixner <tglx@linutronix.de> wrote:
>
> The 32bit variants of vdso_clock_gettime()/getres() have a NULL pointer
> check for the timespec pointer. That's inconsistent vs. 64bit.
>
> But the vdso implementation will never be consistent versus the syscall
> because the only case which it can handle is NULL. Any other invalid
> pointer will cause a segfault. So special casing NULL is not really useful.
>
> Remove it along with the superflouos syscall fallback invocation as that
> will return -EFAULT anyway. That also gets rid of the dubious typecast
> which only works because the pointer is NULL.

Reviewed-by: Andy Lutomirski <luto@kernel.org>

FWIW, the equivalent change to gettimeofday would be an ABI break,
since we historically have that check, and it even makes sense there.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch 2/5] lib/vdso: Move fallback invocation to the callers
  2019-07-28 13:12 ` [patch 2/5] lib/vdso: Move fallback invocation to the callers Thomas Gleixner
@ 2019-07-28 14:37   ` Andy Lutomirski
  2019-07-28 15:31   ` Vincenzo Frascino
  2019-07-30 22:19   ` [tip:timers/urgent] " tip-bot for Thomas Gleixner
  2 siblings, 0 replies; 28+ messages in thread
From: Andy Lutomirski @ 2019-07-28 14:37 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, X86 ML, Andy Lutomirski, Vincenzo Frascino,
	Sean Christopherson, Kees Cook, Paul Bolle, Will Deacon

On Sun, Jul 28, 2019 at 6:20 AM Thomas Gleixner <tglx@linutronix.de> wrote:
>
> To allow syscall fallbacks using the legacy 32bit syscall for 32bit VDSO
> builds, move the fallback invocation out into the callers.
>
> Split the common code out of __cvdso_clock_gettime/getres() and invoke the
> syscall fallback in the 64bit and 32bit variants.
>
> Preparatory work for using legacy syscalls in 32bit VDSO. No functional
> change.

Reviewed-by: Andy Lutomirski <luto@kernel.org>

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch 3/5] lib/vdso/32: Provide legacy syscall fallbacks
  2019-07-28 13:12 ` [patch 3/5] lib/vdso/32: Provide legacy syscall fallbacks Thomas Gleixner
@ 2019-07-28 14:39   ` Andy Lutomirski
  2019-07-28 15:33   ` Vincenzo Frascino
  2019-07-29 14:48   ` Sean Christopherson
  2 siblings, 0 replies; 28+ messages in thread
From: Andy Lutomirski @ 2019-07-28 14:39 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, X86 ML, Andy Lutomirski, Vincenzo Frascino,
	Sean Christopherson, Kees Cook, Paul Bolle, Will Deacon

On Sun, Jul 28, 2019 at 6:20 AM Thomas Gleixner <tglx@linutronix.de> wrote:
>
> To address the regression which causes seccomp to deny applications the
> access to clock_gettime64() and clock_getres64() syscalls because they
> are not enabled in the existing filters.
>
> That trips over the fact that 32bit VDSOs use the new clock_gettime64() and
> clock_getres64() syscalls in the fallback path.
>
> Implement a __cvdso_clock_get*time32() variants which invokes the legacy
> 32bit syscalls when the architecture requests it.
>
> The conditional can go away once all architectures are converted.

Reviewed-by: Andy Lutomirski <luto@kernel.org>

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch 1/5] lib/vdso/32: Remove inconsistent NULL pointer checks
  2019-07-28 14:33   ` Andy Lutomirski
@ 2019-07-28 14:42     ` Thomas Gleixner
  0 siblings, 0 replies; 28+ messages in thread
From: Thomas Gleixner @ 2019-07-28 14:42 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: LKML, X86 ML, Vincenzo Frascino, Sean Christopherson, Kees Cook,
	Paul Bolle, Will Deacon

On Sun, 28 Jul 2019, Andy Lutomirski wrote:

> On Sun, Jul 28, 2019 at 6:20 AM Thomas Gleixner <tglx@linutronix.de> wrote:
> >
> > The 32bit variants of vdso_clock_gettime()/getres() have a NULL pointer
> > check for the timespec pointer. That's inconsistent vs. 64bit.
> >
> > But the vdso implementation will never be consistent versus the syscall
> > because the only case which it can handle is NULL. Any other invalid
> > pointer will cause a segfault. So special casing NULL is not really useful.
> >
> > Remove it along with the superflouos syscall fallback invocation as that
> > will return -EFAULT anyway. That also gets rid of the dubious typecast
> > which only works because the pointer is NULL.
> 
> Reviewed-by: Andy Lutomirski <luto@kernel.org>
> 
> FWIW, the equivalent change to gettimeofday would be an ABI break,
> since we historically have that check, and it even makes sense there.

Of course, because either of the two pointers can be NULL.

Thanks,

	tglx


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch 4/5] x86/vdso/32: Use 32bit syscall fallback
  2019-07-28 13:12 ` [patch 4/5] x86/vdso/32: Use 32bit syscall fallback Thomas Gleixner
@ 2019-07-28 14:50   ` Andy Lutomirski
  2019-07-29 11:23   ` Vincenzo Frascino
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 28+ messages in thread
From: Andy Lutomirski @ 2019-07-28 14:50 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, X86 ML, Andy Lutomirski, Vincenzo Frascino,
	Sean Christopherson, Kees Cook, Paul Bolle, Will Deacon

On Sun, Jul 28, 2019 at 6:20 AM Thomas Gleixner <tglx@linutronix.de> wrote:
>
> The generic VDSO implementation uses the Y2038 safe clock_gettime64() and
> clock_getres_time64() syscalls as fallback for 32bit VDSO. This breaks
> seccomp setups because these syscalls might be not (yet) allowed.
>
> Implement the 32bit variants which use the legacy syscalls and select the
> variant in the core library.
>
> The 64bit time variants are not removed because they are required for the
> time64 based vdso accessors.

Reviewed-by: Andy Lutomirski <luto@kernel.org>

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch 1/5] lib/vdso/32: Remove inconsistent NULL pointer checks
  2019-07-28 13:12 ` [patch 1/5] lib/vdso/32: Remove inconsistent NULL pointer checks Thomas Gleixner
  2019-07-28 14:33   ` Andy Lutomirski
@ 2019-07-28 15:30   ` Vincenzo Frascino
  2019-07-29 14:52   ` Sean Christopherson
  2019-07-30 22:19   ` [tip:timers/urgent] " tip-bot for Thomas Gleixner
  3 siblings, 0 replies; 28+ messages in thread
From: Vincenzo Frascino @ 2019-07-28 15:30 UTC (permalink / raw)
  To: Thomas Gleixner, LKML
  Cc: x86, Andy Lutomirski, Sean Christopherson, Kees Cook, Paul Bolle,
	Will Deacon

On 7/28/19 2:12 PM, Thomas Gleixner wrote:
> The 32bit variants of vdso_clock_gettime()/getres() have a NULL pointer
> check for the timespec pointer. That's inconsistent vs. 64bit.
> 
> But the vdso implementation will never be consistent versus the syscall
> because the only case which it can handle is NULL. Any other invalid
> pointer will cause a segfault. So special casing NULL is not really useful.
> 
> Remove it along with the superflouos syscall fallback invocation as that
> will return -EFAULT anyway. That also gets rid of the dubious typecast
> which only works because the pointer is NULL.

Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com>

> 
> Fixes: 00b26474c2f1 ("lib/vdso: Provide generic VDSO implementation")
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> ---
>  lib/vdso/gettimeofday.c |   18 ++----------------
>  1 file changed, 2 insertions(+), 16 deletions(-)
> 
> --- a/lib/vdso/gettimeofday.c
> +++ b/lib/vdso/gettimeofday.c
> @@ -115,9 +115,6 @@ static __maybe_unused int
>  	struct __kernel_timespec ts;
>  	int ret;
>  
> -	if (res == NULL)
> -		goto fallback;
> -
>  	ret = __cvdso_clock_gettime(clock, &ts);
>  
>  	if (ret == 0) {
> @@ -126,9 +123,6 @@ static __maybe_unused int
>  	}
>  
>  	return ret;
> -
> -fallback:
> -	return clock_gettime_fallback(clock, (struct __kernel_timespec *)res);
>  }
>  
>  static __maybe_unused int
> @@ -204,10 +198,8 @@ int __cvdso_clock_getres(clockid_t clock
>  		goto fallback;
>  	}
>  
> -	if (res) {
> -		res->tv_sec = 0;
> -		res->tv_nsec = ns;
> -	}
> +	res->tv_sec = 0;
> +	res->tv_nsec = ns;
>  
>  	return 0;
>  
> @@ -221,9 +213,6 @@ static __maybe_unused int
>  	struct __kernel_timespec ts;
>  	int ret;
>  
> -	if (res == NULL)
> -		goto fallback;
> -
>  	ret = __cvdso_clock_getres(clock, &ts);
>  
>  	if (ret == 0) {
> @@ -232,8 +221,5 @@ static __maybe_unused int
>  	}
>  
>  	return ret;
> -
> -fallback:
> -	return clock_getres_fallback(clock, (struct __kernel_timespec *)res);
>  }
>  #endif /* VDSO_HAS_CLOCK_GETRES */
> 
> 

-- 
Regards,
Vincenzo

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch 2/5] lib/vdso: Move fallback invocation to the callers
  2019-07-28 13:12 ` [patch 2/5] lib/vdso: Move fallback invocation to the callers Thomas Gleixner
  2019-07-28 14:37   ` Andy Lutomirski
@ 2019-07-28 15:31   ` Vincenzo Frascino
  2019-07-30 22:19   ` [tip:timers/urgent] " tip-bot for Thomas Gleixner
  2 siblings, 0 replies; 28+ messages in thread
From: Vincenzo Frascino @ 2019-07-28 15:31 UTC (permalink / raw)
  To: Thomas Gleixner, LKML
  Cc: x86, Andy Lutomirski, Sean Christopherson, Kees Cook, Paul Bolle,
	Will Deacon

On 7/28/19 2:12 PM, Thomas Gleixner wrote:
> To allow syscall fallbacks using the legacy 32bit syscall for 32bit VDSO
> builds, move the fallback invocation out into the callers.
> 
> Split the common code out of __cvdso_clock_gettime/getres() and invoke the
> syscall fallback in the 64bit and 32bit variants.
> 
> Preparatory work for using legacy syscalls in 32bit VDSO. No functional
> change.
>

Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com>

> Fixes: 00b26474c2f1 ("lib/vdso: Provide generic VDSO implementation")
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> ---
>  lib/vdso/gettimeofday.c |   53 ++++++++++++++++++++++++++++++++----------------
>  1 file changed, 36 insertions(+), 17 deletions(-)
> 
> --- a/lib/vdso/gettimeofday.c
> +++ b/lib/vdso/gettimeofday.c
> @@ -51,7 +51,7 @@ static int do_hres(const struct vdso_dat
>  		ns = vdso_ts->nsec;
>  		last = vd->cycle_last;
>  		if (unlikely((s64)cycles < 0))
> -			return clock_gettime_fallback(clk, ts);
> +			return -1;
>  
>  		ns += vdso_calc_delta(cycles, last, vd->mask, vd->mult);
>  		ns >>= vd->shift;
> @@ -82,14 +82,14 @@ static void do_coarse(const struct vdso_
>  }
>  
>  static __maybe_unused int
> -__cvdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts)
> +__cvdso_clock_gettime_common(clockid_t clock, struct __kernel_timespec *ts)
>  {
>  	const struct vdso_data *vd = __arch_get_vdso_data();
>  	u32 msk;
>  
>  	/* Check for negative values or invalid clocks */
>  	if (unlikely((u32) clock >= MAX_CLOCKS))
> -		goto fallback;
> +		return -1;
>  
>  	/*
>  	 * Convert the clockid to a bitmask and use it to check which
> @@ -104,9 +104,17 @@ static __maybe_unused int
>  	} else if (msk & VDSO_RAW) {
>  		return do_hres(&vd[CS_RAW], clock, ts);
>  	}
> +	return -1;
> +}
>  
> -fallback:
> -	return clock_gettime_fallback(clock, ts);
> +static __maybe_unused int
> +__cvdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts)
> +{
> +	int ret = __cvdso_clock_gettime_common(clock, ts);
> +
> +	if (unlikely(ret))
> +		return clock_gettime_fallback(clock, ts);
> +	return 0;
>  }
>  
>  static __maybe_unused int
> @@ -115,9 +123,12 @@ static __maybe_unused int
>  	struct __kernel_timespec ts;
>  	int ret;
>  
> -	ret = __cvdso_clock_gettime(clock, &ts);
> +	ret = __cvdso_clock_gettime_common(clock, &ts);
>  
> -	if (ret == 0) {
> +	if (unlikely(ret))
> +		ret = clock_gettime_fallback(clock, &ts);
> +
> +	if (likely(!ret)) {
>  		res->tv_sec = ts.tv_sec;
>  		res->tv_nsec = ts.tv_nsec;
>  	}
> @@ -163,17 +174,18 @@ static __maybe_unused time_t __cvdso_tim
>  
>  #ifdef VDSO_HAS_CLOCK_GETRES
>  static __maybe_unused
> -int __cvdso_clock_getres(clockid_t clock, struct __kernel_timespec *res)
> +int __cvdso_clock_getres_common(clockid_t clock, struct __kernel_timespec *res)
>  {
>  	const struct vdso_data *vd = __arch_get_vdso_data();
> -	u64 ns;
> +	u64 hrtimer_res;
>  	u32 msk;
> -	u64 hrtimer_res = READ_ONCE(vd[CS_HRES_COARSE].hrtimer_res);
> +	u64 ns;
>  
>  	/* Check for negative values or invalid clocks */
>  	if (unlikely((u32) clock >= MAX_CLOCKS))
> -		goto fallback;
> +		return -1;
>  
> +	hrtimer_res = READ_ONCE(vd[CS_HRES_COARSE].hrtimer_res);
>  	/*
>  	 * Convert the clockid to a bitmask and use it to check which
>  	 * clocks are handled in the VDSO directly.
> @@ -195,16 +207,22 @@ int __cvdso_clock_getres(clockid_t clock
>  		 */
>  		ns = hrtimer_res;
>  	} else {
> -		goto fallback;
> +		return -1;
>  	}
>  
>  	res->tv_sec = 0;
>  	res->tv_nsec = ns;
>  
>  	return 0;
> +}
> +
> +int __cvdso_clock_getres(clockid_t clock, struct __kernel_timespec *res)
> +{
> +	int ret = __cvdso_clock_getres_common(clock, res);
>  
> -fallback:
> -	return clock_getres_fallback(clock, res);
> +	if (unlikely(ret))
> +		return clock_getres_fallback(clock, res);
> +	return 0;
>  }
>  
>  static __maybe_unused int
> @@ -213,13 +231,14 @@ static __maybe_unused int
>  	struct __kernel_timespec ts;
>  	int ret;
>  
> -	ret = __cvdso_clock_getres(clock, &ts);
> +	ret = __cvdso_clock_getres_common(clock, &ts);
> +	if (unlikely(ret))
> +		ret = clock_getres_fallback(clock, &ts);
>  
> -	if (ret == 0) {
> +	if (likely(!ret)) {
>  		res->tv_sec = ts.tv_sec;
>  		res->tv_nsec = ts.tv_nsec;
>  	}
> -
>  	return ret;
>  }
>  #endif /* VDSO_HAS_CLOCK_GETRES */
> 
> 

-- 
Regards,
Vincenzo

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch 3/5] lib/vdso/32: Provide legacy syscall fallbacks
  2019-07-28 13:12 ` [patch 3/5] lib/vdso/32: Provide legacy syscall fallbacks Thomas Gleixner
  2019-07-28 14:39   ` Andy Lutomirski
@ 2019-07-28 15:33   ` Vincenzo Frascino
  2019-07-29 14:48   ` Sean Christopherson
  2 siblings, 0 replies; 28+ messages in thread
From: Vincenzo Frascino @ 2019-07-28 15:33 UTC (permalink / raw)
  To: Thomas Gleixner, LKML
  Cc: x86, Andy Lutomirski, Sean Christopherson, Kees Cook, Paul Bolle,
	Will Deacon

On 7/28/19 2:12 PM, Thomas Gleixner wrote:
> To address the regression which causes seccomp to deny applications the
> access to clock_gettime64() and clock_getres64() syscalls because they
> are not enabled in the existing filters.
> 
> That trips over the fact that 32bit VDSOs use the new clock_gettime64() and
> clock_getres64() syscalls in the fallback path.
> 
> Implement a __cvdso_clock_get*time32() variants which invokes the legacy
> 32bit syscalls when the architecture requests it.
> 
> The conditional can go away once all architectures are converted.
>

Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com>

> Fixes: 00b26474c2f1 ("lib/vdso: Provide generic VDSO implementation")
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> ---
>  lib/vdso/gettimeofday.c |   46 +++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 45 insertions(+), 1 deletion(-)
> 
> --- a/lib/vdso/gettimeofday.c
> +++ b/lib/vdso/gettimeofday.c
> @@ -117,6 +117,8 @@ static __maybe_unused int
>  	return 0;
>  }
>  
> +#ifndef VDSO_HAS_32BIT_FALLBACK
> +
>  static __maybe_unused int
>  __cvdso_clock_gettime32(clockid_t clock, struct old_timespec32 *res)
>  {
> @@ -132,10 +134,29 @@ static __maybe_unused int
>  		res->tv_sec = ts.tv_sec;
>  		res->tv_nsec = ts.tv_nsec;
>  	}
> -
>  	return ret;
>  }
>  
> +#else
> +
> +static __maybe_unused int
> +__cvdso_clock_gettime32(clockid_t clock, struct old_timespec32 *res)
> +{
> +	struct __kernel_timespec ts;
> +	int ret;
> +
> +	ret = __cvdso_clock_gettime_common(clock, &ts);
> +
> +	if (likely(!ret)) {
> +		res->tv_sec = ts.tv_sec;
> +		res->tv_nsec = ts.tv_nsec;
> +		return 0;
> +	}
> +	return clock_gettime32_fallback(clock, res);
> +}
> +
> +#endif
> +
>  static __maybe_unused int
>  __cvdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz)
>  {
> @@ -225,6 +246,8 @@ int __cvdso_clock_getres(clockid_t clock
>  	return 0;
>  }
>  
> +#ifndef VDSO_HAS_32BIT_FALLBACK
> +
>  static __maybe_unused int
>  __cvdso_clock_getres_time32(clockid_t clock, struct old_timespec32 *res)
>  {
> @@ -241,4 +264,25 @@ static __maybe_unused int
>  	}
>  	return ret;
>  }
> +
> +#else
> +
> +static __maybe_unused int
> +__cvdso_clock_getres_time32(clockid_t clock, struct old_timespec32 *res)
> +{
> +	struct __kernel_timespec ts;
> +	int ret;
> +
> +	ret = __cvdso_clock_getres_common(clock, &ts);
> +
> +	if (likely(!ret)) {
> +		res->tv_sec = ts.tv_sec;
> +		res->tv_nsec = ts.tv_nsec;
> +		return 0;
> +	}
> +
> +	return clock_getres32_fallback(clock, res);
> +}
> +#endif
> +
>  #endif /* VDSO_HAS_CLOCK_GETRES */
> 
> 

-- 
Regards,
Vincenzo

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch 5/5] arm64: compat: vdso: Use legacy syscalls as fallback
  2019-07-28 13:12 ` [patch 5/5] arm64: compat: vdso: Use legacy syscalls as fallback Thomas Gleixner
@ 2019-07-28 15:35   ` Vincenzo Frascino
  2019-07-30 22:22   ` [tip:timers/urgent] " tip-bot for Thomas Gleixner
  1 sibling, 0 replies; 28+ messages in thread
From: Vincenzo Frascino @ 2019-07-28 15:35 UTC (permalink / raw)
  To: Thomas Gleixner, LKML
  Cc: x86, Andy Lutomirski, Sean Christopherson, Kees Cook, Paul Bolle,
	Will Deacon

On 7/28/19 2:12 PM, Thomas Gleixner wrote:
> The generic VDSO implementation uses the Y2038 safe clock_gettime64() and
> clock_getres_time64() syscalls as fallback for 32bit VDSO. This breaks
> seccomp setups because these syscalls might be not (yet) allowed.
> 
> Implement the 32bit variants which use the legacy syscalls and select the
> variant in the core library.
> 
> The 64bit time variants are not removed because they are required for the
> time64 based vdso accessors.
>

Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com>

> Reported-by: Sean Christopherson <sean.j.christopherson@intel.com>
> Reported-by: Paul Bolle <pebolle@tiscali.nl>
> Suggested-by: Andy Lutomirski <luto@kernel.org>
> Fixes: 00b26474c2f1 ("lib/vdso: Provide generic VDSO implementation")
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> ---
> Note:
> 
> The NULL pointer check in the getres/getres32() fallbacks is just wrong.
> The proper return code for a NULL pointer is -EFAULT. How did this ever
> pass any posix test? Also it just should go away because any other invalid
> pointer will be caught in the syscall anyway. The clockid check is also
> part of the syscall so no point in having it here again. Handling calls
> with invalid arguments is not really a performance critical operation.
> 
> ---
>  arch/arm64/include/asm/vdso/compat_gettimeofday.h |   40 ++++++++++++++++++++++
>  1 file changed, 40 insertions(+)
> 
> --- a/arch/arm64/include/asm/vdso/compat_gettimeofday.h
> +++ b/arch/arm64/include/asm/vdso/compat_gettimeofday.h
> @@ -16,6 +16,8 @@
>  
>  #define VDSO_HAS_CLOCK_GETRES		1
>  
> +#define VDSO_HAS_32BIT_FALLBACK		1
> +
>  static __always_inline
>  int gettimeofday_fallback(struct __kernel_old_timeval *_tv,
>  			  struct timezone *_tz)
> @@ -52,6 +54,23 @@ long clock_gettime_fallback(clockid_t _c
>  }
>  
>  static __always_inline
> +long clock_gettime32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
> +{
> +	register struct old_timespec32 *ts asm("r1") = _ts;
> +	register clockid_t clkid asm("r0") = _clkid;
> +	register long ret asm ("r0");
> +	register long nr asm("r7") = __NR_compat_clock_gettime;
> +
> +	asm volatile(
> +	"	swi #0\n"
> +	: "=r" (ret)
> +	: "r" (clkid), "r" (ts), "r" (nr)
> +	: "memory");
> +
> +	return ret;
> +}
> +
> +static __always_inline
>  int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
>  {
>  	register struct __kernel_timespec *ts asm("r1") = _ts;
> @@ -61,6 +80,27 @@ int clock_getres_fallback(clockid_t _clk
>  
>  	/* The checks below are required for ABI consistency with arm */
>  	if ((_clkid >= MAX_CLOCKS) && (_ts == NULL))
> +		return -EINVAL;
> +
> +	asm volatile(
> +	"       swi #0\n"
> +	: "=r" (ret)
> +	: "r" (clkid), "r" (ts), "r" (nr)
> +	: "memory");
> +
> +	return ret;
> +}
> +
> +static __always_inline
> +int clock_getres32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
> +{
> +	register struct old_timespec32 *ts asm("r1") = _ts;
> +	register clockid_t clkid asm("r0") = _clkid;
> +	register long ret asm ("r0");
> +	register long nr asm("r7") = __NR_compat_clock_getres;
> +
> +	/* The checks below are required for ABI consistency with arm */
> +	if ((_clkid >= MAX_CLOCKS) && (_ts == NULL))
>  		return -EINVAL;
>  
>  	asm volatile(
> 
> 

-- 
Regards,
Vincenzo

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch 4/5] x86/vdso/32: Use 32bit syscall fallback
  2019-07-28 13:12 ` [patch 4/5] x86/vdso/32: Use 32bit syscall fallback Thomas Gleixner
  2019-07-28 14:50   ` Andy Lutomirski
@ 2019-07-29 11:23   ` Vincenzo Frascino
  2019-07-29 14:51   ` Sean Christopherson
  2019-07-30 22:21   ` [tip:timers/urgent] " tip-bot for Thomas Gleixner
  3 siblings, 0 replies; 28+ messages in thread
From: Vincenzo Frascino @ 2019-07-29 11:23 UTC (permalink / raw)
  To: Thomas Gleixner, LKML
  Cc: x86, Andy Lutomirski, Sean Christopherson, Kees Cook, Paul Bolle,
	Will Deacon

On 28/07/2019 14:12, Thomas Gleixner wrote:
> The generic VDSO implementation uses the Y2038 safe clock_gettime64() and
> clock_getres_time64() syscalls as fallback for 32bit VDSO. This breaks
> seccomp setups because these syscalls might be not (yet) allowed.
> 
> Implement the 32bit variants which use the legacy syscalls and select the
> variant in the core library.
> 
> The 64bit time variants are not removed because they are required for the
> time64 based vdso accessors.
>

Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>

> Reported-by: Sean Christopherson <sean.j.christopherson@intel.com>
> Reported-by: Paul Bolle <pebolle@tiscali.nl>
> Suggested-by: Andy Lutomirski <luto@kernel.org>
> Fixes: 7ac870747988 ("x86/vdso: Switch to generic vDSO implementation")
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> ---
>  arch/x86/include/asm/vdso/gettimeofday.h |   36 +++++++++++++++++++++++++++++++
>  1 file changed, 36 insertions(+)
> 
> --- a/arch/x86/include/asm/vdso/gettimeofday.h
> +++ b/arch/x86/include/asm/vdso/gettimeofday.h
> @@ -96,6 +96,8 @@ long clock_getres_fallback(clockid_t _cl
>  
>  #else
>  
> +#define VDSO_HAS_32BIT_FALLBACK	1
> +
>  static __always_inline
>  long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
>  {
> @@ -114,6 +116,23 @@ long clock_gettime_fallback(clockid_t _c
>  }
>  
>  static __always_inline
> +long clock_gettime32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
> +{
> +	long ret;
> +
> +	asm (
> +		"mov %%ebx, %%edx \n"
> +		"mov %[clock], %%ebx \n"
> +		"call __kernel_vsyscall \n"
> +		"mov %%edx, %%ebx \n"
> +		: "=a" (ret), "=m" (*_ts)
> +		: "0" (__NR_clock_gettime), [clock] "g" (_clkid), "c" (_ts)
> +		: "edx");
> +
> +	return ret;
> +}
> +
> +static __always_inline
>  long gettimeofday_fallback(struct __kernel_old_timeval *_tv,
>  			   struct timezone *_tz)
>  {
> @@ -146,6 +165,23 @@ clock_getres_fallback(clockid_t _clkid,
>  		: "edx");
>  
>  	return ret;
> +}
> +
> +static __always_inline
> +long clock_getres32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
> +{
> +	long ret;
> +
> +	asm (
> +		"mov %%ebx, %%edx \n"
> +		"mov %[clock], %%ebx \n"
> +		"call __kernel_vsyscall \n"
> +		"mov %%edx, %%ebx \n"
> +		: "=a" (ret), "=m" (*_ts)
> +		: "0" (__NR_clock_getres), [clock] "g" (_clkid), "c" (_ts)
> +		: "edx");
> +
> +	return ret;
>  }
>  
>  #endif
> 
> 

-- 
Regards,
Vincenzo

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch 3/5] lib/vdso/32: Provide legacy syscall fallbacks
  2019-07-28 13:12 ` [patch 3/5] lib/vdso/32: Provide legacy syscall fallbacks Thomas Gleixner
  2019-07-28 14:39   ` Andy Lutomirski
  2019-07-28 15:33   ` Vincenzo Frascino
@ 2019-07-29 14:48   ` Sean Christopherson
  2019-07-30  9:38     ` [patch V2 " Thomas Gleixner
  2 siblings, 1 reply; 28+ messages in thread
From: Sean Christopherson @ 2019-07-29 14:48 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, x86, Andy Lutomirski, Vincenzo Frascino, Kees Cook,
	Paul Bolle, Will Deacon

On Sun, Jul 28, 2019 at 03:12:54PM +0200, Thomas Gleixner wrote:
> To address the regression which causes seccomp to deny applications the
> access to clock_gettime64() and clock_getres64() syscalls because they
> are not enabled in the existing filters.
> 
> That trips over the fact that 32bit VDSOs use the new clock_gettime64() and
> clock_getres64() syscalls in the fallback path.
> 
> Implement a __cvdso_clock_get*time32() variants which invokes the legacy
> 32bit syscalls when the architecture requests it.
> 
> The conditional can go away once all architectures are converted.
> 
> Fixes: 00b26474c2f1 ("lib/vdso: Provide generic VDSO implementation")
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> ---
>  lib/vdso/gettimeofday.c |   46 +++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 45 insertions(+), 1 deletion(-)
> 
> --- a/lib/vdso/gettimeofday.c
> +++ b/lib/vdso/gettimeofday.c
> @@ -117,6 +117,8 @@ static __maybe_unused int
>  	return 0;
>  }
>  
> +#ifndef VDSO_HAS_32BIT_FALLBACK
> +
>  static __maybe_unused int
>  __cvdso_clock_gettime32(clockid_t clock, struct old_timespec32 *res)
>  {
> @@ -132,10 +134,29 @@ static __maybe_unused int
>  		res->tv_sec = ts.tv_sec;
>  		res->tv_nsec = ts.tv_nsec;
>  	}
> -
>  	return ret;
>  }
>  
> +#else
> +
> +static __maybe_unused int
> +__cvdso_clock_gettime32(clockid_t clock, struct old_timespec32 *res)
> +{
> +	struct __kernel_timespec ts;
> +	int ret;
> +
> +	ret = __cvdso_clock_gettime_common(clock, &ts);
> +
> +	if (likely(!ret)) {
> +		res->tv_sec = ts.tv_sec;
> +		res->tv_nsec = ts.tv_nsec;
> +		return 0;
> +	}
> +	return clock_gettime32_fallback(clock, res);
> +}
> +
> +#endif
> +
>  static __maybe_unused int
>  __cvdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz)
>  {
> @@ -225,6 +246,8 @@ int __cvdso_clock_getres(clockid_t clock
>  	return 0;
>  }
>  
> +#ifndef VDSO_HAS_32BIT_FALLBACK
> +
>  static __maybe_unused int
>  __cvdso_clock_getres_time32(clockid_t clock, struct old_timespec32 *res)
>  {
> @@ -241,4 +264,25 @@ static __maybe_unused int
>  	}
>  	return ret;
>  }
> +
> +#else
> +
> +static __maybe_unused int
> +__cvdso_clock_getres_time32(clockid_t clock, struct old_timespec32 *res)
> +{
> +	struct __kernel_timespec ts;
> +	int ret;
> +
> +	ret = __cvdso_clock_getres_common(clock, &ts);
> +
> +	if (likely(!ret)) {
> +		res->tv_sec = ts.tv_sec;
> +		res->tv_nsec = ts.tv_nsec;
> +		return 0;
> +	}
> +
> +	return clock_getres32_fallback(clock, res);
> +}
> +#endif
> +
>  #endif /* VDSO_HAS_CLOCK_GETRES */

Any reason not to have the #ifndef apply only to the fallback?  Wrapping
the entire function and flipping the order of handling 'ret' makes it a bit
difficult to discern that the only difference is the fallback invocation.

static __maybe_unused int
__cvdso_clock_gettime32(clockid_t clock, struct old_timespec32 *res)
{
        struct __kernel_timespec ts;
        int ret;

        ret = __cvdso_clock_gettime_common(clock, &ts);

        if (unlikely(ret))
#ifndef VDSO_HAS_32BIT_FALLBACK
                ret = clock_gettime_fallback(clock, &ts);
#else
                return clock_gettime32_fallback(clock, res);
#endif

        if (likely(!ret)) {
                res->tv_sec = ts.tv_sec;
                res->tv_nsec = ts.tv_nsec;
        }
        return ret;
}

static __maybe_unused int
__cvdso_clock_getres_time32(clockid_t clock, struct old_timespec32 *res)
{
        struct __kernel_timespec ts;
        int ret;

        ret = __cvdso_clock_getres_common(clock, &ts);
        if (unlikely(ret))
#ifndef VDSO_HAS_32BIT_FALLBACK
                ret = clock_getres_fallback(clock, &ts);
#else
                return clock_getres32_fallback(clock, res);
#endif

        if (likely(!ret)) {
                res->tv_sec = ts.tv_sec;
                res->tv_nsec = ts.tv_nsec;
        }
        return ret;
}

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch 4/5] x86/vdso/32: Use 32bit syscall fallback
  2019-07-28 13:12 ` [patch 4/5] x86/vdso/32: Use 32bit syscall fallback Thomas Gleixner
  2019-07-28 14:50   ` Andy Lutomirski
  2019-07-29 11:23   ` Vincenzo Frascino
@ 2019-07-29 14:51   ` Sean Christopherson
  2019-07-30 22:21   ` [tip:timers/urgent] " tip-bot for Thomas Gleixner
  3 siblings, 0 replies; 28+ messages in thread
From: Sean Christopherson @ 2019-07-29 14:51 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, x86, Andy Lutomirski, Vincenzo Frascino, Kees Cook,
	Paul Bolle, Will Deacon

On Sun, Jul 28, 2019 at 03:12:55PM +0200, Thomas Gleixner wrote:
> The generic VDSO implementation uses the Y2038 safe clock_gettime64() and
> clock_getres_time64() syscalls as fallback for 32bit VDSO. This breaks
> seccomp setups because these syscalls might be not (yet) allowed.
> 
> Implement the 32bit variants which use the legacy syscalls and select the
> variant in the core library.
> 
> The 64bit time variants are not removed because they are required for the
> time64 based vdso accessors.
> 
> Reported-by: Sean Christopherson <sean.j.christopherson@intel.com>
> Reported-by: Paul Bolle <pebolle@tiscali.nl>
> Suggested-by: Andy Lutomirski <luto@kernel.org>
> Fixes: 7ac870747988 ("x86/vdso: Switch to generic vDSO implementation")
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> ---

Reviewed-and-tested-by: Sean Christopherson <sean.j.christopherson@intel.com>

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch 1/5] lib/vdso/32: Remove inconsistent NULL pointer checks
  2019-07-28 13:12 ` [patch 1/5] lib/vdso/32: Remove inconsistent NULL pointer checks Thomas Gleixner
  2019-07-28 14:33   ` Andy Lutomirski
  2019-07-28 15:30   ` Vincenzo Frascino
@ 2019-07-29 14:52   ` Sean Christopherson
  2019-07-30 22:19   ` [tip:timers/urgent] " tip-bot for Thomas Gleixner
  3 siblings, 0 replies; 28+ messages in thread
From: Sean Christopherson @ 2019-07-29 14:52 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, x86, Andy Lutomirski, Vincenzo Frascino, Kees Cook,
	Paul Bolle, Will Deacon

On Sun, Jul 28, 2019 at 03:12:52PM +0200, Thomas Gleixner wrote:
> The 32bit variants of vdso_clock_gettime()/getres() have a NULL pointer
> check for the timespec pointer. That's inconsistent vs. 64bit.
> 
> But the vdso implementation will never be consistent versus the syscall
> because the only case which it can handle is NULL. Any other invalid
> pointer will cause a segfault. So special casing NULL is not really useful.
> 
> Remove it along with the superflouos syscall fallback invocation as that

s/superflouos/superfluous

> will return -EFAULT anyway. That also gets rid of the dubious typecast
> which only works because the pointer is NULL.
> 
> Fixes: 00b26474c2f1 ("lib/vdso: Provide generic VDSO implementation")
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> ---

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [patch V2 3/5] lib/vdso/32: Provide legacy syscall fallbacks
  2019-07-29 14:48   ` Sean Christopherson
@ 2019-07-30  9:38     ` Thomas Gleixner
  2019-07-30 14:28       ` Sean Christopherson
                         ` (2 more replies)
  0 siblings, 3 replies; 28+ messages in thread
From: Thomas Gleixner @ 2019-07-30  9:38 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: LKML, x86, Andy Lutomirski, Vincenzo Frascino, Kees Cook,
	Paul Bolle, Will Deacon

To address the regression which causes seccomp to deny applications the
access to clock_gettime64() and clock_getres64() syscalls because they
are not enabled in the existing filters.

That trips over the fact that 32bit VDSOs use the new clock_gettime64() and
clock_getres64() syscalls in the fallback path.

Add a conditional to invoke the 32bit legacy fallback syscalls instead of
the new 64bit variants. The conditional can go away once all architectures
are converted.

Fixes: 00b26474c2f1 ("lib/vdso: Provide generic VDSO implementation")
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
V2: Move the #ifdef into the fallback function
---
 lib/vdso/gettimeofday.c |   12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

--- a/lib/vdso/gettimeofday.c
+++ b/lib/vdso/gettimeofday.c
@@ -125,14 +125,18 @@ static __maybe_unused int
 
 	ret = __cvdso_clock_gettime_common(clock, &ts);
 
+#ifdef VDSO_HAS_32BIT_FALLBACK
+	if (unlikely(ret))
+		return clock_gettime32_fallback(clock, res);
+#else
 	if (unlikely(ret))
 		ret = clock_gettime_fallback(clock, &ts);
+#endif
 
 	if (likely(!ret)) {
 		res->tv_sec = ts.tv_sec;
 		res->tv_nsec = ts.tv_nsec;
 	}
-
 	return ret;
 }
 
@@ -232,8 +236,14 @@ static __maybe_unused int
 	int ret;
 
 	ret = __cvdso_clock_getres_common(clock, &ts);
+
+#ifdef VDSO_HAS_32BIT_FALLBACK
+	if (unlikely(ret))
+		return clock_getres32_fallback(clock, res);
+#else
 	if (unlikely(ret))
 		ret = clock_getres_fallback(clock, &ts);
+#endif
 
 	if (likely(!ret)) {
 		res->tv_sec = ts.tv_sec;

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch V2 3/5] lib/vdso/32: Provide legacy syscall fallbacks
  2019-07-30  9:38     ` [patch V2 " Thomas Gleixner
@ 2019-07-30 14:28       ` Sean Christopherson
  2019-07-30 20:09       ` Andy Lutomirski
  2019-07-30 22:20       ` [tip:timers/urgent] " tip-bot for Thomas Gleixner
  2 siblings, 0 replies; 28+ messages in thread
From: Sean Christopherson @ 2019-07-30 14:28 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, x86, Andy Lutomirski, Vincenzo Frascino, Kees Cook,
	Paul Bolle, Will Deacon

On Tue, Jul 30, 2019 at 11:38:50AM +0200, Thomas Gleixner wrote:
> To address the regression which causes seccomp to deny applications the
> access to clock_gettime64() and clock_getres64() syscalls because they
> are not enabled in the existing filters.
> 
> That trips over the fact that 32bit VDSOs use the new clock_gettime64() and
> clock_getres64() syscalls in the fallback path.
> 
> Add a conditional to invoke the 32bit legacy fallback syscalls instead of
> the new 64bit variants. The conditional can go away once all architectures
> are converted.
> 
> Fixes: 00b26474c2f1 ("lib/vdso: Provide generic VDSO implementation")
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> ---

Reviewed-and-tested-by: Sean Christopherson <sean.j.christopherson@intel.com>

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch V2 3/5] lib/vdso/32: Provide legacy syscall fallbacks
  2019-07-30  9:38     ` [patch V2 " Thomas Gleixner
  2019-07-30 14:28       ` Sean Christopherson
@ 2019-07-30 20:09       ` Andy Lutomirski
  2019-07-30 20:14         ` Thomas Gleixner
  2019-07-30 22:20       ` [tip:timers/urgent] " tip-bot for Thomas Gleixner
  2 siblings, 1 reply; 28+ messages in thread
From: Andy Lutomirski @ 2019-07-30 20:09 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Sean Christopherson, LKML, X86 ML, Andy Lutomirski,
	Vincenzo Frascino, Kees Cook, Paul Bolle, Will Deacon

On Tue, Jul 30, 2019 at 2:39 AM Thomas Gleixner <tglx@linutronix.de> wrote:
>
> To address the regression which causes seccomp to deny applications the
> access to clock_gettime64() and clock_getres64() syscalls because they
> are not enabled in the existing filters.
>
> That trips over the fact that 32bit VDSOs use the new clock_gettime64() and
> clock_getres64() syscalls in the fallback path.
>
> Add a conditional to invoke the 32bit legacy fallback syscalls instead of
> the new 64bit variants. The conditional can go away once all architectures
> are converted.
>

I haven't surveyed all the architectures, but once everything is
converted, shouldn't we use the 32-bit fallback for exactly the same
set of architectures that want clock_gettime32 at all in the vdso?

--Andy

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patch V2 3/5] lib/vdso/32: Provide legacy syscall fallbacks
  2019-07-30 20:09       ` Andy Lutomirski
@ 2019-07-30 20:14         ` Thomas Gleixner
  0 siblings, 0 replies; 28+ messages in thread
From: Thomas Gleixner @ 2019-07-30 20:14 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Sean Christopherson, LKML, X86 ML, Vincenzo Frascino, Kees Cook,
	Paul Bolle, Will Deacon

On Tue, 30 Jul 2019, Andy Lutomirski wrote:

> On Tue, Jul 30, 2019 at 2:39 AM Thomas Gleixner <tglx@linutronix.de> wrote:
> >
> > To address the regression which causes seccomp to deny applications the
> > access to clock_gettime64() and clock_getres64() syscalls because they
> > are not enabled in the existing filters.
> >
> > That trips over the fact that 32bit VDSOs use the new clock_gettime64() and
> > clock_getres64() syscalls in the fallback path.
> >
> > Add a conditional to invoke the 32bit legacy fallback syscalls instead of
> > the new 64bit variants. The conditional can go away once all architectures
> > are converted.
> >
> 
> I haven't surveyed all the architectures, but once everything is
> converted, shouldn't we use the 32-bit fallback for exactly the same
> set of architectures that want clock_gettime32 at all in the vdso?

Yes. That's why I want to remove the conditional once all all converted
over, that's x86/aaarg64 in mainline and a few in next.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [tip:timers/urgent] lib/vdso/32: Remove inconsistent NULL pointer checks
  2019-07-28 13:12 ` [patch 1/5] lib/vdso/32: Remove inconsistent NULL pointer checks Thomas Gleixner
                     ` (2 preceding siblings ...)
  2019-07-29 14:52   ` Sean Christopherson
@ 2019-07-30 22:19   ` tip-bot for Thomas Gleixner
  3 siblings, 0 replies; 28+ messages in thread
From: tip-bot for Thomas Gleixner @ 2019-07-30 22:19 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: luto, linux-kernel, vincenzo.frascino, tglx, mingo, hpa

Commit-ID:  a9446a906f52292c52ecbd5be78eaa4d8395756c
Gitweb:     https://git.kernel.org/tip/a9446a906f52292c52ecbd5be78eaa4d8395756c
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sun, 28 Jul 2019 15:12:52 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Wed, 31 Jul 2019 00:09:09 +0200

lib/vdso/32: Remove inconsistent NULL pointer checks

The 32bit variants of vdso_clock_gettime()/getres() have a NULL pointer
check for the timespec pointer. That's inconsistent vs. 64bit.

But the vdso implementation will never be consistent versus the syscall
because the only case which it can handle is NULL. Any other invalid
pointer will cause a segfault. So special casing NULL is not really useful.

Remove it along with the superflouos syscall fallback invocation as that
will return -EFAULT anyway. That also gets rid of the dubious typecast
which only works because the pointer is NULL.

Fixes: 00b26474c2f1 ("lib/vdso: Provide generic VDSO implementation")
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Reviewed-by: Andy Lutomirski <luto@kernel.org>
Link: https://lkml.kernel.org/r/20190728131648.587523358@linutronix.de

---
 lib/vdso/gettimeofday.c | 18 ++----------------
 1 file changed, 2 insertions(+), 16 deletions(-)

diff --git a/lib/vdso/gettimeofday.c b/lib/vdso/gettimeofday.c
index 2d1c1f241fd9..e28f5a607a5f 100644
--- a/lib/vdso/gettimeofday.c
+++ b/lib/vdso/gettimeofday.c
@@ -115,9 +115,6 @@ __cvdso_clock_gettime32(clockid_t clock, struct old_timespec32 *res)
 	struct __kernel_timespec ts;
 	int ret;
 
-	if (res == NULL)
-		goto fallback;
-
 	ret = __cvdso_clock_gettime(clock, &ts);
 
 	if (ret == 0) {
@@ -126,9 +123,6 @@ __cvdso_clock_gettime32(clockid_t clock, struct old_timespec32 *res)
 	}
 
 	return ret;
-
-fallback:
-	return clock_gettime_fallback(clock, (struct __kernel_timespec *)res);
 }
 
 static __maybe_unused int
@@ -204,10 +198,8 @@ int __cvdso_clock_getres(clockid_t clock, struct __kernel_timespec *res)
 		goto fallback;
 	}
 
-	if (res) {
-		res->tv_sec = 0;
-		res->tv_nsec = ns;
-	}
+	res->tv_sec = 0;
+	res->tv_nsec = ns;
 
 	return 0;
 
@@ -221,9 +213,6 @@ __cvdso_clock_getres_time32(clockid_t clock, struct old_timespec32 *res)
 	struct __kernel_timespec ts;
 	int ret;
 
-	if (res == NULL)
-		goto fallback;
-
 	ret = __cvdso_clock_getres(clock, &ts);
 
 	if (ret == 0) {
@@ -232,8 +221,5 @@ __cvdso_clock_getres_time32(clockid_t clock, struct old_timespec32 *res)
 	}
 
 	return ret;
-
-fallback:
-	return clock_getres_fallback(clock, (struct __kernel_timespec *)res);
 }
 #endif /* VDSO_HAS_CLOCK_GETRES */

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [tip:timers/urgent] lib/vdso: Move fallback invocation to the callers
  2019-07-28 13:12 ` [patch 2/5] lib/vdso: Move fallback invocation to the callers Thomas Gleixner
  2019-07-28 14:37   ` Andy Lutomirski
  2019-07-28 15:31   ` Vincenzo Frascino
@ 2019-07-30 22:19   ` tip-bot for Thomas Gleixner
  2 siblings, 0 replies; 28+ messages in thread
From: tip-bot for Thomas Gleixner @ 2019-07-30 22:19 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: linux-kernel, luto, tglx, vincenzo.frascino, mingo, hpa

Commit-ID:  502a590a170b3b3d0ad998ee0b639ac0b3db1dfa
Gitweb:     https://git.kernel.org/tip/502a590a170b3b3d0ad998ee0b639ac0b3db1dfa
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sun, 28 Jul 2019 15:12:53 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Wed, 31 Jul 2019 00:09:09 +0200

lib/vdso: Move fallback invocation to the callers

To allow syscall fallbacks using the legacy 32bit syscall for 32bit VDSO
builds, move the fallback invocation out into the callers.

Split the common code out of __cvdso_clock_gettime/getres() and invoke the
syscall fallback in the 64bit and 32bit variants.

Preparatory work for using legacy syscalls in 32bit VDSO. No functional
change.

Fixes: 00b26474c2f1 ("lib/vdso: Provide generic VDSO implementation")
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Reviewed-by: Andy Lutomirski <luto@kernel.org>
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Link: https://lkml.kernel.org/r/20190728131648.695579736@linutronix.de

---
 lib/vdso/gettimeofday.c | 53 +++++++++++++++++++++++++++++++++----------------
 1 file changed, 36 insertions(+), 17 deletions(-)

diff --git a/lib/vdso/gettimeofday.c b/lib/vdso/gettimeofday.c
index e28f5a607a5f..a9e7fd029593 100644
--- a/lib/vdso/gettimeofday.c
+++ b/lib/vdso/gettimeofday.c
@@ -51,7 +51,7 @@ static int do_hres(const struct vdso_data *vd, clockid_t clk,
 		ns = vdso_ts->nsec;
 		last = vd->cycle_last;
 		if (unlikely((s64)cycles < 0))
-			return clock_gettime_fallback(clk, ts);
+			return -1;
 
 		ns += vdso_calc_delta(cycles, last, vd->mask, vd->mult);
 		ns >>= vd->shift;
@@ -82,14 +82,14 @@ static void do_coarse(const struct vdso_data *vd, clockid_t clk,
 }
 
 static __maybe_unused int
-__cvdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts)
+__cvdso_clock_gettime_common(clockid_t clock, struct __kernel_timespec *ts)
 {
 	const struct vdso_data *vd = __arch_get_vdso_data();
 	u32 msk;
 
 	/* Check for negative values or invalid clocks */
 	if (unlikely((u32) clock >= MAX_CLOCKS))
-		goto fallback;
+		return -1;
 
 	/*
 	 * Convert the clockid to a bitmask and use it to check which
@@ -104,9 +104,17 @@ __cvdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts)
 	} else if (msk & VDSO_RAW) {
 		return do_hres(&vd[CS_RAW], clock, ts);
 	}
+	return -1;
+}
 
-fallback:
-	return clock_gettime_fallback(clock, ts);
+static __maybe_unused int
+__cvdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts)
+{
+	int ret = __cvdso_clock_gettime_common(clock, ts);
+
+	if (unlikely(ret))
+		return clock_gettime_fallback(clock, ts);
+	return 0;
 }
 
 static __maybe_unused int
@@ -115,9 +123,12 @@ __cvdso_clock_gettime32(clockid_t clock, struct old_timespec32 *res)
 	struct __kernel_timespec ts;
 	int ret;
 
-	ret = __cvdso_clock_gettime(clock, &ts);
+	ret = __cvdso_clock_gettime_common(clock, &ts);
 
-	if (ret == 0) {
+	if (unlikely(ret))
+		ret = clock_gettime_fallback(clock, &ts);
+
+	if (likely(!ret)) {
 		res->tv_sec = ts.tv_sec;
 		res->tv_nsec = ts.tv_nsec;
 	}
@@ -163,17 +174,18 @@ static __maybe_unused time_t __cvdso_time(time_t *time)
 
 #ifdef VDSO_HAS_CLOCK_GETRES
 static __maybe_unused
-int __cvdso_clock_getres(clockid_t clock, struct __kernel_timespec *res)
+int __cvdso_clock_getres_common(clockid_t clock, struct __kernel_timespec *res)
 {
 	const struct vdso_data *vd = __arch_get_vdso_data();
-	u64 ns;
+	u64 hrtimer_res;
 	u32 msk;
-	u64 hrtimer_res = READ_ONCE(vd[CS_HRES_COARSE].hrtimer_res);
+	u64 ns;
 
 	/* Check for negative values or invalid clocks */
 	if (unlikely((u32) clock >= MAX_CLOCKS))
-		goto fallback;
+		return -1;
 
+	hrtimer_res = READ_ONCE(vd[CS_HRES_COARSE].hrtimer_res);
 	/*
 	 * Convert the clockid to a bitmask and use it to check which
 	 * clocks are handled in the VDSO directly.
@@ -195,16 +207,22 @@ int __cvdso_clock_getres(clockid_t clock, struct __kernel_timespec *res)
 		 */
 		ns = hrtimer_res;
 	} else {
-		goto fallback;
+		return -1;
 	}
 
 	res->tv_sec = 0;
 	res->tv_nsec = ns;
 
 	return 0;
+}
+
+int __cvdso_clock_getres(clockid_t clock, struct __kernel_timespec *res)
+{
+	int ret = __cvdso_clock_getres_common(clock, res);
 
-fallback:
-	return clock_getres_fallback(clock, res);
+	if (unlikely(ret))
+		return clock_getres_fallback(clock, res);
+	return 0;
 }
 
 static __maybe_unused int
@@ -213,13 +231,14 @@ __cvdso_clock_getres_time32(clockid_t clock, struct old_timespec32 *res)
 	struct __kernel_timespec ts;
 	int ret;
 
-	ret = __cvdso_clock_getres(clock, &ts);
+	ret = __cvdso_clock_getres_common(clock, &ts);
+	if (unlikely(ret))
+		ret = clock_getres_fallback(clock, &ts);
 
-	if (ret == 0) {
+	if (likely(!ret)) {
 		res->tv_sec = ts.tv_sec;
 		res->tv_nsec = ts.tv_nsec;
 	}
-
 	return ret;
 }
 #endif /* VDSO_HAS_CLOCK_GETRES */

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [tip:timers/urgent] lib/vdso/32: Provide legacy syscall fallbacks
  2019-07-30  9:38     ` [patch V2 " Thomas Gleixner
  2019-07-30 14:28       ` Sean Christopherson
  2019-07-30 20:09       ` Andy Lutomirski
@ 2019-07-30 22:20       ` tip-bot for Thomas Gleixner
  2 siblings, 0 replies; 28+ messages in thread
From: tip-bot for Thomas Gleixner @ 2019-07-30 22:20 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: mingo, tglx, linux-kernel, sean.j.christopherson, hpa

Commit-ID:  c60a32ea4f459f99b98d383cad3b1ac7cfb3f4be
Gitweb:     https://git.kernel.org/tip/c60a32ea4f459f99b98d383cad3b1ac7cfb3f4be
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Tue, 30 Jul 2019 11:38:50 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Wed, 31 Jul 2019 00:09:09 +0200

lib/vdso/32: Provide legacy syscall fallbacks

To address the regression which causes seccomp to deny applications the
access to clock_gettime64() and clock_getres64() syscalls because they
are not enabled in the existing filters.

That trips over the fact that 32bit VDSOs use the new clock_gettime64() and
clock_getres64() syscalls in the fallback path.

Add a conditional to invoke the 32bit legacy fallback syscalls instead of
the new 64bit variants. The conditional can go away once all architectures
are converted.

Fixes: 00b26474c2f1 ("lib/vdso: Provide generic VDSO implementation")
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Sean Christopherson <sean.j.christopherson@intel.com>
Reviewed-by: Sean Christopherson <sean.j.christopherson@intel.com>
Link: https://lkml.kernel.org/r/alpine.DEB.2.21.1907301134470.1738@nanos.tec.linutronix.de

---
 lib/vdso/gettimeofday.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/lib/vdso/gettimeofday.c b/lib/vdso/gettimeofday.c
index a9e7fd029593..e630e7ff57f1 100644
--- a/lib/vdso/gettimeofday.c
+++ b/lib/vdso/gettimeofday.c
@@ -125,14 +125,18 @@ __cvdso_clock_gettime32(clockid_t clock, struct old_timespec32 *res)
 
 	ret = __cvdso_clock_gettime_common(clock, &ts);
 
+#ifdef VDSO_HAS_32BIT_FALLBACK
+	if (unlikely(ret))
+		return clock_gettime32_fallback(clock, res);
+#else
 	if (unlikely(ret))
 		ret = clock_gettime_fallback(clock, &ts);
+#endif
 
 	if (likely(!ret)) {
 		res->tv_sec = ts.tv_sec;
 		res->tv_nsec = ts.tv_nsec;
 	}
-
 	return ret;
 }
 
@@ -232,8 +236,14 @@ __cvdso_clock_getres_time32(clockid_t clock, struct old_timespec32 *res)
 	int ret;
 
 	ret = __cvdso_clock_getres_common(clock, &ts);
+
+#ifdef VDSO_HAS_32BIT_FALLBACK
+	if (unlikely(ret))
+		return clock_getres32_fallback(clock, res);
+#else
 	if (unlikely(ret))
 		ret = clock_getres_fallback(clock, &ts);
+#endif
 
 	if (likely(!ret)) {
 		res->tv_sec = ts.tv_sec;

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [tip:timers/urgent] x86/vdso/32: Use 32bit syscall fallback
  2019-07-28 13:12 ` [patch 4/5] x86/vdso/32: Use 32bit syscall fallback Thomas Gleixner
                     ` (2 preceding siblings ...)
  2019-07-29 14:51   ` Sean Christopherson
@ 2019-07-30 22:21   ` tip-bot for Thomas Gleixner
  3 siblings, 0 replies; 28+ messages in thread
From: tip-bot for Thomas Gleixner @ 2019-07-30 22:21 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: luto, mingo, sean.j.christopherson, tglx, vincenzo.frascino,
	pebolle, linux-kernel, hpa

Commit-ID:  d2f5d3fa26196183adb44a413c44caa9872275b4
Gitweb:     https://git.kernel.org/tip/d2f5d3fa26196183adb44a413c44caa9872275b4
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sun, 28 Jul 2019 15:12:55 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Wed, 31 Jul 2019 00:09:10 +0200

x86/vdso/32: Use 32bit syscall fallback

The generic VDSO implementation uses the Y2038 safe clock_gettime64() and
clock_getres_time64() syscalls as fallback for 32bit VDSO. This breaks
seccomp setups because these syscalls might be not (yet) allowed.

Implement the 32bit variants which use the legacy syscalls and select the
variant in the core library.

The 64bit time variants are not removed because they are required for the
time64 based vdso accessors.

Fixes: 7ac870747988 ("x86/vdso: Switch to generic vDSO implementation")
Reported-by: Sean Christopherson <sean.j.christopherson@intel.com>
Reported-by: Paul Bolle <pebolle@tiscali.nl>
Suggested-by: Andy Lutomirski <luto@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Reviewed-by: Andy Lutomirski <luto@kernel.org>
Link: https://lkml.kernel.org/r/20190728131648.879156507@linutronix.de

---
 arch/x86/include/asm/vdso/gettimeofday.h | 36 ++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/arch/x86/include/asm/vdso/gettimeofday.h b/arch/x86/include/asm/vdso/gettimeofday.h
index ae91429129a6..ba71a63cdac4 100644
--- a/arch/x86/include/asm/vdso/gettimeofday.h
+++ b/arch/x86/include/asm/vdso/gettimeofday.h
@@ -96,6 +96,8 @@ long clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
 
 #else
 
+#define VDSO_HAS_32BIT_FALLBACK	1
+
 static __always_inline
 long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
 {
@@ -113,6 +115,23 @@ long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
 	return ret;
 }
 
+static __always_inline
+long clock_gettime32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
+{
+	long ret;
+
+	asm (
+		"mov %%ebx, %%edx \n"
+		"mov %[clock], %%ebx \n"
+		"call __kernel_vsyscall \n"
+		"mov %%edx, %%ebx \n"
+		: "=a" (ret), "=m" (*_ts)
+		: "0" (__NR_clock_gettime), [clock] "g" (_clkid), "c" (_ts)
+		: "edx");
+
+	return ret;
+}
+
 static __always_inline
 long gettimeofday_fallback(struct __kernel_old_timeval *_tv,
 			   struct timezone *_tz)
@@ -148,6 +167,23 @@ clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
 	return ret;
 }
 
+static __always_inline
+long clock_getres32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
+{
+	long ret;
+
+	asm (
+		"mov %%ebx, %%edx \n"
+		"mov %[clock], %%ebx \n"
+		"call __kernel_vsyscall \n"
+		"mov %%edx, %%ebx \n"
+		: "=a" (ret), "=m" (*_ts)
+		: "0" (__NR_clock_getres), [clock] "g" (_clkid), "c" (_ts)
+		: "edx");
+
+	return ret;
+}
+
 #endif
 
 #ifdef CONFIG_PARAVIRT_CLOCK

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [tip:timers/urgent] arm64: compat: vdso: Use legacy syscalls as fallback
  2019-07-28 13:12 ` [patch 5/5] arm64: compat: vdso: Use legacy syscalls as fallback Thomas Gleixner
  2019-07-28 15:35   ` Vincenzo Frascino
@ 2019-07-30 22:22   ` tip-bot for Thomas Gleixner
  1 sibling, 0 replies; 28+ messages in thread
From: tip-bot for Thomas Gleixner @ 2019-07-30 22:22 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: pebolle, luto, hpa, vincenzo.frascino, tglx,
	sean.j.christopherson, mingo, linux-kernel

Commit-ID:  33a58980ff3cc5dbf0bb1b325746ac69223eda0b
Gitweb:     https://git.kernel.org/tip/33a58980ff3cc5dbf0bb1b325746ac69223eda0b
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sun, 28 Jul 2019 15:12:56 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Wed, 31 Jul 2019 00:09:10 +0200

arm64: compat: vdso: Use legacy syscalls as fallback

The generic VDSO implementation uses the Y2038 safe clock_gettime64() and
clock_getres_time64() syscalls as fallback for 32bit VDSO. This breaks
seccomp setups because these syscalls might be not (yet) allowed.

Implement the 32bit variants which use the legacy syscalls and select the
variant in the core library.

The 64bit time variants are not removed because they are required for the
time64 based vdso accessors.

Fixes: 00b26474c2f1 ("lib/vdso: Provide generic VDSO implementation")
Reported-by: Sean Christopherson <sean.j.christopherson@intel.com>
Reported-by: Paul Bolle <pebolle@tiscali.nl>
Suggested-by: Andy Lutomirski <luto@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Link: https://lkml.kernel.org/r/20190728131648.971361611@linutronix.de

---
 arch/arm64/include/asm/vdso/compat_gettimeofday.h | 40 +++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/arch/arm64/include/asm/vdso/compat_gettimeofday.h b/arch/arm64/include/asm/vdso/compat_gettimeofday.h
index f4812777f5c5..c50ee1b7d5cd 100644
--- a/arch/arm64/include/asm/vdso/compat_gettimeofday.h
+++ b/arch/arm64/include/asm/vdso/compat_gettimeofday.h
@@ -16,6 +16,8 @@
 
 #define VDSO_HAS_CLOCK_GETRES		1
 
+#define VDSO_HAS_32BIT_FALLBACK		1
+
 static __always_inline
 int gettimeofday_fallback(struct __kernel_old_timeval *_tv,
 			  struct timezone *_tz)
@@ -51,6 +53,23 @@ long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
 	return ret;
 }
 
+static __always_inline
+long clock_gettime32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
+{
+	register struct old_timespec32 *ts asm("r1") = _ts;
+	register clockid_t clkid asm("r0") = _clkid;
+	register long ret asm ("r0");
+	register long nr asm("r7") = __NR_compat_clock_gettime;
+
+	asm volatile(
+	"	swi #0\n"
+	: "=r" (ret)
+	: "r" (clkid), "r" (ts), "r" (nr)
+	: "memory");
+
+	return ret;
+}
+
 static __always_inline
 int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
 {
@@ -72,6 +91,27 @@ int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
 	return ret;
 }
 
+static __always_inline
+int clock_getres32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
+{
+	register struct old_timespec32 *ts asm("r1") = _ts;
+	register clockid_t clkid asm("r0") = _clkid;
+	register long ret asm ("r0");
+	register long nr asm("r7") = __NR_compat_clock_getres;
+
+	/* The checks below are required for ABI consistency with arm */
+	if ((_clkid >= MAX_CLOCKS) && (_ts == NULL))
+		return -EINVAL;
+
+	asm volatile(
+	"       swi #0\n"
+	: "=r" (ret)
+	: "r" (clkid), "r" (ts), "r" (nr)
+	: "memory");
+
+	return ret;
+}
+
 static __always_inline u64 __arch_get_hw_counter(s32 clock_mode)
 {
 	u64 res;

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2019-07-30 22:22 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-28 13:12 [patch 0/5] lib/vdso, x86/vdso: Fix fallout from generic VDSO conversion Thomas Gleixner
2019-07-28 13:12 ` [patch 1/5] lib/vdso/32: Remove inconsistent NULL pointer checks Thomas Gleixner
2019-07-28 14:33   ` Andy Lutomirski
2019-07-28 14:42     ` Thomas Gleixner
2019-07-28 15:30   ` Vincenzo Frascino
2019-07-29 14:52   ` Sean Christopherson
2019-07-30 22:19   ` [tip:timers/urgent] " tip-bot for Thomas Gleixner
2019-07-28 13:12 ` [patch 2/5] lib/vdso: Move fallback invocation to the callers Thomas Gleixner
2019-07-28 14:37   ` Andy Lutomirski
2019-07-28 15:31   ` Vincenzo Frascino
2019-07-30 22:19   ` [tip:timers/urgent] " tip-bot for Thomas Gleixner
2019-07-28 13:12 ` [patch 3/5] lib/vdso/32: Provide legacy syscall fallbacks Thomas Gleixner
2019-07-28 14:39   ` Andy Lutomirski
2019-07-28 15:33   ` Vincenzo Frascino
2019-07-29 14:48   ` Sean Christopherson
2019-07-30  9:38     ` [patch V2 " Thomas Gleixner
2019-07-30 14:28       ` Sean Christopherson
2019-07-30 20:09       ` Andy Lutomirski
2019-07-30 20:14         ` Thomas Gleixner
2019-07-30 22:20       ` [tip:timers/urgent] " tip-bot for Thomas Gleixner
2019-07-28 13:12 ` [patch 4/5] x86/vdso/32: Use 32bit syscall fallback Thomas Gleixner
2019-07-28 14:50   ` Andy Lutomirski
2019-07-29 11:23   ` Vincenzo Frascino
2019-07-29 14:51   ` Sean Christopherson
2019-07-30 22:21   ` [tip:timers/urgent] " tip-bot for Thomas Gleixner
2019-07-28 13:12 ` [patch 5/5] arm64: compat: vdso: Use legacy syscalls as fallback Thomas Gleixner
2019-07-28 15:35   ` Vincenzo Frascino
2019-07-30 22:22   ` [tip:timers/urgent] " tip-bot for Thomas Gleixner

This is a public inbox, see mirroring instructions
on how to clone and mirror all data and code used for this inbox