keyboard LED bug + patch
pacman at kosh.dhis.org
pacman at kosh.dhis.org
Fri Feb 27 21:53:10 PST 2009
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);
--
Alan Curry
More information about the xorg-devel
mailing list