|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH] Add check for maximum xenstore key lengths
Hi,
On 19/08/2025 12:52, Owen Smith wrote:
> Fail any xenstore call that exceeds the maximum lengths, as defined
> in xs_wire.h
>
> Signed-off-by: Owen Smith <owen.smith@xxxxxxxxx>
> ---
> src/xenbus/store.c | 159 ++++++++++++++++++++++++++++++++-------------
> 1 file changed, 114 insertions(+), 45 deletions(-)
>
> diff --git a/src/xenbus/store.c b/src/xenbus/store.c
> index afb1954..1ce77ed 100644
> --- a/src/xenbus/store.c
> +++ b/src/xenbus/store.c
> @@ -1099,6 +1099,34 @@ RtlCaptureStackBackTrace(
> __out_opt PULONG BackTraceHash
> );
>
> +static NTSTATUS
> +StoreCheckPathLength(
> + __in_opt PSTR Prefix,
> + __in PSTR Node
> + )
Could you replace the annotations with SAL2 ones (_In_, _In_opt_)?
> +{
> + ULONG Length;
> + ULONG MaximumLength;
> +
> + if (Prefix != NULL) {
> + MaximumLength = Prefix[0] == '/' ?
If Prefix is an empty string, the resulting path will be of the form
"/Node". This check should take this case into account and use
XENSTORE_ABS_PATH_MAX instead.
> + XENSTORE_ABS_PATH_MAX :
> + XENSTORE_REL_PATH_MAX;
> + Length = (ULONG)strlen(Prefix) + 1;
> + } else {
> + MaximumLength = Node[0] == '/' ?
> + XENSTORE_ABS_PATH_MAX :
> + XENSTORE_REL_PATH_MAX;
> + Length = 0;
> + }
> +
> + Length += (ULONG)strlen(Node) + 1;
I think you should check for overflow of Length, both due to the
downcast to ULONG and the addition.
Also, is the +1 necessary here? I don't know if XENSTORE_*_PATH_MAX
counts the null terminator.
> +
> + return Length > MaximumLength ?
> + STATUS_INVALID_BUFFER_SIZE :
> + STATUS_SUCCESS;
> +}
> +
> static NTSTATUS
> StoreRead(
> _In_ PINTERFACE Interface,
> @@ -1116,6 +1144,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 +1177,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 +1202,15 @@ StoreRead(
>
> return STATUS_SUCCESS;
>
> +fail5:
> fail4:
> -fail3:
> StoreFreeResponse(Response);
>
> +fail3:
> fail2:
> -fail1:
> ASSERT(IsZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST)));
>
> +fail1:
> return status;
> }
>
> @@ -1195,6 +1228,10 @@ StoreWrite(
> PXENBUS_STORE_RESPONSE Response;
> NTSTATUS status;
>
> + status = StoreCheckPathLength(Prefix, Node);
> + if (!NT_SUCCESS(status))
> + goto fail1;
> +
StoreWrite is indirectly called by StoreVPrintf, and eventually
StorePrintf which already checks for this, so another check here
shouldn't be necessary. I think checking at the interface boundaries
should be enough unless the path is further transformed.
> RtlZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST));
>
> KeAcquireSpinLock(&Context->Lock, &Irql);
> @@ -1224,30 +1261,31 @@ StoreWrite(
> 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;
> }
>
> @@ -1326,6 +1364,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 +1378,9 @@ StorePrintf(
> va_end(Arguments);
>
> return status;
> +
> +fail1:
> + return status;
> }
>
> static NTSTATUS
> @@ -1352,6 +1397,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 +1428,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 +1473,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 +1506,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 +1535,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 +1727,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 +1749,7 @@ StoreWatchAdd(
>
> status = STATUS_NO_MEMORY;
> if (Path == NULL)
> - goto fail2;
> + goto fail3;
>
> status = (Prefix == NULL) ?
> RtlStringCbPrintfA(Path, Length, "%s", Node) :
> @@ -1736,24 +1795,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 +1829,8 @@ fail3:
>
> __StoreFree(Path);
>
> -fail2:
> - Error("fail2\n");
> +fail3:
> + Error("fail3\n");
>
> (*Watch)->Caller = NULL;
> (*Watch)->Magic = 0;
> @@ -1779,6 +1838,9 @@ fail2:
> ASSERT(IsZeroMemory(*Watch, sizeof (XENBUS_STORE_WATCH)));
> __StoreFree(*Watch);
>
> +fail2:
> + Error("fail2\n");
> +
> fail1:
> Error("fail1 (%08x)\n", status);
>
> @@ -2057,11 +2119,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 +2137,7 @@ StorePermissionsSet(
> Path = __StoreAllocate(Length);
>
> if (Path == NULL)
> - goto fail2;
> + goto fail3;
>
> status = (Prefix == NULL) ?
> RtlStringCbPrintfA(Path, Length, "%s", Node) :
> @@ -2088,7 +2154,7 @@ StorePermissionsSet(
> Length,
> &Used);
> if (!NT_SUCCESS(status))
> - goto fail3;
> + goto fail4;
>
> Segment += Used;
> Length -= Used;
> @@ -2108,17 +2174,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 +2194,12 @@ StorePermissionsSet(
>
> return STATUS_SUCCESS;
>
> +fail7:
> + Error("fail7\n");
> + StoreFreeResponse(Response);
> +
> fail6:
> Error("fail6\n");
> - StoreFreeResponse(Response);
>
> fail5:
> Error("fail5\n");
> @@ -2138,17 +2207,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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |