Messages in this thread Patch in this message |  | | Date | Sat, 27 Jul 2019 23:52:32 +0200 (CEST) | From | Thomas Gleixner <> | Subject | Re: [5.2 REGRESSION] Generic vDSO breaks seccomp-enabled userspace on i386 |
| |
On Sat, 27 Jul 2019, Thomas Gleixner wrote: > On Sat, 27 Jul 2019, Andy Lutomirski wrote: > > > > I think it's getting quite late to start inventing new seccomp > > features to fix this. I think the right solution for 5.3 is to change > > the 32-bit vdso fallback to use the old clock_gettime, i.e. > > clock_gettime32. This is obviously not an acceptable long-term > > solution. > > Sigh. I'll have a look....
Completely untested patch below.
For the record: I have to say that I hate it.
Just to be clear. Once a clever seccomp admin decides to enforce Y2038 compliance by filtering out the legacy syscalls this will force glibc into the syscall slowpath directly because __vdso_clock_gettime64() is gone.
So this needs a proper secccomp solution soener than later.
The fallback change to the legacy syscall is on purpose conditional on CONFIG_SECCOMP so those people who care can get access to __vdso_clock_gettime64() nevertheless.
Thanks,
tglx
8<----------------- --- a/arch/x86/entry/vdso/vdso32/vdso32.lds.S +++ b/arch/x86/entry/vdso/vdso32/vdso32.lds.S @@ -27,7 +27,9 @@ VERSION __vdso_gettimeofday; __vdso_time; __vdso_clock_getres; +#ifndef CONFIG_SECCOMP __vdso_clock_gettime64; +#endif }; LINUX_2.5 { --- a/arch/x86/include/asm/vdso/gettimeofday.h +++ b/arch/x86/include/asm/vdso/gettimeofday.h @@ -101,6 +101,7 @@ long clock_gettime_fallback(clockid_t _c { long ret; +#ifndef CONFIG_SECCOMP asm ( "mov %%ebx, %%edx \n" "mov %[clock], %%ebx \n" @@ -110,6 +111,36 @@ long clock_gettime_fallback(clockid_t _c : "0" (__NR_clock_gettime64), [clock] "g" (_clkid), "c" (_ts) : "edx"); +#else + struct old_timespec32 tmpts; + + /* + * Using clock_gettime and not clock_gettime64 here is a + * temporary workaround to pacify seccomp filters which are + * unaware of the Y2038 safe variant. + */ + + asm ( + "mov %%ebx, %%edx \n" + "mov %[clock], %%ebx \n" + "call __kernel_vsyscall \n" + "mov %%edx, %%ebx \n" + : "=a" (ret), "=m" (tmpts) + : "0" (__NR_clock_gettime), [clock] "g" (_clkid), "c" (&tmpts) + : "edx"); + + /* + * The core code will have to convert that back. A smart compiler + * should notice and avoid the double conversion. If not, bad luck; + * we we are not going to change the core code just to make seccomp + * happy. + */ + + if (!ret) { + _ts->tv_sec = tmpts.tv_sec; + _ts->tv_nsec = tmpts.tv_nsec; + } +#endif return ret; } @@ -136,6 +167,7 @@ clock_getres_fallback(clockid_t _clkid, { long ret; +#ifndef CONFIG_SECCOMP asm ( "mov %%ebx, %%edx \n" "mov %[clock], %%ebx \n" @@ -144,7 +176,32 @@ clock_getres_fallback(clockid_t _clkid, : "=a" (ret), "=m" (*_ts) : "0" (__NR_clock_getres_time64), [clock] "g" (_clkid), "c" (_ts) : "edx"); +#else + struct old_timespec32 tmpts; + + /* + * Using clock_getres and not clock_getres_time64 here is a + * temporary workaround to pacify seccomp filters which are unaware + * of the time64 variants. Technically there is no requirement to + * use the 64bit variant here as the resolution is definitely not + * affected by Y2038, but the end goal of Y2038 is to utilize the + * new 64bit timespec variants for everything. + */ + + asm ( + "mov %%ebx, %%edx \n" + "mov %[clock], %%ebx \n" + "call __kernel_vsyscall \n" + "mov %%edx, %%ebx \n" + : "=a" (ret), "=m" (tmpts) + : "0" (__NR_clock_getres), [clock] "g" (_clkid), "c" (&tmpts) + : "edx"); + if (!ret) { + _ts->tv_sec = tmpts.tv_sec; + _ts->tv_nsec = tmpts.tv_nsec; + } +#endif return ret; }
|  |