Patchwork gnu: mupdf: Fix CVE-2016-8674.

login
register
mail settings
Submitter Kei Yamashita
Date Oct. 25, 2016, 4:53 p.m.
Message ID <87twc0s73r.fsf@openmailbox.org>
Download mbox | patch
Permalink /patch/16807/
State New
Headers show

Comments

Kei Yamashita - Oct. 25, 2016, 4:53 p.m.
Fix for https://blogs.gentoo.org/ago/2016/09/22/mupdf-use-after-free-in-pdf_to_num-pdf-object-c/.
From 97312c3c9e13688081aa513d1c94a9fff1274f75 Mon Sep 17 00:00:00 2001
From: Kei Kebreau <kei@openmailbox.org>
Date: Tue, 25 Oct 2016 12:49:52 -0400
Subject: [PATCH] gnu: mupdf: Fix CVE-2016-8674.

* gnu/packages/patches/mupdf-CVE-2016-8674.patch: New file.
* gnu/local.mk (dist_patch_DATA): Add it.
* gnu/packages/pdf.scm (mupdf): Use it.
---
 gnu/local.mk                                   |   1 +
 gnu/packages/patches/mupdf-CVE-2016-8674.patch | 166 +++++++++++++++++++++++++
 gnu/packages/pdf.scm                           |   3 +-
 3 files changed, 169 insertions(+), 1 deletion(-)
 create mode 100644 gnu/packages/patches/mupdf-CVE-2016-8674.patch
Leo Famulari - Oct. 25, 2016, 5:12 p.m.
On Tue, Oct 25, 2016 at 12:53:28PM -0400, Kei Kebreau wrote:
> Fix for https://blogs.gentoo.org/ago/2016/09/22/mupdf-use-after-free-in-pdf_to_num-pdf-object-c/.

> From 97312c3c9e13688081aa513d1c94a9fff1274f75 Mon Sep 17 00:00:00 2001
> From: Kei Kebreau <kei@openmailbox.org>
> Date: Tue, 25 Oct 2016 12:49:52 -0400
> Subject: [PATCH] gnu: mupdf: Fix CVE-2016-8674.
> 
> * gnu/packages/patches/mupdf-CVE-2016-8674.patch: New file.
> * gnu/local.mk (dist_patch_DATA): Add it.
> * gnu/packages/pdf.scm (mupdf): Use it.

Thank you, please push!
Mark H Weaver - Oct. 26, 2016, 1:46 a.m.
Leo Famulari <leo@famulari.name> writes:

> On Tue, Oct 25, 2016 at 12:53:28PM -0400, Kei Kebreau wrote:
>> Fix for https://blogs.gentoo.org/ago/2016/09/22/mupdf-use-after-free-in-pdf_to_num-pdf-object-c/.
>
>> From 97312c3c9e13688081aa513d1c94a9fff1274f75 Mon Sep 17 00:00:00 2001
>> From: Kei Kebreau <kei@openmailbox.org>
>> Date: Tue, 25 Oct 2016 12:49:52 -0400
>> Subject: [PATCH] gnu: mupdf: Fix CVE-2016-8674.
>> 
>> * gnu/packages/patches/mupdf-CVE-2016-8674.patch: New file.
>> * gnu/local.mk (dist_patch_DATA): Add it.
>> * gnu/packages/pdf.scm (mupdf): Use it.
>
> Thank you, please push!

mupdf-CVE-2016-8674.patch fails to apply:

  https://hydra.gnu.org/build/1581228/nixlog/2/tail-reload

Kei, did you test this?

      Mark
Kei Yamashita - Oct. 26, 2016, 3:49 a.m.
Mark H Weaver <mhw@netris.org> writes:

> Leo Famulari <leo@famulari.name> writes:
>
>> On Tue, Oct 25, 2016 at 12:53:28PM -0400, Kei Kebreau wrote:
>>> Fix for
>>> https://blogs.gentoo.org/ago/2016/09/22/mupdf-use-after-free-in-pdf_to_num-pdf-object-c/.
>>
>>> From 97312c3c9e13688081aa513d1c94a9fff1274f75 Mon Sep 17 00:00:00 2001
>>> From: Kei Kebreau <kei@openmailbox.org>
>>> Date: Tue, 25 Oct 2016 12:49:52 -0400
>>> Subject: [PATCH] gnu: mupdf: Fix CVE-2016-8674.
>>> 
>>> * gnu/packages/patches/mupdf-CVE-2016-8674.patch: New file.
>>> * gnu/local.mk (dist_patch_DATA): Add it.
>>> * gnu/packages/pdf.scm (mupdf): Use it.
>>
>> Thank you, please push!
>
> mupdf-CVE-2016-8674.patch fails to apply:
>
>   https://hydra.gnu.org/build/1581228/nixlog/2/tail-reload
>
> Kei, did you test this?
>
>       Mark
I did not. It was a bad slip up, as I tested all of the rest of my
patches today. I'll be significantly more careful with future security
commits.

Is it frowned upon to revert that commit on its own (it's the third to
last commit as I write this), or should I attempt to patch on top of it?
Mark H Weaver - Oct. 26, 2016, 9:25 a.m.
Kei Kebreau <kei@openmailbox.org> writes:

> Mark H Weaver <mhw@netris.org> writes:
>
>> Leo Famulari <leo@famulari.name> writes:
>>
>>> On Tue, Oct 25, 2016 at 12:53:28PM -0400, Kei Kebreau wrote:
>>>> Fix for
>>>> https://blogs.gentoo.org/ago/2016/09/22/mupdf-use-after-free-in-pdf_to_num-pdf-object-c/.
>>>
>>>> From 97312c3c9e13688081aa513d1c94a9fff1274f75 Mon Sep 17 00:00:00 2001
>>>> From: Kei Kebreau <kei@openmailbox.org>
>>>> Date: Tue, 25 Oct 2016 12:49:52 -0400
>>>> Subject: [PATCH] gnu: mupdf: Fix CVE-2016-8674.
>>>> 
>>>> * gnu/packages/patches/mupdf-CVE-2016-8674.patch: New file.
>>>> * gnu/local.mk (dist_patch_DATA): Add it.
>>>> * gnu/packages/pdf.scm (mupdf): Use it.
>>>
>>> Thank you, please push!
>>
>> mupdf-CVE-2016-8674.patch fails to apply:
>>
>>   https://hydra.gnu.org/build/1581228/nixlog/2/tail-reload
>>
>> Kei, did you test this?
>>
>>       Mark
> I did not. It was a bad slip up, as I tested all of the rest of my
> patches today. I'll be significantly more careful with future security
> commits.
>
> Is it frowned upon to revert that commit on its own (it's the third to
> last commit as I write this), or should I attempt to patch on top of it?

Either way is fine with me.

     Thanks!
       Mark

Patch

diff --git a/gnu/local.mk b/gnu/local.mk
index 0d400e9..53c2bda 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -711,6 +711,7 @@  dist_patch_DATA =						\
   %D%/packages/patches/mupdf-build-with-openjpeg-2.1.patch	\
   %D%/packages/patches/mupdf-CVE-2016-6265.patch		\
   %D%/packages/patches/mupdf-CVE-2016-6525.patch		\
+  %D%/packages/patches/mupdf-CVE-2016-8674.patch		\
   %D%/packages/patches/mupen64plus-ui-console-notice.patch	\
   %D%/packages/patches/musl-CVE-2016-8859.patch			\
   %D%/packages/patches/mutt-store-references.patch		\
diff --git a/gnu/packages/patches/mupdf-CVE-2016-8674.patch b/gnu/packages/patches/mupdf-CVE-2016-8674.patch
new file mode 100644
index 0000000..62e4a02
--- /dev/null
+++ b/gnu/packages/patches/mupdf-CVE-2016-8674.patch
@@ -0,0 +1,166 @@ 
+Fix CVE-2016-8674 (use-after-free in pdf_to_num()).
+
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-8674
+https://security-tracker.debian.org/tracker/CVE-2016-8674
+
+Patch copied from upstream source repository:
+http://git.ghostscript.com/?p=mupdf.git;h=1e03c06456d997435019fb3526fa2d4be7dbc6ec
+
+diff --git a/include/mupdf/pdf/document.h b/include/mupdf/pdf/document.h
+index aabf05f..0078c4a 100644
+--- a/include/mupdf/pdf/document.h
++++ b/include/mupdf/pdf/document.h
+@@ -269,6 +269,10 @@ struct pdf_document_s
+ 		fz_hash_table *images;
+ 		fz_hash_table *fonts;
+ 	} resources;
++
++	int orphans_max;
++	int orphans_count;
++	pdf_obj **orphans;
+ };
+ 
+ /*
+diff --git a/include/mupdf/pdf/object.h b/include/mupdf/pdf/object.h
+index 5bc3dca..bf57455 100644
+--- a/include/mupdf/pdf/object.h
++++ b/include/mupdf/pdf/object.h
+@@ -110,6 +110,7 @@ pdf_obj *pdf_dict_gets(fz_context *ctx, pdf_obj *dict, const char *key);
+ pdf_obj *pdf_dict_getsa(fz_context *ctx, pdf_obj *dict, const char *key, const char *abbrev);
+ void pdf_dict_put(fz_context *ctx, pdf_obj *dict, pdf_obj *key, pdf_obj *val);
+ void pdf_dict_put_drop(fz_context *ctx, pdf_obj *dict, pdf_obj *key, pdf_obj *val);
++void pdf_dict_get_put_drop(fz_context *ctx, pdf_obj *dict, pdf_obj *key, pdf_obj *val, pdf_obj **old_val);
+ void pdf_dict_puts(fz_context *ctx, pdf_obj *dict, const char *key, pdf_obj *val);
+ void pdf_dict_puts_drop(fz_context *ctx, pdf_obj *dict, const char *key, pdf_obj *val);
+ void pdf_dict_putp(fz_context *ctx, pdf_obj *dict, const char *path, pdf_obj *val);
+diff --git a/source/pdf/pdf-object.c b/source/pdf/pdf-object.c
+index b4e33f3..1c19ba4 100644
+--- a/source/pdf/pdf-object.c
++++ b/source/pdf/pdf-object.c
+@@ -1265,11 +1265,14 @@ pdf_dict_geta(fz_context *ctx, pdf_obj *obj, pdf_obj *key, pdf_obj *abbrev)
+ 	return pdf_dict_get(ctx, obj, abbrev);
+ }
+ 
+-void
+-pdf_dict_put(fz_context *ctx, pdf_obj *obj, pdf_obj *key, pdf_obj *val)
++static void
++pdf_dict_get_put(fz_context *ctx, pdf_obj *obj, pdf_obj *key, pdf_obj *val, pdf_obj **old_val)
+ {
+ 	int i;
+ 
++	if (old_val)
++		*old_val = NULL;
++
+ 	RESOLVE(obj);
+ 	if (!OBJ_IS_DICT(obj))
+ 		fz_throw(ctx, FZ_ERROR_GENERIC, "not a dict (%s)", pdf_objkindstr(obj));
+@@ -1295,7 +1298,10 @@ pdf_dict_put(fz_context *ctx, pdf_obj *obj, pdf_obj *key, pdf_obj *val)
+ 		{
+ 			pdf_obj *d = DICT(obj)->items[i].v;
+ 			DICT(obj)->items[i].v = pdf_keep_obj(ctx, val);
+-			pdf_drop_obj(ctx, d);
++			if (old_val)
++				*old_val = d;
++			else
++				pdf_drop_obj(ctx, d);
+ 		}
+ 	}
+ 	else
+@@ -1316,10 +1322,27 @@ pdf_dict_put(fz_context *ctx, pdf_obj *obj, pdf_obj *key, pdf_obj *val)
+ }
+ 
+ void
++pdf_dict_put(fz_context *ctx, pdf_obj *obj, pdf_obj *key, pdf_obj *val)
++{
++	pdf_dict_get_put(ctx, obj, key, val, NULL);
++}
++
++void
+ pdf_dict_put_drop(fz_context *ctx, pdf_obj *obj, pdf_obj *key, pdf_obj *val)
+ {
+ 	fz_try(ctx)
+-		pdf_dict_put(ctx, obj, key, val);
++		pdf_dict_get_put(ctx, obj, key, val, NULL);
++	fz_always(ctx)
++		pdf_drop_obj(ctx, val);
++	fz_catch(ctx)
++		fz_rethrow(ctx);
++}
++
++void
++pdf_dict_get_put_drop(fz_context *ctx, pdf_obj *obj, pdf_obj *key, pdf_obj *val, pdf_obj **old_val)
++{
++	fz_try(ctx)
++		pdf_dict_get_put(ctx, obj, key, val, old_val);
+ 	fz_always(ctx)
+ 		pdf_drop_obj(ctx, val);
+ 	fz_catch(ctx)
+diff --git a/source/pdf/pdf-repair.c b/source/pdf/pdf-repair.c
+index 690bf15..167f609 100644
+--- a/source/pdf/pdf-repair.c
++++ b/source/pdf/pdf-repair.c
+@@ -260,6 +260,27 @@ pdf_repair_obj_stm(fz_context *ctx, pdf_document *doc, int stm_num)
+ 	}
+ }
+ 
++static void
++orphan_object(fz_context *ctx, pdf_document *doc, pdf_obj *obj)
++{
++	if (doc->orphans_count == doc->orphans_max)
++	{
++		int new_max = (doc->orphans_max ? doc->orphans_max*2 : 32);
++
++		fz_try(ctx)
++		{
++			doc->orphans = fz_resize_array(ctx, doc->orphans, new_max, sizeof(*doc->orphans));
++			doc->orphans_max = new_max;
++		}
++		fz_catch(ctx)
++		{
++			pdf_drop_obj(ctx, obj);
++			fz_rethrow(ctx);
++		}
++	}
++	doc->orphans[doc->orphans_count++] = obj;
++}
++
+ void
+ pdf_repair_xref(fz_context *ctx, pdf_document *doc)
+ {
+@@ -528,12 +549,13 @@ pdf_repair_xref(fz_context *ctx, pdf_document *doc)
+ 			/* correct stream length for unencrypted documents */
+ 			if (!encrypt && list[i].stm_len >= 0)
+ 			{
++				pdf_obj *old_obj = NULL;
+ 				dict = pdf_load_object(ctx, doc, list[i].num);
+ 
+ 				length = pdf_new_int(ctx, doc, list[i].stm_len);
+-				pdf_dict_put(ctx, dict, PDF_NAME_Length, length);
+-				pdf_drop_obj(ctx, length);
+-
++				pdf_dict_get_put_drop(ctx, dict, PDF_NAME_Length, length, &old_obj);
++				if (old_obj)
++					orphan_object(ctx, doc, old_obj);
+ 				pdf_drop_obj(ctx, dict);
+ 			}
+ 		}
+diff --git a/source/pdf/pdf-xref.c b/source/pdf/pdf-xref.c
+index 7d21775..0cf20d4 100644
+--- a/source/pdf/pdf-xref.c
++++ b/source/pdf/pdf-xref.c
+@@ -1620,6 +1620,12 @@ pdf_drop_document_imp(fz_context *ctx, pdf_document *doc)
+ 
+ 		pdf_drop_resource_tables(ctx, doc);
+ 
++		for (i = 0; i < doc->orphans_count; i++)
++		{
++			pdf_drop_obj(ctx, doc->orphans[i]);
++		}
++		fz_free(ctx, doc->orphans);
++
+ 		fz_free(ctx, doc);
+ 	}
+ 	fz_always(ctx)
+-- 
+2.9.1
+
diff --git a/gnu/packages/pdf.scm b/gnu/packages/pdf.scm
index 461472a..42547df 100644
--- a/gnu/packages/pdf.scm
+++ b/gnu/packages/pdf.scm
@@ -489,7 +489,8 @@  extracting content or merging files.")
           "1k64pdapyj8a336jw3j61fhn0rp4q6az7d0dqp9r5n3d9rgwa5c0"))
         (patches (search-patches "mupdf-build-with-openjpeg-2.1.patch"
                                  "mupdf-CVE-2016-6265.patch"
-                                 "mupdf-CVE-2016-6525.patch"))
+                                 "mupdf-CVE-2016-6525.patch"
+                                 "mupdf-CVE-2016-8674.patch"))
         (modules '((guix build utils)))
         (snippet
             ;; Delete all the bundled libraries except for mujs, which is