Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

JIT On Win32: A possible future issue

2 views
Skip to first unread message

Jonathan Worthington

unread,
Dec 23, 2003, 12:08:31 AM12/23/03
to perl6-internals
Hi,

I was looking over the WinXP Service Pack 2 "Changes to functionality"
document, which you can get here:-

http://www.microsoft.com/technet/treeview/default.asp?url=/technet/prodtechn
ol/winxppro/maintain/winxpsp2.asp (download available in Word format)

One change is that for all capable 32-bit processors (only a couple so far,
but it'll probably get more common), and for all 64-bit ones, there will now
be "Execution Protection", or NX. Taken from the doc:-

"Execution protection (also known as NX, or no execute) prevents code
execution from data pages such as the default heap, various stacks, and
memory pools. Protection can be applied in both user and kernel-mode.It also
forces developers to avoid executing code out of data pages without
explicitly marking the pages as executable."

JIT was my first thought on reading this, and indeed it gets a specific
mention in the document. Turns out you need to use a bit of the Windows API
(VirtualAlloc) and pass it flags to say execution of data in that page of
memory is OK.

I'm not sure how the memory used for JIT'ing is allocated right now - I
think there are wrapper functions we call to do it - in which case they can
do stuff on a platform specific basis. Or maybe JIT can have it's own
memory allocation functions to ensure only pages used for that get marked as
executable? Marking every page we allocate as executable would be a Bad
Thing I guess.

Anyways, figured it may be worth a mention now, so there isn't an
out-of-the-blue "JIT doesn't work on XP SP2" bug report somewhere down the
line.

Jonathan


Leopold Toetsch

unread,
Dec 23, 2003, 8:27:53 AM12/23/03
to Jonathan Worthington, perl6-i...@perl.org
Jonathan Worthington <jona...@jwcs.net> wrote:
> Hi,

> I was looking over the WinXP Service Pack 2 "Changes to functionality"
> document, which you can get here:-

> http://www.microsoft.com/technet/treeview/default.asp?url=/technet/prodtechn
> ol/winxppro/maintain/winxpsp2.asp (download available in Word format)

> JIT was my first thought on reading this, and indeed it gets a specific


> mention in the document. Turns out you need to use a bit of the Windows API
> (VirtualAlloc) and pass it flags to say execution of data in that page of
> memory is OK.

> I'm not sure how the memory used for JIT'ing is allocated right now - I
> think there are wrapper functions we call to do it - in which case they can
> do stuff on a platform specific basis.

JIT code is run in malloc'ed memory (s. jit.c:1026) as well as JITted
NCI stubs. We already have some system specific stuff for JIT (some
architectures need a page flush before execution).

So best would be to use a set of spcialized function, e.g.:
- mem_alloc_executable
- mem_realloc_executable
- mem_flush_executable
- mem_free_executable

> Anyways, figured it may be worth a mention now, so there isn't an
> out-of-the-blue "JIT doesn't work on XP SP2" bug report somewhere down the
> line.

Yep, thanks - always good to know, where problems might exist.

> Jonathan

leo

Peter Gibbs

unread,
Dec 23, 2003, 10:32:33 AM12/23/03
to l...@toetsch.at, Jonathan Worthington, perl6-i...@perl.org
Leopold Toetsch wrote:

> JIT code is run in malloc'ed memory (s. jit.c:1026) as well as JITted
> NCI stubs. We already have some system specific stuff for JIT (some
> architectures need a page flush before execution).
>
> So best would be to use a set of spcialized function, e.g.:
> - mem_alloc_executable
> - mem_realloc_executable
> - mem_flush_executable
> - mem_free_executable

Note that JIT already fails under Fedora Core 1 because of 'Exec-Shield'
, which is the Linux equivalent of the functionality described by
Jonathan.

Regards
Peter Gibbs
EmKel Systems

Leopold Toetsch

unread,
Dec 23, 2003, 12:13:03 PM12/23/03
to Peter Gibbs, perl6-i...@perl.org

Ah, that's the reason for your bug report WRT JIT/NCI. The question is,
how can we detect the presence of the exec-shield patch. Your `uname -a`
doesn't indicate it.

So we need:

1) a config test/option/whatever (e.g. mallocing some mem, fill in a
"ret" instruction and call that.
2) Some means to allocate executable memory.

Could you please have a look at fedora (kernel) docs?

> Regards
> Peter Gibbs
> EmKel Systems

leo

Vladimir Lipsky

unread,
Dec 23, 2003, 2:28:39 PM12/23/03
to l...@toetsch.at, perl6-internals
> Ah, that's the reason for your bug report WRT JIT/NCI. The question is,
> how can we detect the presence of the exec-shield patch. Your `uname -a`
> doesn't indicate it.

What for? We just always do allocating memory from a JIT dedicated heap with
execute flas set on it, no matter the presence of the exec-shield patch, or
OS is windows XP with service pack 2 installed, or the processor supports
NX.

> 1) a config test/option/whatever (e.g. mallocing some mem, fill in a
> "ret" instruction and call that.

Calling it and BOOM! STATUS_ACCESS_VIOLATION with the following process
termination.

> 2) Some means to allocate executable memory.

Plus, methods to create and free the JIT heap.

0x4C56

Peter Gibbs

unread,
Dec 23, 2003, 2:12:57 PM12/23/03
to l...@toetsch.at, perl6-i...@perl.org
Leopold Toetsch wrote:

> So we need:
>
> 1) a config test/option/whatever (e.g. mallocing some mem, fill in a
> "ret" instruction and call that.
> 2) Some means to allocate executable memory.
>
> Could you please have a look at fedora (kernel) docs?

There are two ways to flag memory as executable:
1) A flag to mmap
2) Calling mprotect after the memory has been allocated

The second method is POSIX-compliant only when used with mmap'd memory.
It does however work with malloc'd memory under Linux, with the caveat
that if the memory is released and reallocated (within the same
process), the executable flag remains set.

As a quick test, I added the following to src/jit.c (based on 'man
mprotect'):

jit_info->native_ptr = jit_info->arena.start =
mem_sys_allocate_zeroed((size_t)jit_info->arena.size);
{
#include <limits.h> /* for PAGESIZE */
#ifndef PAGESIZE
#define PAGESIZE 4096
#endif
char *p = (char *)((int) jit_info->native_ptr & ~(PAGESIZE-1));
size_t len = ((int) jit_info->native_ptr + jit_info->arena.size -
(int)p);
mprotect(p, len, PROT_READ|PROT_WRITE|PROT_EXEC);
}

With this addition, parrot -j runs without segfaulting, so the above
could be used as a basis for a mem_alloc_executable function. Note that
the pointer passed to mprotect must start on a PAGESIZE boundary, so we
get some area of memory marked executable when it need not be.

I don't think we need to check whether exec-shield is active, only that
there is an mprotect function with the appropriate attribute constants.

Leopold Toetsch

unread,
Dec 23, 2003, 2:07:10 PM12/23/03
to Vladimir Lipsky, perl6-i...@perl.org
Vladimir Lipsky <lip...@kaluga.ru> wrote:
>> Ah, that's the reason for your bug report WRT JIT/NCI. The question is,
>> how can we detect the presence of the exec-shield patch. Your `uname -a`
>> doesn't indicate it.

> What for? We just always do allocating memory from a JIT dedicated heap with
> execute flas set on it, no matter the presence of the exec-shield patch,

I doubt, that my kernel has an appropriate allocation function (besides
mmap() with PROT_EXEC - which isn't resizable AFAIK).

> ... or


> OS is windows XP with service pack 2 installed, or the processor supports
> NX.

... or that an older Win32 has the necessary system call to get
executable memory.

>> 1) a config test/option/whatever (e.g. mallocing some mem, fill in a
>> "ret" instruction and call that.

> Calling it and BOOM! STATUS_ACCESS_VIOLATION with the following process
> termination.

A *config* test, yes may crash, why not. That's giving a result.

>> 2) Some means to allocate executable memory.

> Plus, methods to create and free the JIT heap.

I did propose a set of these already.

> 0x4C56

leo

Leopold Toetsch

unread,
Dec 23, 2003, 4:13:16 PM12/23/03
to Peter Gibbs, perl6-i...@perl.org
Peter Gibbs <pe...@emkel.co.za> wrote:
> Leopold Toetsch wrote:

>> So we need:
>>
>> 1) a config test/option/whatever (e.g. mallocing some mem, fill in a
>> "ret" instruction and call that.
>> 2) Some means to allocate executable memory.
>>
>> Could you please have a look at fedora (kernel) docs?

> There are two ways to flag memory as executable:
> 1) A flag to mmap
> 2) Calling mprotect after the memory has been allocated

Good.

> I don't think we need to check whether exec-shield is active, only that
> there is an mprotect function with the appropriate attribute constants.

Considering the alignment effects[1] and the usage of JITted code for
NCI too (where much smaller then page-size chunks are used) I'd prefer
to do a config check and 1) allocate aligned memory then and 2) use
mprotect only, when necessary.

Actuall there is already a test (config/auto/jit/test_c.in) which
executes code in data memory. So we don't need much more then adapt this
test a bit and add the necessary allocation functions.

> Regards
> Peter Gibbs
> EmKel Systems

[1] I don't like to poke holes into this security system, by having
unaligned chunks of executable memory around.

Thanks for your investigations,
leo

Vladimir Lipsky

unread,
Dec 23, 2003, 7:54:09 PM12/23/03
to perl6-internals
From: "Leopold Toetsch" <l...@toetsch.at>

> Vladimir Lipsky <lip...@kaluga.ru> wrote:
> >> Ah, that's the reason for your bug report WRT JIT/NCI. The question is,
> >> how can we detect the presence of the exec-shield patch. Your
`uname -a`
> >> doesn't indicate it.
>
> > What for? We just always do allocating memory from a JIT dedicated heap
with
> > execute flas set on it, no matter the presence of the exec-shield patch,
>
> I doubt, that my kernel has an appropriate allocation function (besides

So do I. Well, there is, of course, HeapCreate on windows but I'm afraid it
marks the memory being reserved as READ & WRITE and there is no mean to pass
the function any flags.

> mmap() with PROT_EXEC - which isn't resizable AFAIK).

Besides VirtualAlloc with PAGE_EXECUTE. As to resizing, yeah it's bad;
VirtualAlloc doesn't do resing either. We will have to rewrite all the
things that malloc() does with relative to resizing. Bad. Very bad.

> > ... or
> > OS is windows XP with service pack 2 installed, or the processor
supports
> > NX.
> .. or that an older Win32 has the necessary system call to get
> executable memory.

Old windows indeferently executes data from pages not marked as EXECUTE. So
there won't be any problems, at least until Microsoft decides to patch them.

> leo

0x4C56


0 new messages