From a58fc51f44daaa45cf4cbf8b3d2eb8f51704e035 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 29 Dec 2007 05:18:33 +0000 Subject: [PATCH] Made the mprotect() fix for SDL_SoftStretch() more general for hardened linux, etc. --- configure.in | 8 +++--- include/SDL_config.h.in | 1 + src/video/SDL_stretch.c | 55 ++++++++++++++++++++++------------------- 3 files changed, 34 insertions(+), 30 deletions(-) diff --git a/configure.in b/configure.in index 62f95880b..2d3b564a0 100644 --- a/configure.in +++ b/configure.in @@ -16,9 +16,9 @@ dnl Set various version strings - taken gratefully from the GTk sources # 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$enable_libc = xyes; then 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"]) diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in index e775ef98c..fb49c0e2f 100644 --- a/include/SDL_config.h.in +++ b/include/SDL_config.h.in @@ -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 */ diff --git a/src/video/SDL_stretch.c b/src/video/SDL_stretch.c index fd3193963..b87fa7b60 100644 --- a/src/video/SDL_stretch.c +++ b/src/video/SDL_stretch.c @@ -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 #include #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 @@ static int generate_rowbytes(int src_w, int dst_w, int bpp) int bpp; int src_w; int dst_w; + int status; } last; int i; @@ -80,11 +82,12 @@ static int generate_rowbytes(int src_w, int dst_w, int bpp) /* 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 @@ static int generate_rowbytes(int src_w, int dst_w, int bpp) 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 @@ static int generate_rowbytes(int src_w, int dst_w, int bpp) } *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_row1, Uint8) 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 @@ int SDL_SoftStretch(SDL_Surface *src, SDL_Rect *srcrect, 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 @@ int SDL_SoftStretch(SDL_Surface *src, SDL_Rect *srcrect, #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 @@ int SDL_SoftStretch(SDL_Surface *src, SDL_Rect *srcrect, 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 @@ int SDL_SoftStretch(SDL_Surface *src, SDL_Rect *srcrect, #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 @@ int SDL_SoftStretch(SDL_Surface *src, SDL_Rect *srcrect, (Uint32 *)dstp, dstrect->w); break; } -#endif pos += inc; }