VOGONS


First post, by Skywing

User metadata
Rank Newbie
Rank
Newbie

Hi,

I've been using DoxBox for about a year or two now. Recently, I got around to installing it on a newer system (Vista x64), on which I had enabled NX by default. DosBox crashes in this configuration (with the default DosBox.conf) when you launch a program, because it switches to the dynamic core and then blows up when trying to execute the generated native code (due to it not being protected as executable).

From five minutes of poking around on Sourceforge, it appears that the problem is in ``dosbox/src/cpu/core_dyn_x86/cache.h'', where it appears that ``malloc'' is used to allocate memory that code is written to (and subsequently executed from).

This is bad because the process heap (used in the default ``malloc'' implementation on Win32) does not contain executable heap segments by default, and will not return executable memory blocks.

A naive solution would be to reprotect the pointer ``malloc'''d, but this is less than ideal, since if somebody else gets a pointer on the same page (if your allocation was <4k), you are stomping on their memory protection (which gets even worse if you try and reprotect it back when you free memory, assuming you had two pointers to the same page checked out and both needed to be executable, after which you would be ripping out the exec protection on one block depending on the ``free()'' order - not a fun bug to track down).

A better solution would be to replace ``malloc'' entirely for purposes of allocations of code blocks on Win32, instead using ``VirtualAlloc(...PAGE_EXECUTE_READWRITE...)''. Alternatively, you could implement your own allocator on top of ``VirtualAlloc'''d regions that are always PAGE_EXECUTE_READWRITE. This may be advantageous as ``VirtualAlloc'' will return chunks of committed memory with a granularity of 4K (and will consume address space with a granularity of 64K, if you are not committing part of a previously reserved region, e.g. passing NULL as the requested allocation address). If you aren't doing a large number of small allocations that all need to be executable, it's probably not worth implementing your own allocator on top of ``VirtualAlloc'', though.

Actually, there's a third option, although it's pretty much an ugly hack (though if you really do have a lot of tiny allocations and don't want to implement an allocator on top of VirtualAlloc due to overhead, it might be worth considering): Create a private heap (``HeapCreate''), then protect each allocation to executable when you get it back from ``HeapAlloc'', never restoring allocations to their original protection. This assumes that the underlying heap allocator will never play with the protections on heap segment pages after returning pointers to them to you (which is probably a stable assumption). Unfortunately, this approach keeps the heap metadata marked as executable, which is still less than ideal. It at least gets you out of the stomping-on-process-heap-protections problem, though.

There are two workarounds for this issue:

1) Add DosBox.exe to the NX exclusion list (or don't enable NX by default). I don't really like this; NX is a good thing, but it's the most performant solution without requiring a code change.
2) Force the standard core, which is obviously less than ideal due to the significant performance hit.

The crash is immediately obvious if you run a program from DoxBox that triggers the dynamic core; it will blow up on the first dynamic core instruction, as EIP is not executable.

- Skywing
http://www.nynaeve.net

Reply 1 of 15, by wd

User metadata
Rank DOSBox Author
Rank
DOSBox Author

Thanks for the information, actually i already "implemented" usage of
VirtualAlloc with the respective bits set, just pcs with data execution
protection enabled (and working) seem to be rare so i didn't get around
to test it yet.

Reply 2 of 15, by Skywing

User metadata
Rank Newbie
Rank
Newbie

Glad to hear it!

As an aside, I think it's not so much that such systems are uncommon, but more that the default configuration for XP and Vista is one where NX is not on by default for third party apps. Srv03/Srv08 should enable it by default, and native 64-bit apps on those platforms also have it pegged on.

I explicitly enable it on all of my systems, so it's probably not something most (Win32) users would be seeing just yet unless they had gone to the trouble to enable it.

- Skywing
http://www.nynaeve.net

Reply 7 of 15, by Skywing

User metadata
Rank Newbie
Rank
Newbie
gulikoza wrote:

I thought the mprotect() call takes care of this?

No mprotect on Win32. Additionally, mprotect()'ing malloc allocations is still dangerous due to the fact that you are not guaranteed that you'll have an entire page to yourself per allocation...

(Note you aren't even guaranteed to get an entire page even if your allocation is >= the native page size. GNU libc malloc only guarantees 8 byte alignment for 32-bit platforms (and 16 byte alignment for 64-bit platforms). The Microsoft VC8 CRT malloc ( msdn2.microsoft.com/en-us/library/ycsb6wwf(vs.80).aspx ) - (the forum cannot handle parens in url blocks, apparently, manually copy the link) is only required to return 16-byte aligned allocations, though the internal behavior of the heap will tend to give you your own pages after a certain size of allocation (an implementation detail that is of course subject to change without notice).

- Skywing
http://www.nynaeve.net

Reply 8 of 15, by wd

User metadata
Rank DOSBox Author
Rank
DOSBox Author

Additionally, mprotect()'ing malloc allocations is still dangerous due to the
fact that you are not guaranteed that you'll have an entire page to yourself
per allocation...

dosbox already page-aligns the recompiler cache memory 😉
Anyway i'll see about creating a compile that uses VirtualAlloc for cache
allocation so you can test if it works that way.

Reply 9 of 15, by wd

User metadata
Rank DOSBox Author
Rank
DOSBox Author

Attached the build, maybe somebody wants to give it a try.
The dlls from the 0.70 release can be used.

Attachments

  • Filename
    dosbox_valloc.rar
    File size
    722.54 KiB
    Downloads
    479 downloads
    File license
    Fair use/fair dealing exception

Reply 11 of 15, by Skywing

User metadata
Rank Newbie
Rank
Newbie
wd wrote:

Attached the build, maybe somebody wants to give it a try.
The dlls from the 0.70 release can be used.

I'll give it a try when I get home from work today. Thanks for the fast response :)

- Skywing
http://www.nynaeve.net

Reply 13 of 15, by Skywing

User metadata
Rank Newbie
Rank
Newbie

Looks good. No problems so far in giving it a test spin here with NX support re-enabled. Looks good on memory usage compared to the malloc allocator with the dynamic core as well. I'd tentatively call it a success, given my 15 minutes of basic QA in one DOS game.

- Skywing
http://www.nynaeve.net

Reply 14 of 15, by wd

User metadata
Rank DOSBox Author
Rank
DOSBox Author

Thanks for testing, seems like a usable alternative.

Looks good on memory usage compared to the malloc allocator with the dynamic core as well.

What why where? Like less memory is allocated? (which should not really happen)

Reply 15 of 15, by Skywing

User metadata
Rank Newbie
Rank
Newbie
wd wrote:

Thanks for testing, seems like a usable alternative.

Looks good on memory usage compared to the malloc allocator with the dynamic core as well.

What why where? Like less memory is allocated? (which should not really happen)

As in it wasn't using significantly more memory than the malloc allocator.

- Skywing
http://www.nynaeve.net