[PATCH] Bugfix for "Pre-validate ChangeGC XIDs": off-by-one in loop index.

Jeremy Huddleston jeremyhu at apple.com
Fri May 14 11:00:04 PDT 2010


Well, the issue is still persistent for my case.  The problem is difficult to discover because multiple points along the route have poor error handling.

1) ActivateDevice needs to handle the case where miPointerDeviceInitialize returns FALSE or we will crash in miPointerConstrainCursor.

271	    if (!((*pScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen)))
(gdb) 
273	        free(pPointer);
(gdb) 
274	        return FALSE;
(gdb) 
279	}

...

Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000020
0x0000000100198694 in miPointerConstrainCursor (pDev=0x103046ad0, pScreen=0x103208b00, pBox=0x110c54f10) at mipointer.c:208
208	    pPointer->limits = *pBox;
(gdb) print pPointer
$1 = (miPointerPtr) 0x0

2) miDCDeviceInitialize's failure and call to miDCDeviceCleanup can crash because miDCDeviceCleanup does not validate input:

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000053
0x000000010015b7fb in FreeGC (value=0x3, gid=0) at gc.c:786
786	    CloseFont(pGC->font, (Font)0);
(gdb) bt
#0  0x000000010015b7fb in FreeGC (value=0x3, gid=0) at gc.c:786
#1  0x00000001001922de in miDCDeviceCleanup (pDev=0x111299580, pScreen=0x10d605fb0) at midispcur.c:859
#2  0x00000001001921cf in miDCDeviceInitialize (pDev=0x111299580, pScreen=0x10d605fb0) at midispcur.c:837
#3  0x00000001001a2f60 in miSpriteDeviceCursorInitialize (pDev=0x111299580, pScreen=0x10d605fb0) at misprite.c:943
#4  0x0000000100198834 in miPointerDeviceInitialize (pDev=0x111299580, pScreen=0x10d605fb0) at mipointer.c:271
#5  0x00000001001389a6 in ActivateDevice (dev=0x111299580, sendevent=1 '\001') at devices.c:470
#6  0x0000000100138da7 in InitCoreDevices () at devices.c:603
#7  0x0000000100130039 in dix_main (argc=4, argv=0x7fff5fbfdb20, envp=0x7fff5fbfd9c0) at main.c:254
#8  0x0000000100018d6f in server_thread (arg=0x102b07860) at quartzStartup.c:63
#9  0x00007fff879fb456 in _pthread_start ()
#10 0x00007fff879fb309 in thread_start ()

or

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000495a80000
0x0000000100004580 in CloseFont (value=0x495a80000, fid=0) at dixfonts.c:486
486	    if (--pfont->refcnt == 0) {
(gdb) bt
#0  0x0000000100004580 in CloseFont (value=0x495a80000, fid=0) at dixfonts.c:486
#1  0x000000010015b809 in FreeGC (value=0x102861ce6, gid=0) at gc.c:786
#2  0x00000001001922de in miDCDeviceCleanup (pDev=0x1106707d0, pScreen=0x101506f10) at midispcur.c:859
#3  0x00000001001921cf in miDCDeviceInitialize (pDev=0x1106707d0, pScreen=0x101506f10) at midispcur.c:837
#4  0x00000001001a2f60 in miSpriteDeviceCursorInitialize (pDev=0x1106707d0, pScreen=0x101506f10) at misprite.c:943
#5  0x0000000100198834 in miPointerDeviceInitialize (pDev=0x1106707d0, pScreen=0x101506f10) at mipointer.c:271
#6  0x00000001001389a6 in ActivateDevice (dev=0x1106707d0, sendevent=1 '\001') at devices.c:470
#7  0x0000000100138da7 in InitCoreDevices () at devices.c:603
#8  0x0000000100130039 in dix_main (argc=4, argv=0x7fff5fbfdb20, envp=0x7fff5fbfd9c0) at main.c:254
#9  0x0000000100018d6f in server_thread (arg=0x1028704d0) at quartzStartup.c:63
#10 0x00007fff879fb456 in _pthread_start ()
#11 0x00007fff879fb309 in thread_start ()


I traced this to miDCMakeGC:

790	        pBuffer->pSourceGC = miDCMakeGC(pWin);

which is just a call to CreateGC:

(gdb) list
417	    int   status;
418	    XID   gcvals[2];
419	
420	    gcvals[0] = IncludeInferiors;
421	    gcvals[1] = FALSE;
422	    pGC = CreateGC((DrawablePtr)pWin,
423			   GCSubwindowMode|GCGraphicsExposures, gcvals, &status,
424			   (XID)0, serverClient);
425	    return pGC;
426	}


CreateGC fails in the call to dixChangeGC in this block:

557	    if (!(*pGC->pScreen->CreateGC)(pGC))
558		*pStatus = BadAlloc;
559	    else if (mask)
560	        *pStatus = dixChangeGC(client, pGC, mask, pval, NULL);
561	    else
562		*pStatus = Success;

which eventually lands us here:

#0  ChangeGCXIDs (client=0x103f0f9c0, pGC=0x1101311f0, mask=98304, pC32=0x103edac90) at gc.c:438
#1  0x000000010015ab7e in dixChangeGC (client=0x103f0f9c0, pGC=0x1101311f0, mask=98304, pC32=0x103edac90, pUnion=0x0) at gc.c:473
#2  0x000000010015ae7a in CreateGC (pDrawable=0x10074cc00, mask=98304, pval=0x103edac90, pStatus=0x103edacac, gcid=0, client=0x103f0f9c0) at gc.c:560



466	    return ChangeGC(client, pGC, mask, vals);
(gdb) print vals
$3 = {{
    val = 2750440, 
    ptr = 0x10029f7e8
  }, {
    val = 0, 
    ptr = 0x100000000
  }, {
    val = 2750440, 
    ptr = 0x10029f7e8
  }, {
    val = 269685576, 
    ptr = 0x110131348
  }, {
    val = 269685728, 
    ptr = 0x1101313e0
  }, {
    val = 269685568, 
    ptr = 0x110131340
  }, {
    val = 2750444, 
    ptr = 0x10029f7ec
  }, {
    val = 19121776, 
    ptr = 0x10123c670
  }, {
    val = 65907568, 
    ptr = 0x103edab70
  }, {
    val = 1451808, 
    ptr = 0x100162720
  }, {
    val = 19125072, 
    ptr = 0x10123d350
  }, {
    val = 269685728, 
    ptr = 0x1101313e0
  }, {
    val = 2750444, 
    ptr = 0x10029f7ec
  }, {
    val = 19121776, 
    ptr = 0x10123c670
  }, {
    val = 19121120, 
    ptr = 0x10123c3e0
  }, {
    val = 269685576, 
    ptr = 0x110131348
  }, {
    val = 65907648, 
    ptr = 0x103edabc0
  }, {
    val = 136390, 
    ptr = 0x1000214c6
  }, {
    val = 2750320, 
    ptr = 0x10029f770
  }, {
    val = 269685232, 
    ptr = 0x1101311f0
  }, {
    val = 19124704, 
    ptr = 0x10123d1e0
  }, {
    val = 19125072, 
    ptr = 0x10123d350
  }, {
    val = 269685728, 
    ptr = 0x1101313e0
  }}


And here's the failure inside ChangeGC:

ChangeGC (client=0x103f0f9c0, pGC=0x1101311f0, mask=98304, pUnion=0x103edaaf0) at gc.c:140
140	    int 	error = 0;
(gdb) 
144	    assert(pUnion);
(gdb) 
145	    pGC->serialNumber |= GC_CHANGE_SERIAL_BIT;
(gdb) 
147	    maskQ = mask;	/* save these for when we walk the GCque */
(gdb) 
148	    while (mask && !error) 
(gdb) 
150		index2 = (BITS32) lowbit (mask);
(gdb) 
151		mask &= ~index2;
(gdb) 
152		pGC->stateChanges |= index2;
(gdb) 
153		switch (index2)
(gdb) 
303			NEXTVAL(unsigned int, newclipmode);
(gdb) 
304			if (newclipmode <= IncludeInferiors)
(gdb) 
308			    clientErrorValue = newclipmode;
(gdb) 
309			    error = BadValue;
(gdb) 
311			break;
(gdb) 
148	    while (mask && !error) 
(gdb)
407	    if (pGC->fillStyle == FillTiled && pGC->tileIsPixel)
(gdb) 
415	    (*pGC->funcs->ChangeGC)(pGC, maskQ);
(gdb) 
416	    return error;




More information about the xorg-devel mailing list