From 97312c3c9e13688081aa513d1c94a9fff1274f75 Mon Sep 17 00:00:00 2001 From: Kei Kebreau 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 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 -- 2.10.1