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

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



On 22/08/2025 16:40, 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>

Reviewed-by: Tu Dinh <ngoc-tu.dinh@xxxxxxxxxx>

> ---
>   src/xenbus/store.c | 163 +++++++++++++++++++++++++++++++++------------
>   1 file changed, 122 insertions(+), 41 deletions(-)
> 
> diff --git a/src/xenbus/store.c b/src/xenbus/store.c
> index afb1954..27e0706 100644
> --- a/src/xenbus/store.c
> +++ b/src/xenbus/store.c
> @@ -1099,6 +1099,51 @@ RtlCaptureStackBackTrace(
>       __out_opt   PULONG  BackTraceHash
>       );
>   
> +static NTSTATUS
> +StoreCheckPathLength(
> +    _In_opt_ PSTR   Prefix,
> +    _In_ PSTR       Node
> +    )
> +{
> +    size_t          MaximumLength;
> +    size_t          Length;
> +
> +    if (Prefix != NULL) {
> +        MaximumLength = (Prefix[0] == '/' || Prefix[0] == '\0') ?
> +                    XENSTORE_ABS_PATH_MAX :
> +                    XENSTORE_REL_PATH_MAX;
> +
> +        Length = strlen(Prefix);
> +        if (Length > MaximumLength)
> +            goto fail1;
> +        MaximumLength -= Length;
> +
> +        if (MaximumLength < 1)
> +            goto fail2;
> +        MaximumLength -= 1;
> +    } else {
> +        MaximumLength = Node[0] == '/' ?
> +                            XENSTORE_ABS_PATH_MAX :
> +                            XENSTORE_REL_PATH_MAX;
> +    }
> +
> +    Length = strlen(Node);
> +    if (Length > MaximumLength)
> +        goto fail3;
> +    MaximumLength -= Length;
> +
> +    if (MaximumLength < 1)
> +        goto fail4;
> +
> +    return STATUS_SUCCESS;
> +
> +fail4:
> +fail3:
> +fail2:
> +fail1:
> +    return STATUS_INVALID_BUFFER_SIZE;
> +}
> +
>   static NTSTATUS
>   StoreRead(
>       _In_ PINTERFACE                     Interface,
> @@ -1116,6 +1161,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 +1194,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 +1219,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 +1295,9 @@ fail3:
>       StoreFreeResponse(Response);
>   
>   fail2:
> -fail1:
>       ASSERT(IsZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST)));
>   
> +fail1:
>       return status;
>   }
>   
> @@ -1326,6 +1376,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 +1390,9 @@ StorePrintf(
>       va_end(Arguments);
>   
>       return status;
> +
> +fail1:
> +    return status;
>   }
>   
>   static NTSTATUS
> @@ -1352,6 +1409,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 +1440,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 +1485,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 +1518,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 +1547,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 +1739,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 +1761,7 @@ StoreWatchAdd(
>   
>       status = STATUS_NO_MEMORY;
>       if (Path == NULL)
> -        goto fail2;
> +        goto fail3;
>   
>       status = (Prefix == NULL) ?
>                RtlStringCbPrintfA(Path, Length, "%s", Node) :
> @@ -1736,24 +1807,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 +1841,8 @@ fail3:
>   
>       __StoreFree(Path);
>   
> -fail2:
> -    Error("fail2\n");
> +fail3:
> +    Error("fail3\n");
>   
>       (*Watch)->Caller = NULL;
>       (*Watch)->Magic = 0;
> @@ -1779,6 +1850,9 @@ fail2:
>       ASSERT(IsZeroMemory(*Watch, sizeof (XENBUS_STORE_WATCH)));
>       __StoreFree(*Watch);
>   
> +fail2:
> +    Error("fail2\n");
> +
>   fail1:
>       Error("fail1 (%08x)\n", status);
>   
> @@ -2057,11 +2131,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 +2149,7 @@ StorePermissionsSet(
>       Path = __StoreAllocate(Length);
>   
>       if (Path == NULL)
> -        goto fail2;
> +        goto fail3;
>   
>       status = (Prefix == NULL) ?
>                RtlStringCbPrintfA(Path, Length, "%s", Node) :
> @@ -2088,7 +2166,7 @@ StorePermissionsSet(
>                                            Length,
>                                            &Used);
>           if (!NT_SUCCESS(status))
> -            goto fail3;
> +            goto fail4;
>   
>           Segment += Used;
>           Length -= Used;
> @@ -2108,17 +2186,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 +2206,12 @@ StorePermissionsSet(
>   
>       return STATUS_SUCCESS;
>   
> +fail7:
> +    Error("fail7\n");
> +    StoreFreeResponse(Response);
> +
>   fail6:
>       Error("fail6\n");
> -    StoreFreeResponse(Response);
>   
>   fail5:
>       Error("fail5\n");
> @@ -2138,17 +2219,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




 


Rackspace

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