See attached. In case of too many mail/BTS/web gateways, I posted a backup copy at http://recycle.lbl.gov/~ldoolitt/087a_SECURITY_libXpm_vulnerabilities.diff
When I say "tested" I mean tested in isolation. My attempts to fully test the debian build process have so far failed, for (I think) unrelated reasons. apt-src and I are not friends yet. - Larry
Candidate response to debian bug #308783, based on http://ftp.x.org/pub/X11R6.8.1/patches/X11R6.8.1-to-X11R6.8.2.patch.gz This patch is to be applied _after_ $ md5sum 087_SECURITY_libXpm_vulnerabilities.diff 810923ff9eac7eb83d96870a4fbaab15 087_SECURITY_libXpm_vulnerabilities.diff Other than sorting out the patch basis and removing fuzz, my only contribution is to remove a compilation warning caused by a missing FUNC(xpmPipeThrough, ...) in RdFToI.c. Verified against the full X11R6.8.2 sources: the only other differences are CVS tags and some trailing spaces in the source. Tested, works. 2005-05-23 Larry Doolittle <[EMAIL PROTECTED]> diff -ur xc~/extras/Xpm/lib/RdFToI.c xc/extras/Xpm/lib/RdFToI.c --- xc~/extras/Xpm/lib/RdFToI.c 2005-05-23 10:12:01.211131000 -0700 +++ xc/extras/Xpm/lib/RdFToI.c 2005-05-23 10:22:48.159031812 -0700 @@ -36,15 +36,11 @@ /* October 2004, source code review by Thomas Biege <[EMAIL PROTECTED]> */ #include "XpmI.h" -#include <sys/stat.h> -#if !defined(NO_ZPIPE) && defined(WIN32) -# define popen _popen -# define pclose _pclose -# if defined(STAT_ZFILE) -# include <io.h> -# define stat _stat -# define fstat _fstat -# endif +#ifndef NO_ZPIPE +#include <fcntl.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/wait.h> #endif LFUNC(OpenReadFile, int, (char *filename, xpmData *mdata)); @@ -122,89 +118,132 @@ } #endif /* CXPMPROG */ -/* - * open the given file to be read as an xpmData which is returned. - */ #ifndef NO_ZPIPE - FILE *s_popen(char *cmd, const char *type); -#else -# define s_popen popen +/* Do not depend on errno after read_through */ +FUNC(xpmPipeThrough, FILE*, (int fd, const char* cmd, const char* arg1, const char* mode)); +FILE* +xpmPipeThrough(fd, cmd, arg1, mode) + int fd; + const char* cmd; + const char* arg1; + const char* mode; +{ + FILE* fp; + int status, fds[2], in = 0, out = 1; + pid_t pid; + if ( 'w' == *mode ) + out = 0, in = 1; + if ( pipe(fds) < 0 ) + return NULL; + pid = fork(); + if ( pid < 0 ) + goto fail1; + if ( 0 == pid ) + { + close(fds[in]); + if ( dup2(fds[out], out) < 0 ) + goto err; + close(fds[out]); + if ( dup2(fd, in) < 0 ) + goto err; + close(fd); + pid = fork(); + if ( pid < 0 ) + goto err; + if ( 0 == pid ) + { + execlp(cmd, cmd, arg1, NULL); + perror(cmd); + goto err; + } + _exit(0); + err: + _exit(1); + } + close(fds[out]); + /* calling process: wait for first child */ + while ( waitpid(pid, &status, 0) < 0 && EINTR == errno ) + ; + if ( WIFSIGNALED(status) || + (WIFEXITED(status) && WEXITSTATUS(status) != 0) ) + goto fail2; + fp = fdopen(fds[in], mode); + if ( !fp ) + goto fail2; + close(fd); /* still open in 2nd child */ + return fp; +fail1: + close(fds[out]); +fail2: + close(fds[in]); + return NULL; +} #endif +/* + * open the given file to be read as an xpmData which is returned. + */ static int OpenReadFile(filename, mdata) char *filename; xpmData *mdata; { -#ifndef NO_ZPIPE - char buf[BUFSIZ]; -# ifdef STAT_ZFILE - char *compressfile; - struct stat status; -# endif -#endif - if (!filename) { mdata->stream.file = (stdin); mdata->type = XPMFILE; } else { -#ifndef NO_ZPIPE - size_t len = strlen(filename); - - if (len == 0) - return(XpmOpenFailed); - if ((len > 2) && !strcmp(".Z", filename + (len - 2))) { - mdata->type = XPMPIPE; - snprintf(buf, sizeof(buf), "uncompress -c \"%s\"", filename); - if (!(mdata->stream.file = s_popen(buf, "r"))) - return (XpmOpenFailed); - - } else if ((len > 3) && !strcmp(".gz", filename + (len - 3))) { - mdata->type = XPMPIPE; - snprintf(buf, sizeof(buf), "gunzip -qc \"%s\"", filename); - if (!(mdata->stream.file = s_popen(buf, "r"))) - return (XpmOpenFailed); - - } else { -# ifdef STAT_ZFILE - if (!(compressfile = (char *) XpmMalloc(len + 4))) + int fd = open(filename, O_RDONLY); +#if defined(NO_ZPIPE) + if ( fd < 0 ) + return XpmOpenFailed; +#else + const char* ext = NULL; + if ( fd >= 0 ) + ext = strrchr(filename, '.'); +#ifdef STAT_ZFILE /* searching for z-files if the given name not found */ + else + { + size_t len = strlen(filename); + char *compressfile = (char *) XpmMalloc(len + 4); + if ( !compressfile ) return (XpmNoMemory); - - snprintf(compressfile, len+4, "%s.Z", filename); - if (!stat(compressfile, &status)) { - snprintf(buf, sizeof(buf), "uncompress -c \"%s\"", compressfile); - if (!(mdata->stream.file = s_popen(buf, "r"))) { + strcpy(compressfile, filename); + strcpy(compressfile + len, ext = ".Z"); + fd = open(compressfile, O_RDONLY); + if ( fd < 0 ) + { + strcpy(compressfile + len, ext = ".gz"); + fd = open(compressfile, O_RDONLY); + if ( fd < 0 ) + { XpmFree(compressfile); - return (XpmOpenFailed); - } - mdata->type = XPMPIPE; - } else { - snprintf(compressfile, len+4, "%s.gz", filename); - if (!stat(compressfile, &status)) { - snprintf(buf, sizeof(buf), "gunzip -c \"%s\"", compressfile); - if (!(mdata->stream.file = s_popen(buf, "r"))) { - XpmFree(compressfile); - return (XpmOpenFailed); - } - mdata->type = XPMPIPE; - } else { -# endif -#endif - if (!(mdata->stream.file = fopen(filename, "r"))) { -#if !defined(NO_ZPIPE) && defined(STAT_ZFILE) - XpmFree(compressfile); -#endif - return (XpmOpenFailed); - } - mdata->type = XPMFILE; -#ifndef NO_ZPIPE -# ifdef STAT_ZFILE + return XpmOpenFailed; } } XpmFree(compressfile); -# endif } #endif + if ( ext && !strcmp(ext, ".Z") ) + { + mdata->type = XPMPIPE; + mdata->stream.file = xpmPipeThrough(fd, "uncompress", "-c", "r"); + } + else if ( ext && !strcmp(ext, ".gz") ) + { + mdata->type = XPMPIPE; + mdata->stream.file = xpmPipeThrough(fd, "gunzip", "-qc", "r"); + } + else +#endif /* z-files */ + { + mdata->type = XPMFILE; + mdata->stream.file = fdopen(fd, "r"); + } + if (!mdata->stream.file) + { + close(fd); + return (XpmOpenFailed); + } } mdata->CommentLength = 0; #ifdef CXPMPROG @@ -221,15 +260,6 @@ xpmDataClose(mdata) xpmData *mdata; { - switch (mdata->type) { - case XPMFILE: - if (mdata->stream.file != (stdin)) - fclose(mdata->stream.file); - break; -#ifndef NO_ZPIPE - case XPMPIPE: + if (mdata->stream.file != (stdin)) fclose(mdata->stream.file); - break; -#endif - } } diff -ur xc~/extras/Xpm/lib/WrFFrI.c xc/extras/Xpm/lib/WrFFrI.c --- xc~/extras/Xpm/lib/WrFFrI.c 2005-05-23 09:28:21.000000000 -0700 +++ xc/extras/Xpm/lib/WrFFrI.c 2005-05-23 10:20:24.000366045 -0700 @@ -38,12 +38,14 @@ * Lorens Younes ([EMAIL PROTECTED]) 4/96 */ -/* October 2004, source code review by Thomas Biege <[EMAIL PROTECTED]> */ - #include "XpmI.h" -#if !defined(NO_ZPIPE) && defined(WIN32) -# define popen _popen -# define pclose _pclose + +#ifndef NO_ZPIPE +#include "sys/wait.h" +#include "sys/types.h" +#include "fcntl.h" +#include "unistd.h" +#include "errno.h" #endif /* MS Windows define a function called WriteFile @#%#&!!! */ @@ -124,7 +126,7 @@ /* let's try to make a valid C syntax name */ if (index(name, '.')) { strncpy(new_name, name, sizeof(new_name)); - new_name[sizeof(new_name)-1] = 0; + new_name[sizeof(new_name)-1] = '\0'; /* change '.' to '_' */ name = s = new_name; while ((dot = index(s, '.'))) { @@ -134,8 +136,7 @@ } if (index(name, '-')) { if (name != new_name) { - strncpy(new_name, name, sizeof(new_name)); - new_name[sizeof(new_name)-1] = 0; + strcpy(new_name, name); name = new_name; } /* change '-' to '_' */ @@ -301,55 +302,48 @@ fprintf(file, ",\n\"XPMENDEXT\""); } + +#ifndef NO_ZPIPE +FUNC(xpmPipeThrough, FILE*, (int fd, + const char* cmd, + const char* arg1, + const char* mode)); +#endif + /* * open the given file to be written as an xpmData which is returned */ -#ifndef NO_ZPIPE - FILE *s_popen(char *cmd, const char *type); -#else -# define s_popen popen -#endif static int OpenWriteFile(filename, mdata) char *filename; xpmData *mdata; { -#ifndef NO_ZPIPE - char buf[BUFSIZ]; - -#endif - if (!filename) { mdata->stream.file = (stdout); mdata->type = XPMFILE; } else { #ifndef NO_ZPIPE - size_t len = strlen(filename); - - if (len == 0) - return(XpmOpenFailed); - + size_t len; +#endif + int fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644); + if ( fd < 0 ) + return(XpmOpenFailed); +#ifndef NO_ZPIPE + len = strlen(filename); if (len > 2 && !strcmp(".Z", filename + (len - 2))) { - snprintf(buf, sizeof(buf), "compress > \"%s\"", filename); - if (!(mdata->stream.file = s_popen(buf, "w"))) - return (XpmOpenFailed); - + mdata->stream.file = xpmPipeThrough(fd, "compress", NULL, "w"); mdata->type = XPMPIPE; } else if (len > 3 && !strcmp(".gz", filename + (len - 3))) { - snprintf(buf, sizeof(buf), "gzip -q > \"%s\"", filename); - if (!(mdata->stream.file = s_popen(buf, "w"))) - return (XpmOpenFailed); - + mdata->stream.file = xpmPipeThrough(fd, "gzip", "-q", "w"); mdata->type = XPMPIPE; - } else { + } else #endif - if (!(mdata->stream.file = fopen(filename, "w"))) - return (XpmOpenFailed); - + { + mdata->stream.file = fdopen(fd, "w"); mdata->type = XPMFILE; -#ifndef NO_ZPIPE } -#endif + if (!mdata->stream.file) + return (XpmOpenFailed); } return (XpmSuccess); } @@ -361,15 +355,7 @@ xpmDataClose(mdata) xpmData *mdata; { - switch (mdata->type) { - case XPMFILE: - if (mdata->stream.file != (stdout)) - fclose(mdata->stream.file); - break; -#ifndef NO_ZPIPE - case XPMPIPE: + if (mdata->stream.file != (stdout)) fclose(mdata->stream.file); - break; -#endif - } } +
signature.asc
Description: Digital signature