[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v2] vsprintf: Make sure argument to %pX specifier is valid



On 12/02/15 16:33, Boris Ostrovsky wrote:
> On 02/12/2015 10:48 AM, Andrew Cooper wrote:
>> On 12/02/15 15:38, Boris Ostrovsky wrote:
>>> On 02/12/2015 10:21 AM, Andrew Cooper wrote:
>>>> On 12/02/15 15:01, Boris Ostrovsky wrote:
>>>>> On 02/12/2015 06:04 AM, Andrew Cooper wrote:
>>>>>> On 11/02/15 20:58, Boris Ostrovsky wrote:
>>>>>>> If invalid pointer (i.e. something smaller than
>>>>>>> HYPERVISOR_VIRT_START)
>>>>>>> is passed for %*ph/%pv/%ps/%pS format specifiers then print
>>>>>>> "(NULL)"
>>>>>>>
>>>>>>> Signed-off-by: Boris Ostrovsky <boris.ostrovsky@xxxxxxxxxx>
>>>>>>> ---
>>>>>>>     xen/common/vsprintf.c |   23 ++++++++++++++++-------
>>>>>>>     1 files changed, 16 insertions(+), 7 deletions(-)
>>>>>>>
>>>>>>> v2:
>>>>>>>     * Print "(NULL)" instead of specifier-specific string
>>>>>>>     * Consider all addresses under HYPERVISOR_VIRT_START as
>>>>>>> invalid.
>>>>>>> (I think
>>>>>>>       this is true for both x86 and ARM but I don't have ARM
>>>>>>> platform
>>>>>>> to test).
>>>>>>>
>>>>>>>
>>>>>>> diff --git a/xen/common/vsprintf.c b/xen/common/vsprintf.c
>>>>>>> index 065cc42..b9542b5 100644
>>>>>>> --- a/xen/common/vsprintf.c
>>>>>>> +++ b/xen/common/vsprintf.c
>>>>>>> @@ -270,6 +270,22 @@ static char *pointer(char *str, char *end,
>>>>>>> const char **fmt_ptr,
>>>>>>>         const char *fmt = *fmt_ptr, *s;
>>>>>>>           /* Custom %p suffixes. See
>>>>>>> XEN_ROOT/docs/misc/printk-formats.txt */
>>>>>>> +
>>>>>>> +    switch ( fmt[1] )
>>>>>>> +    {
>>>>>>> +        case 'h':
>>>>>>> +        case 's':
>>>>>>> +        case 'S':
>>>>>>> +        case 'v':
>>>>>>> +            ++*fmt_ptr;
>>>>>>> +    }
>>>>>>> +
>>>>>>> +    if ( (unsigned long)arg < HYPERVISOR_VIRT_START )
>>>>>>> +    {
>>>>>>> +        char *s = "(NULL)";
>>>>>>> +        return string(str, end, s, -1, -1, 0);
>>>>>>> +    }
>>>>>>> +
>>>>>>>         switch ( fmt[1] )
>>>>>> This wont function, as you have inverted the increment of
>>>>>> *fmt_ptr and
>>>>>> check of fmt[1].
>>>>> fmt value doesn't change, it is stashed at the top of the routine.
>>>> You are correct.  My apologies.  I however dislike the splitting of
>>>> the
>>>> switch into two.
>>>>
>>>>> (What *is* wrong in the above code is the fact that the arg test is
>>>>> done outside the switch. It should be part of the four case
>>>>> statements, otherwise we will print plain %p arguments as "NULL").
>>>>>
>>>>>
>>>>>> "(NULL)" is inappropriate for non-null pointers less than
>>>>>> VIRT_START.
>>>>> Yes, I thought about it after I sent it. "(invalid)"?
>>>> Better, but overriding the number with a string does hide information.
>>>> In the case that the pointer is invalid, it would be useful to see its
>>>> contents.
>>>
>>> How about "<0xXXXXXX>" (i.e. effectively replace "%pv" with "<%p>",
>>> with angle brackets indicating invalid pointer)?
>>>
>> It feels like change for change sake, especially as there is a perfectly
>> good hex decode for plain %p.
>>
>>>>>> Given the VIRT check, I would just put the entire switch statement
>>>>>> inside an "if ( (unsigned long)arg < HYPERVISOR_VIRT_START )" block
>>>>>> and
>>>>>> let it fall through to the plain number case for a bogus pointer.
>>>>> Not sure I understand what you are suggesting here, sorry.
>>>>>
>>>>> -boris
>>>> if ( (unsigned long)arg < HYPERVISOR_VIRT_START )
>>>> {
>>>>       switch ( fmt[1] )
>>>>       {
>>>>       ....
>>>>       }
>>>> }
>>>>
>>>>
>>>> This makes the patch a whole 3 line addition and indenting the whole
>>>> switch block by 4 spaces.
>>> Still don't understand. This will never print anything unless it's a
>>> bad pointer, won't it?
>>>
>>> (And if you meant '>=' then we will simply print the invalid pointer
>>> in plain %p format. Which, btw, may be the solution but we will still
>>> need to bump fmt_ptr, so we again will need another switch or
>>> something to test for sub-specifier)
>> Oops - I did mean >=.  I.e. only do the custom %pX decoding in the case
>> that arg is a plausible pointer.
>>
>> There is no need I can see to alter the fmt_ptr handling.  The code
>> currently works, other than the issue at hand of falling over a bad
>> pointer.
>
> We do, otherwise we will be printing the sub-specifier. Here is
> example of what happens if we don't bump it:
>
>     struct vcpu *badvcpu = NULL;
>     printk("badvcpu: %pv current: %pv\n", badvcpu, current);
>
> console:
>     badvcpu: 0000000000000000v current: d0v0
>

Ah - I see what you mean now.

>
> Also, for %*ph format, if we just go with falling through to plain
> format and not marking somehow that we are printing a bad pointer:
>
>     unsigned badval = 0xab;
>     unsigned *badptr = &badval;
>     printk("badptr = %*ph\n", 1, badptr);
>
> console:
>     badptr = ab
>
> We don't know here whether badptr was pointing to 0xab or it itself
> was 0xab.

Ok.  As this is only for making debug code less fragile, it probably is
better to explicitly call out a bad pointer differently.

~Andrew


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.