Re: tiff / CVE-2018-7456

2018-03-17 Thread Hugo Lefeuvre
So, after some debugging on CVE-2018-7456, I start to get the feeling to
understand the issue.

Here are my conclusions for the moment:

* In any case, the transfer function should not care about other
  channels defined by ExtraSamples (see 2nd and 3rd paragraphs of
  TransferFunction entry, page 84 of the specification), so something
  like the following patch should be a first step:

--- a/libtiff/tif_print.c   2018-03-17 21:56:47.0 +0100
+++ b/libtiff/tif_print.c   2018-03-17 22:05:58.446092016 +0100
@@ -546,7 +546,7 @@
uint16 i;
fprintf(fd, "%2ld: %5u",
l, td->td_transferfunction[0][l]);
-   for (i = 1; i < td->td_samplesperpixel; i++)
+   for (i = 1; i < td->td_samplesperpixel - 
td->td_extrasamples; i++)
fprintf(fd, " %5u",
td->td_transferfunction[i][l]);
fputc('\n', fd);

But it's not enough. Why ?

* I discovered that td->td_samplesperpixel can have arbitrary size while
  td->td_extrasamples stays 0. It shouldn't be the case ! For instance
  the specification doesn't allow RGB with 4 channels and no ExtraSamples.
  And while it doesn't make any sense, libtiff won't notice it.

  I even tried RGB with 8 channels and no ExtraSamples and it worked too.

  So, what should be done ?

  For each PhotometricInterpretation type there is a 'standard' samples
  per pixel value (that is the samples per pixel value without extra samples:
  3 for RGB, etc). Let's name it (standard spp).

  So, what we should do is: If the actual td->td_samplesperpixel is higher
  than (standard spp), then we should assume that td->td_extrasamples is
  td->td_samplesperpixel - (standard spp), even if no ExtraSamples field
  was specified OR if the specified td->td_extrasamples was smaller.

  Obviously we should also take care of filling appropriate
  td->td_sampleinfo entries.

  For example, if an RGB image has td->td_samplesperpixel = 4, then
  td->td_extrasamples should be set to 1 (with arbitrary
  td->td_sampleinfo entry for example 0 - Unspecified data).

Does it work now ?

I think so ! I didn't write the second part of the patch and will wait
for feedback. But you can convince yourself that it doesn't crash anymore
by modifying the sample to add an ExtraSamples = 1 field (using
"tiffset -s 338 1 0 $(sample)" for example).

Link to the specification:
https://www.itu.int/itudoc/itu-t/com16/tiff-fx/docs/tiff6.pdf

Regards,
 Hugo

-- 
 Hugo Lefeuvre (hle)|www.owl.eu.com
4096/ 9C4F C8BF A4B0 8FC5 48EB 56B8 1962 765B B9A8 BACA


signature.asc
Description: PGP signature


Re: tiff / CVE-2018-7456

2018-03-17 Thread Brian May
Hugo Lefeuvre  writes:

> So, in fact it may very well be that the size of the TransferFunction table
> is always at most 3 rows and this definition is right.

Is the code that loads the transfer function safe? Is there any
possibility of tricking the loading function to try and set the 4th row?
-- 
Brian May 



Re: tiff / CVE-2018-7456

2018-03-17 Thread Brian May
Hugo Lefeuvre  writes:

> Sure ? To me it looked like three entries are provided, but the fourth
> (td->td_transferfunction[3]) isn't.

I was about to write justification for how I was absolutely sure of
this.

Then I realized the loop is:

for (i = 1; i < td->td_samplesperpixel; i++)

i.e. it starts at index 1, not index 0 as I had expected. Oops. So the
third iteration is actually referencing the 4th item.

Out by one error. Sorry.
-- 
Brian May 



Re: tiff / CVE-2018-7456

2018-03-17 Thread Brian May
Hugo Lefeuvre  writes:

> So, after some debugging on CVE-2018-7456, I start to get the feeling to
> understand the issue.
>
> Here are my conclusions for the moment:
>
> * In any case, the transfer function should not care about other
>   channels defined by ExtraSamples (see 2nd and 3rd paragraphs of
>   TransferFunction entry, page 84 of the specification), so something
>   like the following patch should be a first step:
>
> --- a/libtiff/tif_print.c 2018-03-17 21:56:47.0 +0100
> +++ b/libtiff/tif_print.c 2018-03-17 22:05:58.446092016 +0100
> @@ -546,7 +546,7 @@
>   uint16 i;
>   fprintf(fd, "%2ld: %5u",
>   l, td->td_transferfunction[0][l]);
> - for (i = 1; i < td->td_samplesperpixel; i++)
> + for (i = 1; i < td->td_samplesperpixel - 
> td->td_extrasamples; i++)
>   fprintf(fd, " %5u",
>   td->td_transferfunction[i][l]);
>   fputc('\n', fd);
>
> But it's not enough. Why ?
>
> * I discovered that td->td_samplesperpixel can have arbitrary size while
>   td->td_extrasamples stays 0. It shouldn't be the case ! For instance
>   the specification doesn't allow RGB with 4 channels and no ExtraSamples.
>   And while it doesn't make any sense, libtiff won't notice it.
>
>   I even tried RGB with 8 channels and no ExtraSamples and it worked too.
>
>   So, what should be done ?
>
>   For each PhotometricInterpretation type there is a 'standard' samples
>   per pixel value (that is the samples per pixel value without extra samples:
>   3 for RGB, etc). Let's name it (standard spp).
>
>   So, what we should do is: If the actual td->td_samplesperpixel is higher
>   than (standard spp), then we should assume that td->td_extrasamples is
>   td->td_samplesperpixel - (standard spp), even if no ExtraSamples field
>   was specified OR if the specified td->td_extrasamples was smaller.

Seems good to me. I would suggest sending a patch upstream, see what
they think.

Also I tend to think some some of assertion might be a good idea,
something that aborts if

(td->td_samplesperpixel - td->td_extrasamples) > 3

As aborting early is probably better then screwing up memory.


For reference, the next value in the struct is:

typedef struct {
[...]

/* Colorimetry parameters */
uint16* td_transferfunction[3];
float*  td_refblackwhite;

[...]
} TIFFDirectory;

So I am guessing when you access td_transferfunction[3], you are
actually accessing td_refblackwhite, which - surprise surprise - happens
to be NULL.
-- 
Brian May 



Review graphite2

2018-03-17 Thread Abhijith PA
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA512

Hello.

I prepared LTS security update for graphite2[1]. Debdiff is attached.
All tests ran successfully. Please review.



- -abhijith

[1]
https://mentors.debian.net/debian/pool/main/g/graphite2/graphite2_1.3.10
- -1~deb7u2.dsc
-BEGIN PGP SIGNATURE-

iQIzBAEBCgAdFiEE7xPqJqaY/zX9fJAuhj1N8u2cKO8FAlquArUACgkQhj1N8u2c
KO8j3A//QeA2nOPNG/j2GJ+j+LSKWRt/khRoL2vY2YpXcIRCJSACCVZT+LqOezLF
BfMTa6TEeu9zXfRQpuAoHBZtOmSbPaldi6flT5eJ469mF/tqBY7Bdx7us5/bmni0
YxAz7tYp6oU3hBUz2HqEgH293cm7+wG7mLjSGG5EVcuFCIwRud0Y7/s0YQV7/xJ6
9YBUnzUPCZ/h0jcZNXpUmo2QWtvvaFj1vg5KQQ3JvKGGdVly9cJse+E1Z8FLih46
4ZNCNMjF3AWnn2MyVk1b9Ej8kr69CsrZqxkRpnVovsg2N7VUuwp+SiYndlBfqTvu
MIr84/NPfCG9F7V8kyO486QRsB8fHYGA4+HnTL/iGZYgEIeRJgIyAQqaOGRhhrgU
NASuJydVTtRiVQuL9mrx/S6lfUFTaYRRGMm7SagDxeHN1wR1SuXxjwm4LOqrRzHD
eR4AxYJmnu9iMZkYaYIsy9VfdimAF63l8mCfVEede1zuug12YunWjUQkZA1xRnjM
xD67lo2RQWx6FMb7uiLt6/EUP6VouXoVJi2jt/BBpXgx66gWLQOb2xvDQAI3pQP2
C4AbI9H+Uvyjbcufe1GusKXkBGvny3LWkQiAwuScfkUMNlhemSsc83wy4jRTgRyb
NGfWN85t8eQMlrviVhdZz0YcFjBMRx5qe9iA+nUL5eANbKSz2RY=
=SOWG
-END PGP SIGNATURE-
diff -Nru graphite2-1.3.10/debian/changelog graphite2-1.3.10/debian/changelog
--- graphite2-1.3.10/debian/changelog   2017-07-04 20:48:57.0 +0530
+++ graphite2-1.3.10/debian/changelog   2018-03-17 08:44:25.0 +0530
@@ -1,3 +1,11 @@
+graphite2 (1.3.10-1~deb7u2) wheezy-security; urgency=high
+
+  * Non-maintainer upload by the LTS Team.
+  * Fix CVE-2018-7999: NULL pointer dereference vulnerability
+(closes: #892590)
+
+ -- Abhijith PA   Sat, 17 Mar 2018 08:44:25 +0530
+
 graphite2 (1.3.10-1~deb7u1) wheezy-security; urgency=high
 
   * Non-maintainer upload by the LTS team.
diff -Nru graphite2-1.3.10/debian/patches/CVE-2018-7999.patch 
graphite2-1.3.10/debian/patches/CVE-2018-7999.patch
--- graphite2-1.3.10/debian/patches/CVE-2018-7999.patch 1970-01-01 
05:30:00.0 +0530
+++ graphite2-1.3.10/debian/patches/CVE-2018-7999.patch 2018-03-17 
08:44:25.0 +0530
@@ -0,0 +1,208 @@
+Description: Fix CVE-2018-7999
+ a NULL pointer dereference vulnerability was found in Segment.cpp during a 
+ dumbRendering operation, which may allow attackers to cause a denial of 
service
+ or possibly have unspecified other impact via a crafted .ttf file.
+
+Author: Abhijith PA 
+Origin: 
https://github.com/silnrsi/graphite/commit/db132b4731a9b4c9534144ba3a18e65b390e9ff6
+Bug: https://github.com/silnrsi/graphite/issues/22
+Bug-Debian: https://bugs.debian.org/892590
+Last-Update: 2018-03-18
+
+--- graphite2-1.3.10.orig/src/GlyphCache.cpp
 graphite2-1.3.10/src/GlyphCache.cpp
+@@ -84,7 +84,7 @@ const SlantBox SlantBox::empty = {0,0,0,
+ class GlyphCache::Loader
+ {
+ public:
+-Loader(const Face & face, const bool dumb_font);//return result 
indicates success. Do not use if failed.
++Loader(const Face & face);//return result indicates success. Do not 
use if failed.
+ 
+ operator bool () const throw();
+ unsigned short int units_per_em() const throw();
+@@ -115,7 +115,7 @@ private:
+ 
+ 
+ GlyphCache::GlyphCache(const Face & face, const uint32 face_options)
+-: _glyph_loader(new Loader(face, bool(face_options & gr_face_dumbRendering))),
++: _glyph_loader(new Loader(face)),
+   _glyphs(_glyph_loader && *_glyph_loader && _glyph_loader->num_glyphs()
+ ? grzeroalloc(_glyph_loader->num_glyphs()) : 0),
+   _boxes(_glyph_loader && _glyph_loader->has_boxes() && 
_glyph_loader->num_glyphs()
+@@ -239,7 +239,7 @@ const GlyphFace *GlyphCache::glyph(unsig
+ 
+ 
+ 
+-GlyphCache::Loader::Loader(const Face & face, const bool dumb_font)
++GlyphCache::Loader::Loader(const Face & face)
+ : _head(face, Tag::head),
+   _hhea(face, Tag::hhea),
+   _hmtx(face, Tag::hmtx),
+@@ -265,52 +265,49 @@ GlyphCache::Loader::Loader(const Face &
+ return;
+ }
+ 
+-if (!dumb_font)
++if ((m_pGlat = Face::Table(face, Tag::Glat, 0x0003)) == NULL
++|| (m_pGloc = Face::Table(face, Tag::Gloc)) == NULL
++|| m_pGloc.size() < 8)
+ {
+-if ((m_pGlat = Face::Table(face, Tag::Glat, 0x0003)) == NULL
+-|| (m_pGloc = Face::Table(face, Tag::Gloc)) == NULL
+-|| m_pGloc.size() < 8)
+-{
+-_head = Face::Table();
+-return;
+-}
+-const byte* p = m_pGloc;
+-int   version = be::read(p);
+-const uint16flags = be::read(p);
+-_num_attrs = be::read(p);
+-// We can accurately calculate the number of attributed glyphs by
+-//  subtracting the length of the attribids array (numAttribs long if 
present)
+-//  and dividing by either 2 or 4 depending on shor or lonf format
+-_long_fmt  = flags & 1;
+-int tmpnumgattrs   = (m_pGloc.size()
+-   - (p - m_pGloc)
+-   - sizeof(uint16)*(flags & 0x2 ? _num_attrs 
: 0))
+-   / (_long_fmt ? size