-- (c) Copyright 2008 Shawn Pringle

xalloc.e: Version of December 29th, 2008

Description

A memory protection API that is portable across several platforms. Including DOS, Windows, OSX, FreeBSD, and Linux.
The idea of this API is to give the programmer a method of telling the OS what he intends to do with various allocated parts of memory. What does he intend to execute and what memory is only data. This seems dubious at first, but if you read about hacking and security flaws you'll see that many exploits are done by tricking a program into executing a peice of memory that was intended to be only data. Data Execute Protection stops that cold. Now, when you are running Windows with DEP enabled, and a program attempts to execute data allocated by allocate() the program will be shutdown. You don't have to do anything except enable it in the system and newer versions of XP and Vista already have it enabled by default.

The problem is, what if you want to execute dynamic code using call(), c_func(), , c_proc(), call_proc(), call_func()? Is the memory address returned by call_back() DEP safe? It turns out, since C is already marked as executable and EUPHORIA routines are interpreted you only need to replace call_back with xcall_back() and you need to ensure that what you pass to call() is returned from allocate_code() and not from allocate().

On Operating systems that do not support DEP this library simply wraps the standard generic memory routines: allocate() and free(). This library will work with either 4.0 or 3.1 versions of EUPHORIA and on any platform.

Constants

Constants are to be sent to the API functions and are the same constants across all platforms.
 
	PAGE_EXECUTE = #10,        -- You may run the data in this page
	PAGE_EXECUTE_READ = #20,   -- You may run and read the data
	PAGE_EXECUTE_READWRITE = #40,-- You may run, read or write this page
	PAGE_EXECUTE_WRITECOPY = #80,-- You may run, read or write this page
	PAGE_WRITECOPY = #08,        
	PAGE_READWRITE = #04,
	PAGE_NOACCESS = #01,        -- 
	PAGE_READONLY = #02         -- You may only read code
-- 

Routines

atom allocate_protect( data, integer protection )

allocates and copies data into memory and gives it protection using Microsoft's Memory Protection Constants. The user may only pass in one of these constants. If you only wish to execute a sequence as machine code use
allocate_code(). If you only want to read and write data into memory use allocate()

Microsoft's Memory Protection Constants
http://msdn.microsoft.com/en-us/library/aa366786(VS.85).aspx

Parameters

The first parameter, data, is the machine code to be put into memory.

atom allocate_code( sequence a_sequence_of_machine_code_bytes )

allocates and copies data into executible memory.

Parameters

The parameter, a_sequence_of_machine_code_bytes, is the machine code to be put into memory. To be later called with call()

Return Value

The function returns the address in memory of the byte-code that can be safely executed whether DEP is enabled or not or 0 if it fails. On the other hand, if you try to execute a code address returned by allocate() with DEP enabled the program will receive a machine exception.

Comments

Use this for the machine code you want to run in memory. The copying is done for you and when the routine returns the memory may not be readable or writable but it is guaranteed to be executable. If you want to also write to this memory after the machine code has been copied you should use allocate_protect() instead and you should read about having memory executable and writable at the same time is a bad idea. You mustn't use free() on memory returned from this function.

free_code( atom addr, integer size )

frees up allocated code memory

Parameters

addr must be an address returned by
allocate_code() or allocate_protect(). Do not pass memory returned from allocate() here! The size is the size you specified when you called the afore mentioned functions.

Comments

Chances are you will not need to call this function because code allocations are typically global scope operations that you want to have available until your process exits.

atom xcall_back( object routine_identifier )

Parameters

routine_identifier can be of the form:

where id is a routine integer identifier returned from routine_id().

Return Value

The function returns a call-back address of a EUPHORIA routine that can be safely executed whether DEP is enabled or not. On the other hand, if you try to execute a code address returned by call_back() with DEP enabled the program will receive a machine exception.

Comments

This routine is a drop-in replacement for call_back(). Use search and replace in your favorite code editor to upgrade.

The routine is implemented by copying call_back() data into executable memory all of the non-DEP related comments that apply to call_back() also apply to xcall_back().