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

Re: [PATCH] Add check for maximum xenstore key lengths



On 21/08/2025 21:59, Tu Dinh wrote:
> On 21/08/2025 12:00, Owen Smith wrote:
>> Check any xenstore path lengths before calling into xenstore, in order
>> to fail without passing control to xenstored, which should fail any request
>> with paths exceeding the defined maximum length.
>>
>> Signed-off-by: Owen Smith <owen.smith@xxxxxxxxx>
>> ---
>>    src/xenbus/store.c | 149 ++++++++++++++++++++++++++++++++-------------
>>    1 file changed, 108 insertions(+), 41 deletions(-)
>>
>> diff --git a/src/xenbus/store.c b/src/xenbus/store.c
>> index afb1954..0c00d23 100644
>> --- a/src/xenbus/store.c
>> +++ b/src/xenbus/store.c
>> @@ -1099,6 +1099,37 @@ RtlCaptureStackBackTrace(
>>        __out_opt   PULONG  BackTraceHash
>>        );
>>    
>> +static NTSTATUS
>> +StoreCheckPathLength(
>> +    _In_opt_ PSTR   Prefix,
>> +    _In_ PSTR       Node
>> +    )
>> +{
>> +    size_t          Length;
>> +    size_t          MaximumLength;
> 
> size_t will still overflow on 32-bit systems. I think you can keep
> things as ULONG and just have a preliminary check for
> XENSTORE_PAYLOAD_MAX on both strlen(Prefix) and strlen(Node), which will
> also take care of the overflow checking.
> 

My bad, the lengths can't be ULONG but must remain size_t.

>> +
>> +    Length = Prefix == NULL ? 0 : strlen(Prefix);
>> +
>> +    if (Length == 0) {
>> +        // Prefix is NULL or empty
>> +        MaximumLength = Node[0] == '/' ?
>> +                            XENSTORE_ABS_PATH_MAX :
>> +                            XENSTORE_REL_PATH_MAX;
>> +
>> +        Length = strlen(Node) + 1;
>> +    } else {
>> +        MaximumLength = Prefix[0] == '/' ?
>> +                            XENSTORE_ABS_PATH_MAX :
>> +                            XENSTORE_REL_PATH_MAX;
>> +
>> +        Length += 1 + strlen(Node) + 1;
>> +    }
>> +
>> +    return Length > MaximumLength ?
>> +                STATUS_INVALID_BUFFER_SIZE :
>> +                STATUS_SUCCESS;
>> +}
>> +
>>    static NTSTATUS
>>    StoreRead(
>>        _In_ PINTERFACE                     Interface,
>> @@ -1116,6 +1147,10 @@ StoreRead(
>>        PXENBUS_STORE_BUFFER                Buffer;
>>        NTSTATUS                            status;
>>    
>> +    status = StoreCheckPathLength(Prefix, Node);
>> +    if (!NT_SUCCESS(status))
>> +        goto fail1;
>> +
>>        (VOID) RtlCaptureStackBackTrace(1, 1, &Caller, NULL);
>>    
>>        RtlZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST));
>> @@ -1145,23 +1180,23 @@ StoreRead(
>>        KeReleaseSpinLock(&Context->Lock, Irql);
>>    
>>        if (!NT_SUCCESS(status))
>> -        goto fail1;
>> +        goto fail2;
>>    
>>        Response = StoreSubmitRequest(Context, &Request);
>>    
>>        status = STATUS_NO_MEMORY;
>>        if (Response == NULL)
>> -        goto fail2;
>> +        goto fail3;
>>    
>>        status = StoreCheckResponse(Response);
>>        if (!NT_SUCCESS(status))
>> -        goto fail3;
>> +        goto fail4;
>>    
>>        Buffer = StoreCopyPayload(Context, Response, Caller);
>>    
>>        status = STATUS_NO_MEMORY;
>>        if (Buffer == NULL)
>> -        goto fail4;
>> +        goto fail5;
>>    
>>        StoreFreeResponse(Response);
>>        ASSERT(IsZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST)));
>> @@ -1170,14 +1205,15 @@ StoreRead(
>>    
>>        return STATUS_SUCCESS;
>>    
>> +fail5:
>>    fail4:
>> -fail3:
>>        StoreFreeResponse(Response);
>>    
>> +fail3:
>>    fail2:
>> -fail1:
>>        ASSERT(IsZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST)));
>>    
>> +fail1:
>>        return status;
>>    }
>>    
>> @@ -1245,9 +1281,9 @@ fail3:
>>        StoreFreeResponse(Response);
>>    
>>    fail2:
>> -fail1:
>>        ASSERT(IsZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST)));
>>    
>> +fail1:
>>        return status;
>>    }
>>    
>> @@ -1326,6 +1362,10 @@ StorePrintf(
>>        va_list                             Arguments;
>>        NTSTATUS                            status;
>>    
>> +    status = StoreCheckPathLength(Prefix, Node);
>> +    if (!NT_SUCCESS(status))
>> +        goto fail1;
>> +
>>        va_start(Arguments, Format);
>>        status = StoreVPrintf(Interface,
>>                                Transaction,
>> @@ -1336,6 +1376,9 @@ StorePrintf(
>>        va_end(Arguments);
>>    
>>        return status;
>> +
>> +fail1:
>> +    return status;
>>    }
>>    
>>    static NTSTATUS
>> @@ -1352,6 +1395,10 @@ StoreRemove(
>>        PXENBUS_STORE_RESPONSE              Response;
>>        NTSTATUS                            status;
>>    
>> +    status = StoreCheckPathLength(Prefix, Node);
>> +    if (!NT_SUCCESS(status))
>> +        goto fail1;
>> +
>>        RtlZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST));
>>    
>>        KeAcquireSpinLock(&Context->Lock, &Irql);
>> @@ -1379,30 +1426,31 @@ StoreRemove(
>>        KeReleaseSpinLock(&Context->Lock, Irql);
>>    
>>        if (!NT_SUCCESS(status))
>> -        goto fail1;
>> +        goto fail2;
>>    
>>        Response = StoreSubmitRequest(Context, &Request);
>>    
>>        status = STATUS_NO_MEMORY;
>>        if (Response == NULL)
>> -        goto fail2;
>> +        goto fail3;
>>    
>>        status = StoreCheckResponse(Response);
>>        if (!NT_SUCCESS(status))
>> -        goto fail3;
>> +        goto fail4;
>>    
>>        StoreFreeResponse(Response);
>>        ASSERT(IsZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST)));
>>    
>>        return STATUS_SUCCESS;
>>    
>> -fail3:
>> +fail4:
>>        StoreFreeResponse(Response);
>>    
>> +fail3:
>>    fail2:
>> -fail1:
>>        ASSERT(IsZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST)));
>>    
>> +fail1:
>>        return status;
>>    }
>>    
>> @@ -1423,6 +1471,10 @@ StoreDirectory(
>>        PXENBUS_STORE_BUFFER                Buffer;
>>        NTSTATUS                            status;
>>    
>> +    status = StoreCheckPathLength(Prefix, Node);
>> +    if (!NT_SUCCESS(status))
>> +        goto fail1;
>> +
>>        (VOID) RtlCaptureStackBackTrace(1, 1, &Caller, NULL);
>>    
>>        RtlZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST));
>> @@ -1452,27 +1504,27 @@ StoreDirectory(
>>        KeReleaseSpinLock(&Context->Lock, Irql);
>>    
>>        if (!NT_SUCCESS(status))
>> -        goto fail1;
>> +        goto fail2;
>>    
>>        Response = StoreSubmitRequest(Context, &Request);
>>    
>>        status = STATUS_NO_MEMORY;
>>        if (Response == NULL)
>> -        goto fail2;
>> +        goto fail3;
>>    
>>        status = StoreCheckResponse(Response);
>>        if (!NT_SUCCESS(status))
>> -        goto fail3;
>> +        goto fail4;
>>    
>>        Buffer = StoreCopyPayload(Context, Response, Caller);
>>    
>>        status = STATUS_NO_MEMORY;
>>        if (Buffer == NULL)
>> -        goto fail4;
>> +        goto fail5;
>>    
>>        status = STATUS_OBJECT_PATH_NOT_FOUND;
>>        if (Buffer->Length == 0)
>> -        goto fail5;
>> +        goto fail6;
>>    
>>        StoreFreeResponse(Response);
>>        ASSERT(IsZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST)));
>> @@ -1481,17 +1533,18 @@ StoreDirectory(
>>    
>>        return STATUS_SUCCESS;
>>    
>> -fail5:
>> +fail6:
>>        StoreFreePayload(Context, Buffer);
>>    
>> +fail5:
>>    fail4:
>> -fail3:
>>        StoreFreeResponse(Response);
>>    
>> +fail3:
>>    fail2:
>> -fail1:
>>        ASSERT(IsZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST)));
>>    
>> +fail1:
>>        return status;
>>    }
>>    
>> @@ -1672,11 +1725,15 @@ StoreWatchAdd(
>>        KIRQL                           Irql;
>>        NTSTATUS                        status;
>>    
>> +    status = StoreCheckPathLength(Prefix, Node);
>> +    if (!NT_SUCCESS(status))
>> +        goto fail1;
>> +
>>        *Watch = __StoreAllocate(sizeof (XENBUS_STORE_WATCH));
>>    
>>        status = STATUS_NO_MEMORY;
>>        if (*Watch == NULL)
>> -        goto fail1;
>> +        goto fail2;
>>    
>>        (*Watch)->Magic = STORE_WATCH_MAGIC;
>>        (VOID) RtlCaptureStackBackTrace(1, 1, &(*Watch)->Caller, NULL);
>> @@ -1690,7 +1747,7 @@ StoreWatchAdd(
>>    
>>        status = STATUS_NO_MEMORY;
>>        if (Path == NULL)
>> -        goto fail2;
>> +        goto fail3;
>>    
>>        status = (Prefix == NULL) ?
>>                 RtlStringCbPrintfA(Path, Length, "%s", Node) :
>> @@ -1736,24 +1793,24 @@ StoreWatchAdd(
>>    
>>        status = STATUS_NO_MEMORY;
>>        if (Response == NULL)
>> -        goto fail3;
>> +        goto fail4;
>>    
>>        status = StoreCheckResponse(Response);
>>        if (!NT_SUCCESS(status))
>> -        goto fail4;
>> +        goto fail5;
>>    
>>        StoreFreeResponse(Response);
>>        ASSERT(IsZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST)));
>>    
>>        return STATUS_SUCCESS;
>>    
>> -fail4:
>> -    Error("fail4\n");
>> +fail5:
>> +    Error("fail5\n");
>>    
>>        StoreFreeResponse(Response);
>>    
>> -fail3:
>> -    Error("fail3\n");
>> +fail4:
>> +    Error("fail4\n");
>>    
>>        ASSERT(IsZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST)));
>>    
>> @@ -1770,8 +1827,8 @@ fail3:
>>    
>>        __StoreFree(Path);
>>    
>> -fail2:
>> -    Error("fail2\n");
>> +fail3:
>> +    Error("fail3\n");
>>    
>>        (*Watch)->Caller = NULL;
>>        (*Watch)->Magic = 0;
>> @@ -1779,6 +1836,9 @@ fail2:
>>        ASSERT(IsZeroMemory(*Watch, sizeof (XENBUS_STORE_WATCH)));
>>        __StoreFree(*Watch);
>>    
>> +fail2:
>> +    Error("fail2\n");
>> +
>>    fail1:
>>        Error("fail1 (%08x)\n", status);
>>    
>> @@ -2057,11 +2117,15 @@ StorePermissionsSet(
>>        PSTR                                PermissionString;
>>        PSTR                                Segment;
>>    
>> +    status = StoreCheckPathLength(Prefix, Node);
>> +    if (!NT_SUCCESS(status))
>> +        goto fail1;
>> +
>>        PermissionString = __StoreAllocate(XENSTORE_PAYLOAD_MAX);
>>    
>>        status = STATUS_NO_MEMORY;
>>        if (PermissionString == NULL)
>> -        goto fail1;
>> +        goto fail2;
>>    
>>        if (Prefix == NULL)
>>            Length = (ULONG)strlen(Node) + sizeof (CHAR);
>> @@ -2071,7 +2135,7 @@ StorePermissionsSet(
>>        Path = __StoreAllocate(Length);
>>    
>>        if (Path == NULL)
>> -        goto fail2;
>> +        goto fail3;
>>    
>>        status = (Prefix == NULL) ?
>>                 RtlStringCbPrintfA(Path, Length, "%s", Node) :
>> @@ -2088,7 +2152,7 @@ StorePermissionsSet(
>>                                             Length,
>>                                             &Used);
>>            if (!NT_SUCCESS(status))
>> -            goto fail3;
>> +            goto fail4;
>>    
>>            Segment += Used;
>>            Length -= Used;
>> @@ -2108,17 +2172,17 @@ StorePermissionsSet(
>>        KeReleaseSpinLock(&Context->Lock, Irql);
>>    
>>        if (!NT_SUCCESS(status))
>> -        goto fail4;
>> +        goto fail5;
>>    
>>        Response = StoreSubmitRequest(Context, &Request);
>>    
>>        status = STATUS_NO_MEMORY;
>>        if (Response == NULL)
>> -        goto fail5;
>> +        goto fail6;
>>    
>>        status = StoreCheckResponse(Response);
>>        if (!NT_SUCCESS(status))
>> -        goto fail6;
>> +        goto fail7;
>>    
>>        StoreFreeResponse(Response);
>>        ASSERT(IsZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST)));
>> @@ -2128,9 +2192,12 @@ StorePermissionsSet(
>>    
>>        return STATUS_SUCCESS;
>>    
>> +fail7:
>> +    Error("fail7\n");
>> +    StoreFreeResponse(Response);
>> +
>>    fail6:
>>        Error("fail6\n");
>> -    StoreFreeResponse(Response);
>>    
>>    fail5:
>>        Error("fail5\n");
>> @@ -2138,17 +2205,17 @@ fail5:
>>    fail4:
>>        Error("fail4\n");
>>    
>> +    __StoreFree(Path);
>> +    ASSERT(IsZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST)));
>> +
>>    fail3:
>>        Error("fail3\n");
>>    
>> -    __StoreFree(Path);
>> -    ASSERT(IsZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST)));
>> +    __StoreFree(PermissionString);
>>    
>>    fail2:
>>        Error("fail2\n");
>>    
>> -    __StoreFree(PermissionString);
>> -
>>    fail1:
>>        Error("fail1 (%08x)\n", status);
>>    
> 
> 
> 
> Ngoc Tu Dinh | Vates XCP-ng Developer
> 
> XCP-ng & Xen Orchestra - Vates solutions
> 
> web: https://vates.tech
> 
> 



Ngoc Tu Dinh | Vates XCP-ng Developer

XCP-ng & Xen Orchestra - Vates solutions

web: https://vates.tech




 


Rackspace

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