keyboard LED bug + patch

Peter Hutterer peter.hutterer at who-t.net
Thu Apr 30 23:22:35 PDT 2009


On Sat, Feb 28, 2009 at 12:53:10AM -0500, pacman at kosh.dhis.org wrote:
> The component: xf86-input-keyboard
> 
> The source file: src/lnx_kbd.c
> 
> The function: GetKbdLeds
> 
> The bug:
>     int real_leds, leds = 0;
> 
>     ioctl(pInfo->fd, KDGETLED, &real_leds);
> 
>     if (real_leds & LED_CAP) leds |= XLED1;
>     if (real_leds & LED_NUM) leds |= XLED2;
>     if (real_leds & LED_SCR) leds |= XLED3;
> 
> The reason:
> KDGETLED actually only stores a single byte at the address indicated by
> &real_leds, which on big-endian systems means the kernel's led state is put
> into the most-significant byte of real_leds. The LED_CAP LED_NUM LED_SCR
> macros then extract some bits from the least-significant byte, which still
> contains stack garbage since real_leds hasn't been initialized.
> 
> Don't believe what the console_ioctl(4) man page says. It's wrong. Go read
> drivers/char/vt_ioctl.c in the kernel source, or run this demo on a
> big-endian machine:
> 
> #include <stdio.h>
> #include <sys/ioctl.h>
> #include <linux/kd.h>
> 
> int main(void)
> {
>   int ioctlret;
>   long longval;
> 
>   longval = -1;
> 
>   ioctlret = ioctl(0, KDGETLED, &longval);
>   printf("ioctlret=%d longval=%08lx\n", ioctlret, longval);
> 
>   return 0;
> }
> 
> The fix is very simple:
> 
> diff --git a/src/lnx_kbd.c b/src/lnx_kbd.c
> index cfe35a3..9144464 100644
> --- a/src/lnx_kbd.c
> +++ b/src/lnx_kbd.c
> @@ -73,7 +73,8 @@ SetKbdLeds(InputInfoPtr pInfo, int leds)
>  static int
>  GetKbdLeds(InputInfoPtr pInfo)
>  {
> -    int real_leds, leds = 0;
> +    char real_leds;
> +    int leds = 0;
>  
>      ioctl(pInfo->fd, KDGETLED, &real_leds);
>  

Pushed, thanks for the patch.
 
Cheers,
  Peter


More information about the xorg-devel mailing list