Received: by 2002:a25:ad19:0:0:0:0:0 with SMTP id y25csp2411875ybi; Sun, 28 Jul 2019 08:28:52 -0700 (PDT) X-Google-Smtp-Source: APXvYqxQjSQaIel3D28vS4gGOEMNTJOwhPQOayBlMbwDbxkl0r34+Km3VTLWE3JOm3bIRoaLdl/+ X-Received: by 2002:a17:90a:7d04:: with SMTP id g4mr108508562pjl.41.1564327732416; Sun, 28 Jul 2019 08:28:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1564327732; cv=none; d=google.com; s=arc-20160816; b=jtjDdi99bXXOPoXpjQAuPOtGM/WKUBV4XgRj4DNrCMqNIuqxkIdzzgIq7gPF2sOfSQ eKvuCbeprvVq/ttUJs7Kp81CB7suqx8haJ9q/+Nb8oMSdfxTaEA1F5xWEmQYkpLu2o9C APykBS1rEasi9dH0KkpAyPpR6E0GONkz0JxY+hif6kHCdneYxynU1oBJOt6S2SCYwzm3 gHGCAG0cv0TNmWXWwjcSYhspPSrDB1q7GEGPtz2usyWj7ybwleS3sq2cnljZ5I4uGsMr 4flxtX2y78SNmQRKn5SwCDoecV2Exq2QuYNBY+KTwgF9nkSVAsqUfveFfoH3yrxa6vyD 85wA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version; bh=F35K+zfag4ltzyCsUASdf81c+ysiklIJwp6fDU8GkBg=; b=ObsnGF2Vtp6IbWZhYB02XNxhstBpNfr2GNlbgm1gUUt+RF7Wc8mfPg3+vIIkepCHrQ 0XSl47qbImCtk4t3M3QKm3R32+myVY/YyMkksrLBz1ZDS+sPuQSBjRs8NIQmgg3qLK4Q R4wp10DioOSeB1VNfLlGVkhprwPSO9+3X0U+ssr366BGfLVysM7cR74wmNl6+wbXEZO0 E9fAjp5JZjiXRqjST4T5b7ywMtdMuzdb2K0xXvzw7wSuepRj9OokEhiadToSW6Vx96p0 FnM78iCzOUNFReCSd1EejLpiwHvPNywK6avboJgCppj0wKFD8z1OtcfzpLm7YQps798y PMlw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id o4si23083226plb.274.2019.07.28.08.28.37; Sun, 28 Jul 2019 08:28:52 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726177AbfG1P1a (ORCPT + 99 others); Sun, 28 Jul 2019 11:27:30 -0400 Received: from mail-qk1-f196.google.com ([209.85.222.196]:33100 "EHLO mail-qk1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726046AbfG1P11 (ORCPT ); Sun, 28 Jul 2019 11:27:27 -0400 Received: by mail-qk1-f196.google.com with SMTP id r6so42502185qkc.0 for ; Sun, 28 Jul 2019 08:27:27 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=F35K+zfag4ltzyCsUASdf81c+ysiklIJwp6fDU8GkBg=; b=V7hrk/1IHBGxJbsyQBGs9oVwcMOEI00tc9ygXi/AWIp7RYi6FXRuseqE9MOQUxfAhl ejy6lFvcSpSeoQ/HP8hA2AlQ6Gi9iA/12GTiKnbUVQphxBNMnpOUoApbh77wiHRv8PAq bYPRe63dDHMrXjZK/Tb7FuD++NP4/rdKXkd+mSnp7zbmDRDGBSaWFDNYjWb2F4YMONwp IkXU4QUUiNKhOKnE+Jpf4QuxUWCWB4rt8Fbh+LQw42eP9+/sZi3MqbDlmc+/QV9hbVaJ RWOM51kgxgymkr9Doo+bQq2ccfVgpkX58HFBLEUWDiW7TwRxDcXKxXNo2SPgFNaEhUOa I8ig== X-Gm-Message-State: APjAAAWJxecD3KrOYlCiNHRyxFvUy6rt5KEQnUAJGPcgOHkcJ+n8Dtg+ s4K1P+6wYQIRvsvRK97fxU1Hq/lP5Sp6XRodang= X-Received: by 2002:a37:4ac3:: with SMTP id x186mr67603060qka.138.1564327646458; Sun, 28 Jul 2019 08:27:26 -0700 (PDT) MIME-Version: 1.0 References: <201907221012.41504DCD@keescook> <201907221135.2C2D262D8@keescook> <201907221620.F31B9A082@keescook> <201907231437.DB20BEBD3@keescook> <201907231636.AD3ED717D@keescook> <20190726180103.GE3188@linux.intel.com> In-Reply-To: From: Arnd Bergmann Date: Sun, 28 Jul 2019 17:27:10 +0200 Message-ID: Subject: Re: [5.2 REGRESSION] Generic vDSO breaks seccomp-enabled userspace on i386 To: Thomas Gleixner Cc: Andy Lutomirski , Sean Christopherson , Kees Cook , Vincenzo Frascino , X86 ML , LKML , Paul Bolle Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Sun, Jul 28, 2019 at 12:30 PM Thomas Gleixner wrote: > On Sun, 28 Jul 2019, Arnd Bergmann wrote: > > On Sat, Jul 27, 2019 at 7:53 PM Andy Lutomirski wrote: > Which is totally irrelevant because res is NULL and that NULL pointer check > should simply return -EFAULT, which is what the syscall fallback returns > because the pointer is NULL. > > But that NULL pointer check is inconsistent anyway: > > - 64 bit does not have it and never had > > - the vdso is not capable of handling faults properly anyway. If the > pointer is not valid, then it will segfault. So just preventing the > segfault for NULL is silly. > > I'm going to just remove it. Ah, you are right, I misread. Anyway, if we want to keep the traditional behavior and get fewer surprises for users of seccomp and anything else that might observe clock_gettime behavior, below is how I'd do it. (not even build tested, x86-only. I'll send a proper patch if this is where we want to take it). Arnd diff --git a/arch/x86/include/asm/vdso/gettimeofday.h b/arch/x86/include/asm/vdso/gettimeofday.h index ae91429129a6..f7b6a50d4811 100644 --- a/arch/x86/include/asm/vdso/gettimeofday.h +++ b/arch/x86/include/asm/vdso/gettimeofday.h @@ -70,6 +70,13 @@ 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) +{ + return -ENOSYS; +} + static __always_inline long gettimeofday_fallback(struct __kernel_old_timeval *_tv, struct timezone *_tz) @@ -97,7 +104,7 @@ long clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts) #else static __always_inline -long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts) +long clock_gettime_fallback(clockid_t _clkid, struct old_timespec32 *_ts) { long ret; @@ -113,6 +120,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 __kernel_timespec *_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) diff --git a/lib/vdso/gettimeofday.c b/lib/vdso/gettimeofday.c index 2d1c1f241fd9..3b3dab53d611 100644 --- a/lib/vdso/gettimeofday.c +++ b/lib/vdso/gettimeofday.c @@ -18,6 +18,7 @@ * clock_mode. * - gettimeofday_fallback(): fallback for gettimeofday. * - clock_gettime_fallback(): fallback for clock_gettime. + * - clock_gettime_fallback(): fallback for clock_gettime32. * - clock_getres_fallback(): fallback for clock_getres. */ #ifdef ENABLE_COMPAT_VDSO @@ -51,7 +52,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 -ENOSYS; ns += vdso_calc_delta(cycles, last, vd->mask, vd->mult); ns >>= vd->shift; @@ -81,15 +82,15 @@ static void do_coarse(const struct vdso_data *vd, clockid_t clk, } while (unlikely(vdso_read_retry(vd, seq))); } -static __maybe_unused int -__cvdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts) +static int +__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 -EINVAL; /* * Convert the clockid to a bitmask and use it to check which @@ -105,7 +106,15 @@ __cvdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts) return do_hres(&vd[CS_RAW], clock, ts); } -fallback: + return -EINVAL; +} + +static __maybe_unused int +__cvdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts) +{ + if (!__cvdso_clock_gettime_common(clock, ts)) + return 0; + return clock_gettime_fallback(clock, ts); } @@ -113,22 +122,14 @@ static __maybe_unused int __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) { + if (!__cvdso_clock_gettime_common(clock, &ts)) { res->tv_sec = ts.tv_sec; res->tv_nsec = ts.tv_nsec; + return 0; } - return ret; - -fallback: - return clock_gettime_fallback(clock, (struct __kernel_timespec *)res); + return clock_gettime32_fallback(clock, res); } static __maybe_unused int