Made the mprotect() fix for SDL_SoftStretch() more general for hardened linux, etc. SDL-1.2
authorSam Lantinga <slouken@libsdl.org>
Sat, 29 Dec 2007 05:18:33 +0000
branchSDL-1.2
changeset 4109 cd2ab40f1219
parent 4108 3feb94233f90
child 4110 b896fb0d4f9f
Made the mprotect() fix for SDL_SoftStretch() more general for hardened linux, etc.
configure.in
include/SDL_config.h.in
src/video/SDL_stretch.c
--- a/configure.in	Sat Dec 29 03:50:29 2007 +0000
+++ b/configure.in	Sat Dec 29 05:18:33 2007 +0000
@@ -16,9 +16,9 @@
 #
 SDL_MAJOR_VERSION=1
 SDL_MINOR_VERSION=2
-SDL_MICRO_VERSION=12
-SDL_INTERFACE_AGE=1
-SDL_BINARY_AGE=12
+SDL_MICRO_VERSION=13
+SDL_INTERFACE_AGE=2
+SDL_BINARY_AGE=13
 SDL_VERSION=$SDL_MAJOR_VERSION.$SDL_MINOR_VERSION.$SDL_MICRO_VERSION
 
 AC_SUBST(SDL_MAJOR_VERSION)
@@ -146,7 +146,7 @@
     if test x$ac_cv_func_strtod = xyes; then
         AC_DEFINE(HAVE_STRTOD)
     fi
-    AC_CHECK_FUNCS(malloc calloc realloc free getenv putenv unsetenv qsort abs bcopy memset memcpy memmove strlen strlcpy strlcat strdup _strrev _strupr _strlwr strchr strrchr strstr itoa _ltoa _uitoa _ultoa strtol strtoul _i64toa _ui64toa strtoll strtoull atoi atof strcmp strncmp _stricmp strcasecmp _strnicmp strncasecmp sscanf snprintf vsnprintf iconv sigaction setjmp nanosleep)
+    AC_CHECK_FUNCS(malloc calloc realloc free getenv putenv unsetenv qsort abs bcopy memset memcpy memmove strlen strlcpy strlcat strdup _strrev _strupr _strlwr strchr strrchr strstr itoa _ltoa _uitoa _ultoa strtol strtoul _i64toa _ui64toa strtoll strtoull atoi atof strcmp strncmp _stricmp strcasecmp _strnicmp strncasecmp sscanf snprintf vsnprintf iconv sigaction setjmp nanosleep mprotect)
 
     AC_CHECK_LIB(iconv, libiconv_open, [EXTRA_LDFLAGS="$EXTRA_LDFLAGS -liconv"])
     AC_CHECK_LIB(m, pow, [EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lm"])
--- a/include/SDL_config.h.in	Sat Dec 29 03:50:29 2007 +0000
+++ b/include/SDL_config.h.in	Sat Dec 29 05:18:33 2007 +0000
@@ -136,6 +136,7 @@
 #undef HAVE_CLOCK_GETTIME
 #undef HAVE_DLVSYM
 #undef HAVE_GETPAGESIZE
+#undef HAVE_MPROTECT
 
 #else
 /* We may need some replacement for stdarg.h here */
--- a/src/video/SDL_stretch.c	Sat Dec 29 03:50:29 2007 +0000
+++ b/src/video/SDL_stretch.c	Sat Dec 29 05:18:33 2007 +0000
@@ -42,14 +42,15 @@
 
 #ifdef USE_ASM_STRETCH
 
-/* OpenBSD has non-executable memory by default, so use mprotect() */
-#ifdef __OpenBSD__
-#define USE_MPROTECT
-#endif
-#ifdef USE_MPROTECT
+#ifdef HAVE_MPROTECT
 #include <sys/types.h>
 #include <sys/mman.h>
 #endif
+#ifdef __GNUC__
+#define PAGE_ALIGNED __attribute__((__aligned__(4096)))
+#else
+#define PAGE_ALIGNED
+#endif
 
 #if defined(_M_IX86) || defined(i386)
 #define PREFIX16	0x66
@@ -62,7 +63,7 @@
 #error Need assembly opcodes for this architecture
 #endif
 
-static unsigned char copy_row[4096];
+static unsigned char copy_row[4096] PAGE_ALIGNED;
 
 static int generate_rowbytes(int src_w, int dst_w, int bpp)
 {
@@ -70,6 +71,7 @@
 		int bpp;
 		int src_w;
 		int dst_w;
+		int status;
 	} last;
 
 	int i;
@@ -80,11 +82,12 @@
 	/* See if we need to regenerate the copy buffer */
 	if ( (src_w == last.src_w) &&
 	     (dst_w == last.dst_w) && (bpp == last.bpp) ) {
-		return(0);
+		return(last.status);
 	}
 	last.bpp = bpp;
 	last.src_w = src_w;
 	last.dst_w = dst_w;
+	last.status = -1;
 
 	switch (bpp) {
 	    case 1:
@@ -100,9 +103,6 @@
 		SDL_SetError("ASM stretch of %d bytes isn't supported\n", bpp);
 		return(-1);
 	}
-#ifdef USE_MPROTECT
-	mprotect(copy_row, sizeof(copy_row), PROT_READ|PROT_WRITE|PROT_EXEC);
-#endif
 	pos = 0x10000;
 	inc = (src_w << 16) / dst_w;
 	eip = copy_row;
@@ -122,15 +122,23 @@
 	}
 	*eip++ = RETURN;
 
-	/* Verify that we didn't overflow (too late) */
+	/* Verify that we didn't overflow (too late!!!) */
 	if ( eip > (copy_row+sizeof(copy_row)) ) {
 		SDL_SetError("Copy buffer overflow");
 		return(-1);
 	}
+#ifdef HAVE_MPROTECT
+	/* Make the code executable */
+	if ( mprotect(copy_row, sizeof(copy_row), PROT_READ|PROT_WRITE|PROT_EXEC) < 0 ) {
+		SDL_SetError("Couldn't make copy buffer executable");
+		return(-1);
+	}
+#endif
+	last.status = 0;
 	return(0);
 }
 
-#else
+#endif /* USE_ASM_STRETCH */
 
 #define DEFINE_COPY_ROW(name, type)			\
 void name(type *src, int src_w, type *dst, int dst_w)	\
@@ -154,8 +162,6 @@
 DEFINE_COPY_ROW(copy_row2, Uint16)
 DEFINE_COPY_ROW(copy_row4, Uint32)
 
-#endif /* USE_ASM_STRETCH */
-
 /* The ASM code doesn't handle 24-bpp stretch blits */
 void copy_row3(Uint8 *src, int src_w, Uint8 *dst, int dst_w)
 {
@@ -195,9 +201,12 @@
 	Uint8 *dstp;
 	SDL_Rect full_src;
 	SDL_Rect full_dst;
-#if defined(USE_ASM_STRETCH) && defined(__GNUC__)
+#ifdef USE_ASM_STRETCH
+	SDL_bool use_asm = SDL_TRUE;
+#ifdef __GNUC__
 	int u1, u2;
 #endif
+#endif /* USE_ASM_STRETCH */
 	const int bpp = dst->format->BytesPerPixel;
 
 	if ( src->format->BitsPerPixel != dst->format->BitsPerPixel ) {
@@ -266,9 +275,9 @@
 
 #ifdef USE_ASM_STRETCH
 	/* Write the opcodes for this stretch */
-	if ( (bpp != 3) &&
+	if ( (bpp == 3) ||
 	     (generate_rowbytes(srcrect->w, dstrect->w, bpp) < 0) ) {
-		return(-1);
+		use_asm = SDL_FALSE;
 	}
 #endif
 
@@ -283,11 +292,7 @@
 			pos -= 0x10000L;
 		}
 #ifdef USE_ASM_STRETCH
-		switch (bpp) {
-		    case 3:
-			copy_row3(srcp, srcrect->w, dstp, dstrect->w);
-			break;
-		    default:
+		if (use_asm) {
 #ifdef __GNUC__
 			__asm__ __volatile__ (
 			"call *%4"
@@ -311,9 +316,8 @@
 #else
 #error Need inline assembly for this compiler
 #endif
-			break;
-		}
-#else
+		} else
+#endif
 		switch (bpp) {
 		    case 1:
 			copy_row1(srcp, srcrect->w, dstp, dstrect->w);
@@ -330,7 +334,6 @@
 			          (Uint32 *)dstp, dstrect->w);
 			break;
 		}
-#endif
 		pos += inc;
 	}