[ofw][PATCH] [IBBUS][WinVerbs][SDP] Validation ofnon-zerosizewhen calling to ExAllocatePoolWithTag
Fab Tillier
ftillier at microsoft.com
Tue Oct 27 09:42:11 PDT 2009
Hi Tzachi,
Tzachi Dar wrote on Tue, 27 Oct 2009 at 03:44:45:
> Let me explain where the whole issue started:
>
> There is a very common coding practice (on windows only?) that is used
> when the amount of memory needed is not known: You call the function
> with zero bytes, get an error of low resources but also the amount of
> memory that should be used. Next you allocate the needed memory and call
> the function again.
>
> An example to that behavior is the function:DWORD GetAdaptersInfo(
> PIP_ADAPTER_INFO pAdapterInfo, PULONG OutBufLen);
>
> The second parameter is described as: pOutBufLen [in, out] A pointer to
> a ULONG variable that specifies the size of the buffer pointed to by the
> pAdapterInfo parameter. If this size is insufficient to hold the adapter
> information, GetAdaptersInfo fills in this variable with the required
> size, and returns an error code of ERROR_BUFFER_OVERFLOW.
>
> An example to this behavior can be found in our code (for example) at
> the function WmQueryCaAttributes:
>
> static ib_ca_attr_t *WmQueryCaAttributes(WM_IB_DEVICE *pDevice) {
> ib_ca_attr_t *attr; UINT32 size; ib_api_status_t ib_status;
>
> size = 0;
> ib_status = pDevice->VerbsInterface.Verbs.
>
> query_ca(pDevice->VerbsInterface.Verbs.p_hca_obj, NULL, &size, NULL);
> if (ib_status != IB_INSUFFICIENT_MEMORY) {
Add a check for size == 0 here and your problem is solved. However, you point out a deficiency in the return codes: there's no way to distinguish between internal memory allocation failure and the user providing too small a buffer. The Windows APIs tend to use STATUS_BUFFER_OVERFLOW vs. STATUS_NO_MEMORY to distinguish between the two. Perhaps doing something similar here would help? In the simplistic case, returning IB_ERROR for internal memory allocation failure would do the trick, so that IB_INSUFFICIENT_MEMORY would only be returned if size was set to a valid value.
Why does query_ca try to allocate memory internally if the specified buffer is NULL? Seems like it should avoid that if it could.
-Fab
> attr = NULL;
> goto out;
> }
>
> attr = ExAllocatePoolWithTag(PagedPool, size, 'acmw');
> if (attr == NULL) {
> goto out;
> }
>
> The function query_ca is being called with a NULL pointer and size =0 in
> order to receive the correct amount of memory. Next we check what
> happens if (ib_status == IB_INSUFFICIENT_MEMORY). We treat this as a
> legal return value. But please note that this value can mean two things:
> 1) The function has returned as expected and all is well. Since the out
> value was NULL it didn't write the result but size points to the amount
> of memory that should be allocated. 2) (this is the case that the
> verifier has caught) The function was running. When it needed to
> allocate memory it failed. It now returns with status ==
> IB_INSUFFICIENT_MEMORY and size ==0. This is a legal value for the
> query_ca() function.
>
> Please note that case #2 will cause ExAllocatePoolWithTag to be called
> with size ==0 and from here is the bugcheck.
>
> So, this is the problem and asserting doesn't help since everything is
> according to the specs, and this can happen.
>
> Please also note that according to
> http://bytes.com/topic/c/answers/508471-malloc-0-a malloc of 0 bytes is
> legal but is implementation dependent while calling
> ExAllocatePoolWithTag with 0 brings a bugcheck.
>
> =======================================================================
> = ===========
>
> That said, we need to think of how we solve the problem ...
>
> Xalex approach was trying to limit the amount of work that will be used
> to make sure that 0 bytes are never allocated. That is, instead of going
> all over the places where ExAllocatePoolWithTag was used and trying to
> verify that 0 was not used, he was trying to make the function
> ExAllocatePoolWithTag behave like malloc.
>
> Thoughts ...
>
> Thanks
> Tzachi
>
>
>> -----Original Message-----
>> From: ofw-bounces at lists.openfabrics.org
>> [mailto:ofw-bounces at lists.openfabrics.org] On Behalf Of Sean Hefty
>> Sent: Monday, October 26, 2009 9:05 PM
>> To: Alex Naslednikov; Fab Tillier; ofw at lists.openfabrics.org;
>> Leonid Keller
>> Subject: RE: [ofw][PATCH] [IBBUS][WinVerbs][SDP] Validation
>> ofnon-zerosizewhen calling to ExAllocatePoolWithTag
>>
>>> I got your point. The problem is that we received zero-size only when
>>> running verifier with a low-mem simulation. It's not a normal
>>> situation, but our code isn't ready for this case. Take into account
>>> that only "problemmatic" calls to ExAllocatePoolWithTag were replaced;
>>> i.e all call were chances to get zero-size > 0. ASSERT may be good for
>>> a check version, but I don't believe we can find and eliminate all the
>>> problemmatic cases by doing so.
>>
>> IMO, this is too broad of a fix and in the wrong place.
>> Replacing standard Windows calls with a macro that looks like
>> a Windows call just obscures what's happening and increases
>> maintenance costs. At this point, we don't know if the call
>> to malloc is wrong, or if some other value is being returned
>> to the code that calls malloc incorrectly.
>>
>> I would expect a fix for a low-memory situation to add a
>> check that malloc worked, versus a check to see if malloc is
>> called with a size of 0. To me, this is pointing to an issue
>> in some other piece of code that isn't being modified by this patch.
>>
>> - Sean
>>
>> _______________________________________________
>> ofw mailing list
>> ofw at lists.openfabrics.org
>> http://lists.openfabrics.org/cgi-bin/mailman/listinfo/ofw
>>
More information about the ofw
mailing list