RFR 8224676: Java crash if VSYSCALL is missing
Vladimir Kempik
vkempik at azul.com
Fri May 24 09:05:29 UTC 2019
Hello
Few more questions to answer:
>Do we know that all relevant versions of linux support this? Is it always available on those versions?
So far it seems to be 2.6.18+
it’s always available since the code doesn’t interact with kernel directly.
Th other possible way to go:
using uname from sys/utsname.h get linux kernel major version, then if its 3+ go «lsl» routine, otherwise go vsyscall way.
Thanks, Vladimir
> 23 мая 2019 г., в 20:16, Mikael Vidstedt <mikael.vidstedt at oracle.com> написал(а):
>
>
> Is this really correct? I think the CPU index needs to be extracted from the number, because not all bits are CPU index..?
>
> Do we know that all relevant versions of linux support this? Is it always available on those versions?
>
> Cheers,
> Mikael
>
>> On May 23, 2019, at 8:23 AM, Vladimir Kempik <vkempik at azul.com> wrote:
>>
>> Hello,
>>
>> Please review the following patch to address the issue:
>>
>> Bug: https://bugs.openjdk.java.net/browse/JDK-8224676
>>
>> Webrev: http://cr.openjdk.java.net/~vkempik/8224676/webrev.00/
>>
>> Summary:
>> Java (and epecially ZGC) is using VSYSCALL linux kernel functionality to get cpu-id for a thread, basically to know on which cpu current thread is running.
>> A relevant peace of code:
>>
>>
>> int os::Linux::sched_getcpu_syscall(void) {
>> unsigned int cpu = 0;
>> int retval = -1;
>>
>> #if defined(IA32)
>> #ifndef SYS_getcpu
>> #define SYS_getcpu 318
>> #endif
>> retval = syscall(SYS_getcpu, &cpu, NULL, NULL);
>> #elif defined(AMD64)
>> // Unfortunately we have to bring all these macros here from vsyscall.h
>> // to be able to compile on old linuxes.
>> #define __NR_vgetcpu 2
>> #define VSYSCALL_START (-10UL << 20)
>> #define VSYSCALL_SIZE 1024
>> #define VSYSCALL_ADDR(vsyscall_nr) (VSYSCALL_START+VSYSCALL_SIZE*(vsyscall_nr))
>> typedef long (*vgetcpu_t)(unsigned int *cpu, unsigned int *node, unsigned long *tcache);
>> vgetcpu_t vgetcpu = (vgetcpu_t)VSYSCALL_ADDR(__NR_vgetcpu);
>> retval = vgetcpu(&cpu, NULL, NULL);
>> #endif
>>
>>
>> In x86 linux it’s going syscall way, which is a bit slow due to context switching.
>> on linux x86_64 it’s using VSYSCALL functionality, which is basically a page at fixed address which can execute 3 different syscalls (their analogues in user space) without context switch, in a very fast way.
>>
>> VSYSCALL functionality is known to be insecure when ASLR is used, hence it’s being disabled sometimes.
>> For example in alpine linux it’s disabled by default and even its emulation (via a trap) by kernel is disabled. So one can’t use VSYSCALL at all and java crashes.
>>
>> There is two ways to work it around: unify x86 and x86_64 routines and go syscall always (could be slow) or use functionality similar to vdso (it’s similar to VSYSCALL but the page is at different address on every app launch).
>>
>> There is no low cost way to find out if VSYSCALL functionality is present or not.
>> This patch remove VSYSCALL functionality and does perform simple asm instruction to get cpu id.
>> it’s very imilar to what happens in vgetcpu function in vdso: https://elixir.bootlin.com/linux/v4.4/source/arch/x86/include/asm/vgtod.h#L77
>>
>> Regards, Vladimir
More information about the hotspot-runtime-dev
mailing list