RFR (S) JDK-7107135 - Stack guard pages becomes writable
Ioi Lam
ioi.lam at oracle.com
Wed Feb 27 15:03:26 PST 2013
On 02/21/2013 07:07 PM, David Holmes wrote:
> <fixed the subject to try and get the email thread to flow >
>
> On 22/02/2013 1:29 AM, Zhengyu Gu wrote:
>> Hi Ioi,
>>
>> 1. os_linux.cpp #1877 : this will restrict os::dll_load() caller to Java
>> thread only, is it ok?
>
> That bit doesn't make sense to me:
>
> 1877 ThreadInVMfromNative tiv(JavaThread::current());
> 1878 debug_only(VMNativeEntryWrapper vew;)
>
> shouldn't we already be _thread_in_vm at this point ??
>
I tried comment them out, and I get an abort. The thread state is
"_thread_in_native". So it looks like we need this code to make the
thread into _thread_in_vm so that we can enter the safe point??
#0 0x0000003075430265 in raise () from /lib64/libc.so.6
#1 0x0000003075431d10 in abort () from /lib64/libc.so.6
#2 0x00002aaaab52cfdb in os::abort (dump_core=true) at
/home/iklam/jdk/hsx24/src/os/linux/vm/os_linux.cpp:1584
#3 0x00002aaaab6ded47 in VMError::report_and_die (this=0x400fe6c0) at
/home/iklam/jdk/hsx24/src/share/vm/utilities/vmError.cpp:1026
#4 0x00002aaaab1031ae in report_vm_error (file=0x2aaaab964e40
"/home/iklam/jdk/hsx24/src/share/vm/runtime/thread.cpp", line=899,
error_msg=0x2aaaab7f20af "fatal error", detail_msg=0x2aaaab968404
"LEAF method calling lock?")
at /home/iklam/jdk/hsx24/src/share/vm/utilities/debug.cpp:227
#5 0x00002aaaab10402a in report_fatal (file=0x2aaaab964e40
"/home/iklam/jdk/hsx24/src/share/vm/runtime/thread.cpp", line=899,
message=0x2aaaab968404 "LEAF method calling lock?") at
/home/iklam/jdk/hsx24/src/share/vm/utilities/debug.cpp:232
#6 0x00002aaaab689187 in Thread::check_for_valid_safepoint_state
(this=0x613800, potential_vm_operation=true)
at /home/iklam/jdk/hsx24/src/share/vm/runtime/thread.cpp:899
#7 0x00002aaaab70ccff in VMThread::execute (op=0x400feb60) at
/home/iklam/jdk/hsx24/src/share/vm/runtime/vmThread.cpp:597
#8 0x00002aaaab52b6ec in os::dll_load (filename=0x745240
"/scratch/iklam/jdk/hsx24/test/runtime/JTwork/scratch/libtest-rwx.so",
ebuf=0x400ff070 "\320\307j", ebuflen=1024) at
/home/iklam/jdk/hsx24/src/os/linux/vm/os_linux.cpp:1898
#9 0x00002aaaab368a3b in JVM_LoadLibrary (name=0x745240
"/scratch/iklam/jdk/hsx24/test/runtime/JTwork/scratch/libtest-rwx.so")
at /home/iklam/jdk/hsx24/src/share/vm/prims/jvm.cpp:3644
#10 0x00002aaaac1ad92f in
Java_java_lang_ClassLoader_00024NativeLibrary_load () from
/scratch/iklam/jdk/official/jdk1.7.0_09/jre/lib/amd64/libjava.so
#11 0x00002aaaac649b9b in ?? ()
#12 0x00000000400ff6b0 in ?? ()
#13 0x00002aaaac62c298 in ?? ()
#14 0x00000000400ff660 in ?? ()
#15 0x0000000000000000 in ?? ()
>> 2. Using safepoint to modify stack guard is still not safe, since not
>> all Java threads stop at safepoint. Have you thought about racing
>> scenarios?
>
> There is no guaranteed fix for this problem, we can only do what we
> can do. If a thread hits the Java guard pages while in native then I
> think that causes an abort anyway. So if the guard is disabled we just
> won't abort (a good thing?) but if we hit the pthread/libc guard pages
> then we will abort anyway.
>
> David
> -----
>
>> 3. typo - os_linux.cpp #1821 liner -> linker
>>
>> Thanks,
>>
>> -Zhengyu
>>>
>>> -------- Original Message --------
>>> Subject: Re: RFR (S) JDK-7107135 - Stack guard pages becomes
>>> writable
>>> Date: Wed, 20 Feb 2013 10:40:39 -0800
>>> From: Ioi Lam <ioi.lam at oracle.com>
>>> To: hotspot-runtime-dev at openjdk.java.net
>>>
>>>
>>>
>>> [Moving the discussion tohotspot-runtime-dev at openjdk.java.net]
>>>
>>> The original request for review is cut-and-pasted atthe end of this
>>> message.
>>>
>>> Thanks
>>> - Ioi
>>>
>>>
>>> On 02/20/2013 08:25 AM, Dean Long wrote:
>>> > On 2/20/2013 3:01 AM, David Holmes wrote:
>>> >> On 20/02/2013 6:32 PM, Dean Long wrote:
>>> >>> On 2/20/2013 12:12 AM, David Holmes wrote:
>>> >>>> On 20/02/2013 3:29 PM, Dean Long wrote:
>>> >>>>> On 2/19/2013 6:48 PM, David Holmes wrote:
>>> >>>>>> On 20/02/2013 11:39 AM, Dean Long wrote:
>>> >>>>>>> On 2/19/2013 5:35 PM, David Holmes wrote:
>>> >>>>>>>> On 20/02/2013 11:24 AM, Dean Long wrote:
>>> >>>>>>>>>>
>>> >>>>>>>>> If os::Linux::default_guard_size() returns non-zero, we
>>> set an
>>> >>>>>>>>> attribute
>>> >>>>>>>>> for pthread_create telling it to create guard pages for us.
>>> >>>>>>>>> These guard pages aren't set to rwx by the dynamic linker
>>> because
>>> >>>>>>>>> pthreads knows about them.
>>> >>>>>>>>
>>> >>>>>>>> Are you saying that these guard pages don't get reset when the
>>> >>>>>>>> library
>>> >>>>>>>> is loaded (or that they will at least get repaired
>>> afterwards) ?
>>> >>>>>>>
>>> >>>>>>> They will not be reset.
>>> >>>>>>
>>> >>>>>> Can you point me to any docs or the source code that
>>> demonstrates
>>> >>>>>> this? From previous discussions the OS only allowed you to
>>> set page
>>> >>>>>> bits not read them, and hence not add them. So I'd like to
>>> see how
>>> >>>>>> they are achieving this.
>>> >>>>>>
>>> >>>>>
>>> >>>>> The magic happens here in change_stack_perm():
>>> >>>>>
>>> >>>>>http://sourceware.org/git/?p=glibc.git;a=blob;f=nptl/allocatestack.c#l314
>>>
>>> >>>>>
>>> >>>>>
>>> >>>>
>>> >>>> But that simply makes the stack readable, writable and
>>> executable but
>>> >>>> skipping over the guard pages. The initial protection of the guard
>>> >>>> pages happens here:
>>> >>>>
>>> >>>> 634 if (mprotect (guard, guardsize, PROT_NONE) != 0)
>>> >>>>
>>> >>>> but I don't see anything in this code that prevents the guard
>>> pages
>>> >>>> from being modified when a library with executable stack is
>>> loaded?
>>> >>>>
>>> >>>
>>> >>> The code path that does the modifying looks like: dlopen --> ...
>>> -->
>>> >>> __make_stacks_executable --> change_stack_perm.
>>> >>
>>> >> Ah I see. The above is what causes the problem, but it skips the
>>> >> built-in guard pages.
>>> >>
>>> >> I'm sure someone thought this made sense at some point. :( But it
>>> >> sure seems like a bug to me.
>>> >>
>>> > Which part seems buggy, changing the permissions? It seems necessary
>>> > as long as executable stacks is
>>> > a supported feature. It would be nice if dlopen() would just fail to
>>> > load these libraries based on some flag
>>> > in the executable's ELF file. I think the existing flag means "no
>>> > executable stacks used by this module",
>>> > but "no executable stacks used by this process" would make more sense
>>> > for Java.
>>> >
>>> > dl
>>> >
>>> >> Thanks,
>>> >> David
>>> >>
>>> >>>> Also note that for user supplied stack memory there are no
>>> guard pages
>>> >>>> added.
>>> >>>>
>>> >>> OK.
>>> >>>
>>> >>> dl
>>> >>>
>>> >>>> David
>>> >>>> -----
>>> >>>>
>>> >>>>> I wish there was a way to change the guardsize after the
>>> thread is
>>> >>>>> created.
>>> >>>>>
>>> >>>>> dl
>>> >>>>>
>>> >>>
>>> >
>>>
>>> Please review:
>>> http://javaweb.us.oracle.com/~iklam/webrev/7107135/stack_guard_001/
>>>
>>> Bug: Stack guard pages are no more protected after loading a shared
>>> library with executable stack
>>> https://jbs.oracle.com/bugs/browse/JDK-7107135
>>>
>>> Background:
>>>
>>> Recent versions of Linux support Non-Executable Stack
>>> protection -- by default, the stack is made non-executable to
>>> prevent code injection via overflowing on-stack buffers.
>>>
>>> However, some old Linux DLLs require the stack to be
>>> executable. For backwards compatibility, after loading such
>>> DLLs, the Linux dynamic loader makes the stack executable.
>>>
>>> Due to a limitation of the Linux system call API, the Linux
>>> dynamic loader makes the stack readable/writable as well. This
>>> disables Java's stack guard.
>>>
>>> Summary of fix:
>>>
>>> 1. Check if DLL requires executable stack by inspecting ELF
>>> header.
>>> 2. Enter a Safepoint and load such DLLs in the VM thread.
>>> - immediately after loading, change all Java stack guards
>>> back to PROT_NONE.
>>> 3. Leave Safepoint to resume Java execution.
>>>
>>> I also added a global flag LoadExecStackDllInVMThread to load
>>> such "bad" DLLs outside of the safepoint (in case the DLL
>>> invokes JNI functions inside static constructors, which are
>>> executed before dlopen() returns).
>>>
>>> Note:
>>>
>>> I got this code from an outside contributor and I don't really
>>> understand what this block does. Please comment if it's
>>> correct:
>>>
>>> 1877: ThreadInVMfromNative tiv(JavaThread::current());
>>> 1878: debug_only(VMNativeEntryWrapper vew;)
>>>
>>> Tests executed:
>>>
>>> * JPRT
>>> * UTE (vm.quick.testlist)
>>> * JTREG (hotspot/tests/runtime, hotspot/tests/closed/runtime)
>>>
>>> Thanks,
>>> Ioi
>>>
>>>
>>>
>>>
>>
More information about the hotspot-runtime-dev
mailing list