From taviso at sdf.lonestar.org Wed Feb 4 03:41:18 2009 From: taviso at sdf.lonestar.org (Tavis Ormandy) Date: Wed, 4 Feb 2009 03:41:18 +0000 Subject: [Png-mng-security] potentially serious memory handling error in libpng Message-ID: <20090204034118.GA4309@sdf.lonestar.org> Hey Glenn, Greg and others, I've discovered a potentially serious error in libpng, it requires an allocation failure at a specific time in order to work, and so probably explains why nobody has reported running into this by accident. Unfortunately, an attacker can usually create this easily (e.g. just preparing a highly compressable image of ridiculous size). The problem is in pngread.c, 1433 if (info_ptr->row_pointers == NULL) 1434 { 1435 info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr, 1436 info_ptr->height * png_sizeof(png_bytep)); 1437 #ifdef PNG_FREE_ME_SUPPORTED 1438 info_ptr->free_me |= PNG_FREE_ROWS; 1439 #endif 1440 for (row = 0; row < (int)info_ptr->height; row++) 1441 { 1442 info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr, 1443 png_get_rowbytes(png_ptr, info_ptr)); 1444 } 1445 } Here you can see (info_ptr->free_me & PNG_FREE_ROWS) is set after the space for the pointers has been allocated, but _before_ the rows themselves have been allocated. If any of row allocations fail, a portion of the pointers in info_ptr->row_pointers are going to be unintialised junk, (this is easy to control if an application will render two images an attacker will supply, the first one can poison the heap and succeed, the second triggers the fault, resulting in free(attacker_controlled). These can be exploitable (although its tricky) by setting up "fake" heap chunks, and pointing the system allocator at it. I've got a demo that works on my machine, I'm using setrlimit() to make allocation failure more reliable, but unless you're using the same distribution as me it may need tweaking, 3 required files attached. (note, i modified the pngs by hand so im cheating and using png_set_crc_action() instead of fixing them up, sorry!) $ gcc -ggdb3 -O0 pngdecode.c libpng-1.2.34/.libs/libpng.a -o pngdecode -lm -lz $ gdb -q ./pngdecode (gdb) r Breakpoint 1, png_default_error (png_ptr=0x80642d8, error_message=0x4b0d2bd2 "invalid literal/lengths set") at pngerror.c:218 218 if (*error_message == '#') (gdb) c Breakpoint 1, png_default_error (png_ptr=0x80642d8, error_message=0x8061450 "Out of Memory!") at pngerror.c:218 218 if (*error_message == '#') (gdb) bt #0 png_default_error (png_ptr=0x80642d8, error_message=0x8061450 "Out of Memory!") at pngerror.c:218 #1 0x08056ff3 in png_error (png_ptr=0x80642d8, error_message=0x8061450 "Out of Memory!") at pngerror.c:80 #2 0x08056cea in png_malloc (png_ptr=0x80642d8, size=33132) at pngmem.c:442 #3 0x0804c8c8 in png_read_png (png_ptr=0x80642d8, info_ptr=0x8064008, transforms=0, params=0x0) at pngread.c:1442 (gdb) frame 3 #3 0x0804c8c8 in png_read_png (png_ptr=0x80642d8, info_ptr=0x8064008, transforms=0, params=0x0) at pngread.c:1442 1442 info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr, (gdb) p row $2 = 3993 (gdb) p info_ptr->height $3 = 15173 Memory allocation failed here when row < info_ptr->height, so the rest of the pointers in this array are unintialised junk. (gdb) c libpng error: Out of Memory! Program received signal SIGSEGV, Segmentation fault. 0x48997fe9 in free () from /lib/tls/libc.so.6 (gdb) bt #0 0x48997fe9 in free () from /lib/tls/libc.so.6 #1 0x08056d97 in png_free_default (png_ptr=0x80642d8, ptr=0x5080) at pngmem.c:525 #2 0x08056d76 in png_free (png_ptr=0x80642d8, ptr=0x5080) at pngmem.c:509 #3 0x080494d9 in png_free_data (png_ptr=0x80642d8, info_ptr=0x8064008, mask=32767, num=-1) at png.c:571 #4 0x080495a2 in png_info_destroy (png_ptr=0x80642d8, info_ptr=0x8064008) at png.c:598 #5 0x0804c20b in png_read_destroy (png_ptr=0x80642d8, info_ptr=0x8064008, end_info_ptr=0x0) at pngread.c:1166 #6 0x0804c12c in png_destroy_read_struct (png_ptr_ptr=0xffffce54, info_ptr_ptr=0xffffce50, end_info_ptr_ptr=0x0) at pngread.c:1107 ... (gdb) frame 3 #3 0x080494d9 in png_free_data (png_ptr=0x80642d8, info_ptr=0x8064008, mask=32767, num=-1) at png.c:571 571 png_free(png_ptr, info_ptr->row_pointers[row]); (gdb) p row $4 = 4028 (gdb) p info_ptr->row_pointers[row] $5 = (png_byte *) 0x5080
row is > 3993, where the allocation failure happened. I suppose the easiest fix is just to png_memset(foo, 0, n) row_pointers as soon as they're allocated, before free_me gets the ROW_POINTERS flag set. png_free handles free(NULL), so you dont have rely on the system allocator being sane. Oneliner below. $ diff -up pngread.c.orig pngread.c --- pngread.c.orig 2009-02-04 03:33:27.605190000 +0000 +++ pngread.c 2009-02-04 03:34:25.383958000 +0000 @@ -1434,6 +1434,8 @@ png_read_png(png_structp png_ptr, png_in { info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr, info_ptr->height * png_sizeof(png_bytep)); + png_memset(info_ptr->row_pointers, 0, + info_ptr->height * png_sizeof(png_bytep)); #ifdef PNG_FREE_ME_SUPPORTED info_ptr->free_me |= PNG_FREE_ROWS; #endif I'm not sure if you need additional logic to handle 16bit machines, like the unused logic in png_zalloc()? Thanks, Tavis. -- ------------------------------------- taviso at sdf.lonestar.org | finger me for my gpg key. ------------------------------------------------------- -------------- next part -------------- /* * * $Author: taviso $ * */ #include #include #include #include bool decode(FILE *infile) { png_structp png_ptr; png_infop info_ptr; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); info_ptr = png_create_info_struct(png_ptr); png_set_crc_action(png_ptr, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE); if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(infile); return false; } png_init_io(png_ptr, infile); png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(infile); return true; } int main(int argc, char **argv) { FILE *filea, *fileb; struct rlimit r; // limit allocation r.rlim_cur = r.rlim_max = 128 * 1024 * 1024; setrlimit(RLIMIT_AS, &r); filea = fopen("crash-a.png", "r"); fileb = fopen("crash-b.png", "r"); decode(filea); decode(fileb); return 0; } -------------- next part -------------- A non-text attachment was scrubbed... Name: crash-a.png Type: image/png Size: 8623 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: crash-b.png Type: image/png Size: 8623 bytes Desc: not available URL: From glennrp at comcast.net Wed Feb 4 12:45:57 2009 From: glennrp at comcast.net (glennrp at comcast.net) Date: Wed, 4 Feb 2009 12:45:57 +0000 (UTC) Subject: [Png-mng-security] potentially serious memory handling error in libpng In-Reply-To: <814158823.762121233751148330.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> Message-ID: <1938845382.763951233751557958.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> ----- Original Message ----- From: "Tavis Ormandy" To: glennrp at comcast.net, png-mng-security at simple.dallas.tx.us Cc: scarybeasts at gmail.com Sent: Tuesday, February 3, 2009 10:41:18 PM GMT -05:00 US/Canada Eastern Subject: potentially serious memory handling error in libpng Hey Glenn, Greg and others, I've discovered a potentially serious error in libpng, it requires an allocation failure at a specific time in order to work, and so probably explains why nobody has reported running into this by accident. Unfortunately, an attacker can usually create this easily (e.g. just preparing a highly compressable image of ridiculous size). The problem is in pngread.c, 1433 if (info_ptr->row_pointers == NULL) 1434 { 1435 info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr, 1436 info_ptr->height * png_sizeof(png_bytep)); 1437 #ifdef PNG_FREE_ME_SUPPORTED 1438 info_ptr->free_me |= PNG_FREE_ROWS; 1439 #endif 1440 for (row = 0; row < (int)info_ptr->height; row++) 1441 { 1442 info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr, 1443 png_get_rowbytes(png_ptr, info_ptr)); 1444 } 1445 } Here you can see (info_ptr->free_me & PNG_FREE_ROWS) is set after the space for the pointers has been allocated, but _before_ the rows themselves have been allocated. If any of row allocations fail, a portion of the pointers in info_ptr->row_pointers are going to be unintialised junk, Rats. I liked the version number 1.2.34 as the final stable version number. Would this cure the defect? insert between 1439 and 1440 for (row = 0; row < (int)info_ptr->height; row++) info_ptr->row_pointers[row] = NULL; Oh, never mind, your "memset" solution is more compact. Glenn (this is easy to control if an application will render two images an attacker will supply, the first one can poison the heap and succeed, the second triggers the fault, resulting in free(attacker_controlled). These can be exploitable (although its tricky) by setting up "fake" heap chunks, and pointing the system allocator at it. I've got a demo that works on my machine, I'm using setrlimit() to make allocation failure more reliable, but unless you're using the same distribution as me it may need tweaking, 3 required files attached. (note, i modified the pngs by hand so im cheating and using png_set_crc_action() instead of fixing them up, sorry!) $ gcc -ggdb3 -O0 pngdecode.c libpng-1.2.34/.libs/libpng.a -o pngdecode -lm -lz $ gdb -q ./pngdecode (gdb) r Breakpoint 1, png_default_error (png_ptr=0x80642d8, error_message=0x4b0d2bd2 "invalid literal/lengths set") at pngerror.c:218 218 if (*error_message == '#') (gdb) c Breakpoint 1, png_default_error (png_ptr=0x80642d8, error_message=0x8061450 "Out of Memory!") at pngerror.c:218 218 if (*error_message == '#') (gdb) bt #0 png_default_error (png_ptr=0x80642d8, error_message=0x8061450 "Out of Memory!") at pngerror.c:218 #1 0x08056ff3 in png_error (png_ptr=0x80642d8, error_message=0x8061450 "Out of Memory!") at pngerror.c:80 #2 0x08056cea in png_malloc (png_ptr=0x80642d8, size=33132) at pngmem.c:442 #3 0x0804c8c8 in png_read_png (png_ptr=0x80642d8, info_ptr=0x8064008, transforms=0, params=0x0) at pngread.c:1442 (gdb) frame 3 #3 0x0804c8c8 in png_read_png (png_ptr=0x80642d8, info_ptr=0x8064008, transforms=0, params=0x0) at pngread.c:1442 1442 info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr, (gdb) p row $2 = 3993 (gdb) p info_ptr->height $3 = 15173 Memory allocation failed here when row < info_ptr->height, so the rest of the pointers in this array are unintialised junk. (gdb) c libpng error: Out of Memory! Program received signal SIGSEGV, Segmentation fault. 0x48997fe9 in free () from /lib/tls/libc.so.6 (gdb) bt #0 0x48997fe9 in free () from /lib/tls/libc.so.6 #1 0x08056d97 in png_free_default (png_ptr=0x80642d8, ptr=0x5080) at pngmem.c:525 #2 0x08056d76 in png_free (png_ptr=0x80642d8, ptr=0x5080) at pngmem.c:509 #3 0x080494d9 in png_free_data (png_ptr=0x80642d8, info_ptr=0x8064008, mask=32767, num=-1) at png.c:571 #4 0x080495a2 in png_info_destroy (png_ptr=0x80642d8, info_ptr=0x8064008) at png.c:598 #5 0x0804c20b in png_read_destroy (png_ptr=0x80642d8, info_ptr=0x8064008, end_info_ptr=0x0) at pngread.c:1166 #6 0x0804c12c in png_destroy_read_struct (png_ptr_ptr=0xffffce54, info_ptr_ptr=0xffffce50, end_info_ptr_ptr=0x0) at pngread.c:1107 ... (gdb) frame 3 #3 0x080494d9 in png_free_data (png_ptr=0x80642d8, info_ptr=0x8064008, mask=32767, num=-1) at png.c:571 571 png_free(png_ptr, info_ptr->row_pointers[row]); (gdb) p row $4 = 4028 (gdb) p info_ptr->row_pointers[row] $5 = (png_byte *) 0x5080
row is > 3993, where the allocation failure happened. I suppose the easiest fix is just to png_memset(foo, 0, n) row_pointers as soon as they're allocated, before free_me gets the ROW_POINTERS flag set. png_free handles free(NULL), so you dont have rely on the system allocator being sane. Oneliner below. $ diff -up pngread.c.orig pngread.c --- pngread.c.orig 2009-02-04 03:33:27.605190000 +0000 +++ pngread.c 2009-02-04 03:34:25.383958000 +0000 @@ -1434,6 +1434,8 @@ png_read_png(png_structp png_ptr, png_in { info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr, info_ptr->height * png_sizeof(png_bytep)); + png_memset(info_ptr->row_pointers, 0, + info_ptr->height * png_sizeof(png_bytep)); #ifdef PNG_FREE_ME_SUPPORTED info_ptr->free_me |= PNG_FREE_ROWS; #endif I'm not sure if you need additional logic to handle 16bit machines, like the unused logic in png_zalloc()? Dunno. I think my version (explicitly setting the pointers one by one) would be immune to pointer-size problems. Glenn Thanks, Tavis. -- ------------------------------------- taviso at sdf.lonestar.org | finger me for my gpg key. ------------------------------------------------------- -------------- next part -------------- An HTML attachment was scrubbed... URL: From taviso at sdf.lonestar.org Wed Feb 4 13:58:53 2009 From: taviso at sdf.lonestar.org (Tavis Ormandy) Date: Wed, 4 Feb 2009 13:58:53 +0000 Subject: [Png-mng-security] potentially serious memory handling error in libpng In-Reply-To: <1938845382.763951233751557958.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> References: <814158823.762121233751148330.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> <1938845382.763951233751557958.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> Message-ID: <20090204135853.GA26501@sdf.lonestar.org> On Wed, Feb 04, 2009 at 12:45:57PM +0000, glennrp at comcast.net wrote: > Rats. I liked the version number 1.2.34 as the final stable version number. > > Would this cure the defect? > > insert between 1439 and 1440 > > for (row = 0; row < (int)info_ptr->height; row++) > info_ptr->row_pointers[row] = NULL; > > Oh, never mind, your "memset" solution is more compact. > > Glenn > > > I'm not sure if you need additional logic to handle 16bit machines, like the > > unused logic in png_zalloc()? > > Dunno. I think my version (explicitly setting the pointers one by one) > would be immune to pointer-size problems. > > Glenn > Good point, you're right. This sounds good to me. Thanks, Tavis. -- ------------------------------------- taviso at sdf.lonestar.org | finger me for my gpg key. ------------------------------------------------------- From glennrp at comcast.net Wed Feb 4 19:25:45 2009 From: glennrp at comcast.net (glennrp at comcast.net) Date: Wed, 4 Feb 2009 19:25:45 +0000 (UTC) Subject: [Png-mng-security] potentially serious memory handling error in libpng In-Reply-To: <20090204135853.GA26501@sdf.lonestar.org> Message-ID: <639149277.1000321233775545970.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> SECURITY SENSITIVE Libpng-1.2.35beta01 addresses this vulnerability along with a similar one in the pCAL chunk reader. There's another in the code that builds the 16-bit gamma table but I doubt that it could be exploited. I fixed it anyway. Addressees please note that this message is private and should not be immediately reflected to the debian public mailing list like last time. Give us 2 weeks to run through the usual beta, rc1 cycle. Tavis, please pass this along to the security community. Glenn ----- Original Message ----- From: "Tavis Ormandy" To: glennrp at comcast.net Cc: scarybeasts at gmail.com, png-mng-security at simple.dallas.tx.us Sent: Wednesday, February 4, 2009 8:58:53 AM GMT -05:00 US/Canada Eastern Subject: Re: potentially serious memory handling error in libpng On Wed, Feb 04, 2009 at 12:45:57PM +0000, glennrp at comcast.net wrote: > Rats. I liked the version number 1.2.34 as the final stable version number. > > Would this cure the defect? > > insert between 1439 and 1440 > > for (row = 0; row < (int)info_ptr->height; row++) > info_ptr->row_pointers[row] = NULL; > > Oh, never mind, your "memset" solution is more compact. > > Glenn > > > I'm not sure if you need additional logic to handle 16bit machines, like the > > unused logic in png_zalloc()? > > Dunno. I think my version (explicitly setting the pointers one by one) > would be immune to pointer-size problems. > > Glenn > Good point, you're right. This sounds good to me. Thanks, Tavis. -- ------------------------------------- taviso at sdf.lonestar.org | finger me for my gpg key. ------------------------------------------------------- -------------- next part -------------- An HTML attachment was scrubbed... URL: From glennrp at comcast.net Wed Feb 4 19:37:47 2009 From: glennrp at comcast.net (glennrp at comcast.net) Date: Wed, 4 Feb 2009 19:37:47 +0000 (UTC) Subject: [Png-mng-security] potentially serious memory handling error in libpng In-Reply-To: <639149277.1000321233775545970.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> Message-ID: <645834766.1008241233776267821.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> SECURITY SENSITIVE I forgot to include the URL, which is http://www.simplesystems.org/users/glennrp/sbo/lp1235b01 Glenn ----- Original Message ----- From: glennrp at comcast.net To: "Tavis Ormandy" Cc: scarybeasts at gmail.com, png-mng-security at simple.dallas.tx.us Sent: Wednesday, February 4, 2009 2:25:45 PM GMT -05:00 US/Canada Eastern Subject: Re: [Png-mng-security] potentially serious memory handling error in libpng SECURITY SENSITIVE Libpng-1.2.35beta01 addresses this vulnerability... -------------- next part -------------- An HTML attachment was scrubbed... URL: From glennrp at comcast.net Wed Feb 4 20:46:41 2009 From: glennrp at comcast.net (glennrp at comcast.net) Date: Wed, 4 Feb 2009 20:46:41 +0000 (UTC) Subject: [Png-mng-security] potentially serious memory handling error in libpng In-Reply-To: <645834766.1008241233776267821.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> Message-ID: <734509249.1048421233780401281.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> I omitted the code to fix two of the instances in the gamma_16 handler. This is fixed in libpng-1.2.35beta02 which you can find at http://www.simplesystems.org/users/glennrp/sbo/lp1235b02 Glenn ----- Original Message ----- From: glennrp at comcast.net To: "Tavis Ormandy" Cc: scarybeasts at gmail.com, png-mng-security at simple.dallas.tx.us Sent: Wednesday, February 4, 2009 2:37:47 PM GMT -05:00 US/Canada Eastern Subject: Re: [Png-mng-security] potentially serious memory handling error in libpng SECURITY SENSITIVE I forgot to include the URL, which is http://www.simplesystems.org/users/glennrp/sbo/lp1235b01 Glenn ----- Original Message ----- From: glennrp at comcast.net To: "Tavis Ormandy" Cc: scarybeasts at gmail.com, png-mng-security at simple.dallas.tx.us Sent: Wednesday, February 4, 2009 2:25:45 PM GMT -05:00 US/Canada Eastern Subject: Re: [Png-mng-security] potentially serious memory handling error in libpng SECURITY SENSITIVE Libpng-1.2.35beta01 addresses this vulnerability... _______________________________________________ Png-mng-security mailing list Png-mng-security at simplesystems.org http://www.simplesystems.org/mailman/listinfo/png-mng-security -------------- next part -------------- An HTML attachment was scrubbed... URL: From glennrp at comcast.net Thu Feb 5 00:09:51 2009 From: glennrp at comcast.net (glennrp at comcast.net) Date: Thu, 5 Feb 2009 00:09:51 +0000 (UTC) Subject: [Png-mng-security] potential optimizing away of initialization loop In-Reply-To: <734509249.1048421233780401281.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> Message-ID: <743691153.1157671233792591855.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> SECURITY SENSITIVE I seem to recall in the past having trouble with optimizing compilers removing loops that apparently don't really do anything. In this bugfix we introduce the first loop in for (i=0; i From newt at pobox.com Thu Feb 5 00:59:35 2009 From: newt at pobox.com (Greg Roelofs) Date: Wed, 4 Feb 2009 16:59:35 -0800 Subject: [Png-mng-security] potential optimizing away of initialization loop In-Reply-To: <743691153.1157671233792591855.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> Message-ID: <200902050059.n150xZtt006807@bolt.sonic.net> > I seem to recall in the past having trouble with optimizing > compilers removing loops that apparently don't really do > anything. In this bugfix we introduce the first loop in > for (i=0; i element[i] = NULL; > for (i=0; i element[i] = png_malloc(...); > I think the presence of the call to an external function > i.e., png_malloc() in the second loop will prevent the first > loop from being optimized away. Is that correct, and > therefore we should not worry about it? I don't think so. The compiler can trivially see that the assignment (regardless of the value) in the second loop is whacking the previous assignment, so the latter isn't necessary. Only way to be sure is to check the assembler output, but in general, function calls protect you only when your data member is being passed as an argument, not when it's being assigned. Greg From jbowler at acm.org Thu Feb 5 01:41:45 2009 From: jbowler at acm.org (John Bowler) Date: Wed, 4 Feb 2009 17:41:45 -0800 Subject: [Png-mng-security] potential optimizing away of initialization loop In-Reply-To: <743691153.1157671233792591855.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> References: <734509249.1048421233780401281.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> <743691153.1157671233792591855.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> Message-ID: <005101c98732$e808dfa0$b81a9ee0$@org> From: glennrp at comcast.net >I seem to recall in the past having trouble with optimizing >compilers removing loops that apparently don't really do >anything. In this bugfix we introduce the first loop in > > for (i=0; i element[i] = NULL; > for (i=0; i element[i] = png_malloc(...); The compiler cannot know that the pointer 'element' is not aliased, therefore element[i+1] might be accessed from within png_malloc while it still contains NULL. What is more the compiler cannot know that png_malloc does not call longjmp, causing the loop to terminate before all element[i] are overwritten. That applies to any function call unless the compiler knows about the function. >I think the presence of the call to an external function >i.e., png_malloc() in the second loop will prevent the first >loop from being optimized away. Is that correct, and >therefore we should not worry about it? Yes, that is correct, for the two reasons given above. In it might be possible for the compilation system to work out that png_malloc does not leave 'element' accessible to other functions, but in that case the optimizer should also notice that png_malloc can all longjmp... John Bowler From glennrp at comcast.net Thu Feb 5 15:03:52 2009 From: glennrp at comcast.net (glennrp at comcast.net) Date: Thu, 5 Feb 2009 15:03:52 +0000 (UTC) Subject: [Png-mng-security] potentially serious memory handling error in libpng In-Reply-To: <20090204135853.GA26501@sdf.lonestar.org> Message-ID: <1158766282.1389861233846232220.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> ----- Original Message ----- From: "Tavis Ormandy" To: glennrp at comcast.net Cc: scarybeasts at gmail.com, png-mng-security at simple.dallas.tx.us Sent: Wednesday, February 4, 2009 8:58:53 AM GMT -05:00 US/Canada Eastern Subject: Re: potentially serious memory handling error in libpng On Wed, Feb 04, 2009 at 12:45:57PM +0000, glennrp at comcast.net wrote: > Rats. I liked the version number 1.2.34 as the final stable version number. > > Would this cure the defect? > > insert between 1439 and 1440 > > for (row = 0; row < (int)info_ptr->height; row++) > info_ptr->row_pointers[row] = NULL; > > Oh, never mind, your "memset" solution is more compact. > > Glenn > > > I'm not sure if you need additional logic to handle 16bit machines, like the > > unused logic in png_zalloc()? > > Dunno. I think my version (explicitly setting the pointers one by one) > would be immune to pointer-size problems. > > Glenn > Good point, you're right. This sounds good to me. Thanks, Tavis. In the other hand, we have been getting away with using memset to initialize pointers to zero all along. When we create the png_struct we memset it to zero, and later on we check for read_fn == NULL, etc. So in the case that memset is not safe for this purpose we have a few other bugs to fix. For now let's just assume it's safe and start another bug on the open png-mng-implement list about memset safety. Glenn -------------- next part -------------- An HTML attachment was scrubbed... URL: From tgl at sss.pgh.pa.us Thu Feb 5 15:20:42 2009 From: tgl at sss.pgh.pa.us (Tom Lane) Date: Thu, 05 Feb 2009 10:20:42 -0500 Subject: [Png-mng-security] potentially serious memory handling error in libpng In-Reply-To: <1158766282.1389861233846232220.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> References: <1158766282.1389861233846232220.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> Message-ID: <19644.1233847242@sss.pgh.pa.us> glennrp at comcast.net writes: > In the other hand, we have been getting away with using memset > to initialize pointers to zero all along. As has every other piece of C software on the planet. Don't worry about it. (The memset also seems much less likely to fall victim to any hypothetical overaggressive-optimization bugs.) regards, tom lane From taviso at sdf.lonestar.org Thu Feb 5 15:25:47 2009 From: taviso at sdf.lonestar.org (Tavis Ormandy) Date: Thu, 5 Feb 2009 15:25:47 +0000 Subject: [Png-mng-security] potentially serious memory handling error in libpng In-Reply-To: <19644.1233847242@sss.pgh.pa.us> References: <1158766282.1389861233846232220.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> <19644.1233847242@sss.pgh.pa.us> Message-ID: <20090205152547.GA4677@sdf.lonestar.org> On Thu, Feb 05, 2009 at 10:20:42AM -0500, Tom Lane wrote: > glennrp at comcast.net writes: > > In the other hand, we have been getting away with using memset > > to initialize pointers to zero all along. > > As has every other piece of C software on the planet. Don't worry about > it. (The memset also seems much less likely to fall victim to any > hypothetical overaggressive-optimization bugs.) > > regards, tom lane Okay, thanks for the clarification, the unusual logic in png_default_zalloc() confused me, perhaps it is just redundant paranoid checking? Thanks, Tavis. -- ------------------------------------- taviso at sdf.lonestar.org | finger me for my gpg key. ------------------------------------------------------- From jbowler at acm.org Thu Feb 5 16:37:58 2009 From: jbowler at acm.org (John Bowler) Date: Thu, 5 Feb 2009 08:37:58 -0800 Subject: [Png-mng-security] potentially serious memory handling error in libpng In-Reply-To: <1158766282.1389861233846232220.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> References: <20090204135853.GA26501@sdf.lonestar.org> <1158766282.1389861233846232220.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> Message-ID: <006001c987b0$1b694f10$523bed30$@org> From: glennrp at comcast.net >In the other hand, we have been getting away with using memset >to initialize pointers to zero all along. When we create the png_struct >we memset it to zero, and later on we check for read_fn == NULL, etc. > >So in the case that memset is not safe for this purpose we have a few >other bugs to fix. An architecture where the NULL pointer is not the bit pattern 0 will fail immediately, so we can be reasonably sure no such architecture is running an unmodified libpng. Memset is *much* safer for this purpose. It's the best way to ensure that every field in the structure is initialized. It's much more of a security risk to rely on the code explicitly initializing every field. John Bowler From glennrp at comcast.net Thu Feb 5 17:28:42 2009 From: glennrp at comcast.net (glennrp at comcast.net) Date: Thu, 5 Feb 2009 17:28:42 +0000 (UTC) Subject: [Png-mng-security] potentially serious memory handling error in libpng In-Reply-To: <834086322.1472611233854639404.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> Message-ID: <1825567138.1475351233854922086.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> ----- Original Message ----- From: "John Bowler" To: glennrp at comcast.net, "Tavis Ormandy" Cc: png-mng-security at simple.dallas.tx.us Sent: Thursday, February 5, 2009 11:37:58 AM GMT -05:00 US/Canada Eastern Subject: RE: [Png-mng-security] potentially serious memory handling error in libpng From: glennrp at comcast.net >In the other hand, we have been getting away with using memset >to initialize pointers to zero all along. When we create the png_struct >we memset it to zero, and later on we check for read_fn == NULL, etc. > >So in the case that memset is not safe for this purpose we have a few >other bugs to fix. An architecture where the NULL pointer is not the bit pattern 0 will fail immediately, so we can be reasonably sure no such architecture is running an unmodified libpng. Doesn't this depend only on the C compiler implementation rather than the architecture? Memset is *much* safer for this purpose. It's the best way to ensure that every field in the structure is initialized. It's much more of a security risk to rely on the code explicitly initializing every field. John Bowler I would not suggest doing away with memset entirely but rather something like this memset (*png_ptr, 0, sizeof(png_ptr)); #ifdef PNG_MEMSET_POINTERS_IS_UNSAFE png_ptr->read_fn=NULL; png_ptr->write_fn=NULL; png_ptr->malloc_fn=NULL; #endif #ifdef PNG_MEMSET_POINTERS_IS_UNSAFE for (i=0; i From bfriesen at simple.dallas.tx.us Thu Feb 5 17:46:05 2009 From: bfriesen at simple.dallas.tx.us (Bob Friesenhahn) Date: Thu, 5 Feb 2009 11:46:05 -0600 (CST) Subject: [Png-mng-security] potentially serious memory handling error in libpng In-Reply-To: <1825567138.1475351233854922086.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> References: <1825567138.1475351233854922086.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> Message-ID: On Thu, 5 Feb 2009, glennrp at comcast.net wrote: > > Googling for "memset null pointer" turns up a lot of flame wars and pretty much > agreement that the NULL pointer does not have to be all zeroes. However, no > one seems to be able to provide an example. Therefore in the above I would > leave PNG_MEMSET_POINTERS_IS_UNSAFE undefined by default. Don't the C and C++ specifications specify the value for NULL? I have only seen mention of "0" or "(void *) 0". My own software (and most other software) would fail to work if NULL was not also zero and I have never seen such a failure. Bob ====================================== Bob Friesenhahn bfriesen at simple.dallas.tx.us, http://www.simplesystems.org/users/bfriesen/ GraphicsMagick Maintainer, http://www.GraphicsMagick.org/ From newt at pobox.com Thu Feb 5 17:57:42 2009 From: newt at pobox.com (Greg Roelofs) Date: Thu, 5 Feb 2009 09:57:42 -0800 Subject: [Png-mng-security] potentially serious memory handling error in libpng In-Reply-To: Message-ID: <200902051757.n15HvgjK020280@bolt.sonic.net> >> Googling for "memset null pointer" turns up a lot of flame wars and pretty much >> agreement that the NULL pointer does not have to be all zeroes. However, no >> one seems to be able to provide an example. Therefore in the above I would >> leave PNG_MEMSET_POINTERS_IS_UNSAFE undefined by default. > Don't the C and C++ specifications specify the value for NULL? I have > only seen mention of "0" or "(void *) 0". I don't have the spec, but the K&R wording is that the literal integer 0 is equivalent to a NULL pointer only via cast, assignment, or comparison. Direct memory access is none of those things. > My own software (and most other software) would fail to work if NULL > was not also zero and I have never seen such a failure. The entire planet's software would fail if compilers used a different representation for NULL; we don't need to worry about it in practice. (And just say "no" to more ifdefs. Yeesh.) Greg From tgl at sss.pgh.pa.us Thu Feb 5 18:14:01 2009 From: tgl at sss.pgh.pa.us (Tom Lane) Date: Thu, 05 Feb 2009 13:14:01 -0500 Subject: [Png-mng-security] potentially serious memory handling error in libpng In-Reply-To: <200902051757.n15HvgjK020280@bolt.sonic.net> References: <200902051757.n15HvgjK020280@bolt.sonic.net> Message-ID: <22187.1233857641@sss.pgh.pa.us> Greg Roelofs writes: > I don't have the spec, but the K&R wording is that the literal integer 0 > is equivalent to a NULL pointer only via cast, assignment, or comparison. Right. In theory a compiler could use a not-all-zeroes bit pattern to represent a NULL pointer, if it were willing to do appropriate pushups when casting between pointers and integers. In practice, no one does, and no one ever will because almost no extant C code would run on their machine if they did. The spec-required casting behavior would negate any possible win from using such a representation anyway, I'd think. I concur that writing an ifdef for this is beyond silly. Just memset it and be done. regards, tom lane From glennrp at comcast.net Fri Feb 6 05:13:45 2009 From: glennrp at comcast.net (glennrp at comcast.net) Date: Fri, 6 Feb 2009 05:13:45 +0000 (UTC) Subject: [Png-mng-security] libpng-1.2.35beta03 In-Reply-To: <1400024207.1812281233897168560.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> Message-ID: <875560825.1812371233897225112.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> I've posted libpng-1.2.35beta03 at http://www.simplesystems.org/users/glennrp/sbo/lp1235b03 It uses png_memset() to initialize the pointer arrays. Glenn From newt at pobox.com Fri Feb 6 06:06:26 2009 From: newt at pobox.com (Greg Roelofs) Date: Thu, 5 Feb 2009 22:06:26 -0800 Subject: [Png-mng-security] libpng-1.2.35beta03 In-Reply-To: <875560825.1812371233897225112.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> Message-ID: <200902060606.n1666Q28024149@bolt.sonic.net> > I've posted libpng-1.2.35beta03 at > http://www.simplesystems.org/users/glennrp/sbo/lp1235b03 > It uses png_memset() to initialize the pointer arrays. Haven't checked the code, but I noticed in one of the earlier e-mails that some pseudocode had an incorrect memset() size (missing sizeof()). Is that fixed/avoided in this beta? (I think it was the message with the ifdef in it.) Greg From glennrp at comcast.net Fri Feb 6 12:03:37 2009 From: glennrp at comcast.net (glennrp at comcast.net) Date: Fri, 6 Feb 2009 12:03:37 +0000 (UTC) Subject: [Png-mng-security] libpng-1.2.35beta03 In-Reply-To: <200902060606.n1666Q28024149@bolt.sonic.net> Message-ID: <15664790.12651233921817164.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> ----- Original Message ----- From: "Greg Roelofs" To: glennrp at comcast.net Cc: png-mng-security at simple.dallas.tx.us Sent: Friday, February 6, 2009 1:06:26 AM GMT -05:00 US/Canada Eastern Subject: Re: [Png-mng-security] libpng-1.2.35beta03 > I've posted libpng-1.2.35beta03 at > http://www.simplesystems.org/users/glennrp/sbo/lp1235b03 > It uses png_memset() to initialize the pointer arrays. Haven't checked the code, but I noticed in one of the earlier e-mails that some pseudocode had an incorrect memset() size (missing sizeof()). Is that fixed/avoided in this beta? (I think it was the message with the ifdef in it.) Greg I don't remember. I would have to look at the code. Glenn From jbowler at acm.org Fri Feb 6 17:26:02 2009 From: jbowler at acm.org (John Bowler) Date: Fri, 6 Feb 2009 09:26:02 -0800 Subject: [Png-mng-security] libpng-1.2.35beta03 In-Reply-To: <15664790.12651233921817164.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> References: <200902060606.n1666Q28024149@bolt.sonic.net> <15664790.12651233921817164.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> Message-ID: <008401c9887f$fcca24a0$f65e6de0$@org> From: glennrp at comcast.net > I've posted libpng-1.2.35beta03 at > http://www.simplesystems.org/users/glennrp/sbo/lp1235b03 > It uses png_memset() to initialize the pointer arrays. >From: "Greg Roelofs" >>...earlier ... pseudocode had an incorrect memset() >>size (missing sizeof()). I checked the diff: http://www.simplesystems.org/users/glennrp/sbo/lp1235b03/libpng-1.2.35beta03 -1.2.34-diff.txt It seems fine. That's the downside to using the "sizeof" operator. It's very hard to maintain code of the form: png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr, (png_uint_32)(num * png_sizeof(png_uint_16p ))); png_memset(png_ptr->gamma_16_to_1, 0, num * png_sizeof(png_uint_16p)); The problem is ensuring that the size calculation: "num * png_sizeof(png_uint_16p)" remains the same in both cases as the code is edited. An improvement would be to create and use either "png_zalloc" (like malloc but zeros the result) or png_calloc (takes a count like calloc and zeros the result.) Then all the allocated memory would be guaranteed to be set to zero. My personal opinion is that code that has security requirements should *never* use malloc for data structures. Of course libpng should use malloc for line buffers, because there are performance implications when bytes of line buffers are touched, but line buffers of garbage can be handled correctly by libpng. John Bowler From glennrp at comcast.net Fri Feb 6 19:05:31 2009 From: glennrp at comcast.net (glennrp at comcast.net) Date: Fri, 6 Feb 2009 19:05:31 +0000 (UTC) Subject: [Png-mng-security] libpng-1.2.35beta03 In-Reply-To: <008401c9887f$fcca24a0$f65e6de0$@org> Message-ID: <86044954.231601233947131551.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> An improvement would be to create and use either "png_zalloc" (like malloc but zeros the result) or png_calloc (takes a count like calloc and zeros the result.) Then all the allocated memory would be guaranteed to be set to zero. Not a bad idea, but let's save it for libpng-1.4.0 We have png_zalloc() but I seem to recall there was some frowning upon it a while back. I don't remember why. Maybe it was simply because we were zeroing some arrays that are perfectly safe uninitialized. Glenn From newt at pobox.com Mon Feb 9 21:42:30 2009 From: newt at pobox.com (Greg Roelofs) Date: Mon, 9 Feb 2009 13:42:30 -0800 Subject: [Png-mng-security] libpng: memory overwrite (png_check_keyword()) [SuSE] Message-ID: <200902092142.n19LgUJ8018508@bolt.sonic.net> Is this an old bug that SuSE just got around to fixing, or a new one that hasn't been reported here? http://lwn.net/Alerts/317619/ - libpng This update of libpng fixes the function png_check_keyword() that allowed setting arbitrary bytes in the process memory to 0. (CVE-2008-5907) Affected products: openSUSE 10.3-11.1, OES, SLES9, NLD9, SLES 10, SLED10 Greg From newt at pobox.com Mon Feb 9 21:47:52 2009 From: newt at pobox.com (Greg Roelofs) Date: Mon, 9 Feb 2009 13:47:52 -0800 Subject: [Png-mng-security] libpng: memory overwrite (png_check_keyword()) [SuSE] In-Reply-To: <200902092142.n19LgUJ8018508@bolt.sonic.net> Message-ID: <200902092147.n19Llq9l025700@bolt.sonic.net> > Is this an old bug that SuSE just got around to fixing, or a new one that > hasn't been reported here? Hmmm, looks like maybe it's the one Jon Foster reported on png-mng-implement on 26 November. He never got a response, and I didn't check the release notes to see if it was quietly addressed in the meantime. Yes? No? Greg From glennrp at comcast.net Mon Feb 9 22:53:02 2009 From: glennrp at comcast.net (glennrp at comcast.net) Date: Mon, 9 Feb 2009 22:53:02 +0000 (UTC) Subject: [Png-mng-security] libpng: memory overwrite (png_check_keyword()) [SuSE] In-Reply-To: <200902092147.n19Llq9l025700@bolt.sonic.net> Message-ID: <943414630.393351234219982524.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> ----- Original Message ----- From: "Greg Roelofs" To: png-mng-security at simple.dallas.tx.us Sent: Monday, February 9, 2009 4:47:52 PM GMT -05:00 US/Canada Eastern Subject: Re: [Png-mng-security] libpng: memory overwrite (png_check_keyword()) [SuSE] > Is this an old bug that SuSE just got around to fixing, or a new one that > hasn't been reported here? Hmmm, looks like maybe it's the one Jon Foster reported on png-mng-implement on 26 November. He never got a response, and I didn't check the release notes to see if it was quietly addressed in the meantime. Yes? No? Greg _______________________________________________ I suppose it's this one: version 1.2.34beta05 [December 5, 2008] Removed redundant check for key==NULL before calling png_check_keyword() to ensure that new_key gets initialized and removed extra warning (Arvan Pritchard). Glenn From newt at pobox.com Tue Feb 10 19:08:09 2009 From: newt at pobox.com (Greg Roelofs) Date: Tue, 10 Feb 2009 11:08:09 -0800 Subject: [Png-mng-security] libpng: memory overwrite (png_check_keyword()) [SuSE] In-Reply-To: <943414630.393351234219982524.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> Message-ID: <200902101908.n1AJ89cV002380@bolt.sonic.net> > I suppose it's this one: > version 1.2.34beta05 [December 5, 2008] > Removed redundant check for key==NULL before calling png_check_keyword() > to ensure that new_key gets initialized and removed extra warning > (Arvan Pritchard). No, it's internal to png_check_keyword(). In any case, it's fixed in the current 1.2 beta: (*new_key)[79] = '\0'; (It was reported in 1.0.41.) Greg From glennrp at comcast.net Thu Feb 12 13:23:37 2009 From: glennrp at comcast.net (glennrp at comcast.net) Date: Thu, 12 Feb 2009 13:23:37 +0000 (UTC) Subject: [Png-mng-security] libpng-1.0.43rc01 and libpng-1.2.35rc01 available Message-ID: <8013846.1688371234445017373.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> libpng-1.0.43rc01 is available at http://www.simplesystems.org/users/glennrp/sbo/lp1043r01 and libpng-1.2.35rc01 is available at http://www.simplesystems.org/users/glennrp/sbo/lp1235r01 There are no changes from beta03. Glenn From glennrp at gmail.com Fri Feb 13 00:08:39 2009 From: glennrp at gmail.com (Glenn Randers-Pehrson) Date: Thu, 12 Feb 2009 19:08:39 -0500 Subject: [Png-mng-security] libpng-1.2.35rc02 and libpng-1.0.43rc02 are available Message-ID: libpng-1.2.35rc02 and libpng-1.0.43rc02 are available from http://www.simplesystems.org/users/glennrp/sbo/lp1235r02 There was a typo in one of the png_memset() calls, thereby validating John Bowler's assertion that png_calloc() would be easier to maintain than png_malloc();png_memset(). I think the problem was only cosmetic. png_sizeof(png_colorp) should have been png_sizeof(png_charp). Both have the value 4, I believe. Glenn From glennrp at gmail.com Sat Feb 14 16:41:28 2009 From: glennrp at gmail.com (Glenn Randers-Pehrson) Date: Sat, 14 Feb 2009 11:41:28 -0500 Subject: [Png-mng-security] libpng-1.4.0beta48 is available Message-ID: libpng-1.4.0beta48 is available at http://www.simplesystems.org/users/glennrp/sbo/lp140b48 This implements png_calloc() and uses it wherever libpng-1.2.35rc03 uses "png_malloc();png_memset()". I plan to release libpng-1.2.35, 1.0.43, and 1.4.0beta48 publicly on Thursday 19 February 2009. Glenn From glennrp at gmail.com Wed Feb 18 12:47:59 2009 From: glennrp at gmail.com (Glenn Randers-Pehrson) Date: Wed, 18 Feb 2009 07:47:59 -0500 Subject: [Png-mng-security] Order of building gamma_16_table and png_do_chop Message-ID: In pngrtran.c we have this: #if defined(PNG_READ_GAMMA_SUPPORTED) if ((png_ptr->transformations & PNG_GAMMA) && #if defined(PNG_READ_BACKGROUND_SUPPORTED) !((png_ptr->transformations & PNG_BACKGROUND) && ((png_ptr->num_trans != 0) || (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) && #endif (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)) png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1, png_ptr->gamma_table, png_ptr->gamma_16_table, png_ptr->gamma_shift); #endif #if defined(PNG_READ_16_TO_8_SUPPORTED) if (png_ptr->transformations & PNG_16_TO_8) png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1); #endif Later on, when building gamma tables, we use png_info->depth to decide whether to build the 16-bit gamma tables or the 8-bit table. png_info->depth gets set in png_do_chop(). This means that the 16-bit gamma tables get built even if the user has called png_set_strip_16(). That seems to me to be a waste, and it unnecessarily exposes applications to the current memory allocation vulnerability. For example, it makes mozilla/firefox vulnerable, even though it uses png_set_strip_16((). Is there any reason not to swap these two blocks of code in libpng-1.4.0beta, to avoid unnecessarily building the 16-bit gamma tables? Glenn From glennrp at comcast.net Wed Feb 18 21:44:11 2009 From: glennrp at comcast.net (glennrp at comcast.net) Date: Wed, 18 Feb 2009 21:44:11 +0000 (UTC) Subject: [Png-mng-security] libpng-1.0.43 and libpng-1.2.35 ready to go In-Reply-To: <1226855479.1604341234993395731.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> Message-ID: <9610616.1604871234993451934.JavaMail.root@sz0023a.westchester.pa.mail.comcast.net> Libpng-1.0.43 and libpng-1.2.35 are ready for release. You can preview them at http://www.simplesystems.org/users/glennrp/sbo/lpng1235 http://www.simplesystems.org/users/glennrp/sbo/lpng1043 I've included a *ADVISORY* file and a patch set that should work against versions since 1.0.19 and 1.2.9. Here is the advisory: Libpng-1.2.34 ADVISORY 19 February 2009 A vulnerability has been reported in libpng-1.2.34. The bug is of the form malloc an array of N elements for (i=0; i Message-ID: <2023321167.65831235050785480.JavaMail.root@zmail01.collab.prod.int.phx2.redhat.com> Hello, I notice that the CVE id which was assigned to the arbitrary free() wasn't communicated to you by Tavis. It was assigned CVE-2009-0040. The Fedora updates will reference this ID, as I suspect will a number of other vendor-sec member update. Thanks. -- JB