After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 765094 - Test case for cve-2015-4491 is not MALLOC_CHECK_=2 safe
Test case for cve-2015-4491 is not MALLOC_CHECK_=2 safe
Status: RESOLVED FIXED
Product: gdk-pixbuf
Classification: Platform
Component: general
git master
Other Linux
: Normal normal
: ---
Assigned To: gdk-pixbuf-maint
gdk-pixbuf-maint
: 758104 778600 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2016-04-15 10:20 UTC by Dimitri John Ledkov
Modified: 2017-07-28 12:03 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
skip-perturb-for-cve-2015-4491-original-test.patch (928 bytes, patch)
2016-04-15 10:20 UTC, Dimitri John Ledkov
rejected Details | Review
gdk-pixbuf: Add gdk_pixbuf_calculate_rowstride() (3.52 KB, patch)
2017-07-26 15:20 UTC, Bastien Nocera
none Details | Review
bmp: Avoid allocating large buffers when not needed (2.78 KB, patch)
2017-07-26 15:20 UTC, Bastien Nocera
none Details | Review
gdk-pixbuf: Tighten rowstride overflow check (1.28 KB, patch)
2017-07-27 11:22 UTC, Bastien Nocera
committed Details | Review
gdk-pixbuf: Add gdk_pixbuf_calculate_rowstride() (3.51 KB, patch)
2017-07-27 11:22 UTC, Bastien Nocera
none Details | Review
bmp: Avoid allocating large buffers when not needed (2.78 KB, patch)
2017-07-27 11:22 UTC, Bastien Nocera
committed Details | Review
gdk-pixbuf: Add gdk_pixbuf_calculate_rowstride() (4.07 KB, patch)
2017-07-28 12:02 UTC, Bastien Nocera
committed Details | Review

Description Dimitri John Ledkov 2016-04-15 10:20:51 UTC
Created attachment 326078 [details] [review]
skip-perturb-for-cve-2015-4491-original-test.patch

Hello,

This is similar to:
https://bugzilla.gnome.org/show_bug.cgi?id=753908
https://bugzilla.gnome.org/show_bug.cgi?id=754387

But I am not sure.

It appears that functions to load the image in cve-2015-4491 are not MALLOC_CHECK_2=2 safe, and thus for carefully randomly chosen MALLOC_PERTURB_ the test case runs out of memory. There is a bodge fix in the already - which skips the test upon function returns ENOMEM. However, what I am arguing here, the amount of memory on the system does not matter, as even on systems with a lot of memory all of it is exhausted and before that function can return ENOMEM oomkiller kills the whole test binary for me on s390x.

Thus I conclude that gdk_pixbuf_new_from_resource_at_scale() is not MALLOC_PERTRUB_ safe. And instead of skipping the test all the time, it should be run without MALLOC_PERTURB_ or the gdk_pixbuf_new_from_resource_at_scale() should be fixed to support running under MALLOC_PERTURB_

I will attach my proposed patch, which temporarily turns off and restores MALLOC_PERTRUB_.

This is against 2.32.2

Regards,

Dimitri.
Comment 1 Dimitri John Ledkov 2016-04-15 10:21:45 UTC
One can probably also remove the
   if (skip_if_insufficient_memory (&err))
     return;
with proposed patch applied.
Comment 2 Dimitri John Ledkov 2016-04-15 10:54:31 UTC
For me the following values of MALLOC_PERTURB_ were good/bad:
# for i in `seq 256`; do export MALLOC_PERTURB_=$i; .libs/lt-cve-2015-4491>/dev/null && echo $i: good || echo $i: bad; done
1: bad
2: good
3: good
4: bad
5: bad
6: good
7: good
8: good
9: good
10: bad
11: good
12: good
13: good
14: bad
15: good
16: good
17: good
18: good

I gave up after that.
Comment 3 Bastien Nocera 2016-12-19 18:15:54 UTC
(In reply to Dimitri John Ledkov from comment #0)
<snip>
> Thus I conclude that gdk_pixbuf_new_from_resource_at_scale() is not
> MALLOC_PERTRUB_ safe. And instead of skipping the test all the time, it
> should be run without MALLOC_PERTURB_ or the
> gdk_pixbuf_new_from_resource_at_scale() should be fixed to support running
> under MALLOC_PERTURB_

The latter needs to happen.
Comment 4 Bastien Nocera 2017-07-26 14:49:10 UTC
The test fails because it can't allocate 5.7 gigs of RAM. With memory overcommit, and because the memory is never initialised, this would take a bit of time, but not that much.

The way to fix this problem is to avoid the allocation in the first place, as the (calculated) rowstride times the height would overflow.

We'd need a way to check the calculated rowstride:
        /* Always align rows to 32-bit boundaries */
        rowstride = (width * channels + 3) & ~3;
before allocating the pixbuf in src/io-bmp.c DecodeHeader()
Comment 5 Bastien Nocera 2017-07-26 14:49:17 UTC
*** Bug 778600 has been marked as a duplicate of this bug. ***
Comment 6 Bastien Nocera 2017-07-26 14:51:08 UTC
*** Bug 758104 has been marked as a duplicate of this bug. ***
Comment 7 Bastien Nocera 2017-07-26 15:20:17 UTC
Created attachment 356430 [details] [review]
gdk-pixbuf: Add gdk_pixbuf_calculate_rowstride()

To calculate the rowstride without allocating memory!
Comment 8 Bastien Nocera 2017-07-26 15:20:22 UTC
Created attachment 356431 [details] [review]
bmp: Avoid allocating large buffers when not needed

Avoid allocating nearly 6 gigs of data when parsing the CVE-2015-4491
test only to free it when we've calculated that the rowstride * height
would overflow by calculating the rowstride before doing the allocation,
using the new gdk_pixbuf_calculate_rowstride() helper.
Comment 9 Bastien Nocera 2017-07-26 15:22:03 UTC
Philip, if you want to check this for sanity. I probably forgot to update the API docs, and I would have preferred not making this public...
Comment 10 Tobias Mueller 2017-07-27 07:40:42 UTC
Review of attachment 356430 [details] [review]:

::: gdk-pixbuf/gdk-pixbuf.c
@@ +453,3 @@
+
+	/* Overflow? */
+	if (width > (G_MAXUINT - 3) / channels)

Is G_MAXUINT intentional?  I expected G_MAXINT due to the return type being a (signed) int.

Previously, the result was assigned to "rowstride" which used to be unsigned int, i.e. l448. Now, however, the result seems to a signed int.
Comment 11 Bastien Nocera 2017-07-27 10:46:29 UTC
(In reply to Tobias Mueller from comment #10)
> Review of attachment 356430 [details] [review] [review]:
> 
> ::: gdk-pixbuf/gdk-pixbuf.c
> @@ +453,3 @@
> +
> +	/* Overflow? */
> +	if (width > (G_MAXUINT - 3) / channels)
> 
> Is G_MAXUINT intentional?  I expected G_MAXINT due to the return type being
> a (signed) int.
> 
> Previously, the result was assigned to "rowstride" which used to be unsigned
> int, i.e. l448. Now, however, the result seems to a signed int.

This should be MAXINT, yes. Introduced in https://bugzilla.gnome.org/show_bug.cgi?id=777315
by the person I added as a reviewer ;)
Comment 12 Bastien Nocera 2017-07-27 11:22:07 UTC
Created attachment 356467 [details] [review]
gdk-pixbuf: Tighten rowstride overflow check

The rowstride is stored as an int, and is an int in the public API.
Making it an unsigned int for those calculations would increase
the limit, which would obviously cause problems when the calculated
value ends up between G_MAXUINT and G_MAXINT in the positives.
Comment 13 Bastien Nocera 2017-07-27 11:22:16 UTC
Created attachment 356468 [details] [review]
gdk-pixbuf: Add gdk_pixbuf_calculate_rowstride()

To calculate the rowstride without allocating memory!
Comment 14 Bastien Nocera 2017-07-27 11:22:30 UTC
Created attachment 356469 [details] [review]
bmp: Avoid allocating large buffers when not needed

Avoid allocating nearly 6 gigs of data when parsing the CVE-2015-4491
test only to free it when we've calculated that the rowstride * height
would overflow by calculating the rowstride before doing the allocation,
using the new gdk_pixbuf_calculate_rowstride() helper.
Comment 15 Bastien Nocera 2017-07-27 11:23:51 UTC
Comment on attachment 356467 [details] [review]
gdk-pixbuf: Tighten rowstride overflow check

Attachment 356467 [details] pushed as bb5492e - gdk-pixbuf: Tighten rowstride overflow check
Comment 16 Philip Withnall 2017-07-28 10:46:00 UTC
Review of attachment 356468 [details] [review]:

r+ with some nitpicks.

::: gdk-pixbuf/gdk-pixbuf.c
@@ +435,3 @@
+ *
+ * Return value: the rowstride for the given values, or -1 in case of error.
+ **/

Nitpick: */ rather than **/ (that’s the modern gtk-doc style).

Also, add a `Since: 2.36` line.
Comment 17 Philip Withnall 2017-07-28 10:47:03 UTC
Review of attachment 356469 [details] [review]:

Nice.
Comment 18 Bastien Nocera 2017-07-28 12:02:38 UTC
Created attachment 356508 [details] [review]
gdk-pixbuf: Add gdk_pixbuf_calculate_rowstride()

To calculate the rowstride without allocating memory!
Comment 19 Bastien Nocera 2017-07-28 12:03:46 UTC
Attachment 356469 [details] pushed as a8c4ac9 - bmp: Avoid allocating large buffers when not needed
Attachment 356508 [details] pushed as c1a9690 - gdk-pixbuf: Add gdk_pixbuf_calculate_rowstride()