Xext: store the GenericMasks in the resource system.
This fixes a severe issue - when the client died the event mask didn't get unregistered and a future event would dereference dangling pointers. By storing the event masks in the resource system we can free them when the client dies.
This commit is contained in:
parent
db86b8839f
commit
acce270935
53
Xext/geext.c
53
Xext/geext.c
|
@ -36,12 +36,15 @@
|
||||||
#define SERVER_GE_MAJOR 1
|
#define SERVER_GE_MAJOR 1
|
||||||
#define SERVER_GE_MINOR 0
|
#define SERVER_GE_MINOR 0
|
||||||
|
|
||||||
|
#define rClient(obj) (clients[CLIENT_ID((obj)->resource)])
|
||||||
|
|
||||||
int GEEventBase;
|
int GEEventBase;
|
||||||
int GEErrorBase;
|
int GEErrorBase;
|
||||||
DevPrivateKey GEClientPrivateKey = &GEClientPrivateKey;
|
DevPrivateKey GEClientPrivateKey = &GEClientPrivateKey;
|
||||||
int GEEventType; /* The opcode for all GenericEvents will have. */
|
int GEEventType; /* The opcode for all GenericEvents will have. */
|
||||||
|
|
||||||
|
int RT_GECLIENT = 0;
|
||||||
|
|
||||||
|
|
||||||
GEExtension GEExtensions[MAXEXTENSIONS];
|
GEExtension GEExtensions[MAXEXTENSIONS];
|
||||||
|
|
||||||
|
@ -53,6 +56,7 @@ static const int version_requests[] = {
|
||||||
|
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
static void SGEGenericEvent(xEvent* from, xEvent* to);
|
static void SGEGenericEvent(xEvent* from, xEvent* to);
|
||||||
|
static void GERecalculateWinMask(WindowPtr pWin);
|
||||||
|
|
||||||
#define NUM_VERSION_REQUESTS (sizeof (version_requests) / sizeof (version_requests[0]))
|
#define NUM_VERSION_REQUESTS (sizeof (version_requests) / sizeof (version_requests[0]))
|
||||||
|
|
||||||
|
@ -211,6 +215,43 @@ SGEGenericEvent(xEvent* from, xEvent* to)
|
||||||
GEExtensions[gefrom->extension & 0x7F].evswap(gefrom, geto);
|
GEExtensions[gefrom->extension & 0x7F].evswap(gefrom, geto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resource callback, invoked when the client disconnects and the associated
|
||||||
|
* GE masks must be destroyed.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
GEClientGone(WindowPtr pWin, XID id)
|
||||||
|
{
|
||||||
|
GenericClientMasksPtr gclmask;
|
||||||
|
GenericMaskPtr gmask, prev = NULL;
|
||||||
|
|
||||||
|
if (!pWin || !pWin->optional)
|
||||||
|
return Success;
|
||||||
|
|
||||||
|
gclmask = pWin->optional->geMasks;
|
||||||
|
for (gmask = gclmask->geClients; gmask; gmask = gmask->next)
|
||||||
|
{
|
||||||
|
if (gmask->resource == id)
|
||||||
|
{
|
||||||
|
if (prev)
|
||||||
|
{
|
||||||
|
prev->next = gmask->next;
|
||||||
|
xfree(gmask);
|
||||||
|
} else {
|
||||||
|
gclmask->geClients = NULL;
|
||||||
|
CheckWindowOptionalNeed(pWin);
|
||||||
|
GERecalculateWinMask(pWin);
|
||||||
|
xfree(gmask);
|
||||||
|
}
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
prev = gmask;
|
||||||
|
}
|
||||||
|
|
||||||
|
FatalError("Client not a GE client");
|
||||||
|
return BadImplementation;
|
||||||
|
}
|
||||||
|
|
||||||
/* Init extension, register at server.
|
/* Init extension, register at server.
|
||||||
* Since other extensions may rely on XGE (XInput does already), it is a good
|
* Since other extensions may rely on XGE (XInput does already), it is a good
|
||||||
* idea to init XGE first, before any other extension.
|
* idea to init XGE first, before any other extension.
|
||||||
|
@ -234,6 +275,9 @@ GEExtensionInit(void)
|
||||||
GEErrorBase = extEntry->errorBase;
|
GEErrorBase = extEntry->errorBase;
|
||||||
GEEventType = GEEventBase;
|
GEEventType = GEEventBase;
|
||||||
|
|
||||||
|
RT_GECLIENT = CreateNewResourceType((DeleteType)GEClientGone);
|
||||||
|
RegisterResourceName(RT_GECLIENT, "GECLIENT");
|
||||||
|
|
||||||
memset(GEExtensions, 0, sizeof(GEExtensions));
|
memset(GEExtensions, 0, sizeof(GEExtensions));
|
||||||
|
|
||||||
EventSwapVector[GenericEvent] = (EventSwapPtr) SGEGenericEvent;
|
EventSwapVector[GenericEvent] = (EventSwapPtr) SGEGenericEvent;
|
||||||
|
@ -338,7 +382,7 @@ GEWindowSetMask(ClientPtr pClient, DeviceIntPtr pDev,
|
||||||
cli = evmasks->geClients;
|
cli = evmasks->geClients;
|
||||||
while(cli)
|
while(cli)
|
||||||
{
|
{
|
||||||
if (cli->client == pClient && cli->dev == pDev)
|
if (rClient(cli) == pClient && cli->dev == pDev)
|
||||||
break;
|
break;
|
||||||
cli = cli->next;
|
cli = cli->next;
|
||||||
}
|
}
|
||||||
|
@ -352,16 +396,17 @@ GEWindowSetMask(ClientPtr pClient, DeviceIntPtr pDev,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cli->next = evmasks->geClients;
|
cli->next = evmasks->geClients;
|
||||||
cli->client = pClient;
|
cli->resource = FakeClientID(pClient->index);
|
||||||
cli->dev = pDev;
|
cli->dev = pDev;
|
||||||
evmasks->geClients = cli;
|
evmasks->geClients = cli;
|
||||||
|
AddResource(cli->resource, RT_GECLIENT, (pointer)pWin);
|
||||||
}
|
}
|
||||||
cli->eventMask[extension] = mask;
|
cli->eventMask[extension] = mask;
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
/* remove client. */
|
/* remove client. */
|
||||||
cli = pWin->optional->geMasks->geClients;
|
cli = pWin->optional->geMasks->geClients;
|
||||||
if (cli->client == pClient && cli->dev == pDev)
|
if (rClient(cli) == pClient && cli->dev == pDev)
|
||||||
{
|
{
|
||||||
pWin->optional->geMasks->geClients = cli->next;
|
pWin->optional->geMasks->geClients = cli->next;
|
||||||
xfree(cli);
|
xfree(cli);
|
||||||
|
@ -372,7 +417,7 @@ GEWindowSetMask(ClientPtr pClient, DeviceIntPtr pDev,
|
||||||
|
|
||||||
while(cli)
|
while(cli)
|
||||||
{
|
{
|
||||||
if (cli->client == pClient && cli->dev == pDev)
|
if (rClient(cli) == pClient && cli->dev == pDev)
|
||||||
{
|
{
|
||||||
prev->next = cli->next;
|
prev->next = cli->next;
|
||||||
xfree(cli);
|
xfree(cli);
|
||||||
|
|
|
@ -43,10 +43,10 @@ from the author.
|
||||||
* A grab has only one instance of this struct.
|
* A grab has only one instance of this struct.
|
||||||
*/
|
*/
|
||||||
typedef struct _GenericMaskRec {
|
typedef struct _GenericMaskRec {
|
||||||
ClientPtr client; /* client who set the event mask */
|
struct _GenericMaskRec* next;
|
||||||
|
XID resource; /* id for the resource manager */
|
||||||
DeviceIntPtr dev;
|
DeviceIntPtr dev;
|
||||||
Mask eventMask[MAXEXTENSIONS]; /* one mask per extension */
|
Mask eventMask[MAXEXTENSIONS]; /* one mask per extension */
|
||||||
struct _GenericMaskRec* next;
|
|
||||||
} GenericMaskRec, *GenericMaskPtr;
|
} GenericMaskRec, *GenericMaskPtr;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -175,7 +175,7 @@ ProcXExtendedGrabDevice(ClientPtr client)
|
||||||
(XGenericEventMask*)(((XEventClass*)&stuff[1]) + stuff->event_count);
|
(XGenericEventMask*)(((XEventClass*)&stuff[1]) + stuff->event_count);
|
||||||
|
|
||||||
gemasks = xcalloc(1, sizeof(GenericMaskRec));
|
gemasks = xcalloc(1, sizeof(GenericMaskRec));
|
||||||
gemasks->client = client;
|
gemasks->resource = FakeClientID(client->index);
|
||||||
gemasks->next = NULL;
|
gemasks->next = NULL;
|
||||||
gemasks->eventMask[xgeMask->extension & 0x7F] = xgeMask->evmask;
|
gemasks->eventMask[xgeMask->extension & 0x7F] = xgeMask->evmask;
|
||||||
|
|
||||||
|
|
14
dix/events.c
14
dix/events.c
|
@ -2118,7 +2118,7 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
|
||||||
/* Handle generic events */
|
/* Handle generic events */
|
||||||
if (type == GenericEvent)
|
if (type == GenericEvent)
|
||||||
{
|
{
|
||||||
GenericMaskPtr pClient;
|
GenericMaskPtr gmask;
|
||||||
/* We don't do more than one GenericEvent at a time. */
|
/* We don't do more than one GenericEvent at a time. */
|
||||||
if (count > 1)
|
if (count > 1)
|
||||||
{
|
{
|
||||||
|
@ -2132,16 +2132,16 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* run through all clients, deliver event */
|
/* run through all clients, deliver event */
|
||||||
for (pClient = GECLIENT(pWin); pClient; pClient = pClient->next)
|
for (gmask = GECLIENT(pWin); gmask; gmask = gmask->next)
|
||||||
{
|
{
|
||||||
if (pClient->eventMask[GEEXTIDX(pEvents)] & filter)
|
if (gmask->eventMask[GEEXTIDX(pEvents)] & filter)
|
||||||
{
|
{
|
||||||
if (XaceHook(XACE_RECEIVE_ACCESS, pClient->client, pWin,
|
if (XaceHook(XACE_RECEIVE_ACCESS, rClient(gmask), pWin,
|
||||||
pEvents, count))
|
pEvents, count))
|
||||||
/* do nothing */;
|
/* do nothing */;
|
||||||
else if (TryClientEvents(pClient->client, pDev,
|
else if (TryClientEvents(rClient(gmask), pDev,
|
||||||
pEvents, count,
|
pEvents, count,
|
||||||
pClient->eventMask[GEEXTIDX(pEvents)],
|
gmask->eventMask[GEEXTIDX(pEvents)],
|
||||||
filter, grab) > 0)
|
filter, grab) > 0)
|
||||||
{
|
{
|
||||||
deliveries++;
|
deliveries++;
|
||||||
|
@ -2223,7 +2223,7 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
|
||||||
{
|
{
|
||||||
GenericClientMasksPtr gemasks = pWin->optional->geMasks;
|
GenericClientMasksPtr gemasks = pWin->optional->geMasks;
|
||||||
GenericMaskPtr geclient = gemasks->geClients;
|
GenericMaskPtr geclient = gemasks->geClients;
|
||||||
while(geclient && geclient->client != client)
|
while(geclient && rClient(geclient) != client)
|
||||||
geclient = geclient->next;
|
geclient = geclient->next;
|
||||||
if (geclient)
|
if (geclient)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue
Block a user