[PATCH 3/5] dix: set pointer to NULL after freeing at CloseDevice

Simon Thum simon.thum at gmx.de
Tue Apr 5 08:40:38 PDT 2011


On 04/05/2011 02:46 PM, Tiago Vignatti wrote:
> On 04/05/2011 03:54 PM, ext Simon Thum wrote:
>> On 04/05/2011 01:27 PM, Tiago Vignatti wrote:
>>> On 04/05/2011 03:14 PM, ext Simon Thum wrote:
>>>> On 04/04/2011 07:54 PM, Tiago Vignatti wrote:
>>>>> It will fix two possible cases of use after free in RemoveDevice.
>>>>>
>>>>> Signed-off-by: Tiago Vignatti<tiago.vignatti at nokia.com>
>>>>> ---
>>>>>    dix/devices.c |    1 +
>>>>>    1 files changed, 1 insertions(+), 0 deletions(-)
>>>>>
>>>>> diff --git a/dix/devices.c b/dix/devices.c
>>>>> index 534931c..0288e15 100644
>>>>> --- a/dix/devices.c
>>>>> +++ b/dix/devices.c
>>>>> @@ -941,6 +941,7 @@ CloseDevice(DeviceIntPtr dev)
>>>>>        free(dev->config_info);     /* Allocated in
>>>>> xf86ActivateDevice. */
>>>>>        dev->config_info = NULL;
>>>>>        dixFreeObjectWithPrivates(dev, PRIVATE_DEVICE);
>>>>> +    dev = NULL;
>>>>>    }
>>>>>
>>>>>    /**
>>>> OK, but _how_ does it do what you say it does? I'm just seeing a dead
>>>> store to a local.
>>>
>>> if you check RemoveDevice, you will see two loops (for) with a
>>> conditional (tmp = dev). If one of these conditional takes true path it
>>> will call CloseDevice(tmp), which in turn will free(tmp) through
>>> dixFreeObjectWithPrivates(dev, PRIVATE_DEVICE). Next, when it returns,
>>> the conditional to stop the loop in RemoveDevice will test the value of
>>> tmp, which cannot be done because was previously freed.
>> That can be done, because they're comparing the pointer without
>> dereferencing. Still, the loops in RD are strange. They're disguised
>> ways to get the device out of the global lists, which should be done
>> strictly before CloseDevice is called. But they seem correct (though
>> weird) to me as long as the device is only ever in at most one of the
>> lists. All dereferencing is done before CloseDevice().
>>
>> Making RemoveDevice readable instead would be nice, but why? What
>> actually leads you to think this dead store solves a problem?
> 
> all right, nevermind and sorry about the confusion.
> 
> I was caught about a false positive here in the statical analyzer which
> lead me to miscook the patch: the problem started when I haven't paid
> attention that tmp was passed by value instead reference; later there is
> this thing of deference a value not allocated (prev = tmp) but which
> won't be used.
Well maybe it's not the best style, but clearly valid - if you are
willing to assume that that the removal will not be preempted by a
device addition which allocates just that precise address still stored
in locals. Which is 99% safe and should be made 100% safe by ensuring RD
is called with signals off.

Sounds more like an analyzer problem.

> 
> Thanks for checking and ignore this patch.
> 
> 
> PS: as a enhancement for RemoveDevice, can we use break on both loops
> when a device is found given there will be only one device removed at
> one time?
It'd certainly be an improvement. Also check for signal safety when
you're at it.

Cheers,

Simon


More information about the xorg-devel mailing list