File sec-006-cve-2008-5239.diff of Package xine-lib

tree 2561516e6353
parent 9c97a9a9ba17
author Matthias Hopf <mhopf@suse.de> 1231089706 0
committer Matthias Hopf <mhopf@suse.de> 1231089706 0
revision 9638
branch default

Fix for CVE-2008-5239
xine-lib 1.1.12, and other 1.1.15 and earlier versions, does not
properly handle (a) negative and (b) zero values during unspecified
read function calls in input_file.c, input_net.c, input_smb.c, and
input_http.c, which allows remote attackers to cause a denial of
service (crash) or possibly execute arbitrary code via vectors such as
(1) a file or (2) an HTTP response, which triggers consequences such
as out-of-bounds reads and heap-based buffer overflows.
diff --git a/src/input/input_dvb.c b/src/input/input_dvb.c
--- a/src/input/input_dvb.c
+++ b/src/input/input_dvb.c
@@ -2602,6 +2602,10 @@
   buf_element_t        *buf = fifo->buffer_pool_alloc (fifo);
   int                   total_bytes;
 
+  if (todo < 0 || todo > buf->size) {
+    buf->free_buffer (buf);
+    return NULL;
+  }
 
   buf->content = buf->mem;
   buf->type    = BUF_DEMUX_BLOCK;
diff --git a/src/input/input_dvd.c b/src/input/input_dvd.c
--- a/src/input/input_dvd.c
+++ b/src/input/input_dvd.c
@@ -849,6 +849,9 @@
 
 static off_t dvd_plugin_read (input_plugin_t *this_gen, char *ch_buf, off_t len) {
 /*  dvd_input_plugin_t *this = (dvd_input_plugin_t*)this_gen; */
+
+  if (len < 4)
+    return -1;
 
   /* FIXME: Tricking the demux_mpeg_block plugin */
   ch_buf[0] = 0;
diff --git a/src/input/input_file.c b/src/input/input_file.c
--- a/src/input/input_file.c
+++ b/src/input/input_file.c
@@ -145,6 +145,9 @@
 static off_t file_plugin_read (input_plugin_t *this_gen, char *buf, off_t len) {
   file_input_plugin_t *this = (file_input_plugin_t *) this_gen;
 
+  if (len < 0)
+    return -1;
+
 #ifdef HAVE_MMAP
   if ( check_mmap_file(this) ) {
     off_t l = len;
@@ -165,6 +168,11 @@
 
   file_input_plugin_t  *this = (file_input_plugin_t *) this_gen;
   buf_element_t        *buf = fifo->buffer_pool_alloc (fifo);
+
+  if (todo < 0 || todo > buf->size) {
+    buf->free_buffer (buf);
+    return NULL;
+  }
 
   buf->type = BUF_DEMUX_BLOCK;
 
diff --git a/src/input/input_gnome_vfs.c b/src/input/input_gnome_vfs.c
--- a/src/input/input_gnome_vfs.c
+++ b/src/input/input_gnome_vfs.c
@@ -120,6 +120,11 @@
 {
 	off_t total_bytes;
 	buf_element_t *buf = fifo->buffer_pool_alloc (fifo);
+
+	if (todo < 0 || todo > buf->size) {
+		buf->free_buffer (buf);
+		return NULL;
+	}
 
 	buf->content = buf->mem;
 	buf->type = BUF_DEMUX_BLOCK;
diff --git a/src/input/input_http.c b/src/input/input_http.c
--- a/src/input/input_http.c
+++ b/src/input/input_http.c
@@ -421,6 +421,9 @@
 
   num_bytes = 0;
 
+  if (nlen < 0)
+    return -1;
+
   if (this->curpos < this->preview_size) {
 
     if (nlen > (this->preview_size - this->curpos))
@@ -437,7 +440,7 @@
 
   n = nlen - num_bytes;
 
-  if (n) {
+  if (n > 0) {
     int read_bytes;
     read_bytes = http_plugin_read_int (this, &buf[num_bytes], n);
     
@@ -503,6 +506,11 @@
   off_t                 total_bytes;
   buf_element_t        *buf = fifo->buffer_pool_alloc (fifo);
 
+  if (todo < 0 || todo > buf->size) {
+    buf->free_buffer (buf);
+    return NULL;
+  }
+
   buf->content = buf->mem;
   buf->type = BUF_DEMUX_BLOCK;
 
@@ -554,7 +562,7 @@
   if ((origin == SEEK_CUR) && (offset >= 0)) {
 
     for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) {
-      if( !this_gen->read (this_gen, this->seek_buf, BUFSIZE) )
+      if( this_gen->read (this_gen, this->seek_buf, BUFSIZE) <= 0 )
         return this->curpos;
     }
 
@@ -576,7 +584,7 @@
       offset -= this->curpos;
 
       for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) {
-        if( !this_gen->read (this_gen, this->seek_buf, BUFSIZE) )
+        if( this_gen->read (this_gen, this->seek_buf, BUFSIZE) <= 0 )
           return this->curpos;
       }
 
@@ -996,6 +1004,7 @@
     this->preview_size = http_plugin_read_int (this, this->preview, MAX_PREVIEW_SIZE);
   }
   if (this->preview_size < 0) {
+    this->preview_size = 0;
     xine_log (this->stream->xine, XINE_LOG_MSG, _("input_http: read error %d\n"), errno);
     return -12;
   }
diff --git a/src/input/input_mms.c b/src/input/input_mms.c
--- a/src/input/input_mms.c
+++ b/src/input/input_mms.c
@@ -121,6 +121,11 @@
   int                   total_bytes;
 
   lprintf ("mms_plugin_read_block: %"PRId64" bytes...\n", todo);
+
+  if (todo < 0 || todo > buf->size) {
+    buf->free_buffer (buf);
+    return NULL;
+  }
 
   buf->content = buf->mem;
   buf->type = BUF_DEMUX_BLOCK;
diff --git a/src/input/input_net.c b/src/input/input_net.c
--- a/src/input/input_net.c
+++ b/src/input/input_net.c
@@ -253,6 +253,9 @@
 
   lprintf("reading %" PRIdMAX " bytes...\n", (intmax_t)len);
 
+  if (len < 0)
+    return -1;
+
   total=0;
   if (this->curpos < this->preview_size) {
     n = this->preview_size - this->curpos;
@@ -287,6 +290,11 @@
   /* net_input_plugin_t   *this = (net_input_plugin_t *) this_gen; */
   buf_element_t        *buf = fifo->buffer_pool_alloc (fifo);
   off_t                 total_bytes;
+
+  if (todo < 0 || todo > buf->size) {
+    buf->free_buffer (buf);
+    return NULL;
+  }
 
   buf->content = buf->mem;
   buf->type = BUF_DEMUX_BLOCK;
@@ -331,7 +339,7 @@
   if ((origin == SEEK_CUR) && (offset >= 0)) {
 
     for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) {
-      if( !this_gen->read (this_gen, this->seek_buf, BUFSIZE) )
+      if( this_gen->read (this_gen, this->seek_buf, BUFSIZE) <= 0 )
         return this->curpos;
     }
 
@@ -353,7 +361,7 @@
       offset -= this->curpos;
 
       for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) {
-        if( !this_gen->read (this_gen, this->seek_buf, BUFSIZE) )
+        if( this_gen->read (this_gen, this->seek_buf, BUFSIZE) <= 0 )
           return this->curpos;
       }
 
diff --git a/src/input/input_pnm.c b/src/input/input_pnm.c
--- a/src/input/input_pnm.c
+++ b/src/input/input_pnm.c
@@ -83,7 +83,8 @@
   lprintf ("pnm_plugin_read: %"PRId64" bytes ...\n", len);
 
   n = pnm_read (this->pnm, buf, len);
-  this->curpos += n;
+  if (n >= 0)
+    this->curpos += n;
 
   return n;
 }
@@ -95,6 +96,11 @@
   int                   total_bytes;
 
   lprintf ("pnm_plugin_read_block: %"PRId64" bytes...\n", todo);
+
+  if (todo < 0 || todo > buf->size) {
+    buf->free_buffer (buf);
+    return NULL;
+  }
 
   buf->content = buf->mem;
   buf->type = BUF_DEMUX_BLOCK;
@@ -123,10 +129,16 @@
   if ((origin == SEEK_CUR) && (offset >= 0)) {
 
     for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) {
-      this->curpos += pnm_plugin_read (this_gen, this->scratch, BUFSIZE);
+      off_t n = pnm_plugin_read (this_gen, this->scratch, BUFSIZE);
+      if (n <= 0)
+	return this->curpos;
+      this->curpos += n;
     }
 
-    this->curpos += pnm_plugin_read (this_gen, this->scratch, offset);
+    off_t n = pnm_plugin_read (this_gen, this->scratch, offset);
+    if (n <= 0)
+      return this->curpos;
+    this->curpos += n;
   }
 
   return this->curpos;
diff --git a/src/input/input_pvr.c b/src/input/input_pvr.c
--- a/src/input/input_pvr.c
+++ b/src/input/input_pvr.c
@@ -423,6 +423,9 @@
 
 static off_t pvr_plugin_read (input_plugin_t *this_gen, char *buf, off_t len) {
   /*pvr_input_plugin_t *this = (pvr_input_plugin_t *) this_gen;*/
+
+  if (len < 4)
+    return -1;
 
   /* FIXME: Tricking the demux_mpeg_block plugin */
   buf[0] = 0;
@@ -1199,6 +1202,9 @@
   buf_element_t        *buf;
   int                   speed = _x_get_speed(this->stream);
 
+  if (todo < 0 || todo > buf->size)
+    return NULL;
+
   if( !this->pvr_running ) {
     xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "input_pvr: thread died, aborting\n");
     return NULL;  
diff --git a/src/input/input_rtp.c b/src/input/input_rtp.c
--- a/src/input/input_rtp.c
+++ b/src/input/input_rtp.c
@@ -453,6 +453,9 @@
   struct timespec timeout;
   off_t copied = 0; 
   
+  if (length < 0)
+    return -1;
+
   while(length > 0) {
 
     off_t n;
@@ -524,6 +527,10 @@
   buf_element_t        *buf = fifo->buffer_pool_alloc (fifo);
   int                   total_bytes;
 
+  if (todo < 0 || todo > buf->size) {
+    buf->free_buffer (buf);
+    return NULL;
+  }
 
   buf->content = buf->mem;
   buf->type    = BUF_DEMUX_BLOCK;
@@ -609,11 +616,14 @@
   if (data_type == INPUT_OPTIONAL_DATA_PREVIEW) {
     if (!this->preview_read_done) {
       this->preview_size = rtp_plugin_read(this_gen, this->preview, MAX_PREVIEW_SIZE);
+      if (this->preview_size < 0)
+	this->preview_size = 0;
       lprintf("Preview data length = %d\n", this->preview_size);
 
       this->preview_read_done = 1;
     }
-    memcpy(data, this->preview, this->preview_size);
+    if (this->preview_size)
+      memcpy(data, this->preview, this->preview_size);
     return this->preview_size;
   }
   else {
diff --git a/src/input/input_rtsp.c b/src/input/input_rtsp.c
--- a/src/input/input_rtsp.c
+++ b/src/input/input_rtsp.c
@@ -84,7 +84,8 @@
   lprintf ("rtsp_plugin_read: %"PRId64" bytes ...\n", len);
 
   n = rtsp_session_read (this->rtsp, buf, len);
-  this->curpos += n;
+  if (n > 0)
+    this->curpos += n;
 
   return n;
 }
@@ -96,6 +97,11 @@
   int                   total_bytes;
 
   lprintf ("rtsp_plugin_read_block: %"PRId64" bytes...\n", todo);
+
+  if (todo < 0 || todo > buf->size) {
+    buf->free_buffer (buf);
+    return NULL;
+  }
 
   buf->content = buf->mem;
   buf->type = BUF_DEMUX_BLOCK;
@@ -123,10 +129,16 @@
   if ((origin == SEEK_CUR) && (offset >= 0)) {
 
     for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) {
-      this->curpos += rtsp_plugin_read (this_gen, this->scratch, BUFSIZE);
+      off_t n = rtsp_plugin_read (this_gen, this->scratch, BUFSIZE);
+      if (n <= 0)
+	return this->curpos;
+      this->curpos += n;
     }
 
-    this->curpos += rtsp_plugin_read (this_gen, this->scratch, offset);
+    off_t n = rtsp_plugin_read (this_gen, this->scratch, offset);
+    if (n <= 0)
+      return this->curpos;
+    this->curpos += n;
   }
 
   return this->curpos;
diff --git a/src/input/input_smb.c b/src/input/input_smb.c
--- a/src/input/input_smb.c
+++ b/src/input/input_smb.c
@@ -69,6 +69,8 @@
 	smb_input_t *this = (smb_input_t *) this_gen;
 	off_t n, num_bytes;
 
+	if (len < 0)
+		return -1;
 	num_bytes = 0;
 
 	while (num_bytes < len)
@@ -88,6 +90,11 @@
 {
 	off_t total_bytes;
 	buf_element_t *buf = fifo->buffer_pool_alloc (fifo);
+
+	if (todo < 0 || todo > buf->size) {
+		buf->free_buffer (buf);
+		return NULL;
+	}
 
 	buf->content = buf->mem;
 	buf->type = BUF_DEMUX_BLOCK;
diff --git a/src/input/input_stdin_fifo.c b/src/input/input_stdin_fifo.c
--- a/src/input/input_stdin_fifo.c
+++ b/src/input/input_stdin_fifo.c
@@ -85,6 +85,8 @@
   off_t n, total;
 
   lprintf ("reading %"PRId64" bytes...\n", len);
+  if (len < 0)
+    return -1;
 
   total=0;
   if (this->curpos < this->preview_size) {
@@ -121,6 +123,11 @@
   /* stdin_input_plugin_t  *this = (stdin_input_plugin_t *) this_gen; */
   buf_element_t         *buf = fifo->buffer_pool_alloc (fifo);
 
+  if (todo < 0 || todo > buf->size) {
+    buf->free_buffer (buf);
+    return NULL;
+  }
+
   buf->content = buf->mem;
   buf->type = BUF_DEMUX_BLOCK;
 
@@ -146,7 +153,7 @@
   if ((origin == SEEK_CUR) && (offset >= 0)) {
 
     for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) {
-      if( !this_gen->read (this_gen, this->seek_buf, BUFSIZE) )
+      if( this_gen->read (this_gen, this->seek_buf, BUFSIZE) <= 0 )
         return this->curpos;
     }
 
@@ -168,7 +175,7 @@
       offset -= this->curpos;
 
       for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) {
-        if( !this_gen->read (this_gen, this->seek_buf, BUFSIZE) )
+        if( this_gen->read (this_gen, this->seek_buf, BUFSIZE) <= 0 )
           return this->curpos;
       }
 
@@ -270,6 +277,8 @@
 
   this->preview_size = stdin_plugin_read (&this->input_plugin, this->preview,
 					  MAX_PREVIEW_SIZE);
+  if (this->preview_size < 0)
+    this->preview_size = 0;
   this->curpos          = 0;
 
   return 1;
openSUSE Build Service is sponsored by