Xi: check for GetAttr permission when listing or querying devices.

If the check fails, leave the device off the returned list of info
structures.  Under XI2, this may cause inconsistent views of the device
topology after a change (for example, devices disappearing from view,
or showing as attached to a master that cannot be seen).  More work is
needed to deal with topology changes and device relabeling.

Signed-off-by: Eamon Walsh <ewalsh@tycho.nsa.gov>
This commit is contained in:
Eamon Walsh 2009-06-18 23:19:21 -04:00
parent 00bc8d34c6
commit 84662e40c3
2 changed files with 83 additions and 52 deletions

View File

@ -306,6 +306,25 @@ ListDeviceInfo(ClientPtr client, DeviceIntPtr d, xDeviceInfoPtr dev,
CopySwapClasses(client, d, &dev->num_classes, classbuf);
}
/***********************************************************************
*
* This procedure checks if a device should be left off the list.
*
*/
static Bool
ShouldSkipDevice(ClientPtr client, DeviceIntPtr d)
{
/* don't send master devices other than VCP/VCK */
if (!IsMaster(d) || d == inputInfo.pointer || d == inputInfo.keyboard)
{
int rc = XaceHook(XACE_DEVICE_ACCESS, client, d, DixGetAttrAccess);
if (rc == Success)
return FALSE;
}
return TRUE;
}
/***********************************************************************
*
@ -323,12 +342,10 @@ ProcXListInputDevices(ClientPtr client)
xListInputDevicesReply rep;
int numdevs = 0;
int namesize = 1; /* need 1 extra byte for strcpy */
int rc, size = 0;
int i = 0, size = 0;
int total_length;
char *devbuf;
char *classbuf;
char *namebuf;
char *savbuf;
char *devbuf, *classbuf, *namebuf, *savbuf;
Bool *skip;
xDeviceInfo *dev;
DeviceIntPtr d;
@ -343,55 +360,51 @@ ProcXListInputDevices(ClientPtr client)
AddOtherInputDevices();
for (d = inputInfo.devices; d; d = d->next) {
if (IsMaster(d) &&
d != inputInfo.pointer &&
d != inputInfo.keyboard)
continue; /* don't send master devices other than VCP/VCK */
/* allocate space for saving skip value */
skip = xcalloc(sizeof(Bool), inputInfo.numDevices);
if (!skip)
return BadAlloc;
/* figure out which devices to skip */
numdevs = 0;
for (d = inputInfo.devices; d; d = d->next, i++) {
skip[i] = ShouldSkipDevice(client, d);
if (skip[i])
continue;
rc = XaceHook(XACE_DEVICE_ACCESS, client, d, DixGetAttrAccess);
if (rc != Success)
return rc;
SizeDeviceInfo(d, &namesize, &size);
numdevs++;
}
for (d = inputInfo.off_devices; d; d = d->next) {
if (IsMaster(d) &&
d != inputInfo.pointer &&
d != inputInfo.keyboard)
continue; /* don't send master devices other than VCP/VCK */
for (d = inputInfo.off_devices; d; d = d->next, i++) {
skip[i] = ShouldSkipDevice(client, d);
if (skip[i])
continue;
rc = XaceHook(XACE_DEVICE_ACCESS, client, d, DixGetAttrAccess);
if (rc != Success)
return rc;
SizeDeviceInfo(d, &namesize, &size);
numdevs++;
}
/* allocate space for reply */
total_length = numdevs * sizeof(xDeviceInfo) + size + namesize;
devbuf = (char *)xcalloc(1, total_length);
classbuf = devbuf + (numdevs * sizeof(xDeviceInfo));
namebuf = classbuf + size;
savbuf = devbuf;
/* fill in and send reply */
i = 0;
dev = (xDeviceInfoPtr) devbuf;
for (d = inputInfo.devices; d; d = d->next)
{
if (IsMaster(d) &&
d != inputInfo.pointer &&
d != inputInfo.keyboard)
continue; /* don't count master devices other than VCP/VCK */
for (d = inputInfo.devices; d; d = d->next, i++) {
if (skip[i])
continue;
ListDeviceInfo(client, d, dev++, &devbuf, &classbuf, &namebuf);
}
for (d = inputInfo.off_devices; d; d = d->next)
{
if (IsMaster(d) &&
d != inputInfo.pointer &&
d != inputInfo.keyboard)
continue; /* don't count master devices other than VCP/VCK */
for (d = inputInfo.off_devices; d; d = d->next, i++) {
if (skip[i])
continue;
ListDeviceInfo(client, d, dev++, &devbuf, &classbuf, &namebuf);
}
@ -400,6 +413,7 @@ ProcXListInputDevices(ClientPtr client)
WriteReplyToClient(client, sizeof(xListInputDevicesReply), &rep);
WriteToClient(client, total_length, savbuf);
xfree(savbuf);
xfree(skip);
return Success;
}

View File

@ -40,9 +40,11 @@
#include "xkbsrv.h"
#include "xserver-properties.h"
#include "exevents.h"
#include "xace.h"
#include "xiquerydevice.h"
static Bool ShouldSkipDevice(ClientPtr client, int deviceid, DeviceIntPtr d);
static int ListDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo* info);
static int SizeDeviceInfo(DeviceIntPtr dev);
static void SwapDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo* info);
@ -65,8 +67,9 @@ ProcXIQueryDevice(ClientPtr client)
xXIQueryDeviceReply rep;
DeviceIntPtr dev = NULL;
int rc = Success;
int len = 0;
int i = 0, len = 0;
char *info, *ptr;
Bool *skip = NULL;
REQUEST(xXIQueryDeviceReq);
REQUEST_SIZE_MATCH(xXIQueryDeviceReq);
@ -79,28 +82,27 @@ ProcXIQueryDevice(ClientPtr client)
client->errorValue = stuff->deviceid;
return rc;
}
}
if (dev)
len += SizeDeviceInfo(dev);
}
else
{
len = 0;
for (dev = inputInfo.devices; dev; dev = dev->next)
skip = xcalloc(sizeof(Bool), inputInfo.numDevices);
if (!skip)
return BadAlloc;
for (dev = inputInfo.devices; dev; dev = dev->next, i++)
{
if (stuff->deviceid == XIAllDevices ||
(stuff->deviceid == XIAllMasterDevices && IsMaster(dev)))
skip[i] = ShouldSkipDevice(client, stuff->deviceid, dev);
if (!skip[i])
len += SizeDeviceInfo(dev);
}
for (dev = inputInfo.off_devices; dev; dev = dev->next)
for (dev = inputInfo.off_devices; dev; dev = dev->next, i++)
{
if (stuff->deviceid == XIAllDevices ||
(stuff->deviceid == XIAllMasterDevices && IsMaster(dev)))
skip[i] = ShouldSkipDevice(client, stuff->deviceid, dev);
if (!skip[i])
len += SizeDeviceInfo(dev);
}
dev = NULL;
}
info = xcalloc(1, len);
@ -124,10 +126,10 @@ ProcXIQueryDevice(ClientPtr client)
rep.num_devices = 1;
} else
{
for (dev = inputInfo.devices; dev; dev = dev->next)
i = 0;
for (dev = inputInfo.devices; dev; dev = dev->next, i++)
{
if (stuff->deviceid == XIAllDevices ||
(stuff->deviceid == XIAllMasterDevices && IsMaster(dev)))
if (!skip[i])
{
len = ListDeviceInfo(dev, (xXIDeviceInfo*)info);
if (client->swapped)
@ -137,10 +139,9 @@ ProcXIQueryDevice(ClientPtr client)
}
}
for (dev = inputInfo.off_devices; dev; dev = dev->next)
for (dev = inputInfo.off_devices; dev; dev = dev->next, i++)
{
if (stuff->deviceid == XIAllDevices ||
(stuff->deviceid == XIAllMasterDevices && IsMaster(dev)))
if (!skip[i])
{
len = ListDeviceInfo(dev, (xXIDeviceInfo*)info);
if (client->swapped)
@ -154,6 +155,7 @@ ProcXIQueryDevice(ClientPtr client)
WriteReplyToClient(client, sizeof(xXIQueryDeviceReply), &rep);
WriteToClient(client, rep.length * 4, ptr);
xfree(ptr);
xfree(skip);
return rc;
}
@ -172,6 +174,21 @@ SRepXIQueryDevice(ClientPtr client, int size, xXIQueryDeviceReply *rep)
}
/**
* @return Whether the device should be included in the returned list.
*/
static Bool
ShouldSkipDevice(ClientPtr client, int deviceid, DeviceIntPtr dev)
{
/* if all devices are not being queried, only master devices are */
if (deviceid == XIAllDevices || IsMaster(dev))
{
int rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGetAttrAccess);
if (rc == Success)
return FALSE;
}
return TRUE;
}
/**
* @return The number of bytes needed to store this device's xXIDeviceInfo