Package: mimetex
Version: 1.50-1
Severity: normal
Tags: patch
User: ubuntu-de...@lists.ubuntu.com
Usertags: origin-ubuntu karmic ubuntu-patch



*** /tmp/tmpXGbr7m
In Ubuntu, we've applied the attached patch to achieve the following:

  * SECURITY UPDATE: arbitrary code execution via long picture, circle and
    input tags
    - mimetex.c: replace strcpy with strninit macro that uses strncpy,
      adjust some buffer sizes.
    - CVE-2009-1382
  * SECURITY UPDATE: information disclosure via input and counter tags
    - mimetex.c: disable input and counter tags.
    - CVE-2009-2459

We thought you might be interested in doing the same. 


-- System Information:
Debian Release: squeeze/sid
  APT prefers karmic-updates
  APT policy: (500, 'karmic-updates'), (500, 'karmic-security'), (500, 'karmic')
Architecture: amd64 (x86_64)

Kernel: Linux 2.6.31-11-generic (SMP w/2 CPU cores)
Locale: LANG=en_CA.UTF-8, LC_CTYPE=en_CA.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
diff -u mimetex-1.50/debian/changelog mimetex-1.50/debian/changelog
only in patch2:
unchanged:
--- mimetex-1.50.orig/mimetex.c
+++ mimetex-1.50/mimetex.c
@@ -378,6 +378,22 @@
 #endif
 #include "mimetex.h"
 
+/* ---
+ * internal buffer sizes
+ * --------------------- */
+#if !defined(MAXEXPRSZ)
+  #define MAXEXPRSZ (32768-1)		/*max #bytes in input tex expression*/
+#endif
+#if !defined(MAXSUBXSZ)
+  #define MAXSUBXSZ (((MAXEXPRSZ+1)/2)-1)/*max #bytes in input subexpression*/
+#endif
+#if !defined(MAXTOKNSZ)
+  #define MAXTOKNSZ (((MAXSUBXSZ+1)/4)-1) /* max #bytes in input token */
+#endif
+#if !defined(MAXFILESZ)
+  #define MAXFILESZ (65536-1)		/*max #bytes in input (output) file*/
+#endif
+
 /* -------------------------------------------------------------------------
 adjustable default values
 -------------------------------------------------------------------------- */
@@ -563,6 +579,15 @@
 	{ char *p; while((p=strchr((s),(c)))!=NULL) strcpy(p,p+1); } else
 #define	slower(s)  if ((s)!=NULL)	/* lowercase all chars in s */ \
 	{ char *p=(s); while(*p!='\000'){*p=tolower(*p); p++;} } else
+/* --- check if a string is empty --- */
+#define	isempty(s)  ((s)==NULL?1:(*(s)=='\000'?1:0))
+/* --- strncpy() n bytes and make sure it's null-terminated --- */
+#define	strninit(target,source,n) if( (target)!=NULL && (n)>=0 ) { \
+	  char *thissource = (source); \
+	  (target)[0] = '\000'; \
+	  if ( (n)>0 && thissource!=NULL ) { \
+	    strncpy((target),thissource,(n)); \
+	    (target)[(n)] = '\000'; } }
 
 /* ---
  * PART2
@@ -7008,7 +7033,7 @@
 -------------------------------------------------------------------------- */
 char	*texsubexpr(), picexpr[2049], *picptr=picexpr, /* picture {expre} */
 	putexpr[256], *putptr,*multptr,	/*[multi]put (x,y[;xinc,yinc;num])*/
-	pream[64], *preptr,		/* optional put preamble */
+	pream[96], *preptr,		/* optional put preamble */
 	picelem[1025];			/* picture element following put */
 subraster   *rasterize(), *picelemsp=NULL, /* rasterize picture elements */
 	*new_subraster(), *picturesp=NULL, /* subraster for entire picture */
@@ -7085,11 +7110,13 @@
   *pream = '\000';			/* init preamble as empty string */
   if ( (putptr=strchr(putexpr,'$')) != NULL ) /*check for $ pream terminator*/
     { *putptr++ = '\000';		/* replace $ by '\0', bump past $ */
-      strcpy(pream,putexpr); }		/* copy leading preamble from put */
+      strninit(pream,putexpr,92); }	/* copy leading preamble from put */
   else					/* look for any non-digit preamble */
-    { for ( preptr=pream,putptr=putexpr; ; putptr++ )
+    { int npream = 0;			/* #chars in preamble */
+      for ( preptr=pream,putptr=putexpr; ; npream++,putptr++ )
 	if ( *putptr == '\000'		/* end-of-putdata signalled */
-	||   !isalpha((int)(*putptr)) ) break; /* or found non-alpha char */
+	||   !isalpha((int)(*putptr))	/* or found non-alpha char */
+	||   npream > 92 ) break;	/* or preamble too long */
 	else *preptr++ = *putptr;	/* copy alpha char to preamble */
       *preptr = '\000'; }		/* null-terminate preamble */
   /* --- interpret preamble --- */
@@ -7130,7 +7157,7 @@
    } /* --- end-of-if(*preptr!='\000') --- */
   if ( msgfp!=NULL && msglevel>=29 )	/* debugging */
     fprintf(msgfp,
-    "picture> pream;x,y;xinc,yinc;num=\"%s\";%.2lf,%.2lf;%.2lf,%.2lf;%d\n",
+    "picture> pream;x,y;xinc,yinc;num=\"%s\";%.2f,%.2f;%.2f,%.2f;%d\n",
     pream,x,y,xinc,yinc,num);
   /* -----------------------------------------------------------------------
   now obtain {...} picture element following [multi]put, and rasterize it
@@ -7171,7 +7198,7 @@
 	  ypos = height - iy; }		/* so set for upper instead */
     if ( msgfp!=NULL && msglevel>=29 )	/* debugging */
       fprintf(msgfp,
-      "picture> inum,x,y,ix,iy,xpos,ypos=%d,%.2lf,%.2lf,%d,%d,%d,%d\n",
+      "picture> inum,x,y,ix,iy,xpos,ypos=%d,%.2f,%.2f,%d,%d,%d,%d\n",
       inum,x,y,ix,iy,xpos,ypos);
     /* --- embed token raster at xpos,ypos, and quit if out-of-bounds --- */
     if ( !rastput(picturerp,picelemsp->image,ypos,xpos,0) ) break;
@@ -7362,7 +7389,7 @@
 /* --- now interpret xdiam[,ydiam] returned in circexpr --- */
 if ( (qptr=strchr(circexpr,';')) != NULL ) /* semicolon signals quads data */
   { *qptr = '\000';			/* replace semicolon by '\0' */
-    strcpy(quads,qptr+1);		/* save user-requested quads */
+    strninit(quads,qptr+1,128);		/* save user-requested quads */
     if ( (qptr=strchr(quads,',')) != NULL ) /* have theta0,theta1 instead */
       {	*qptr = '\000';			/* replace , with null */
 	theta0 = strtod(quads,NULL);	/* theta0 precedes , */
@@ -7842,11 +7869,11 @@
 /* -------------------------------------------------------------------------
 Allocations and Declarations
 -------------------------------------------------------------------------- */
-char	*texsubexpr(), tag[512]="\000", filename[1024]="\000"; /* args */
+char	*texsubexpr(), tag[1024]="\000", filename[1024]="\000"; /* args */
 subraster *rasterize(), *inputsp=NULL; /* rasterized input image */
 int	status, rastreadfile();	/* read input file */
 int	format=0, npts=0;	/* don't reformat (numerical) input */
-char	subexpr[8192],		/* concatanated lines from input file */
+char	subexpr[MAXFILESZ+1] = "\000",		/* concatanated lines from input file */
 	*mimeprep(),		/* preprocess inputted data */
 	*dtoa(), *reformat=NULL; /* reformat numerical input */
 /* -------------------------------------------------------------------------
@@ -7854,14 +7881,14 @@
 -------------------------------------------------------------------------- */
 /* --- parse for optional [tag] or [fmt] arg, bump expression past it --- */
 if ( *(*expression) == '[' )		/* check for []-enclosed value */
-  { char argfld[2048];			/* optional argument field */
+  { char argfld[MAXTOKNSZ+1];		/* optional argument field */
     *expression = texsubexpr(*expression,argfld,"[","]",0,0);
     if ( (reformat=strstr(argfld,"dtoa")) != NULL ) /* dtoa requested */
       {	format = 1;			/* signal dtoa() format */
 	if ( (reformat=strchr(reformat,'=')) != NULL ) /* have dtoa= */
 	  npts = (int)strtol(reformat+1,NULL,0); } /* so set npts */
     if ( format == 0 )			/* reformat not requested */
-      strcpy(tag,argfld); }		/* so interpret arg as tag */
+      strninit(tag,argfld,1020); }	/* so interpret arg as tag */
 /* --- parse for {filename} arg, and bump expression past it --- */
 *expression = texsubexpr(*expression,filename,"{","}",0,0);
 /* --- check for alternate filename:tag --- */
@@ -7870,10 +7897,11 @@
  { char	*delim = strchr(filename,':');	/* look for : in filename:tag */
    if ( delim != (char *)NULL )		/* found it */
     { *delim = '\000';			/* null-terminate filename at : */
-      strcpy(tag,delim+1); } }		/* and stuff after : is tag */
+      strninit(tag,delim+1,1020); } }	/* and stuff after : is tag */
 /* --------------------------------------------------------------------------
 Read file and rasterize constructed subexpression
 -------------------------------------------------------------------------- */
+if ( 0 ) {				/* Disabled to fix CVE-2009-2459 */
 status = rastreadfile(filename,tag,subexpr); /* read file */
 if ( *subexpr == '\000' ) goto end_of_job;   /* quit if problem */
 /* --- rasterize input subexpression  --- */
@@ -7883,6 +7911,13 @@
    if ( d != 0.0 )			/* conversion to double successful */
     if ( (reformat=dtoa(d,npts)) != NULL ) /* reformat successful */
      strcpy(subexpr,reformat); }	/*replace subexpr with reformatted*/
+  }
+
+/* Send an error message to the user */
+sprintf(subexpr,
+"\\ \\text{[\\backslash input\\lbrace %.128s\\rbrace\\ not permitted]}\\ ",
+(isempty(filename)?"???":filename));
+
 inputsp = rasterize(subexpr,size);	/* rasterize subexpression */
 /* --- return input image to caller --- */
 end_of_job:
@@ -7923,7 +7958,7 @@
 Allocations and Declarations
 -------------------------------------------------------------------------- */
 char	*texsubexpr(), filename[1024]="\000", /* counter file */
-	logfile[1024]="\000", tag[512]="\000"; /* log file and tag */
+	logfile[1024]="\000", tag[1024]="\000"; /* log file and tag */
 subraster *rasterize(), *countersp=NULL; /* rasterized counter image */
 FILE	*fp=NULL, *logfp=NULL;	/* counter and log file pointers */
 int	rastreadfile(), rastwritefile(); /* to read and write counter file */
@@ -7981,6 +8016,13 @@
 /* --------------------------------------------------------------------------
 Read and parse file, increment and rewrite counter (with optional underscore)
 -------------------------------------------------------------------------- */
+
+/* Disabled to fix CVE-2009-2459 */
+sprintf(text,
+"\\ \\text{[\\backslash counter\\lbrace %.128s\\rbrace\\ not permitted]}\\ ",
+(isempty(filename)?"???":filename));
+goto rasterize_counter;		/* rasterize error message */
+
 if ( strlen(filename) > 1 )		/* make sure we got {filename} arg */
   {
   /* --- read and interpret first (and only) line from counter file --- */
@@ -8042,6 +8084,7 @@
     strcat(text,ordinal[ordindex]);	/* then st,nd,rd, or th */
     strcat(text,"}}"); }		/* finish with }} */
 /* --- rasterize it --- */
+rasterize_counter:
 countersp = rasterize(text,size);	/* rasterize counter subexpression */
 /* --- return counter image to caller --- */
 end_of_job:

Reply via email to