1665N/AFrom d9da580b46a28ab497de2e94fdc7b9ff953dab17 Mon Sep 17 00:00:00 2001
1665N/AFrom: Tobias Stoeckmann <tobias@stoeckmann.org>
1665N/ADate: Sun, 25 Sep 2016 21:30:03 +0200
1665N/ASubject: [PATCH:libXv] Protocol handling issues in libXv - CVE-2016-5407
1665N/A
1665N/AThe Xv query functions for adaptors and encodings suffer from out of
1665N/Aboundary accesses if a hostile X server sends a maliciously crafted
1665N/Aresponse.
1665N/A
1665N/AA previous fix already checks the received length against fixed values
1665N/Abut ignores additional length specifications which are stored inside
1665N/Athe received data.
1665N/A
1665N/AThese lengths are accessed in a for-loop. The easiest way to guarantee
1665N/Aa correct processing is by validating all lengths against the
1665N/Aremaining size left before accessing referenced memory.
1665N/A
1665N/AThis makes the previously applied check obsolete, therefore I removed
1665N/Ait.
1665N/A
1665N/ASigned-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
1665N/AReviewed-by: Matthieu Herrb <matthieu@herrb.eu>
1665N/A---
1665N/A src/Xv.c | 46 +++++++++++++++++++++++++++++-----------------
1665N/A 1 file changed, 29 insertions(+), 17 deletions(-)
1665N/A
1665N/Adiff --git a/src/Xv.c b/src/Xv.c
1665N/Aindex e47093a..be450c4 100644
1665N/A--- a/src/Xv.c
1665N/A+++ b/src/Xv.c
1665N/A@@ -158,6 +158,7 @@ XvQueryAdaptors(
1665N/A size_t size;
1665N/A unsigned int ii, jj;
1665N/A char *name;
1665N/A+ char *end;
1665N/A XvAdaptorInfo *pas = NULL, *pa;
1665N/A XvFormat *pfs, *pf;
1665N/A char *buffer = NULL;
1665N/A@@ -197,17 +198,13 @@ XvQueryAdaptors(
1665N/A /* GET INPUT ADAPTORS */
1665N/A
1665N/A if (rep.num_adaptors == 0) {
1665N/A- /* If there's no adaptors, there's nothing more to do. */
1665N/A+ /* If there are no adaptors, there's nothing more to do. */
1665N/A status = Success;
1665N/A goto out;
1665N/A }
1665N/A
1665N/A- if (size < (rep.num_adaptors * sz_xvAdaptorInfo)) {
1665N/A- /* If there's not enough data for the number of adaptors,
1665N/A- then we have a problem. */
1665N/A- status = XvBadReply;
1665N/A- goto out;
1665N/A- }
1665N/A+ u.buffer = buffer;
1665N/A+ end = buffer + size;
1665N/A
1665N/A size = rep.num_adaptors * sizeof(XvAdaptorInfo);
1665N/A if ((pas = Xmalloc(size)) == NULL) {
1665N/A@@ -225,9 +222,12 @@ XvQueryAdaptors(
1665N/A pa++;
1665N/A }
1665N/A
1665N/A- u.buffer = buffer;
1665N/A pa = pas;
1665N/A for (ii = 0; ii < rep.num_adaptors; ii++) {
1665N/A+ if (u.buffer + sz_xvAdaptorInfo > end) {
1665N/A+ status = XvBadReply;
1665N/A+ goto out;
1665N/A+ }
1665N/A pa->type = u.pa->type;
1665N/A pa->base_id = u.pa->base_id;
1665N/A pa->num_ports = u.pa->num_ports;
1665N/A@@ -239,6 +239,10 @@ XvQueryAdaptors(
1665N/A size = u.pa->name_size;
1665N/A u.buffer += pad_to_int32(sz_xvAdaptorInfo);
1665N/A
1665N/A+ if (u.buffer + size > end) {
1665N/A+ status = XvBadReply;
1665N/A+ goto out;
1665N/A+ }
1665N/A if ((name = Xmalloc(size + 1)) == NULL) {
1665N/A status = XvBadAlloc;
1665N/A goto out;
1665N/A@@ -259,6 +263,11 @@ XvQueryAdaptors(
1665N/A
1665N/A pf = pfs;
1665N/A for (jj = 0; jj < pa->num_formats; jj++) {
1665N/A+ if (u.buffer + sz_xvFormat > end) {
1665N/A+ Xfree(pfs);
1665N/A+ status = XvBadReply;
1665N/A+ goto out;
1665N/A+ }
1665N/A pf->depth = u.pf->depth;
1665N/A pf->visual_id = u.pf->visual;
1665N/A pf++;
1665N/A@@ -327,6 +336,7 @@ XvQueryEncodings(
1665N/A size_t size;
1665N/A unsigned int jj;
1665N/A char *name;
1665N/A+ char *end;
1665N/A XvEncodingInfo *pes = NULL, *pe;
1665N/A char *buffer = NULL;
1665N/A union {
1665N/A@@ -364,17 +374,13 @@ XvQueryEncodings(
1665N/A /* GET ENCODINGS */
1665N/A
1665N/A if (rep.num_encodings == 0) {
1665N/A- /* If there's no encodings, there's nothing more to do. */
1665N/A+ /* If there are no encodings, there's nothing more to do. */
1665N/A status = Success;
1665N/A goto out;
1665N/A }
1665N/A
1665N/A- if (size < (rep.num_encodings * sz_xvEncodingInfo)) {
1665N/A- /* If there's not enough data for the number of adaptors,
1665N/A- then we have a problem. */
1665N/A- status = XvBadReply;
1665N/A- goto out;
1665N/A- }
1665N/A+ u.buffer = buffer;
1665N/A+ end = buffer + size;
1665N/A
1665N/A size = rep.num_encodings * sizeof(XvEncodingInfo);
1665N/A if ((pes = Xmalloc(size)) == NULL) {
1665N/A@@ -391,10 +397,12 @@ XvQueryEncodings(
1665N/A pe++;
1665N/A }
1665N/A
1665N/A- u.buffer = buffer;
1665N/A-
1665N/A pe = pes;
1665N/A for (jj = 0; jj < rep.num_encodings; jj++) {
1665N/A+ if (u.buffer + sz_xvEncodingInfo > end) {
1665N/A+ status = XvBadReply;
1665N/A+ goto out;
1665N/A+ }
1665N/A pe->encoding_id = u.pe->encoding;
1665N/A pe->width = u.pe->width;
1665N/A pe->height = u.pe->height;
1665N/A@@ -405,6 +413,10 @@ XvQueryEncodings(
1665N/A size = u.pe->name_size;
1665N/A u.buffer += pad_to_int32(sz_xvEncodingInfo);
1665N/A
1665N/A+ if (u.buffer + size > end) {
1665N/A+ status = XvBadReply;
1665N/A+ goto out;
1665N/A+ }
1665N/A if ((name = Xmalloc(size + 1)) == NULL) {
1665N/A status = XvBadAlloc;
1665N/A goto out;
1665N/A--
1665N/A2.7.4
1665N/A