[PATCH] xkb: Don't swap XkbSetGeometry data in the input buffer

Peter Hutterer peter.hutterer at who-t.net
Thu Jan 29 19:15:37 PST 2015


On Fri, Jan 16, 2015 at 08:08:59PM +0100, Olivier Fourdan wrote:
> The XkbSetGeometry request embeds data which needs to be swapped when the
> server and the client have different endianess.
> 
> _XkbSetGeometry() invokes functions that swap these data directly in the
> input buffer.
> 
> However, ProcXkbSetGeometry() may call _XkbSetGeometry() more than once
> (if there is more than one keyboard), thus causing on swapped clients the
> same data to be swapped twice in memory, further causing a server crash
> because the strings lengths on the second time are way off bounds.
> 
> To allow _XkbSetGeometry() to run reliably more than once with swapped
> clients, do not swap the data in the buffer, use variables instead.
> 
> Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>

Keith, please merge this one directly, thanks.

Cheers,
   Peter

> ---
>  xkb/xkb.c | 35 +++++++++++++++++++----------------
>  1 file changed, 19 insertions(+), 16 deletions(-)
> 
> diff --git a/xkb/xkb.c b/xkb/xkb.c
> index 15c7f34..b9a3ac4 100644
> --- a/xkb/xkb.c
> +++ b/xkb/xkb.c
> @@ -4961,14 +4961,13 @@ static char *
>  _GetCountedString(char **wire_inout, Bool swap)
>  {
>      char *wire, *str;
> -    CARD16 len, *plen;
> +    CARD16 len;
>  
>      wire = *wire_inout;
> -    plen = (CARD16 *) wire;
> +    len = *(CARD16 *) wire;
>      if (swap) {
> -        swaps(plen);
> +        swaps(&len);
>      }
> -    len = *plen;
>      str = malloc(len + 1);
>      if (str) {
>          memcpy(str, &wire[2], len);
> @@ -4985,25 +4984,28 @@ _CheckSetDoodad(char **wire_inout,
>  {
>      char *wire;
>      xkbDoodadWireDesc *dWire;
> +    xkbAnyDoodadWireDesc any;
> +    xkbTextDoodadWireDesc text;
>      XkbDoodadPtr doodad;
>  
>      dWire = (xkbDoodadWireDesc *) (*wire_inout);
> +    any = dWire->any;
>      wire = (char *) &dWire[1];
>      if (client->swapped) {
> -        swapl(&dWire->any.name);
> -        swaps(&dWire->any.top);
> -        swaps(&dWire->any.left);
> -        swaps(&dWire->any.angle);
> +        swapl(&any.name);
> +        swaps(&any.top);
> +        swaps(&any.left);
> +        swaps(&any.angle);
>      }
>      CHK_ATOM_ONLY(dWire->any.name);
> -    doodad = XkbAddGeomDoodad(geom, section, dWire->any.name);
> +    doodad = XkbAddGeomDoodad(geom, section, any.name);
>      if (!doodad)
>          return BadAlloc;
>      doodad->any.type = dWire->any.type;
>      doodad->any.priority = dWire->any.priority;
> -    doodad->any.top = dWire->any.top;
> -    doodad->any.left = dWire->any.left;
> -    doodad->any.angle = dWire->any.angle;
> +    doodad->any.top = any.top;
> +    doodad->any.left = any.left;
> +    doodad->any.angle = any.angle;
>      switch (doodad->any.type) {
>      case XkbOutlineDoodad:
>      case XkbSolidDoodad:
> @@ -5026,12 +5028,13 @@ _CheckSetDoodad(char **wire_inout,
>                                                dWire->text.colorNdx);
>              return BadMatch;
>          }
> +        text = dWire->text;
>          if (client->swapped) {
> -            swaps(&dWire->text.width);
> -            swaps(&dWire->text.height);
> +            swaps(&text.width);
> +            swaps(&text.height);
>          }
> -        doodad->text.width = dWire->text.width;
> -        doodad->text.height = dWire->text.height;
> +        doodad->text.width = text.width;
> +        doodad->text.height = text.height;
>          doodad->text.color_ndx = dWire->text.colorNdx;
>          doodad->text.text = _GetCountedString(&wire, client->swapped);
>          doodad->text.font = _GetCountedString(&wire, client->swapped);
> -- 
> 2.1.0
> 


More information about the xorg-devel mailing list