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;
+#endifint 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