[SDL] [proposal] use mprotect() in code generation
Sam Hocevar
sam at zoy.org
Wed Mar 1 15:01:42 PST 2006
This patch uses mprotect() on the page containing the dynamically
generated code from SDL_stretch.c. It is useful on systems that enforce
a security policy such as forbidding writable pages to be executed.
Ideally this patch should check for various headers on the system at
the configure step, but I just hardcoded a #ifdef __linux__ test for
now. Let me know if there is interest in it and I will send a polished
patch.
Regards,
--
Sam.
-------------- next part --------------
diff -puriN SDL-1.2.9.orig/src/video/SDL_stretch.c SDL-1.2.9/src/video/SDL_stretch.c
--- SDL-1.2.9.orig/src/video/SDL_stretch.c 2004-05-16 23:08:55 +0200
+++ SDL-1.2.9/src/video/SDL_stretch.c 2006-03-01 13:28:46 +0100
@@ -43,10 +43,23 @@ static char rcsid =
!defined(__WATCOMC__) && !defined(__LCC__) && !defined(__FREEBCC__)) || \
(defined(i386) && defined(__GNUC__) && defined(USE_ASMBLIT))
#define USE_ASM_STRETCH
+#if defined(__linux__)
+#define USE_MPROTECT
+#endif
#endif
#ifdef USE_ASM_STRETCH
+#ifdef USE_MPROTECT
+#include <stdlib.h>
+#include <stdint.h>
+#include <limits.h>
+#ifndef PAGESIZE
+#define PAGESIZE 4096
+#endif
+#include <sys/mman.h>
+#endif
+
#if defined(WIN32) || defined(i386)
#define PREFIX16 0x66
#define STORE_BYTE 0xAA
@@ -58,10 +71,16 @@ static char rcsid =
#error Need assembly opcodes for this architecture
#endif
+#define MAX_CODE_LENGTH 4096
+
#if defined(__ELF__) && defined(__GNUC__)
-extern unsigned char _copy_row[4096] __attribute__ ((alias ("copy_row")));
+extern unsigned char *_copy_row __attribute__ ((alias ("copy_row")));
+#endif
+#ifdef USE_MPROTECT
+static unsigned char *copy_row;
+#else
+static unsigned char copy_row[MAX_CODE_LENGTH];
#endif
-static unsigned char copy_row[4096];
static int generate_rowbytes(int src_w, int dst_w, int bpp)
{
@@ -70,12 +89,25 @@ static int generate_rowbytes(int src_w,
int src_w;
int dst_w;
} last;
+#ifdef USE_MPROTECT
+ static unsigned char *code_buffer;
+#endif
int i;
int pos, inc;
unsigned char *eip;
unsigned char load, store;
+#ifdef USE_MPROTECT
+ if ( ! copy_row ) {
+ code_buffer = malloc(MAX_CODE_LENGTH + PAGESIZE - 1);
+ if ( ! code_buffer ) {
+ return(-1);
+ }
+ copy_row = (unsigned char *)(((uintptr_t)code_buffer + PAGESIZE - 1) & ~(uintptr_t)(PAGESIZE - 1));
+ }
+#endif
+
/* See if we need to regenerate the copy buffer */
if ( (src_w == last.src_w) &&
(dst_w == last.dst_w) && (bpp == last.bpp) ) {
@@ -99,6 +131,9 @@ static int generate_rowbytes(int src_w,
SDL_SetError("ASM stretch of %d bytes isn't supported\n", bpp);
return(-1);
}
+#ifdef USE_MPROTECT
+ mprotect(copy_row, MAX_CODE_LENGTH, PROT_READ|PROT_WRITE);
+#endif
pos = 0x10000;
inc = (src_w << 16) / dst_w;
eip = copy_row;
@@ -119,10 +154,13 @@ static int generate_rowbytes(int src_w,
*eip++ = RETURN;
/* Verify that we didn't overflow (too late) */
- if ( eip > (copy_row+sizeof(copy_row)) ) {
+ if ( eip > (copy_row+MAX_CODE_LENGTH) ) {
SDL_SetError("Copy buffer overflow");
return(-1);
}
+#ifdef USE_MPROTECT
+ mprotect(copy_row, MAX_CODE_LENGTH, PROT_READ|PROT_EXEC);
+#endif
return(0);
}
@@ -284,15 +322,20 @@ int SDL_SoftStretch(SDL_Surface *src, SD
copy_row3(srcp, srcrect->w, dstp, dstrect->w);
break;
default:
+ {
+#ifdef USE_MPROTECT
+ void *code = copy_row;
+#else
+ void *code = ©_row;
+#endif
#ifdef __GNUC__
__asm__ __volatile__ (
- "call _copy_row"
+ "call %4"
: "=&D" (u1), "=&S" (u2)
- : "0" (dstp), "1" (srcp)
+ : "0" (dstp), "1" (srcp), "r" (code)
: "memory" );
#else
#ifdef WIN32
- { void *code = ©_row;
__asm {
push edi
push esi
@@ -304,11 +347,11 @@ int SDL_SoftStretch(SDL_Surface *src, SD
pop esi
pop edi
}
- }
#else
#error Need inline assembly for this compiler
#endif
#endif /* __GNUC__ */
+ }
break;
}
#else
More information about the SDL
mailing list