summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEamon Walsh <ewalsh@tycho.nsa.gov>2009-06-18 23:19:21 -0400
committerEamon Walsh <ewalsh@tycho.nsa.gov>2009-06-23 21:15:27 -0400
commit84662e40c3d4141ebb298a1ad714f75056a4ab74 (patch)
tree5eeca48cb1457ef7791c1c6284a745222f31f675
parent00bc8d34c68dab6c818cd1c7e03e9992d1d0cbfc (diff)
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>
-rw-r--r--Xi/listdev.c80
-rw-r--r--Xi/xiquerydevice.c55
2 files changed, 83 insertions, 52 deletions
diff --git a/Xi/listdev.c b/Xi/listdev.c
index 95c1532b4..1c847fbeb 100644
--- a/Xi/listdev.c
+++ b/Xi/listdev.c
@@ -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;
}
diff --git a/Xi/xiquerydevice.c b/Xi/xiquerydevice.c
index 6aa168521..33628a6ef 100644
--- a/Xi/xiquerydevice.c
+++ b/Xi/xiquerydevice.c
@@ -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