|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |