Browse Source
* gnu/packages/patches/libxv-CVE-2016-5407.patch: New file. * gnu/local.mk (dist_patch_DATA): Add it. * gnu/packages/xorg.scm (libxv)[replacement]: New field. (libxv/fixed): New variable.wip-deploy

3 changed files with 171 additions and 0 deletions
@ -0,0 +1,162 @@ |
|||
Fix CVE-2016-5407: |
|||
|
|||
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-5407 |
|||
|
|||
Patch copied from upstream source repository: |
|||
|
|||
https://cgit.freedesktop.org/xorg/lib/libXv/commit/?id=d9da580b46a28ab497de2e94fdc7b9ff953dab17 |
|||
|
|||
From d9da580b46a28ab497de2e94fdc7b9ff953dab17 Mon Sep 17 00:00:00 2001 |
|||
From: Tobias Stoeckmann <tobias@stoeckmann.org> |
|||
Date: Sun, 25 Sep 2016 21:30:03 +0200 |
|||
Subject: [PATCH] Protocol handling issues in libXv - CVE-2016-5407 |
|||
|
|||
The Xv query functions for adaptors and encodings suffer from out of |
|||
boundary accesses if a hostile X server sends a maliciously crafted |
|||
response. |
|||
|
|||
A previous fix already checks the received length against fixed values |
|||
but ignores additional length specifications which are stored inside |
|||
the received data. |
|||
|
|||
These lengths are accessed in a for-loop. The easiest way to guarantee |
|||
a correct processing is by validating all lengths against the |
|||
remaining size left before accessing referenced memory. |
|||
|
|||
This makes the previously applied check obsolete, therefore I removed |
|||
it. |
|||
|
|||
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org> |
|||
Reviewed-by: Matthieu Herrb <matthieu@herrb.eu> |
|||
---
|
|||
src/Xv.c | 46 +++++++++++++++++++++++++++++----------------- |
|||
1 file changed, 29 insertions(+), 17 deletions(-) |
|||
|
|||
diff --git a/src/Xv.c b/src/Xv.c
|
|||
index e47093a..be450c4 100644
|
|||
--- a/src/Xv.c
|
|||
+++ b/src/Xv.c
|
|||
@@ -158,6 +158,7 @@ XvQueryAdaptors(
|
|||
size_t size; |
|||
unsigned int ii, jj; |
|||
char *name; |
|||
+ char *end;
|
|||
XvAdaptorInfo *pas = NULL, *pa; |
|||
XvFormat *pfs, *pf; |
|||
char *buffer = NULL; |
|||
@@ -197,17 +198,13 @@ XvQueryAdaptors(
|
|||
/* GET INPUT ADAPTORS */ |
|||
|
|||
if (rep.num_adaptors == 0) { |
|||
- /* If there's no adaptors, there's nothing more to do. */
|
|||
+ /* If there are no adaptors, there's nothing more to do. */
|
|||
status = Success; |
|||
goto out; |
|||
} |
|||
|
|||
- if (size < (rep.num_adaptors * sz_xvAdaptorInfo)) {
|
|||
- /* If there's not enough data for the number of adaptors,
|
|||
- then we have a problem. */
|
|||
- status = XvBadReply;
|
|||
- goto out;
|
|||
- }
|
|||
+ u.buffer = buffer;
|
|||
+ end = buffer + size;
|
|||
|
|||
size = rep.num_adaptors * sizeof(XvAdaptorInfo); |
|||
if ((pas = Xmalloc(size)) == NULL) { |
|||
@@ -225,9 +222,12 @@ XvQueryAdaptors(
|
|||
pa++; |
|||
} |
|||
|
|||
- u.buffer = buffer;
|
|||
pa = pas; |
|||
for (ii = 0; ii < rep.num_adaptors; ii++) { |
|||
+ if (u.buffer + sz_xvAdaptorInfo > end) {
|
|||
+ status = XvBadReply;
|
|||
+ goto out;
|
|||
+ }
|
|||
pa->type = u.pa->type; |
|||
pa->base_id = u.pa->base_id; |
|||
pa->num_ports = u.pa->num_ports; |
|||
@@ -239,6 +239,10 @@ XvQueryAdaptors(
|
|||
size = u.pa->name_size; |
|||
u.buffer += pad_to_int32(sz_xvAdaptorInfo); |
|||
|
|||
+ if (u.buffer + size > end) {
|
|||
+ status = XvBadReply;
|
|||
+ goto out;
|
|||
+ }
|
|||
if ((name = Xmalloc(size + 1)) == NULL) { |
|||
status = XvBadAlloc; |
|||
goto out; |
|||
@@ -259,6 +263,11 @@ XvQueryAdaptors(
|
|||
|
|||
pf = pfs; |
|||
for (jj = 0; jj < pa->num_formats; jj++) { |
|||
+ if (u.buffer + sz_xvFormat > end) {
|
|||
+ Xfree(pfs);
|
|||
+ status = XvBadReply;
|
|||
+ goto out;
|
|||
+ }
|
|||
pf->depth = u.pf->depth; |
|||
pf->visual_id = u.pf->visual; |
|||
pf++; |
|||
@@ -327,6 +336,7 @@ XvQueryEncodings(
|
|||
size_t size; |
|||
unsigned int jj; |
|||
char *name; |
|||
+ char *end;
|
|||
XvEncodingInfo *pes = NULL, *pe; |
|||
char *buffer = NULL; |
|||
union { |
|||
@@ -364,17 +374,13 @@ XvQueryEncodings(
|
|||
/* GET ENCODINGS */ |
|||
|
|||
if (rep.num_encodings == 0) { |
|||
- /* If there's no encodings, there's nothing more to do. */
|
|||
+ /* If there are no encodings, there's nothing more to do. */
|
|||
status = Success; |
|||
goto out; |
|||
} |
|||
|
|||
- if (size < (rep.num_encodings * sz_xvEncodingInfo)) {
|
|||
- /* If there's not enough data for the number of adaptors,
|
|||
- then we have a problem. */
|
|||
- status = XvBadReply;
|
|||
- goto out;
|
|||
- }
|
|||
+ u.buffer = buffer;
|
|||
+ end = buffer + size;
|
|||
|
|||
size = rep.num_encodings * sizeof(XvEncodingInfo); |
|||
if ((pes = Xmalloc(size)) == NULL) { |
|||
@@ -391,10 +397,12 @@ XvQueryEncodings(
|
|||
pe++; |
|||
} |
|||
|
|||
- u.buffer = buffer;
|
|||
-
|
|||
pe = pes; |
|||
for (jj = 0; jj < rep.num_encodings; jj++) { |
|||
+ if (u.buffer + sz_xvEncodingInfo > end) {
|
|||
+ status = XvBadReply;
|
|||
+ goto out;
|
|||
+ }
|
|||
pe->encoding_id = u.pe->encoding; |
|||
pe->width = u.pe->width; |
|||
pe->height = u.pe->height; |
|||
@@ -405,6 +413,10 @@ XvQueryEncodings(
|
|||
size = u.pe->name_size; |
|||
u.buffer += pad_to_int32(sz_xvEncodingInfo); |
|||
|
|||
+ if (u.buffer + size > end) {
|
|||
+ status = XvBadReply;
|
|||
+ goto out;
|
|||
+ }
|
|||
if ((name = Xmalloc(size + 1)) == NULL) { |
|||
status = XvBadAlloc; |
|||
goto out; |
|||
--
|
|||
2.10.1 |
|||
|
Loading…
Reference in new issue